I am an engineering student, busy with a project using DrJava as an IDE (it is the standard IDE we use during the course), and the Princeton STDLIB.
I have been having problems with understanding, writing and using objects. I would like to ask what is wrong with the way I wrote my following code. I will give the error lines after the coding:
public class GameObject
{
// Default implementation of a game object
private double G = 6.67408e-11;
private double radiusKoeff = 0.01;
public class Planet
{
double mass;
double size;
double velocityX;
double velocityY;
double positionX;
double positionY;
public Planet(double m, double vx, double vy, double px, double py)
{
mass = m;
size = m * radiusKoeff;
velocityX = vx;
velocityY = vy;
positionX = px;
positionY = py;
}//constructor for the planet type
public double GravForce(Planet a, Planet b)
{
double distanceX, distanceY, distance;
distanceX = Math.abs(a.positionX - b.positionX);
distanceY = Math.abs(a.positionY - b.positionY);
distance = Math.sqrt((distanceX)*(distanceX) + (distanceY)*(distanceY));
double force = (G * a.mass * b.mass) / (distance*distance);
return force;
}//calculates the gravitational force between two objects
}
public static void main(String[] args)
{
String filename = args[0];
Planet first = new Planet(1.25e24, 1, 0, 0, 0);
Planet second = new Planet(1e24, 1, 0, 5, 0);
**StdOut.println(GravForce( first, second ));**
}
}
Error: The method GravForce(GameObject.Planet, GameObject.Planet) is undefined for the type GameObject.
The error is thrown for the GravForce function I try to call.
Any help would be greatly appreciated.
Modify your method like this
public double GravForce(Planet b)
{
double distanceX, distanceY, distance;
distanceX = Math.abs(this.positionX - b.positionX);
distanceY = Math.abs(this.positionY - b.positionY);
distance = Math.sqrt((distanceX)*(distanceX) + (distanceY)*(distanceY));
double force = (G * this.mass * b.mass) / (distance*distance);
return force;
}//calculates the gravitational force between two objects
Then in main
public static void main(String[] args)
{
String filename = args[0];
Planet first = new Planet(1.25e24, 1, 0, 0, 0);
Planet second = new Planet(1e24, 1, 0, 5, 0);
StdOut.println(first.GravForce(second));
}
Related
I'm doing this project where I need to have this specific class structure and find the slope. I need to somehow find the slope using points 1 and 2 (p1, p2).
//file MyPoint
import java.text.DecimalFormat;
public class MyPoint {
private double x;
private double y;
public MyPoint() {
double xP = x;
double yP = y;
}
public double getX(double x) {
return x;
}
public double getY(double y) {
return y;
}
public String toString() {
DecimalFormat df_obj = new DecimalFormat("#.###");
return "(" + df_obj.format(getX(x)) + "," + df_obj.format(getY(y)) + ")";
}
}
//file MyLine
public class MyLine {
private MyPoint p1;
private MyPoint p2;
private double slope;
private double xint;
private double yint;
public MyLine(MyPoint p1, MyPoint p2) {
p1 = new MyPoint();
p2 = new MyPoint();
}
public static MyPoint getPointOne(MyPoint p1) {
return p1;
}
public static MyPoint getPointTwo(MyPoint p2) {
return p2;
}
public static double getSlope() {
double slope = //don't know what to put here in order to get the slope from p1 and p2;
return slope;
}
}
The slope is calculated as rise/run which means delta Y divided by delta X.
double slope = (p1.getY() - p2.getY())/(p1.getX() - p2.getX());
and the equation of the line is y = slope*x + b where b is the y-intercept (where the line crosses the y-axis if extended that far).
double b = y - slope*x; // use either point for x,y
A common slope calculation between 2 points would be:
slope = DeltaY / DeltaX = (y2 - y1) / (x2 - x1)
So in your getSlope() method you'd use:
double slope = (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
By the way I think there are a couple of mistakes in your code:
your getX() and getY() don't need to have 'x' and 'y' respectively as parameters. The x and y values are inside the MyPoint class' p1 and p2 instances.
On the other hand, the MyPoint constructor needs to receive the 'x' and 'y' parameters, in order to assign them to the inner xP and yP variables respectively.
I am coding a method that calculates the intersection of a line and a circle as a first step to write some kind of ray casting demo. In case an intersection is calculated it gets the shortest distance to the two points of intersection that will be the collision point, then it repeats the process where the new line originates from the collision point.
I was motivated by this video of a laser hitting different circles.
The method receives the angle of the line, the point where it originates, the size of the window, the radius of the circles, the array of centers of the circles and the GraphicsContext object from JavaFX.
The method has a couple of booleans to determine whether a collision has been made or not, and an ArrayList to store the collisions that will be later drawn on a JavaFX Canvas.
Inside a while loop the equation of the line is defined with the form y = m*x + b. Then checks which of the circles has a distance between the circle center and the line smaller than the radius of the line, this is calculated with the method explained here: math.stackexchange.com.
In case the distance to the center is smaller than the radius a collision occurs against that circle. As far as I know to find the intersection between a line and a circle you need to solve the equation system: y = m*x + b, (x-x1)^2 + (y-y1)^2 = r^2, that I solved via substitution. This results in a second degree polinomial equation that has a real solution if: p1*p1 >= 4*p0*p2.
The solution with the shortest distance to the origin point is the one that the line hits first and is the solution to our problem. A new angle is calculated with the center of the circle, the collision point and the origin point. With this a new line is defined and the loop repeats until no collision against the circles is calculated, situation where the collision against the borders of the window is calculated.
At the end a for loop draws all of the lines defined as couples of points inside collisionList.
This is the code, I've tried to comment it as best as I could:
private void extendPoint(double angle, Point origin, double x, double y, double radius, ArrayList<Point> pointList) {
double newAngle = angle; //Angle that defines the direction of the line
//This is used if the line does not hit a circle
double angle11 = Math.atan2(origin.getY(), origin.getX());
double angle_11 = Math.atan2(origin.getY(), -origin.getX());
double angle_1_1 = angle11 + Math.PI;
double angle1_1 = angle_11 + Math.PI;
boolean noCollision = true; //Will be true if the line does not hit a circle
boolean repeat = true; //If no collision has been made the while loop stops with this
Point currentPoint = Point.copy(origin); // (x0, y0)
Point collision = new Point(-1,-1); //Stores the collision point
Point newDirection = new Point(-1,-1); //Stores the new direction after a collision, returns(magnitud, angle) of a vector
ArrayList <Point> collisionList = new ArrayList<>(); //ArrayList of collision points that will be drawn later
collisionList.add(origin); //The origin point is added as a collision for representation purposes
while(repeat == true) {
//Line equation that passes through a point with an angle
//y = a*x - a*x0 + y0; -> y = m*x + b;
double m = Math.tan(-newAngle);
double a = m;
double b = -m*currentPoint.getX() + (currentPoint.getY());
for(int i = 0; i < pointList.size(); i++) {
Point gridPoint = pointList.get(i); //(x1, y1)
//From: https://math.stackexchange.com/questions/2552687/distance-between-line-and-point
//Given a line defined as A*x + B*y + C = 0
//x*(y1-y0)+y*(x1-x0)+(-y0*(x1-x0)-x0*(y1-y0)
double A = gridPoint.getY()-currentPoint.getY();
double B = gridPoint.getX()-currentPoint.getX();
double C = -currentPoint.getY()*B + currentPoint.getX()*A;
// double d_cp_gp = Math.abs(m*gridPoint.getX()-b*(gridPoint.getY()))/(Math.sqrt(m*m + 1));
double d_cp_gp = Math.abs(A + B + C)/Math.sqrt(A*A + B*B);
if(d_cp_gp < radius) {
System.out.println("radio " + d_cp_gp);
//The intersection between a line and a circunference:
//Circunference: (x-x1)^2 + (y-y1)^2 = r^2
//Line: y = tan(alpha)*(x-x0)+y0 -> y = a*x + b; a = tan(alfa), b = -tan(alfa)*x0 + y0
//Substituting the line equation in the circunference equation:
//x^2*(1+a^2) + x*(-2x1 + 2*a*b) + 2*a*b + x1^2+b^2-r^2 = 0
double p2 = 1 + a*a;
double p1 = -2*gridPoint.getX() + 2*a*b;
double p0 = gridPoint.getX()*gridPoint.getX() + b*b - radius*radius;
double p0_ = 4*p0*p2;
System.out.println(p1*p1 + " " + p0_);
//Check if the second order equation has solutions
if(p1*p1 >= p0_) {
System.out.println("IT HAS SOLUTION");
//Solution
double root = Math.sqrt(p1*p1 - p0_);
double sol1x = (-p1 + root)/(2*p2);
double sol2x = (-p1 - root)/(2*p2);
double sol1y = a*sol1x - a*currentPoint.getX() + currentPoint.getY();
double sol2y = a*sol1x - a*currentPoint.getX() + currentPoint.getY();
//The line will intersect twice with the circle, we want the solution
//with the shortest distance to currentPoint (x0,y0)
double distSol1 = Math.sqrt(Math.pow(currentPoint.getX()- sol1x, 2) +
Math.pow(currentPoint.getY() - sol1y, 2));
double distSol2 = Math.sqrt(Math.pow(currentPoint.getX()- sol2x, 2) +
Math.pow(currentPoint.getY() - sol2y, 2));
//The collision point is the point that the line hits first
if(distSol1 < distSol2) {
collision.setXY(sol1x, sol1y);
}
else {
collision.setXY(sol2x, sol2y);
}
//newAngle returns a vector with the form (magnitude, angle)
newDirection = newAngle(currentPoint, gridPoint, collision, radius);
currentPoint = collision;
//The new line after the collision is defined here
m = Math.tan(-newDirection.getY());
a = m;
b = -m*collision.getX() + (collision.getY());
collisionList.add(collision);
System.out.println("A collision has been calculated successfully: " + collision.toString());
//If a collision
noCollision= false;
}
}
//If no collisions have been detected at the end of the for loop exit the while loop
if(i == pointList.size() - 1 && noCollision == true) {
repeat = false;
}
}
//If no collision has been calculated with the circles this
//calculates the collision with the limits of the window
if(noCollision == true && repeat == false) {
if(angle<angle11 || angle > angle1_1) {
collision.setXY(x, m*x + b);
}
else if(angle > angle11 && angle < angle_11){
collision.setXY((0 - b)/m, 0);
}
else if(angle > angle_11 && angle < angle_1_1) {
collision.setXY(0, m*0 + b);
}
else if(angle> angle_1_1 && angle < angle1_1) {
collision.setXY((y - b)/m, y);
}
collisionList.add(collision);
}
}
System.out.println("Number of collisions: " + (int)(collisionList.size() - 1));
}
My main problem is that the shortest distance to a circle doesn't seem to be calculated properly, which directly difficults if the rest of the code works properly.
I've tried different methods to find the shortest distance and this is the one that I liked the most as I find it easy to understand, however the implementation doesn't work properly. I've thought that this could be because of JavaFX coordinate system (x increases to the right and y to the bottom) but I'm not sure, I'm a bit lost at this point.
Thanks for your time.
Edit:
As suggested I am adding some extra code to facilitate reproducibility.
The Point and Vector classes are defined as follows:
public class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;}
public double getX() {
return x;}
public double getY() {
return y;}
public void setX(double x) {
this.x = x;}
public void setY(double y) {
this.y = y;}
public void setXY(double x, double y) {
this.x = x;
this.y = y;}
#Override
public String toString() {
return("(" + this.x + "," + this.y + ")");
}
public static Point copy(Point a) {
return new Point(a.getX(), a.getY());
}
}
public class Vector {
private double vx;
private double vy;
private double ptoApX;
private double ptoApY;
private double angle;
private double modulo;
public Vector(double vx, double vy) {
this.vx = vx;
this.vy = vy;
this.ptoApX = 0;
this.ptoApY = 0;
this.angle = angle(vx,vy);
this.modulo = modulo(vx,vy);
}
//Getters
public double getVx() {
return this.vx;
}
public double getVy() {
return this.vy;
}
public double getPtoApX() {
return this.ptoApX;
}
public double getPtoApY() {
return this.ptoApY;
}
public double getAngle() {
return this.angle;
}
public double getModulo() {
return this.modulo;
}
//Setters
public void setVx(double vx) {
this.vx = vx;
}
public void setVy(double vy) {
this.vy = vy;
}
public void setPtoApX(double ptoApX) {
this.ptoApX = ptoApX;
}
public void setPtoApY(double ptoApY) {
this.ptoApY = ptoApY;
}
public void setAngle(double angle) {
this.angle = angle;
}
public void setModulo(double modulo) {
this.modulo = modulo;
}
//To String
#Override
public String toString() {
return "("+this.getVx()+","+this.getVy()+")";
}
public static double dotProduct(Vector a, Vector b) {
return a.getVx()*b.getVx() + a.getVy()*b.getVy();
}
public static Vector escalarProduct(Vector v, double n) {
return new Vector(n*v.getVx(), n*v.getVy());
}
public static Vector vectorWith2Points(Point a, Point b) {
Point p = Point.resta(a,b);
return new Vector(p.getX(),p.getY());
}
public static Vector vectorPointAngle(Point a, double angle, double modulo) {
double angleRadians = Math.toRadians(angle);
Point b = new Point(Math.cos(angleRadians)*modulo, Math.sin(angleRadians)*modulo);
return vectorWith2Points(a,b);
}
public static double modulo(double vx, double vy) {
return Math.sqrt(vx*vx + vy*vy);
}
public static double angle(double vx, double vy) {
return Math.atan2(vy, vx);
}
public static Vector normalize(Vector v) {
return new Vector(v.getVx()/v.getModulo(),v.getVy()/v.getModulo());
}
public static double angle2vectors(Vector u, Vector v) {
double argument = dotProduct(u,v)/(u.getModulo()*v.getModulo());
return Math.acos(argument);
}
public static Point polar2cart(double r, double angle) {
return new Point(r*Math.cos(angle), r*Math.sin(angle));
}
public static Point cart2polar(Point p) {
return new Point(modulo(p.getX(), p.getY()), angle(p.getX(), p.getY()));
}
}
And the method to obtain the new angle after a collision:
private Point newAngle(Point origin, Point center, Point c, double radius) {
//Normal vector
Vector n = Vector.vectorWith2Points(c, center);
Vector nNorm = Vector.normalize(n);
//Incident vector
Vector d = Vector.vectorWith2Points(c, origin);
//Tangent vector
Vector tg = new Vector(-nNorm.getVy(), nNorm.getVx());
//Reflected vector
double product = Vector.dotProduct(d,tg);
Vector r = new Vector(d.getVx()-2*product*tg.getVx(),
d.getVy() - 2*product*tg.getVy());
return new Point(r.getModulo(), r.getAngle());
}
An example of the code of different angles where a collision should be detected:
double x = 600;
double y = 400;
double radius = 10;
Point origin = new Point(x/2, y/2);
ArrayList<Point> pointList = new ArrayList<>();
pointList.add(new Point(40,40));
pointList.add(new Point(500,100));
pointList.add(new Point(40,330));
pointList.add(new Point(450,300));
//This should return a solution
extendPoint(0.4363323129985824, origin, x, y, radius, pointList);
extendPoint(2.6179938779914944, origin, x, y, radius, pointList);
//this returns a solution when it should not
extendPoint(1.5707963267948966, origin, x, y, radius, pointList);
extendPoint(-1.5707963267948966, origin, x, y, radius, pointList);
I wrote an class with everything needed to run the code here: https://pastebin.com/wMjUh9pZ
I think you should create a class that represents an intersection by a ray.
class Intersection{
double distance;
Point loc;
double normal;
}
That way, distance is along the ray and normal is the normal of the object intersected.
Then I would have a method for finding the intersetion of a circle and a point.
List<Intersection> lineAndCircle( Point org, double angle, Point center, double radius){...}
You seem to have a similar method but you're doing more work in it.
Then you also want to check the edge of the screen.
Intersection lineAndBoundary( Point org, double angle){ ... }
You have a very similar method, but you seem to be doing a lot more work in the method. . This way you are testing separate methods. Then your algorithm works as.
1 go through circles and find intersections.
2 get the intersection with the boundary.
3 find the closest intersection ( the smallest distance greater than 0 )
Doing it this way makes it a bit more extensible. First our ray is re-used a lot. Lets make a class.
class Ray{
Point origin;
double angle;
}
Then we collide a ray with multiple objects.
interface Interceptable{
List<Intersection> intercepts(Ray r);
}
Then we can use different classes.
class Circle implements Interceptable{
Point pos;
double radius;
#Override
List<Intersection> collides(Ray r){
...
}
}
Now you can right collides and testable.
Circle a = new Circle( new Point( 40, 40 ), 5 );
List<Intersection> yes = a.collides( new Ray( new Point(0, 0), 3.14/4 ) );
List<Intersection> no = a.collides( new Ray( new Point(0, 0), 0) ) );
Then you can narrow your example down to. "How do I write a collide method?" or "Why doesn't my collide method work for this ray/circle pair? I expect it to hit at two points, but it misses." etc.
Here is a complete runnable example that creates a swing window. I kinda enjoy making toy programs like this.
Note that I used an interface for the Intersectable. So now it is circles, but it could be anything that returns a list of Intersection
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.event.*;
import java.util.*;
public class RayAndCircle{
public static void main(String[] args){
List<Intersectable> circles = new ArrayList<>();
for(int i = 0; i<250; i++){
double r = Math.random()*50 + 50;
double x = 2048*Math.random();
double y = 2048*Math.random();
circles.add( new Circle( r, new double[]{x,y}));
}
List<LineSegment> segments = new ArrayList<>();
JFrame frame = new JFrame("Ray caster");
JPanel panel = new JPanel(){
#Override
public Dimension getPreferredSize(){
return new Dimension(2048, 2048);
}
#Override
public void paintComponent( Graphics g){
g.setColor(Color.RED);
for( Intersectable c: circles ){
c.draw(g);
}
g.setColor(Color.BLACK);
for( LineSegment segment: segments){
g.drawLine( (int) segment.a[0], (int) segment.a[1],(int)segment.b[0], (int)segment.b[1]);
}
}
};
panel.addMouseListener( new MouseAdapter(){
#Override
public void mouseClicked( MouseEvent evt ){
double x = evt.getPoint().getX();
double y = evt.getPoint().getY();
double theta = Math.random() * Math.PI * 2;
double dx = Math.cos( theta );
double dy = Math.sin( theta );
Ray ray = new Ray( new double[] {x, y}, new double[]{ dx, dy } );
int count = 500;
Intersectable last = null;
while( ray != null && count > 0 ){
Intersection hit = null;
Intersectable next = null;
for(Intersectable c: circles){
if(c == last){
continue;
}
List<Intersection> intersections = c.intersects(ray);
for(Intersection i : intersections){
if( hit == null ){
hit = i;
next = c;
} else{
if( hit.s > i.s ){
hit = i;
next = c;
}
}
}
}
if(hit != null){
last = next;
segments.add( new LineSegment( ray.origin, new double[]{ hit.pos[0], hit.pos[1] } ) );
count--;
//reflected portion of ray.
double dot = hit.normal[0]*ray.direction[0] + hit.normal[1]*ray.direction[1];
double rx = ray.direction[0] - 2 * hit.normal[0]*dot;
double ry = ray.direction[1] - 2 * hit.normal[1]*dot;
double z = Math.sqrt(rx*rx + ry*ry);
ray = new Ray(hit.pos, new double[] { rx/z, ry/z});
} else{
ray = null;
}
}
panel.repaint();
}
});
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class Ray{
double[] origin; double[] direction;
public Ray( double[] origin, double[] direction){
this.origin = new double[]{origin[0], origin[1]};
this.direction = new double[]{direction[0], direction[1]};
}
}
class Intersection{
double s;
double[] pos;
double[] normal;
Circle b;
public Intersection(double s, double[] pos, double[] normal){
this.s = s;
this.pos = pos;
setNormal(normal);
}
public void setNormal(double[] normal){
double m = Math.sqrt(normal[0]*normal[0] + normal[1]*normal[1]);
if( Double.isNaN(m) || m == 0) throw new RuntimeException("Invalid normal! Magnitude of" + m);
this.normal = new double[] { normal[0]/m , normal[1]/m };
}
}
interface Intersectable{
List<Intersection> intersects(Ray ray);
void draw(Graphics g);
}
class Circle implements Intersectable{
double[] origin;
double radius;
public Circle( double radius, double[] origin){
this.radius = radius;
this.origin = new double[]{origin[0], origin[1]};
}
Intersection intersectionAt(Ray ray, double s){
//intersection.
double locx = ray.origin[0] + s*ray.direction[0];
double locy = ray.origin[1] + s*ray.direction[1];
double nx = (locx - origin[0])/radius;
double ny = (locy - origin[1])/radius;
return new Intersection( s, new double[]{ locx, locy }, new double[]{nx, ny} );
}
public List<Intersection> intersects(Ray ray){
double rx = origin[0] - ray.origin[0];
double ry = origin[1] - ray.origin[1];
double m2 = rx*rx + ry*ry;
double m = Math.sqrt(m2);
//position along ray that is closest to circles origin.
double s = rx*ray.direction[0] + ry*ray.direction[1];
//closest distance to circle.
double approach = Math.sqrt(m2 - s*s);
List<Intersection> result = new ArrayList<>();
if( approach < radius ){
//two intersections at points on circle.
//radius is hypotenuse and approach is one of the lengths.
double l = Math.sqrt( radius*radius - approach*approach);
double s1 = s - l;
if(s1 > 0){
result.add( intersectionAt(ray, s1) );
}
double s2 = s + l;
if(s2 > 0){
//intersection!
result.add(intersectionAt(ray, s2) );
}
} else if(approach == radius){
//one intersection tangent.
if( s > 0 ){
result.add( intersectionAt(ray, s) );
}
} else{
//miss.
}
return result;
}
public void draw(Graphics g){
g.fillOval(
(int)(origin[0] - radius),
(int)(origin[1] - radius),
(int)radius*2,
(int)radius*2
);
}
}
class LineSegment{
double[] a, b;
public LineSegment( double[] a, double[] b){
this.a = new double[]{a[0], a[1]};
this.b = new double[]{b[0], b[1]};
}
}
You'll probably be most interested in the intersects method of the Circle class, and the small chunk of code burried in the mouseClicked method that calculates the reflected ray.
If you only want to know if the line intersects if a given circle, create a second line which originates at the center of the given circle and the direction is the direction of your initial line rotated by 90 degrees. Then compute the intersection of the two lines. If then the distance between the intersection point and the center of the circle is smaller then the radius, both intersect.
A while ago I wrote a small Geometry lib, I striped out the sections which are relevant for you, here is my code:
Line class
public class Line {
final Vector2D positionVector;
final Vector2D directionVector;
public Line(final Vector2D positionVector, final Vector2D directionVector) {
this.positionVector = positionVector;
this.directionVector = directionVector;
}
public OptionalDouble computeIntersection(final Line line) {
final double numerator = line.getPositionVector().subtract(this.positionVector).cross(this.directionVector);
final double denominator = this.directionVector.cross(line.directionVector);
if (Math.abs(numerator) < 1e-10 && Math.abs(denominator) < 1e-10) {
// collinear
return OptionalDouble.of(Double.POSITIVE_INFINITY);
} else if (Math.abs(denominator) < 1e-10) {
// parallel
return OptionalDouble.empty(); // Lines are parallel.
}
final double t = line.getPositionVector().subtract(this.positionVector).cross(line.directionVector) / denominator;
return OptionalDouble.of(t);
}
public Vector2D getPositionVector() {
return positionVector;
}
public Vector2D getDirectionVector() {
return directionVector;
}
public Point2D getClosestPointOnLine(final Point2D point) {
final Line line = new Line(new Vector2D(point.getX(), point.getY()), this.directionVector.turn90DegreeClockwise());
final OptionalDouble intersection = this.computeIntersection(line);
final Vector2D result = this.positionVector.add(this.directionVector.lerp(intersection.getAsDouble()));
return new Point2D(result.getX(), result.getY());
}
}
intersection function
public static PointResult intersection(final Line l1, final Circle c1) {
final Point2D intersection = l1.getClosestPointOnLine(c1.getCenter());
final double dist = intersection.distance(c1.getCenter());
if (Math.abs(dist - c1.getRadius()) < 1e-10) {
final List<Point2D> result = new LinkedList<>();
result.add(intersection);
return new PointResult(Collections.unmodifiableList(result));
} else if (dist < c1.getRadius()) {
// we have two points
final double adjacentLeg = Math.sqrt(c1.getRadius() * c1.getRadius() - dist * dist);
final Point2D pt1 = intersection.pointAt(l1.getDirectionVector().angle(), adjacentLeg);
final Point2D pt2 = intersection.pointAt(l1.getDirectionVector().angle() + Math.PI, adjacentLeg);
final List<Point2D> result = new LinkedList<>();
result.add(pt1);
result.add(pt2);
return new PointResult(Collections.unmodifiableList(result));
}
return new PointResult();
}
TestCase
#Test
void testIntersectionLineCircleTwoPoints() {
final Point2D ptCircleCenter = new Point2D(2.0, 5.0);
final Point2D ptLineCircleIntersection = new Point2D(5.0, 2.0);
final Point2D pt1 = new Point2D(3.0, 0.0);
final Point2D pt2 = new Point2D(7.0, 4.0);
final double a = Math.sqrt((2.0 * 2.0) + (2.0 * 2.0));
final double b = ptCircleCenter.diff(ptLineCircleIntersection).norm();
final double radius = Math.sqrt((a * a) + (b * b));
final Line l1 = new Line(pt1, pt2);
final Circle circle = new Circle(ptCircleCenter, radius);
PointResult intersection = GeometryOperation.intersection(l1, circle);
assertTrue(intersection.getPoints().isPresent());
assertEquals(2, intersection.getPoints().get().size());
assertEquals(7.0, intersection.getPoints().get().get(0).getX(), 1e-10);
assertEquals(4.0, intersection.getPoints().get().get(0).getY(), 1e-10);
assertEquals(3.0, intersection.getPoints().get().get(1).getX(), 1e-10);
assertEquals(0.0, intersection.getPoints().get().get(1).getY(), 1e-10);
}
I did not add the Circle, Vector2D and Point2D class because they are trivial. And the class PointResult is just a list.
I'm kind of new to Java, and trying to write a code that calculate the distance of two points 2 and 3, and scale of 10. Somehow, it does not work. Can you give me a hint, so I can fix the code?
import java.lang.Math;
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public float scale(int factor) {
new Point(x * factor, y * factor);
return factor;
}
public float distance(){
double distance = Math.sqrt(x * x + y * y);
return distance;
}
public void main(String[] args) {
float p = new Point(2,3).scale(10);
System.out.println(distance);
}
}
In scale you are creating a new point with the scaled values and doing nothing with it. You're leaving x and y of the point in question untouched.
You probably mean to multiply x and y by factor, rather than creating a new point.
Also you're printing a variable named distance, which does not exist (so this probably doesnt even compile), rather than calling the method named distance() and printing its returned value.
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public static Point scalePoint(Point p, int factor) { //scale a given point p by a given factor
Point scaledPoint = new Point(p.x * factor, p.y * factor); //by multipling the x and y value with the factor
return scaledPoint; //and return the new scaled point
}
public static double calculateDistance(Point p1, Point p2){ //to calculate the distance between two points
double distance = Math.sqrt(p1.x * p2.x + p1.y * p2.y); //send the two points as parameter to this method
return distance; //and return the distance between this two as a double value
}
public static void main(String[] args) {
Point p = new Point(2,3);
Point scaledPoint = scalePoint(p, 10);
double distance = calculateDistance(p, scaledPoint);
System.out.println(distance);
}
}
At the moment your distance method is calculating the distance of a point from the origin (i.e. point 0,0). It would make more sense if you made that explicit:
class Point {
private static final Point ORIGIN = new Point(0, 0);
private final int x;
private final int y;
public float distanceTo(Point other) {
float xDelta = other.x - this.x;
float yDelta = other.y - this.y;
return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
}
public Point scale(float factor) {
return new Point(x * factor, y * factor);
}
}
Then finding the distance to the origin becomes point.distanceTo(Point.ORIGIN) which makes the intent clearer.
I am trying to pass aF variable. But when debugging, it shows to have a value of 0. Any idea? below is the code I am using (Update: I included the whole code).
import java.util.ArrayList;
import java.util.List;
public class EOS {
//defining constants, input variables
public static final double GAS_CONSTANT = 8.3144598; //J K-1 mol-1
double criticalTemperature;
double criticalPressure;
double temperature;
double pressure;
double molecularWeight;
public EOS(double criticalTemperature, double criticalPressure, double temperature, double pressure, double molecularWeight) {
this.criticalTemperature = criticalTemperature;
this.criticalPressure = criticalPressure;
this.temperature = temperature;
this.pressure = pressure;
this.molecularWeight = molecularWeight;
}
// calculation of A* and B* (values of "a" and "b" will be provided by subclasses)
public double aStar(double a) {
return a * pressure / (Math.pow(GAS_CONSTANT, 2) * Math.pow(temperature, 2));
}
public double bStar(double b) {
return b * pressure / (GAS_CONSTANT * temperature);
}
//calculation of Z Value. The idea is to form the cubic function of Z as follow:
public List<Double> calculateZ(double aStar, double bStar, double uValue, double wValue) {
List<Double> solution = new ArrayList<>();
double a, b, c, q, r, d;
a = -1 - bStar + uValue * bStar;
b = aStar + wValue * Math.pow(bStar, 2) - uValue * bStar - uValue * Math.pow(bStar, 2);
c = - bStar * aStar - wValue * Math.pow(bStar, 2) - wValue * Math.pow(bStar, 3);
q = (3*b-Math.pow(a, 2))/3;
r = (2*Math.pow(a, 3)-9*a*b+27*c)/27;
d = (Math.pow(q, 3)/27) + (Math.pow(r, 2)/4);
if (d == 0) {
double x1 = 2*Math.pow(-r/2, 1/3) -(a/3);
double x2 = -2*Math.pow(-r/2, 1/3) -(a/3);
double x3 = x2;
double[] temp = {x1, x2, x3};
for (int i = 0; i < temp.length; i++) {
if (temp[i] > 0) {
solution.add(temp[i]);
}
}
} else if (d > 0) {
double x1 = Math.pow((-r/2)+Math.pow(d, 0.5),1/3)+Math.pow((-r/2)+Math.pow(d, 0.5),1/3)-(a/3);
solution.add(x1);
} else {
double theta = Math.acos((3*r/(2*q))*Math.sqrt(-3/q));
double x1 = 2*Math.sqrt(-q/3)*Math.cos(theta/3)-(a/3);
double x2 = 2*Math.sqrt(-q/3)*Math.cos((theta+2*Math.PI)/3)-(a/3);
double x3 = 2*Math.sqrt(-q/3)*Math.cos((theta+4*Math.PI)/3)-(a/3);
double[] temp = {x1, x2, x3};
for (int i = 0; i < temp.length; i++) {
if (temp[i] > 0) {
solution.add(temp[i]);
}
}
}
return solution;
}
}
Here the subclass
import java.util.Collections;
public class Soave extends EOS {
public Soave (double aFactor, double criticalTemperature, double criticalPressure, double temperature, double pressure, double molecularWeight) {
super(criticalTemperature, criticalPressure, temperature, pressure, molecularWeight);
this.aF = aFactor;
this.fW = 0.48+1.574*aFactor-0.176*Math.pow(aFactor, 2);
}
double aF;
double uValue = 1;
double wValue = 0;
double fW;
public double reducedTemperature = temperature / criticalTemperature;
public double bValue = 0.08664*GAS_CONSTANT*criticalTemperature/criticalPressure;
public double aValue() {
double term1 = 1 - Math.sqrt(reducedTemperature);
double term2 = 1+fW*term1;
double term3 = Math.pow(term2, 2.0);
double term4 = Math.pow(GAS_CONSTANT, 2)*Math.pow(criticalTemperature, 2.0);
return 0.42748*term3*term4/criticalPressure;
}
public double aStarValue = aStar(aValue());
public double bStarValue = bStar(bValue);
public double gasZValue = Collections.max(calculateZ(aStarValue, bStarValue, uValue, wValue));
public double liquidZValue = Collections.min(calculateZ(aStarValue, bStarValue, uValue, wValue));
public double gasDensity = pressure * molecularWeight / (1000 * gasZValue * GAS_CONSTANT * temperature);
public double liquidDensity = pressure * molecularWeight / (1000 * liquidZValue * GAS_CONSTANT * temperature);
}
So now when we create an instance of Soave for the following inputs, we should get for liquidDensity a value of 568.77
double p = 500000;
double t = 318.15;
double pC = 3019900;
double tC = 507.9;
double aF = 0.299;
double mW = 86;
Soave soave = new Soave(aF, tC, pC, t, p, mW);
System.out.println(soave.liquidDensity);
You set your fW variable prior to actually setting the value of aF so it is using the default value of the primitive double which is 0.
Either create a getter for fW where you do the calculations or more the calculation for fW inside the constructor block.
So Either you do like this:
public class Soave extends EOS {
public double aF;
double uValue = 1;
double wValue = 0;
public double fW;
public Soave (double aFactor, double criticalTemperature, double criticalPressure, double temperature, double pressure, double molecularWeight) {
super(criticalTemperature, criticalPressure, temperature, pressure, molecularWeight);
this.aF = aFactor;
fW = 0.48+1.574*aF-0.176*Math.pow(aF, 2); //This will give you the proper number.
}
Alternatively add a getter and do the calculation directly(No need for the fW-variable in the class then).
public double getfWValue() {
return 0.48+1.574*aF-0.176*Math.pow(aF, 2);
}
If so then use that directly in your print-statement instead.
System.out.println(soave.getfWValue());
It is surely the matter of passing the argument or reading it. Look at the piece of code where you pass the value(Most likely you pass 0, it's quite "hard" to make it 0 while reading). If you still can't find your mistake, post the proper code here.
This question already has answers here:
Is there possibility of sum of ArrayList without looping
(13 answers)
Closed 8 years ago.
I have an ArrayList:
ArrayList<MSS_Vector_Alg> vectors = new ArrayList<MSS_Vector_Alg>();
It will contain objects like
MSS_Vector_Alg(float x, float y, float z)
as you can see it has an (x,y,z) value. I am looking to add all the x values, y values and z values so I can get a (x-total, y-total, z-total). Is there a way I can do that?
Code ( classes for reference ):
MSS_Vector_Alg:
public class MSS_Vector_Alg {
float x;
float y;
float z;
int dimension;
String unit;
//basic ... assumes a 3D vector will be used
public MSS_Vector_Alg(){
this.x = 0;
this.y = 0;
this.z = 0;
this.dimension = 3;
this.unit = "unit";
}
//3D vector constructor
public MSS_Vector_Alg(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
this.dimension = 3;
this.unit = "unit";
}
//2D vector constructor
public MSS_Vector_Alg (float x, float y){
this.x = x;
this.y = y;
this.dimension = 2;
this.unit = "unit";
}
//1D vector constructor
public MSS_Vector_Alg(float x){
this.x = x;
this.dimension = 1;
this.unit = "unit";
}
// getter and setters
}
MSS_Vector_Math:
public final class MSS_Vector_Math {
// a list of possible method for various vector operations
//addition
public static MSS_Vector_Alg add(ArrayList<MSS_Vector_Alg> vectors){
//TODO
return null;
}
//opposite
public static MSS_Vector_Alg opposite(MSS_Vector_Alg vector){
float tempx;
float tempy;
float tempz;
tempx = -vector.getx();
tempy = -vector.gety();
tempz = -vector.getz();
MSS_Vector_Alg rev = new MSS_Vector_Alg(tempx, tempy, tempz);
return rev;
}
//scalar multiplication
public static MSS_Vector_Alg scalarMultiply(MSS_Vector_Alg vector, float scalar){
float scax;
float scay;
float scaz;
scax = vector.getx() * scalar;
scay = vector.gety() * scalar;
scaz = vector.getz() * scalar;
MSS_Vector_Alg smul = new MSS_Vector_Alg(scax, scay, scaz);
return smul;
}
//dot multiply
public static Float dotMultiply (MSS_Vector_Alg vector1,MSS_Vector_Alg vector2 ){
float dotx;
float doty;
float dotz;
float dotmul;
dotx = vector1.getx()*vector2.getx();
doty = vector1.gety()*vector2.gety();
dotz = vector1.getz()*vector2.getz();
dotmul = dotx + doty + dotz;
return dotmul;
}
//cross multiply
public static MSS_Vector_Alg crossMultiply(MSS_Vector_Alg vector1,MSS_Vector_Alg vector2){
float x1, y1, z1, x2, y2, z2, crossx, crossy, crossz;
x1 = vector1.getx();
y1 = vector1.gety();
z1 = vector1.getz();
x2 = vector2.getx();
y2 = vector2.gety();
z2 = vector2.getz();
crossx = (y1*z2)-(z1*y2);
crossy = (z1*x2)-(x1*z2);
crossz = (x1*y2)-(y1*x2);
MSS_Vector_Alg crsmul = new MSS_Vector_Alg(crossx, crossy, crossz);
return crsmul;
}
//convert from polar to algebraic
public static MSS_Vector_Alg convertPolarToAlgebraic(MSS_Vector_Pol polarVector){
float conx, cony, conz, r;
r = polarVector.getMagnitude();
conx = ((float)r * (float)Math.cos(polarVector.getAlpha()));
cony = ((float)r * (float)Math.cos(polarVector.getBeta()));
conz = ((float)r * (float)Math.cos(polarVector.getGamma()));
MSS_Vector_Alg conv = new MSS_Vector_Alg(conx, cony, conz);
return conv;
}
//convert from algebraic to polar
public static MSS_Vector_Pol convertAlgebraicToPolar(MSS_Vector_Alg algVector){
float conx, cony, conz, r, alpha, beta, gamma;
conx = algVector.getx();
cony = algVector.gety();
conz = algVector.getz();
r = (float)Math.sqrt((conx*conx + cony*cony + conz*conz));
alpha = (float)Math.acos(conx/r);
beta = (float)Math.acos(cony/r);
gamma = (float)Math.acos(conz/r);
MSS_Vector_Pol polvec = new MSS_Vector_Pol(r, alpha, beta, gamma);
return polvec;
}
//check validity of directional angles in 3D
public static boolean checkAngles3D(float alpha, float beta, float gamma){
//TODO
return true;
}
//check validity of directional angle in 2D
public static boolean checkAngle2D(float alpha){
//TODO
return true;
}
//check validity of directional angle in 1D
public static boolean checkAngle1D(float alpha){
//TODO
return true;
}
}
Most elegant solution would probably be to use Java Stream API:
List<MSS_Vector_Alg> vectors = new ArrayList<MSS_Vector_Alg>();
float sumOfXs = (float) vectors.stream().mapToDouble(mss -> mss.x).sum();
float sumOfYs = (float) vectors.stream().mapToDouble(mss -> mss.y).sum();
float sumOfZs = (float) vectors.stream().mapToDouble(mss -> mss.z).sum();
Have you tried iterating over the list and adding those numbers?
List<MSSVectorAlg> vectors = new ArrayList<MSSVectorAlg>();
int xTotal = 0, yTotal = 0, zTotal = 0;
for (MSSVectorAlg vector : vectors)
{
xTotal += vector.getX();
yTotal += vector.getY();
zTotal += vector.getZ();
}