On the line where I call getDistance(points[i], points[j]) I am getting error asking my to change my getDistance method parameters to doubles instead of arrays, though I thought I was passing an array to the method due to how multidimensional arrays work.
public static void main(String[] args) {
double[][] points = {
{1.0, 2.0, 3.0},
{0.0, 0.0, 2.0},
{1.0, 1.5, 4.0},
{3.0, 2.0, 1.0}
};
for(int i=0; i<points.length; i++){
for(int j=1; j<points[0].length; j++){
getDistance(points[i], points[j]);
}
}
}
public double getDistance(Array points1[], Array points2[]){
double x1 = Array.getDouble(points1, 0);
double x2 = Array.getDouble(points2, 0);
double y1 = Array.getDouble(points1, 1);
double y2 = Array.getDouble(points2, 1);
double z1 = Array.getDouble(points1, 2);
double z2 = Array.getDouble(points2, 2);
double distance = Math.sqrt(Math.pow(x1 - x2, 2) +(Math.pow(y1 - y2, 2) +
(Math.pow(z1 - z2, 2))));
return distance;
}
Your method getDistance defines the two parameters as type Array where as where you call it the type is double[] which is not the same.
Rewrite your getDistance as follows;
public double getDistance(double[] points1, double[] points2){
double x1 = points1[0];
double x2 = points2[0];
double y1 = points1[1];
double y2 = points2[1];
double z1 = points1[2];
double z2 = points2[2];
double distance = Math.sqrt(Math.pow(x1 - x2, 2) +(Math.pow(y1 - y2, 2) +
(Math.pow(z1 - z2, 2))));
return distance;
}
Your method should declare an array the same as you did in your main.
Now:
Instead of public double getDistance(Array points1[], Array points2[])
Should be:
public double getDistance(double points1[], double points2[])
Related
Hi I'm currently trying to calculate a longitude/latitude point from 2 longitude/latitude points (bilateration) with distance & I've currenty done that :
double EARTH_RADIUS = 6378137.0;
double longitude1 = 4.062787;
double latitude1 = 49.243828;
double x1 = EARTH_RADIUS * (Math.cos(Math.toRadians(latitude1)) * Math.cos(Math.toRadians(longitude1)));
double y1 = EARTH_RADIUS *(Math.cos(Math.toRadians(latitude1)) * Math.sin(Math.toRadians(longitude1)));
double longitude2 = 4.062023;
double latitude2 = 49.243851;
double x2 = EARTH_RADIUS * (Math.cos(Math.toRadians(latitude2)) * Math.cos(Math.toRadians(longitude2)));
double y2 = EARTH_RADIUS *(Math.cos(Math.toRadians(latitude2)) * Math.sin(Math.toRadians(longitude2)));
System.out.println(x1 + " " + y1);
System.out.println(x2 + " " + y2);
double[][] positions = new double[][] { { x1, y1 }, { x2, y2 } };
double[] distances = new double[] { 10.0, 10.0};
NonLinearLeastSquaresSolver solver = new NonLinearLeastSquaresSolver(new TrilaterationFunction(positions, distances), new LevenbergMarquardtOptimizer());
Optimum optimum = solver.solve();
double[] centroid = optimum.getPoint().toArray();
System.out.println(Arrays.toString(centroid));
I'm using this library https://github.com/lemmingapex/trilateration to trilaterate my point.
Converting longitude & latitude points to a cartesian plan & using a library to get a point on it, giving me this output :
[INFO] GCLOUD: 4153447.729890433 295011.4801210027
[INFO] GCLOUD: 4153449.72871882 294955.95932889543
[INFO] GCLOUD: [4153448.7293046266, 294983.7197249491]
So now I'm trying to convert this point into latitude & longitude point to put it on Google Map but I have no clue how to do that & if a Java library already exist for bilateration?
EDIT :
So I've done that :
private static final double EARTH_RADIUS = 6371;
private static final int X = 0;
private static final int Y = 1;
private static final int Z = 2;
public static double[] triangulation(double lat0, double lon0, double r0, double lat1, double lon1, double r1) {
double[] p1 = latlon2cartesian(lat0, lon0);
double[] p2 = latlon2cartesian(lat1, lon1);
double[][] positions = new double[][] { { p1[X], p1[Y], p1[Z] }, { p2[X], p2[Y], p2[Z] } };
double[] distances = new double[] { r0, r1};
NonLinearLeastSquaresSolver solver = new NonLinearLeastSquaresSolver(new TrilaterationFunction(positions, distances), new LevenbergMarquardtOptimizer());
Optimum optimum = solver.solve();
double[] centroid = optimum.getPoint().toArray();
System.out.println(Arrays.toString(p1));
System.out.println(Arrays.toString(p2));
System.out.println(Arrays.toString(centroid));
return cartesian2latlon(centroid[X], centroid[Y], centroid[Z]);
}
private static double[] latlon2cartesian(double lat, double lon) {
lat = Math.toRadians(lat);
lon = Math.toRadians(lon);
return new double[] { Math.cos(lon) * Math.cos(lat) * EARTH_RADIUS, Math.sin(lon) * Math.cos(lat) * EARTH_RADIUS, Math.sin(lat) * EARTH_RADIUS };
}
private static double[] cartesian2latlon(double x, double y, double z) {
return new double[] { Math.toDegrees(Math.asin(z / EARTH_RADIUS)), Math.toDegrees(Math.atan2(y, x)) };
}
But I don't get correct values with :
System.out.println(Arrays.toString(Bilateration.triangulation(49.243828, 4.062787, 5.0, 49.243851, 4.062023, 6.5)));
I get :
[49.2453096100026, 3.9213007384886387]
Near (2km away) but the point should be around 49.24385234064716, 4.062335368930235.
For this code, I am trying to determine the distance between (x1, y1) and (x2, y2). The equation for the distance is sqrt(x2 - x1)^2 + (y2 - y1)^2.
The code looks like this,
import java.util.Scanner;
public class CoordinateGeometry {
public static void main(String [] args) {
Scanner scnr = new Scanner(System.in);
double x1;
double y1;
double x2;
double y2;
double pointsDistance;
double xDist;
double yDist;
pointsDistance = 0.0;
xDist = 0.0;
yDist = 0.0;
x1 = scnr.nextDouble();
y1 = scnr.nextDouble();
x2 = scnr.nextDouble();
y2 = scnr.nextDouble();
poinsDistance = Math.sqrt(Math.pow(x2 - x1, 2) + (Math.pow(y2 - y1, 2));
System.out.println(pointsDistance);
}
}
I keep getting an error, CoordinateGeometry.java:23: error: ')' expected
poinsDistance = Math.sqrt(Math.pow(x2 - x1, 2) + (Math.pow(y2 - y1, 2));
^
1 error
What does this error mean?
Also an example would be, for points (1.0, 2.0) and (1.0, 5.0), pointsDistance is 3.0.
You are missing closing ) at the end of line
poinsDistance = Math.sqrt(Math.pow(x2 - x1, 2) + (Math.pow(y2 - y1, 2)));
Or remove the opening ( before Math.pow.
Your code should look like this:
poinsDistance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
So I've been trying to implement Perlin noise recently, and have run into some unusual problems. Whenever the edges of the grid in which the random vectors are stored are crossed, the derivative appears to be discontinuous.
Here's a link to a picture of the output (on the right), along with a 1 dimensional slice (on the left).
The Output
class perlin{
private double[][][] grid;
public perlin(int x,int y, int seed){
Random r = new Random(seed);
grid = new double[x+1][y+1][2];
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
grid[i][j][0] = 2*r.nextDouble()-1;
grid[i][j][1] = 2*r.nextDouble()-1;
}
}
}
public static double lerp(double a, double b, double t){
double c = t * t * t * (t * (t * 6 - 15) + 10);
return (b * c) + (a * (1 - c));
}
public double get(double x, double y){
double x2;
double y2;
double x3;
double y3;
x2 = x * (grid.length-1);
y2 = y * (grid[0].length-1);
x3 = down(x2);
y3 = down(y2);
x2 = x2 - x3;
y2 = y2 - y3;
int i = (int) (x3);
int j = (int) (y3);
return lerp(lerp(dot(x2, y2, grid[i][j][0], grid[i][j][1] ), dot(1 - x2, y2, grid[i + 1][j][0], grid[i + 1][j][1]),x2), lerp(dot(x2, 1 - y2, grid[i][j + 1][0], grid[i][j +1][1] ), dot(1 - x2,1 - y2, grid[i + 1][j + 1][0], grid[i + 1][j + 1][1] ), x2),y2 );
// return 0;
}
public static double dot(double x1, double y1, double x2, double y2){
return x1 * x2 + y1 * y2;
}
private static double down(double a){
if (a == 0){
return 0;
}
if(a == Math.floor(a)){
return a - 1;
}else{
return Math.floor(a);
}
}
}
From what I understand about the math behind this, the derivative of the noise should be continuous at all points, but that does not appear to be the case.
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.
regarding the following code, can I make it better for distance() method?
It feels like it's not completely OOP with this method.. how can I change code to be better OOD for this one ?
Thanks !!
public class Line extends Shape {
private Point lineP1;
private Point lineP2;
public Line(int x1, int x2, int y1, int y2, Color myColor) {
super(x1, x2, y1, y2, myColor);
lineP1 = new Point(this.getX1(),this.getY1());
lineP2 = new Point(this.getX2(),this.getY2());
}
#Override
public void draw(Graphics g) {
g.drawLine(this.getX1(), this.getY1(), this.getX2(), this.getY2());
g.setColor(Color.GREEN);
}
#Override
public boolean contains(Point p) {
if((this.distance(lineP1, p)+this.distance(lineP2, p)) == this.distance(lineP1, lineP2))
return true;
return false;
}
/**#return distance between two given points
* This method return the distance between two given points*/
private double distance(Point p1,Point p2 ){
return Math.sqrt(Math.pow((p1.getX()-p2.getX()), 2) + Math.pow((p1.getY()-p2.getY()), 2));
}
}//class Line
Your distance method seems to be ok (but it would be more performant, if you saved the differences in variables and used the * operator to multiply those values with themselfs instear of using Math.pow).
However, since floating point calculations tend to return inexact results, I don't recomend using the sum of the distances between the end node and the point to test as criterium.
But there's another good way determining, if a point is near a line or not: using the hesse normal form. It works like this:
Let P1 and P2 be vectors corresponing to the end points. * denotes the scalar multiplication and || the length of a vector:
D = (P2 - P1) / |P2 - P1|;
Let N be the vector D with coordinates swaped and the new x coordinate multiplied with -1 (i.e. a vector ortogonal to D).
Then the distance of a point H to the line can be determined like this
| N * H - N * P1 |
Also if H is between P1 and P2 can be checked like this (assuming without loss of generality D * P1 < D * P2):
D * P1 <= D * H <= D * P2
Using scalar products has the additional benefit, that calculating a scalar product only takes 2 multiplication and 1 addition in a 2D space.
This is how you could do this in java code
// components of normal vector
private double normalX;
private double normalY;
// components of direction vector
private double directionX;
private double directionY;
// the value of (N * P) for all points P on the line
private double normalScalarProduct;
// the range allowed for (D * P) for points on the line
private double minDirectionScalarProduct;
private double maxDirectionScalarProduct;
// error ranges; adjust as appropriate
private static final double directionAllowedError = 0.1;
private static final double normalAllowedError = 0.1;
public Line(int x1, int x2, int y1, int y2, Color myColor) {
...
double dx = x2 - x1;
double dy = y2 - y1;
double length = distance(dx, dy);
if (length == 0) {
// choose arbitrary direction, if length == 0
length = 1;
dx = 1;
}
// normalize direction
dx /= length;
dy /= length;
// set D and N values
this.directionX = dx;
this.directionY = dy;
this.normalX = -dy;
this.normalY = dx;
double prod1 = scalarProduct(directionX, directionY, x1, y1);
double prod2 = scalarProduct(directionX, directionY, x2, y2);
if (prod1 < prod2) {
minDirectionScalarProduct = prod1 - directionAllowedError;
maxDirectionScalarProduct = prod2 + directionAllowedError;
} else {
minDirectionScalarProduct = prod2 - directionAllowedError;
maxDirectionScalarProduct = prod1 + directionAllowedError;
}
normalScalarProduct = scalarProduct(x1, y1, normalX, normalY);
}
private static double scalarProduct(double x1, double y1, double x2, double y2) {
return x1*x2 + y1*y2;
}
public boolean contains(Point p) {
if (Math.abs(scalarProduct(p.getX(), p.getX(), normalX, normalY) - normalScalarProduct) <= normalAllowedError) {
// close enough to the line -> check, if between end points
double d = scalarProduct(p.getX(), p.getX(), directionX, directionY);
return minDirectionScalarProduct <= d && d <= maxDirectionScalarProduct;
}
return false;
}
private double distance(double dx, double dy) {
return Math.sqrt(dx*dx + dy*dy);
}