How do I create a interactive canvas basic geometric shapes - java

I am currently on spring break and since I only work 25 hours a week I have too much free time on my hands. I am a Computer Science student and I decided to spend my free time improving my coding skills and my understanding of electromagnetic physics by creating a very simple calculator that is used to solve Coulomb's law with vectors which are used to solve the force between any two charged particles in a system of charged particles.
Now I have a somewhat accurate calculator working, I still have a few minor inaccuracies that I need to address but the code can be found down below, but it still works enough for the next step I would like to achieve.
This next step for me is to create a GUI and an interactive graph for the users to see. I say interactive because my ideal program would give the user the ability to drag and drop points on the canvas all the while the program is calculating the force vectors and net force that is present between the points the user places on the space. I would also be satisfied with just being able to draw the graph given the charges and XY-coordinates as well.
My question is does anyone know of any good tutorials or respectable libraries that I can look into to achieve either of these two ideas? I have a strong background in Java so I would prefer this to be done in Java, but I am never one to step away from learning a new language when I need too.
Code:
Charge.java
package objects;
/**
* Charge is an object used to represent an arbitrarily charged particle in some
* XY-plane. This class will store the value of the charge, the XY-coordinates
* of that charge's location, and functions to access these values.
*
* #author Seth
*
*/
public class Charge {
private double q; // the charge of the particle in Coulombs
private double x; // the location along the x-axis of the charge
private double y; // the location along the y-axis of the charge
public Charge(double x, double y, double q) {
this.x = x;
this.y = y;
this.q = q;
}
/**
* public method to get q
*
* #return
* double - value of the Charge object
*/
public double getQ() {
if (this != null)
return q;
else
return 0;
}
/**
* public method to get x
*
* #return
* double - value of the x coordinate
*/
public double getX() {
if (this != null)
return x;
else
return 0;
}
/**
* public method to get y
*
* #return
* double - value of the y coordinate
*/
public double getY() {
if (this != null)
return y;
else
return 0;
}
}
ElectricForceCalculator.java
package objects;
/**
* ElectricForceCalculator is a class that has the ability to solve the net
* force between two charged particles in a xy-plane
*
* #author Seth
*
*/
public class ElectricForceCalculator {
/**
* Private method used to find the force between two charges
*
* #param Q
* Charge - The charged we are focused on
* #param q
* Charge - The second charge effecting Q
* #return double array - the force vectors found where i = 0 is the x
* direction and i = 1 is the y direction
*/
private double[] calcForceHelper(Charge Q, Charge q) {
double radius, quanOfCharge;
double[] radiusVector = new double[2], forceVector = new double[2];
double x1 = Q.getX(), y1 = Q.getY();
double x2 = q.getX(), y2 = q.getY();
double q1 = Q.getQ(), q2 = q.getQ();
System.out.print("Calculating radius of Q and q...\n\t");
radius = calcRadius(x1, x2, y1, y2);
System.out.print("Calculating radiusVector of Q and q...\n\t");
radiusVector = calcRadiusVector(x1, x2, y1, y2, radius);
System.out.print("Calculating quantityOfCharge of Q and q...\n\t");
quanOfCharge = calcCharge(q1, q2, radius);
System.out.print("Calculating Force Vector of Q and q...\n\t");
forceVector = calcForceVector(radius, radiusVector, quanOfCharge);
return forceVector;
}
/**
* Public method used to find the overall net force of a system of charged
* particles
*
* #param Q
* Charge - the Charge object we are focused on
* #param q
* Charge array - the list of all the other Charge object
* effecting Q
* #param numCharges
* int - the number of indices found in the list of Charge
* objects q
* #return double - value of the net force experienced by Charge object Q
*/
public double calcForce(Charge Q, Charge[] q, int numCharges) {
double result;
double[] sum = { 0.0, 0.0 }, tempSum = new double[2];
for (int i = 0; i < numCharges - 1; i++) {
tempSum = calcForceHelper(Q, q[i]); // Help with readability to call
// method helper
fixSigns(Q, q[i], tempSum);
sum[0] += tempSum[0];
sum[1] += tempSum[1];
}
System.out.println("\nOverall force Vector on Q = (" + sum[0] + ")x + (" + sum[1] + ")y.");
result = Math.pow(sum[0], 2) + Math.pow(sum[1], 2);
result = Math.sqrt(result);
double theta = calcTheta(sum);
System.out.print("Force on charge Q by all other charges = " + result + " at ");
if (sum[1] > 0) {
if (sum[0] > 0)
System.out.print((float) Math.round(90 - theta) + " degrees.");
else
System.out.print((float) Math.round(180 - theta) + " degrees.");
} else {
if (sum[0] > 0)
System.out.print((float) Math.round(180 + theta) + " degrees.");
else
System.out.print((float) Math.round(270 + theta) + " degrees.");
}
return result;
}
/**
* Method used to assign negative values to any forces that should be
* negative
*
* #param Q
* Charge - the charge we are focused on
* #param q
* charge - the charge effecting Q
* #param tempSum
* the force vectors we are fixing, if needed
*/
private void fixSigns(Charge Q, Charge q, double[] tempSum) {
if (Q.getQ() < 0 && q.getQ() < 0) {
if (q.getX() > Q.getX())
tempSum[0] *= -1;
if (q.getY() > Q.getY())
tempSum[1] *= -1;
} else if (Q.getQ() > 0 && q.getQ() > 0) {
if (q.getX() > Q.getX())
tempSum[0] *= -1;
if (q.getY() > Q.getY())
tempSum[1] *= -1;
} else {
if (q.getX() < Q.getX())
tempSum[0] *= -1;
if (q.getY() < Q.getY())
tempSum[1] *= -1;
}
}
/**
* Private method used to calculate the angle Theta between two vectors
*
* #param forceVector
* double array - the force vectors we are finding the angle
* between
* #return double - the angle between the two force vectors given
*/
private double calcTheta(double[] vectors) {
double result = Math.abs(vectors[1]) / Math.abs(vectors[0]);// finds
// angle
// between 0
// and 90
result = Math.toDegrees(Math.atan(result));
return result;
}
/**
* Private method used to calculate the force vectors experienced by a
* charged particle
*
* #param radius
* double - distance between two charges
* #param radiusVector
* double array - the radius vectors between two charges
* #param quanOfCharge
* double - the quantity of charge given by k(coulomb's constant)
* * charge of Q * charge of q
* #return double array - the force vectors experienced by two charges
*/
private double[] calcForceVector(double radius, double[] radiusVector, double quanOfCharge) {
double[] result = new double[2];
double theta = calcTheta(radiusVector), magnitude = quanOfCharge;
result[0] = magnitude * Math.cos(Math.toRadians(theta));
result[1] = magnitude * Math.sin(Math.toRadians(theta));
System.out.print("Force Vector = (" + result[0] + ")x + (" + result[1] + ")y.\n");
return result;
}
/**
* private method used to calculate the quantity of charge between two
* charged particles(k * charge of Q * charge of q)
*
* #param Q
* double - the charge in Coulombs of the Charge object Q
* #param q
* double - the charge in Coulombs of the Charge object q
* #return double - the quantity of charge
*/
private double calcCharge(double Q, double q, double d) {
double result;
result = (((Q * q) / (d * d)) * 9E9);
result = Math.abs(result);
System.out.print("Quantity of charge(Q*q*k) = " + result + "\n");
return result;
}
/**
* Private method used to calculate the radius vector between two points on
* a xy-plane
*
* #param x1
* double - x coordinate of the Charge object Q
* #param x2
* double - y coordinate of the Charge object q
* #param y1
* double - x coordinate of the Charge object Q
* #param y2
* double - y coordinate of the Charge object q
* #param radius
* double - distance between the two points
* #return double array - the distance vectors between two charges
*/
private static double[] calcRadiusVector(double x1, double x2, double y1, double y2, double radius) {
double[] result = new double[2];
result[0] = (x2 - x1) / radius;
result[1] = (y2 - y1) / radius;
result[0] = Math.abs(result[0]);
result[1] = Math.abs(result[1]);
System.out.print("Radius vector = (" + result[0] + ")x + (" + result[1] + ")y\n");
return result;
}
/**
* Private method used to calculate the distance between two points on a
* xy-plane using the distance formula or [(x2-x1)+(y2-y1]^(1/2)
*
* #param x1
* double - x coordinate of the Charge object Q
* #param x2
* double - y coordinate of the Charge object q
* #param y1
* double - x coordinate of the Charge object Q
* #param y2
* double - y coordinate of the Charge object q
* #return double - distance between the two points given
*/
private double calcRadius(double x1, double x2, double y1, double y2) {
double distance = Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2);
distance = Math.sqrt(distance);
System.out.print("Radius = " + distance + "\n");
return distance;
}
/**
* Main
*
* #param args
*/
public static void main(String[] args) {
Charge Q = new Charge(-.02, .015, -4E-6);
Charge[] q = new Charge[2];
q[0] = new Charge(.035, .005, 3E-6);
q[1] = new Charge(-.0837, .0262, 4E-6);
ElectricForceCalculator calc = new ElectricForceCalculator();
calc.calcForce(Q, q, 3);
}
}
Sample output:
charge Q is -4.0E-6 C at (x,y) = (-0.02, 0.015).
charge q1 is 3.0E-6 C at (x,y) = (0.035, 0.005).
charge q1 is 4.0E-6 C at (x,y) = (-0.0837, 0.0262).
Calculating radius of Q and q...
Radius = 0.05590169943749475
Calculating radiusVector of Q and q...
Radius vector = (0.9838699100999075)x + (0.17888543819998312)y
Calculating quantityOfCharge of Q and q...
Quantity of charge(Q*q*k) = 34.559999999999995
Calculating Force Vector of Q and q...
Force Vector = (34.0025440930528)x + (6.182280744191415)y.
Calculating radius of Q and q...
Radius = 0.06467712114805357
Calculating radiusVector of Q and q...
Radius vector = (0.984892321570454)x + (0.17316788071568426)y
Calculating quantityOfCharge of Q and q...
Quantity of charge(Q*q*k) = 34.4239839545986
Calculating Force Vector of Q and q...
Force Vector = (33.903917474748674)x + (5.96112834720856)y.
Overall force Vector on Q = (0.09862661830412378)x + (-0.2211523969828546)y.
Force on charge Q by all other charges = 0.24214787327038295

Related

Given a set of points in 3d space, find all sets of points within a distance of eachother

I have a set of 3d points S.
I need to find the set X of all sets of points in S which are within manhattan distance d of each other.
i.e. for each set Y in X there exists atleast one point in 3d space that is within distance d of all points in Y
The length of set S will never be >20 but I will have to run this analysis on a stream of sets which are being produced at ~10 new sets per second, so whatever solution I use will have to be fairly efficient.
an example to help visualize the problem, given the following:
the output would be ((A,B), (B,C,E), (B,D,E))
we only care about the largest possible sets so the sets (B,C), (B,D), (B,E), (C,E) and (D,E), while within the given parameters, are not in the output given they are subsets of other sets in X
also this I'm doing this in java but any pointers in terms of algorithms or pseudo code would be greatly appreciated, thanks in advance.
A solution in pseudocode would be:
calculate_intersections(areas):
intersections = calculate every two intersecting areas
combinations = combine_intersections(intersections)
reduced = remove all sets in combinations that are included in bigger sets
combine_intersections(intersections):
do:
combinations = new HashSet
for s1 in intersections:
for s2 in intersections:
diff_1_2 = s1 \ s2
diff_2_1 = s2 \ s1
if diff_1_2.len == 1 && diff_2_1.len == 1:
union = diff_1_2 + diff_2_1
if union in intersections:
union2 = s1 + s2
if !union2 in intersections:
combinations.add(union)
while (combinations not empty)
An implementation in Java could look like this:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.collections4.SetUtils;
public class IntersectionSetCalculation {
private static class ManhattanDistanceArea {
private String id;
private Vector3D center;
private double distance;
public ManhattanDistanceArea(Vector3D center, double distance, String id) {
this.center = center;
this.distance = distance;
this.id = id;
}
#Override
public String toString() {
return id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((center == null) ? 0 : center.hashCode());
long temp;
temp = Double.doubleToLongBits(distance);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManhattanDistanceArea other = (ManhattanDistanceArea) obj;
if (center == null) {
if (other.center != null)
return false;
}
else if (!center.equals(other.center))
return false;
if (Double.doubleToLongBits(distance) != Double.doubleToLongBits(other.distance))
return false;
if (id == null) {
if (other.id != null)
return false;
}
else if (!id.equals(other.id))
return false;
return true;
}
public boolean intersects(ManhattanDistanceArea other) {
double maxDist = distance + other.distance;
return center.distance(other.center, 1) < maxDist;
}
}
/**
* Calculate the intersection of all areas (maximum of 2 areas in an intersection)
*/
public static Set<Set<ManhattanDistanceArea>> getIntersectingAreas(Set<ManhattanDistanceArea> areas) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>();
for (ManhattanDistanceArea area : areas) {
for (ManhattanDistanceArea area2 : areas) {
if (!area.equals(area2) && area.intersects(area2)) {
HashSet<ManhattanDistanceArea> intersection = new HashSet<ManhattanDistanceArea>();
intersection.add(area);
intersection.add(area2);
intersections.add(intersection);
}
}
}
Set<Set<ManhattanDistanceArea>> combined = combineIntersections(intersections);
Set<Set<ManhattanDistanceArea>> reduced = reduceIntersections(combined);
return reduced;
}
/**
* Combine the small intersections (with a maximum of 2 areas in an intersection) to bigger intersections
*/
public static Set<Set<ManhattanDistanceArea>> combineIntersections(Set<Set<ManhattanDistanceArea>> inters) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>(inters);
Set<Set<ManhattanDistanceArea>> combinations;
do {
combinations = new HashSet<Set<ManhattanDistanceArea>>();
for (Set<ManhattanDistanceArea> intersecting1 : intersections) {
for (Set<ManhattanDistanceArea> intersecting2 : intersections) {
Set<ManhattanDistanceArea> diff_1_2 = SetUtils.difference(intersecting1, intersecting2);
Set<ManhattanDistanceArea> diff_2_1 = SetUtils.difference(intersecting2, intersecting1);
if (diff_1_2.size() == 1 && diff_2_1.size() == 1) {
Set<ManhattanDistanceArea> union_1_2 = SetUtils.union(diff_1_2, diff_2_1);
if (intersections.contains(union_1_2)) {
Set<ManhattanDistanceArea> union = SetUtils.union(intersecting1, intersecting2);
if (!intersections.contains(union)) {
combinations.add(union);
}
}
}
}
}
intersections.addAll(combinations);
} while (!combinations.isEmpty());
return intersections;
}
/**
* Remove the small intersections that are completely covered by bigger intersections
*/
public static Set<Set<ManhattanDistanceArea>> reduceIntersections(Set<Set<ManhattanDistanceArea>> inters) {
Set<Set<ManhattanDistanceArea>> intersections = new HashSet<Set<ManhattanDistanceArea>>(inters);
Iterator<Set<ManhattanDistanceArea>> iter = intersections.iterator();
while (iter.hasNext()) {
Set<ManhattanDistanceArea> intersection = iter.next();
for (Set<ManhattanDistanceArea> intersection2 : inters) {
if (intersection2.size() > intersection.size() && intersection2.containsAll(intersection)) {
iter.remove();
break;
}
}
}
return intersections;
}
public static void main(String[] args) {
final double dist = 2d;//the manhattan distance d
ManhattanDistanceArea A = new ManhattanDistanceArea(new Vector3D(0, -3, 0), dist, "A");
ManhattanDistanceArea B = new ManhattanDistanceArea(new Vector3D(0, 0, 0), dist, "B");
ManhattanDistanceArea C = new ManhattanDistanceArea(new Vector3D(3.5, 0, 0), dist, "C");
ManhattanDistanceArea D = new ManhattanDistanceArea(new Vector3D(0, 3.5, 0), dist, "D");
ManhattanDistanceArea E = new ManhattanDistanceArea(new Vector3D(1, 1, 0), dist, "E");
ManhattanDistanceArea F = new ManhattanDistanceArea(new Vector3D(-1, 1, 0), dist, "F");
//test the example you provided
Set<ManhattanDistanceArea> abcde = new HashSet<ManhattanDistanceArea>();
abcde.addAll(Arrays.asList(new ManhattanDistanceArea[] {A, B, C, D, E}));
//test another example
Set<ManhattanDistanceArea> abcdef = new HashSet<ManhattanDistanceArea>();
abcdef.addAll(abcde);
abcdef.add(F);
Set<Set<ManhattanDistanceArea>> intersectionsABCDE = getIntersectingAreas(abcde);
Set<Set<ManhattanDistanceArea>> intersectionsABCDEF = getIntersectingAreas(abcdef);
System.out.println(intersectionsABCDE);
System.out.println(intersectionsABCDEF);
//test the runntime for 1000 calculation
double startTime = System.currentTimeMillis();
final int calculations = 1000;
for (int i = 0; i < calculations; i++) {
Set<ManhattanDistanceArea> areas = new HashSet<ManhattanDistanceArea>();
for (int j = 0; j < 20; j++) {
areas.add(new ManhattanDistanceArea(new Vector3D(Math.random() * 10 - 5, Math.random() * 10 - 5, Math.random() * 10 - 5), dist,
"A" + j));
}
getIntersectingAreas(areas);
}
System.out.println("\nTime used for " + calculations + " intersection calculations (with sets of size 20): "
+ (System.currentTimeMillis() - startTime) + "ms");
}
}
For the implementation I used this class Vector3D:
public class Vector3D {
public double x;
public double y;
public double z;
public static final Vector3D NAN_VEC = new Vector3D(Double.NaN, Double.NaN, Double.NaN);
public static final Vector3D NULL_VEC = new Vector3D(0, 0, 0);
public enum Axis {
X, Y, Z;
}
public Vector3D() {
}
/**
* Crate a new Vector2D with x and y components.
*/
public Vector3D(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3D(double... val) {
x = val[0];
y = val[1];
z = val[2];
}
/**
* Create a Vector3D by two angles (in degree).
*
* The first angle is in XY direction. The second angle is the Z direction.
*
* An angle (XY) of 0° results in (x, y) = (1, 0); 90° in (x, y) = (0, 1); ... An angle (Z) of 0° results in (x, y, z) = (x, y, 0); 90° in (x, y,
* z) = (x, y, 1); -90° in (x, y, z) = (x, y, -1)
*
* The resulting vector has a length of 1.
*
* #param angleXY
* The angle of the new vector (in degree) for the XY direction (from 0 to 360).
*
* #param angleZ
* The angle of the new vector (in degree) for the Z direction (from -90 to 90).
*/
public Vector3D(double angleXY, double angleZ) {
x = Math.cos(angleXY * Math.PI / 180) * Math.cos(angleZ * Math.PI / 180);
y = Math.sin(angleXY * Math.PI / 180) * Math.cos(angleZ * Math.PI / 180);
z = Math.sin(angleZ * Math.PI / 180);
double len = length();
x /= len;
y /= len;
z /= len;
}
private Vector3D(Vector3D clone) {
this.x = clone.x;
this.y = clone.y;
}
#Override
public Vector3D clone() {
return new Vector3D(this);
}
#Override
public String toString() {
return "Vector3D[x: " + x + " y: " + y + " z:" + z + "]";
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Vector3D) {
Vector3D v = (Vector3D) obj;
return Math.abs(x - v.x) < 1e-8 && Math.abs(y - v.y) < 1e-8 && Math.abs(z - v.z) < 1e-8;
}
return false;
}
/**
* Get this vector as 3D-Array.
*/
public double[] asArray() {
return new double[] {x, y, z};
}
/**
* The (euclidean) length of the Vector.
*/
public double length() {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
}
/**
* The length of this vector in a given norm.
*
* #param norm
* The norm of the vector length.
*
* #return The length of this vector in the given norm.
*/
public double length(int norm) {
if (norm == Integer.MAX_VALUE) {
return Math.max(Math.max(x, y), z);
}
return Math.pow(Math.pow(x, norm) + Math.pow(y, norm) + Math.pow(z, norm), 1.0 / norm);
}
/**
* Rotate this vector an angle (in degrees) around an axis resulting in a new Vector that is returned.
*
* #param degrees
* The angle to return the vector.
*
* #param axis
* The axis around which the vector is rotated.
*
* #return The new created vector.
*/
public Vector3D rotate(double degrees, Axis axis) {
double cos = Math.cos(degrees * Math.PI / 180);
double sin = Math.sin(degrees * Math.PI / 180);
switch (axis) {
case X:
return new Vector3D(x, cos * y - sin * z, sin * y + cos * z);
case Y:
return new Vector3D(cos * x + sin * z, y, -sin * x + cos * z);
case Z:
return new Vector3D(cos * x - sin * y, sin * x + cos * y, z);
default:
return null;
}
}
/**
* Project the vector given as parameter on this vector.
*
* #param vec
* The vector that is to be projected on this vector.
*
* #return The projected vector.
*/
public Vector3D project(Vector3D vec) {
return mult(scalar(vec) / Math.pow(length(), 2));
}
/**
* Add another Vector3D to this vector resulting in a new Vector that is returned.
*
* #param vec
* The vector added to this vector.
*
* #return The new created vector.
*/
public Vector3D add(Vector3D vec) {
return new Vector3D(x + vec.x, y + vec.y, z + vec.z);
}
/**
* Subtract another Vector3D from this vector resulting in a new Vector that is returned.
*
* #param vec
* The vector subtracted from this vector.
*
* #return The new created vector.
*/
public Vector3D sub(Vector3D vec) {
return new Vector3D(x - vec.x, y - vec.y, z - vec.z);
}
/**
* Multiply this vector with a scalar resulting in a new Vector that is returned.
*
* #param scalar
* The scalar to multiply this vector with.
*
* #return The new created vector.
*/
public Vector3D mult(double scalar) {
return new Vector3D(x * scalar, y * scalar, z * scalar);
}
/**
* Check whether this vector is linearly dependent to the parameter vector.
*
* #param vec
* The checked vector.
*
* #return True if the vectors are linearly dependent. False otherwise.
*/
public boolean isLinearlyDependent(Vector3D vec) {
double t1 = (x == 0 ? 0 : vec.x / x);
double t2 = (y == 0 ? 0 : vec.y / y);
double t3 = (z == 0 ? 0 : vec.z / z);
return Math.abs(t1 - t2) < 1e-5 && Math.abs(t1 - t3) < 1e-5 && t1 != 0;//all parameters t are equal and != 0
}
/**
* Calculate the scalar product of this vector and the parameter vector.
*
* #param vec
* The vector to calculate the scalar with this vector.
*
* #return The scalar of the vectors.
*/
public double scalar(Vector3D vec) {
return this.x * vec.x + this.y * vec.y + this.z * vec.z;
}
/**
* Calculate the cross product of this vector with another vector (resulting vector = this X parameter vector)
*
* #param vec
* The second vector for the cross product calculation.
*
* #return The cross product vector of the two vectors.
*/
public Vector3D cross(Vector3D vec) {
return new Vector3D(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
}
/**
* Create a new vector with the same direction but a different length as this vector.
*
* #param length
* The length of the new vector.
*
* #return The new vector with a new length.
*/
public Vector3D setLength(double length) {
double len = length();
return new Vector3D(x * length / len, y * length / len, z * length / len);
}
/**
* Get the distance of this point's position vector to another point's position vector.
*
* #param p
* The second point's position vector.
*
* #return The distance between the points.
*/
public double distance(Vector3D p) {
return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y) + (this.z - p.z) * (this.z - p.z));
}
/**
* Get the distance of this point's position vector to another point's position vector in a given norm.
*
* #param p
* The second point's position vector.
*
* #param norm
* The norm in which the distance is calculated (1 -> manhattan, 2 -> euclide, ...)
*
* #return The distance between the points in the given norm.
*/
public double distance(Vector3D p, int norm) {
return Math.pow((Math.pow(Math.abs(this.x - p.x), norm) + Math.pow(Math.abs(this.y - p.y), norm) + Math.pow(Math.abs(this.z - p.z), norm)),
1d / norm);
}
/**
* Change this vector to the new coordinates.
*/
public void move(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Move a point's position vector in a direction (by a vector) and a distance.
*
* #param p
* The direction vector.
*
* #param distance
* The distance to move the new vector
*
* #return The new created vector.
*/
public Vector3D moveTo(Vector3D p, double distance) {
double d = distance(p);
double dx = p.x - x;
double dy = p.y - y;
double dz = p.z - z;
double coef = distance / d;
return new Vector3D(x + dx * coef, y + dy * coef, z + dz * coef);
}
/**
* Get the angle difference of this vector to another vector.
*
* #param vec
* The other vector.
*
* #return The angle difference of the two vectors (from 0° to 180°).
*/
public double getAngleTo(Vector3D vec) {
double angle = Math.acos(scalar(vec) / (length() * vec.length())) * 180 / Math.PI;
if (angle > 180) {
angle = 360 - angle;
}
return angle;
}
/**
* Get the vector from this point to another.
*
* #param vec
* The point to which the vector is calculated.
*
* #return The vector from this points position vector to the other point.
*/
public Vector3D vectorTo(Vector3D vec) {
return new Vector3D(vec.x - x, vec.y - y, vec.z - z);
}
/**
* Checks whether a point (by its position vector) is in a given range of this point.
*
* #param p
* The point that is checked.
*
* #param range
* The range used for the check.
*
* #return True if the point is in the range of this point (distance <= range).
*/
public boolean isInRange(Vector3D p, double range) {
return p != this && distance(p) <= range;
}
}
and the class SetUtils from the apache commons lib.
I also added some tests:
the test from your question
another test with a bigger intersection set
a test for the runtime
The results are:
[[A, B], [B, E, C], [B, E, D]]
[[A, B], [B, E, C], [D, E, F, B]]
Time used for 1000 intersection calculations (with sets of size 20):
791.0ms
So the results seem to be correct and you can calculate more than 1000 intersections in a second.
Exhaustive distance computation between 20 points, i.e. 190 distances is nothing for a PC. Time will measure in microseconds. You can draw the desired information from the "close to" relation encoded in a matrix.

Java draw pixel circle in 2D array

I have this code:
void drawCircle(int x, int y, int r, int color) {
double PI = 3.1415926535;
double i, angle, x1, y1;
for (i = 0; i < 360; i += 1) {
angle = i;
x1 = r * cos(angle * PI / 180);
y1 = r * sin(angle * PI / 180);
int ElX = (int) (x + x1);
int ElY = (int) (y + y1);
myPixelElements[ElX][ElY].setElementColor(color);
}
}
It almost works but for some reason it draws 2 dots wrong:
cos and sin functions produce double values from -1 to +1, and when you cast double to int like this: int ElX = (int) (x + x1), some data will be inevitably lost, because such cast just chops the decimal part away. Instead, I suggest rounding double with Math.round, check example below:
System.out.println((int) 0.99); // 0
System.out.println((int) -0.99); // 0
System.out.println(Math.round(0.99)); // 1
System.out.println(Math.round(-0.99)); // -1
Note that Math.round returns long, so it still must be casted to int:
int ElX = (int) Math.round(x + x1);
int ElY = (int) Math.round(y + y1);
Output
Before After
****** *****
* * *** ***
* * * *
* * ** **
* * * *
* ** * *
* * * *
* * ** **
* * * *
****** *** ***
* *****
You're doing integer division in these lines:
x1 = r * cos(angle * PI / 180);
y1 = r * sin(angle * PI / 180);
A couple things are going on here. First, the integer division issue (change 180 to 180.0 to get a quick fix there). Second, you're doing the whole PI / 180.0 calculation every time through the loop - try pulling it out into its own variable:
double degToRadFactor = 3.1415926535 / 180.0
// ...
x1 = r * cos(angle * degToRadFactor)
y1 = r * sin(angle * degToRadFactor)

Java - Exception in thread "main" java.lang.StackOverflowError when applying recursion

I wrote a program to calculate values for the Zeta function through the Abel-Plana formula.
Depending on the value of the error term referenced, Java returns an error message for Exception in thread "main" java.lang.StackOverflowError.
Here is a working copy of the program with test values. The Complex.Java program is a helper program.
/**************************************************************************
**
** Abel-Plana Formula for the Zeta Function
**
**************************************************************************
** Axion004
** 08/16/2015
**
** This program computes the value for Zeta(z) using a definite integral
** approximation through the Abel-Plana formula. The Abel-Plana formula
** can be shown to approximate the value for Zeta(s) through a definite
** integral. The integral approximation is handled through the Composite
** Simpson's Rule known as Adaptive Quadrature.
**************************************************************************/
import java.util.*;
import java.math.*;
public class AbelMain extends Complex {
public static void main(String[] args) {
AbelMain();
}
// Main method
public static void AbelMain() {
double re = 0, im = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.println("Calculation of the Riemann Zeta " +
"Function in the form Zeta(s) = a + ib.");
System.out.println();
System.out.print("Enter the value of [a] inside the Riemann Zeta " +
"Function: ");
try {
re = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for a.");
}
System.out.print("Enter the value of [b] inside the Riemann Zeta " +
"Function: ");
try {
im = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for b.");
}
start = System.currentTimeMillis();
Complex z = new Complex(re, im);
System.out.println("The value for Zeta(s) is " + AbelPlana(z));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> Numerator = Sin(z * arctan(t))
* <br> Denominator = (1 + t^2)^(z/2) * (e^(pi*t) + 1)
* #param t - the value of t passed into the integrand.
* #param z - The complex value of z = a + i*b
* #return the value of the complex function.
*/
public static Complex f(double t, Complex z) {
Complex num = (z.multiply(Math.atan(t))).sin();
Complex D1 = new Complex(1 + t*t, 0).pow(z.divide(2.0));
double D2 = Math.pow(Math.E, Math.PI * t) + 1.0;
Complex den = D1.multiply(D2);
return num.divide(den);
}
/**
* Adaptive quadrature - See http://www.mathworks.com/moler/quad.pdf
* #param a - the lower bound of integration.
* #param b - the upper bound of integration.
* #param z - The complex value of z = a + i*b
* #return the approximate numerical value of the integral.
*/
public static Complex adaptiveQuad(double a, double b, Complex z) {
BigDecimal EPSILON = new BigDecimal(1E-20);
double step = b - a;
double c = (a + b) / 2.0;
double d = (a + c) / 2.0;
double e = (b + c) / 2.0;
Complex S1 = (f(a, z).add(f(c, z).multiply(4)).add(f(b, z))).
multiply(step / 6.0);
Complex S2 = (f(a, z).add(f(d, z).multiply(4)).add(f(c, z).multiply(2))
.add(f(e, z).multiply(4)).add(f(b, z))).multiply(step / 12.0);
Complex result = (S2.minus(S1)).divide(15.0);
if(BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON) == -1
|| BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON)
== 0)
return S2.add(result);
else
return adaptiveQuad(a, c, z).add(adaptiveQuad(c, b, z));
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> C1 = 2^(z-1) / (z-1)
* <br> C2 = 2^(z)
* #param z - The complex value of z = a + i*b
* #return the value of Zeta(z) through C1, C2, and the
* quadrature approximation.
*/
public static Complex AbelPlana(Complex z) {
Complex two = new Complex(2.0, 0.0);
Complex C1 = two.pow(z.minus(1.0)).divide(z.minus(1.0));
Complex C2 = two.pow(z);
Complex mult = C2.multiply(adaptiveQuad(0, 10, z));
if ( z.re < 0 && z.re % 2 == 0 && z.im == 0)
return new Complex(0.0, 0.0);
else
return C1.minus(mult);
}
// Needed to reference the super class
public AbelMain(double re, double im) {
super(re, im);
}
}
The BigDecimal EPSILON = new BigDecimal(1E-20); variable works fine and returns values.
Calculation of the Riemann Zeta Function in the form Zeta(s) = a + ib.
Enter the value of [a] inside the Riemann Zeta Function: 54
Enter the value of [b] inside the Riemann Zeta Function: 2
The value for Zeta(s) is 3.742894786684807E13 + 1.6565035537902216E14*i
Total time taken is 0.01 seconds.
Helper program
/**************************************************************************
**
** Complex Numbers
**
**************************************************************************
** Axion004
** 08/20/2015
**
** This class is necessary as a helper class for the calculation of
** imaginary numbers. The calculation of Zeta(z) inside AbelMain is in
** the form of z = a + i*b.
**************************************************************************/
public class Complex extends Object{
public double re;
public double im;
/**
Constructor for the complex number z = a + i*b
#param re Real part
#param im Imaginary part
*/
public Complex (double re, double im) {
this.re = re;
this.im = im;
}
/**
Real part of the Complex number
#return Re[z] where z = a + i*b.
*/
public double real() {
return re;
}
/**
Imaginary part of the Complex number
#return Im[z] where z = a + i*b.
*/
public double imag() {
return im;
}
/**
Complex conjugate of the Complex number
in which the conjugate of z is z-bar.
#return z-bar where z = a + i*b and z-bar = a - i*b
*/
public Complex conjugate() {
return new Complex(re, -im);
}
/**
Addition of two Complex numbers (z is unchanged).
<br>(a+i*b) + (c+i*d) = (a+c) + i*(b+d)
#param t is the number to add.
#return z+t where z = a+i*b and t = c+i*d
*/
public Complex add(Complex t) {
return new Complex(re + t.real(), im + t.imag());
}
/**
Addition of Complex number and a double.
#param d is the number to add.
#return z+d where z = a+i*b and d = double
*/
public Complex add(double d){
return new Complex(this.re + d, this.im);
}
/**
Subtraction of two Complex numbers (z is unchanged).
<br>(a+i*b) - (c+i*d) = (a-c) + i*(b-d)
#param t is the number to subtract.
#return z-t where z = a+i*b and t = c+i*d
*/
public Complex minus(Complex t) {
return new Complex(re - t.real(), im - t.imag());
}
/**
Subtraction of Complex number and a double.
#param d is the number to subtract.
#return z-d where z = a+i*b and d = double
*/
public Complex minus(double d){
return new Complex(this.re - d, this.im);
}
/**
Complex multiplication (z is unchanged).
<br> (a+i*b) * (c+i*d) = (a*c)+ i(b*c) + i(a*d) - (b*d)
#param t is the number to multiply by.
#return z*t where z = a+i*b and t = c+i*d
*/
public Complex multiply(Complex t) {
return new Complex(re * t.real() - im * t.imag(), re *
t.imag() + im * t.real());
}
/**
Complex multiplication by a double.
#param d is the double to multiply by.
#return z*d where z = a+i*b and d = double
*/
public Complex multiply(double d){
return new Complex(this.re * d,this.im * d);}
/**
Modulus of a Complex number or the distance from the origin in
* the polar coordinate plane.
#return |z| where z = a + i*b.
*/
public double mod() {
if ( re != 0.0 || im != 0.0)
return Math.sqrt(re*re + im*im);
else
return 0.0;
}
/**
* Modulus of a Complex number squared
* #param z = a + i*b
* #return |z|^2 where z = a + i*b
*/
public double abs(Complex z) {
return Math.sqrt(Math.pow(re*re, 2) + Math.pow(im*im, 2));
}
/**
Division of Complex numbers (doesn't change this Complex number).
<br>(a+i*b) / (c+i*d) = (a+i*b)*(c-i*d) / (c+i*d)*(c-i*d) =
* (a*c+b*d) + i*(b*c-a*d) / (c^2-d^2)
#param t is the number to divide by
#return new Complex number z/t where z = a+i*b
*/
public Complex divide (Complex t) {
double denom = Math.pow(t.mod(), 2); // Square the modulus
return new Complex((re * t.real() + im * t.imag()) / denom,
(im * t.real() - re * t.imag()) / denom);
}
/**
Division of Complex number by a double.
#param d is the double to divide
#return new Complex number z/d where z = a+i*b
*/
public Complex divide(double d){
return new Complex(this.re / d, this.im / d);
}
/**
Exponential of a complex number (z is unchanged).
<br> e^(a+i*b) = e^a * e^(i*b) = e^a * (cos(b) + i*sin(b))
#return exp(z) where z = a+i*b
*/
public Complex exp () {
return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) *
Math.sin(im));
}
/**
The Argument of a Complex number or the angle in radians
with respect to polar coordinates.
<br> Tan(theta) = b / a, theta = Arctan(b / a)
<br> a is the real part on the horizontal axis
<br> b is the imaginary part of the vertical axis
#return arg(z) where z = a+i*b.
*/
public double arg() {
return Math.atan2(im, re);
}
/**
The log or principal branch of a Complex number (z is unchanged).
<br> Log(a+i*b) = ln|a+i*b| + i*Arg(z) = ln(sqrt(a^2+b^2))
* + i*Arg(z) = ln (mod(z)) + i*Arctan(b/a)
#return log(z) where z = a+i*b
*/
public Complex log() {
return new Complex(Math.log(this.mod()), this.arg());
}
/**
The square root of a Complex number (z is unchanged).
Returns the principal branch of the square root.
<br> z = e^(i*theta) = r*cos(theta) + i*r*sin(theta)
<br> r = sqrt(a^2+b^2)
<br> cos(theta) = a / r, sin(theta) = b / r
<br> By De Moivre's Theorem, sqrt(z) = sqrt(a+i*b) =
* e^(i*theta / 2) = r(cos(theta/2) + i*sin(theta/2))
#return sqrt(z) where z = a+i*b
*/
public Complex sqrt() {
double r = this.mod();
double halfTheta = this.arg() / 2;
return new Complex(Math.sqrt(r) * Math.cos(halfTheta), Math.sqrt(r) *
Math.sin(halfTheta));
}
/**
The real cosh function for Complex numbers.
<br> cosh(theta) = (e^(theta) + e^(-theta)) / 2
#return cosh(theta)
*/
private double cosh(double theta) {
return (Math.exp(theta) + Math.exp(-theta)) / 2;
}
/**
The real sinh function for Complex numbers.
<br> sinh(theta) = (e^(theta) - e^(-theta)) / 2
#return sinh(theta)
*/
private double sinh(double theta) {
return (Math.exp(theta) - Math.exp(-theta)) / 2;
}
/**
The sin function for the Complex number (z is unchanged).
<br> sin(a+i*b) = cosh(b)*sin(a) + i*(sinh(b)*cos(a))
#return sin(z) where z = a+i*b
*/
public Complex sin() {
return new Complex(cosh(im) * Math.sin(re), sinh(im)*
Math.cos(re));
}
/**
The cos function for the Complex number (z is unchanged).
<br> cos(a +i*b) = cosh(b)*cos(a) + i*(-sinh(b)*sin(a))
#return cos(z) where z = a+i*b
*/
public Complex cos() {
return new Complex(cosh(im) * Math.cos(re), -sinh(im) *
Math.sin(re));
}
/**
The hyperbolic sin of the Complex number (z is unchanged).
<br> sinh(a+i*b) = sinh(a)*cos(b) + i*(cosh(a)*sin(b))
#return sinh(z) where z = a+i*b
*/
public Complex sinh() {
return new Complex(sinh(re) * Math.cos(im), cosh(re) *
Math.sin(im));
}
/**
The hyperbolic cosine of the Complex number (z is unchanged).
<br> cosh(a+i*b) = cosh(a)*cos(b) + i*(sinh(a)*sin(b))
#return cosh(z) where z = a+i*b
*/
public Complex cosh() {
return new Complex(cosh(re) *Math.cos(im), sinh(re) *
Math.sin(im));
}
/**
The tan of the Complex number (z is unchanged).
<br> tan (a+i*b) = sin(a+i*b) / cos(a+i*b)
#return tan(z) where z = a+i*b
*/
public Complex tan() {
return (this.sin()).divide(this.cos());
}
/**
The arctan of the Complex number (z is unchanged).
<br> tan^(-1)(a+i*b) = 1/2 i*(log(1-i*(a+b*i))-log(1+i*(a+b*i))) =
<br> -1/2 i*(log(i*a - b+1)-log(-i*a + b+1))
#return arctan(z) where z = a+i*b
*/
public Complex atan(){
Complex ima = new Complex(0.0,-1.0); //multiply by negative i
Complex num = new Complex(this.re,this.im-1.0);
Complex den = new Complex(-this.re,-this.im-1.0);
Complex two = new Complex(2.0, 0.0); // divide by 2
return ima.multiply(num.divide(den).log()).divide(two);
}
/**
* The Math.pow equivalent of two Complex numbers.
* #param z - the complex base in the form z = a + i*b
* #return z^y where z = a + i*b and y = c + i*d
*/
public Complex pow(Complex z){
Complex a = z.multiply(this.log());
return a.exp();
}
/**
* The Math.pow equivalent of a Complex number to the power
* of a double.
* #param d - the double to be taken as the power.
* #return z^d where z = a + i*b and d = double
*/
public Complex pow(double d){
Complex a=(this.log()).multiply(d);
return a.exp();
}
/**
Override the .toString() method to generate complex numbers, the
* string representation is now a literal Complex number.
#return a+i*b, a-i*b, a, or i*b as desired.
*/
public String toString() {
if (re != 0.0 && im > 0.0) {
return re + " + " + im +"*i";
}
if (re !=0.0 && im < 0.0) {
return re + " - "+ (-im) + "*i";
}
if (im == 0.0) {
return String.valueOf(re);
}
if (re == 0.0) {
return im + "*i";
}
return re + " + i*" + im;
}
}
Increasing the error term to BigDecimal EPSILON = new BigDecimal(1E-50); causes the program to return java.lang.StackOverflowError.
/**************************************************************************
**
** Abel-Plana Formula for the Zeta Function
**
**************************************************************************
** Axion004
** 08/16/2015
**
** This program computes the value for Zeta(z) using a definite integral
** approximation through the Abel-Plana formula. The Abel-Plana formula
** can be shown to approximate the value for Zeta(s) through a definite
** integral. The integral approximation is handled through the Composite
** Simpson's Rule known as Adaptive Quadrature.
**************************************************************************/
import java.util.*;
import java.math.*;
public class AbelMain extends Complex {
public static void main(String[] args) {
AbelMain();
}
// Main method
public static void AbelMain() {
double re = 0, im = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.println("Calculation of the Riemann Zeta " +
"Function in the form Zeta(s) = a + ib.");
System.out.println();
System.out.print("Enter the value of [a] inside the Riemann Zeta " +
"Function: ");
try {
re = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for a.");
}
System.out.print("Enter the value of [b] inside the Riemann Zeta " +
"Function: ");
try {
im = scan.nextDouble();
}
catch (Exception e) {
System.out.println("Please enter a valid number for b.");
}
start = System.currentTimeMillis();
Complex z = new Complex(re, im);
System.out.println("The value for Zeta(s) is " + AbelPlana(z));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> Numerator = Sin(z * arctan(t))
* <br> Denominator = (1 + t^2)^(z/2) * (e^(pi*t) + 1)
* #param t - the value of t passed into the integrand.
* #param z - The complex value of z = a + i*b
* #return the value of the complex function.
*/
public static Complex f(double t, Complex z) {
Complex num = (z.multiply(Math.atan(t))).sin();
Complex D1 = new Complex(1 + t*t, 0).pow(z.divide(2.0));
double D2 = Math.pow(Math.E, Math.PI * t) + 1.0;
Complex den = D1.multiply(D2);
return num.divide(den);
}
/**
* Adaptive quadrature - See http://www.mathworks.com/moler/quad.pdf
* #param a - the lower bound of integration.
* #param b - the upper bound of integration.
* #param z - The complex value of z = a + i*b
* #return the approximate numerical value of the integral.
*/
public static Complex adaptiveQuad(double a, double b, Complex z) {
BigDecimal EPSILON = new BigDecimal(1E-50);
double step = b - a;
double c = (a + b) / 2.0;
double d = (a + c) / 2.0;
double e = (b + c) / 2.0;
Complex S1 = (f(a, z).add(f(c, z).multiply(4)).add(f(b, z))).
multiply(step / 6.0);
Complex S2 = (f(a, z).add(f(d, z).multiply(4)).add(f(c, z).multiply(2))
.add(f(e, z).multiply(4)).add(f(b, z))).multiply(step / 12.0);
Complex result = (S2.minus(S1)).divide(15.0);
if(BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON) == -1
|| BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON)
== 0)
return S2.add(result);
else
return adaptiveQuad(a, c, z).add(adaptiveQuad(c, b, z));
}
/**
* The definite integral for Zeta(z) in the Abel-Plana formula.
* <br> C1 = 2^(z-1) / (z-1)
* <br> C2 = 2^(z)
* #param z - The complex value of z = a + i*b
* #return the value of Zeta(z) through C1, C2, and the
* quadrature approximation.
*/
public static Complex AbelPlana(Complex z) {
Complex two = new Complex(2.0, 0.0);
Complex C1 = two.pow(z.minus(1.0)).divide(z.minus(1.0));
Complex C2 = two.pow(z);
Complex mult = C2.multiply(adaptiveQuad(0, 10, z));
if ( z.re < 0 && z.re % 2 == 0 && z.im == 0)
return new Complex(0.0, 0.0);
else
return C1.minus(mult);
}
// Needed to reference the super class
public AbelMain(double re, double im) {
super(re, im);
}
}
Test Run
Calculation of the Riemann Zeta Function in the form Zeta(s) = a + ib.
Enter the value of [a] inside the Riemann Zeta Function: 54
Enter the value of [b] inside the Riemann Zeta Function: 2
Exception in thread "main" java.lang.StackOverflowError
at sun.misc.FpUtils.getExponent(FpUtils.java:147)
at java.lang.Math.getExponent(Math.java:1310)
at java.lang.StrictMath.floorOrCeil(StrictMath.java:355)
at java.lang.StrictMath.floor(StrictMath.java:340)
at java.lang.Math.floor(Math.java:424)
at sun.misc.FloatingDecimal.dtoa(FloatingDecimal.java:620)
at sun.misc.FloatingDecimal.<init>(FloatingDecimal.java:459)
at java.lang.Double.toString(Double.java:196)
at java.math.BigDecimal.valueOf(BigDecimal.java:1069)
at AbelMain.adaptiveQuad(AbelMain.java:92)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
at AbelMain.adaptiveQuad(AbelMain.java:97)
These two lines point to
if(BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON) == -1
|| BigDecimal.valueOf(S2.minus(S1).mod()).compareTo(EPSILON)
== 0)
and
return adaptiveQuad(a, c, z).add(adaptiveQuad(c, b, z));
Is this error due to infinite recursion? That value for epsilon might have to be above a certain threshold?
Yes, StackOverflowError is most due to infinite recursion.
You could try debugging the code, but in instances like this, it's probably easier for the old method: Insert a print statement in the beginning of the adaptiveQuad method, printing the current state/parameters.
When it dies, a clear pattern may be visible.
You mix "float" and "BigDecimal", with terrific side effects... in particular (I tried with input data 54 and 2), when you use "step" float variable, as result of difference between a an b, after a while it reaches a "fixed point" of 1.0587911840678754E-22, due to the internal representation of Complex data, where you use floats.
Well, at this point, this "step" never change, S1 and S2 neither, and difference remains the same ("result" evaluates 0.0, -2.3915493791143544E-44) so it never goes under EPSILON (as 1E-50) and algorithm recurses infinitely (or better, until explodes). In other words, you avoided approximations from a side, using BigDecimal, but you reintroduced it via float usage :)
Try to remove float usage everywhere (in Complex too), and everything should run fine.

generate point in random direction from center

I am trying to randmly create set of points with random position of an initial point.
Unfortunatly almost all of my generated points are located in upper left corner. Is there a mistake in my calculations?
private void makePath() {
int r = 25;
Random rand = new Random();
double angle = Math.toRadians(rand.nextInt(361));
int nx = (int) (x + r * Math.cos(angle));
int ny = (int) (y - r * Math.sin(angle));
path.add(new Point2D(nx, ny));
}
For the values, try using:
int nx = (int) (x + r * Math.cos(angle));
int ny = (int) (y + r * Math.sin(angle));
Using y + r * ... instead. This is coming from a method I wrote to do the exact same thing:
/**
* Generates a new point within a circular radius from
* the given <tt>x</tt> and <tt>y</tt> coordinates. This
* is done by generating a random offset along the
* horizontal axis, then applying a rotation.
*
* #param seed The seed to generate the point from.
* #param x The x coordinate of the center of the
* circle.
* #param y The y coordinate of the center of the
* circle.
* #return The newly generated point, within the
* specified radius of the point <tt>(x, y)
* </tt>.
* #see ClusterGenerator#RADIUS
*/
private static Point makePoint(final Random seed, final int x, final int y) {
final int offset = seed.nextInt(RADIUS);
final double rotation = 2 * Math.PI * Math.random();
final int x1 = (int) (Math.sin(rotation) * offset);
final int y1 = (int) (Math.cos(rotation) * offset);
return new Point(x + x1, y + y1);
}

How can I measure distance and create a bounding box based on two latitude+longitude points in Java?

I am wanting to find the distance between two different points. This I know can be accomplished with the great circle distance.
http://www.meridianworlddata.com/Distance-calculation.asp
Once done, with a point and distance I would like to find the point that distance north, and that distance east in order to create a box around the point.
Here is a Java implementation of Haversine formula. I use this in a project to calculate distance in miles between lat/longs.
public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75; // miles (or 6371.0 kilometers)
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
* Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist;
}
Or you could use SimpleLatLng. Apache 2.0 licensed and used in one production system that I know of: mine.
Short story:
I was searching for a simple geo library and couldn't find one to fit my needs. And who wants to write and test and debug these little geo tools over and over again in every application? There's got to be a better way!
So SimpleLatLng was born as a way to store latitude-longitude data, do distance calculations, and create shaped boundaries.
I know I'm two years too late to help the original poster, but my aim is to help the people like me who find this question in a search. I would love to have some people use it and contribute to the testing and vision of this little lightweight utility.
We've had some success using OpenMap to plot a lot of positional data. There's a LatLonPoint class that has some basic functionality, including distance.
For a more accurate distance (0.5mm) you can also use the Vincenty approximation:
/**
* Calculates geodetic distance between two points specified by latitude/longitude using Vincenty inverse formula
* for ellipsoids
*
* #param lat1
* first point latitude in decimal degrees
* #param lon1
* first point longitude in decimal degrees
* #param lat2
* second point latitude in decimal degrees
* #param lon2
* second point longitude in decimal degrees
* #returns distance in meters between points with 5.10<sup>-4</sup> precision
* #see Originally posted here
*/
public static double distVincenty(double lat1, double lon1, double lat2, double lon2) {
double a = 6378137, b = 6356752.314245, f = 1 / 298.257223563; // WGS-84 ellipsoid params
double L = Math.toRadians(lon2 - lon1);
double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM;
double lambda = L, lambdaP, iterLimit = 100;
do {
sinLambda = Math.sin(lambda);
cosLambda = Math.cos(lambda);
sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda)
+ (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
if (sinSigma == 0)
return 0; // co-incident points
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
sigma = Math.atan2(sinSigma, cosSigma);
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
cosSqAlpha = 1 - sinAlpha * sinAlpha;
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
if (Double.isNaN(cos2SigmaM))
cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)
double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
lambdaP = lambda;
lambda = L + (1 - C) * f * sinAlpha
* (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
} while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);
if (iterLimit == 0)
return Double.NaN; // formula failed to converge
double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
double deltaSigma = B
* sinSigma
* (cos2SigmaM + B
/ 4
* (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM
* (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
double dist = b * A * (sigma - deltaSigma);
return dist;
}
This code was freely adapted from http://www.movable-type.co.uk/scripts/latlong-vincenty.html
Corrected Haversine Distance formula....
public static double HaverSineDistance(double lat1, double lng1, double lat2, double lng2)
{
// mHager 08-12-2012
// http://en.wikipedia.org/wiki/Haversine_formula
// Implementation
// convert to radians
lat1 = Math.toRadians(lat1);
lng1 = Math.toRadians(lng1);
lat2 = Math.toRadians(lat2);
lng2 = Math.toRadians(lng2);
double dlon = lng2 - lng1;
double dlat = lat2 - lat1;
double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return EARTH_RADIUS * c;
}
http://www.movable-type.co.uk/scripts/latlong.html
public static Double distanceBetweenTwoLocationsInKm(Double latitudeOne, Double longitudeOne, Double latitudeTwo, Double longitudeTwo) {
if (latitudeOne == null || latitudeTwo == null || longitudeOne == null || longitudeTwo == null) {
return null;
}
Double earthRadius = 6371.0;
Double diffBetweenLatitudeRadians = Math.toRadians(latitudeTwo - latitudeOne);
Double diffBetweenLongitudeRadians = Math.toRadians(longitudeTwo - longitudeOne);
Double latitudeOneInRadians = Math.toRadians(latitudeOne);
Double latitudeTwoInRadians = Math.toRadians(latitudeTwo);
Double a = Math.sin(diffBetweenLatitudeRadians / 2) * Math.sin(diffBetweenLatitudeRadians / 2) + Math.cos(latitudeOneInRadians) * Math.cos(latitudeTwoInRadians) * Math.sin(diffBetweenLongitudeRadians / 2)
* Math.sin(diffBetweenLongitudeRadians / 2);
Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (earthRadius * c);
}
You can use the Java Geodesy Library for GPS, it uses the Vincenty's formulae which takes account of the earths surface curvature.
Implementation goes like this:
import org.gavaghan.geodesy.*;
...
GeodeticCalculator geoCalc = new GeodeticCalculator();
Ellipsoid reference = Ellipsoid.WGS84;
GlobalPosition pointA = new GlobalPosition(latitude, longitude, 0.0);
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0);
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance();
The resulting distance is in meters.
This method would help you find the distance between to geographic location in km.
private double getDist(double lat1, double lon1, double lat2, double lon2)
{
int R = 6373; // radius of the earth in kilometres
double lat1rad = Math.toRadians(lat1);
double lat2rad = Math.toRadians(lat2);
double deltaLat = Math.toRadians(lat2-lat1);
double deltaLon = Math.toRadians(lon2-lon1);
double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
Math.cos(lat1rad) * Math.cos(lat2rad) *
Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
return d;
}
Kotlin version of Haversine formula. Returned result in meters. Tested on https://www.vcalc.com/wiki/vCalc/Haversine+-+Distance
const val EARTH_RADIUS_IN_METERS = 6371007.177356707
fun distance(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Double {
val latDiff = Math.toRadians(abs(lat2 - lat1))
val lngDiff = Math.toRadians(abs(lng2 - lng1))
val a = sin(latDiff / 2) * sin(latDiff / 2) +
cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) *
sin(lngDiff / 2) * sin(lngDiff / 2)
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
return EARTH_RADIUS_IN_METERS * c
}
I know that there are many answers, but in doing some research on this topic, I found that most answers here use the Haversine formula, but the Vincenty formula is actually more accurate. There was one post that adapted the calculation from a Javascript version, but it's very unwieldy. I found a version that is superior because:
It also has an open license.
It uses OOP principles.
It has greater flexibility to choose the ellipsoid you want to use.
It has more methods to allow for different calculations in the future.
It is well documented.
VincentyDistanceCalculator
I typically use MATLAB with the Mapping Toolbox, and then use the code in my Java using MATLAB Builder JA. It makes my life a lot simpler. Given most schools have it for free student access, you can try it out (or get the trial version to get over your work).
For Android, there is a simple approach.
public static float getDistanceInMeter(LatLng start, LatLng end) {
float[] results = new float[1];
Location.distanceBetween(start.latitude, start.longitude, end.latitude, end.longitude, results);
return results[0];
}
;
https://developer.android.com/reference/android/location/Location#distanceBetween(lat1,lng1,lat2,lng2,output[])

Categories

Resources