Java geometry problem: perimeter of circular segment - java

Seq is a method which for given line: line's point a and slope b returns perimeter of circular segment. I used the equation of circle and line and solved it for x, and then I easily get two points. But instead of (3.5,1.9) approximately I get (6.528,0.0832000000000006)..
public class Circle {
Point center;
double r;
public double seq(Point a, double b) {
double n = -b*a.getX() + a.getY();
System.out.println("n: "+n);
if (r*r*(b*b+1)-Math.pow(b*center.getX()-center.getY()+n, 2) > 0) {
double temp = (1+b*b);
System.out.println("coeficient x^2: "+temp);
double temp1 = 2*((-1)*center.getX()+b*n-b*center.getY());
System.out.println("coeficient x: "+ temp);
double free_term = center.getX()*center.getX() + n*n -2*n*center.getY() + center.getY()*center.getY() - r*r;
System.out.println("free term: "+free_term);
double D = Math.sqrt(temp1*temp1-4*temp*free_term);
System.out.println(temp1*temp1-4*temp*free_term);
double x1 = ((-1)*temp1+Math.sqrt(temp1*temp1-4*temp*free_term))/2*temp;
double x2 = ((-1)*temp1-Math.sqrt(temp1*temp1-4*temp*free_term))/2*temp;
double y1 = b*x1 - b*a.getX() + a.getY();
double y2 = b*x2 - b*a.getX() + a.getY();
System.out.println("("+x1+","+y1+")"+", ("+x2+","+y2+")");
Point A = new Point(x1,y1);
Point B = new Point(x2,y2);
double d = A.dist(B);
System.out.println("d: "+d);
double angle = Math.acos((2*r*r-d*d)/2*r*r);
System.out.println("angle "+ alfa);
double l = r*Math.PI*angle/Math.toRadians(180);
return l+d;
} else return 0;
}
}
Main:
Circle k = new Circle();
Point c = new Point(0,0);
k.center = c;
k.r = 4;
Point a = new Point(0,4);
System.out.println(k.seq(a, -3.0/5.0));
Console:
n: 4.0
coeficient x^2: 1.3599999999999999
coeficient x: -4.8
free term: 0.0
23.04
(6.528,0.0832000000000006), (0.0,4.0)
d: 7.612890793910023
angleNaN
NaN

Your problem is in the implementation of the quadratic formula. You might think that A/2*B means A/(2*B) but in reality it's (A/2)*B. So add the parentheses in around the divisor:
double x1 = ((-1)*temp1+Math.sqrt(temp1*temp1-4*temp*free_term))/(2*temp);
double x2 = ((-1)*temp1-Math.sqrt(temp1*temp1-4*temp*free_term))/(2*temp);

Related

how can I use a counter controlled iteration in the print/math section on this square root program

I was thinking about adding a while loop to the program that'll loop for maybe 10 times instead of writing 10 println statements. but I found it hard since the value of x is different every time in the math section. I wrote this code before, now I want to shorten it. It's a square root finder program that uses the Babylonian method to find the square root of an integer between [S > 20 || S < 400]
int S;
System.out.print("Enter an integer, S: ");
S = myInput.nextInt();
if (S < 0) {
System.out.println("This program can not take the square root of a negative number.");
}
else if (S < 20 || S > 400) {
System.out.println("This value is out of range.");
}
else {
double a = S / 2.0;
double b = S / a;
double c = a + b;
double d = 0.5 * c;
// for x2
double e = S / d;
double f = d + e;
double g = 0.5 * f;
// for x3
double h = S / g;
double i = g + h;
double j = 0.5 * i;
// for x4
double k = S / j;
double l = j + k;
double m = 0.5 * l;
// for x5
double n = S / m;
double o = m + n;
double p = 0.5 * o;
// for x6
double q = S / p;
double r = p + q;
double s = 0.5 * r;
// for x7
double t = S / s;
double u = s + t;
double v = 0.5 * u;
// for x8
double w = S / v;
double x = v + w;
double y = 0.5 * x;
// for x9
double z = S / y;
double aa = y + z;
double ab = 0.5 * aa;
System.out.printf("%nx0 = %8.4f ", a);
System.out.printf("%nx1 = %8.4f ", d);
System.out.printf("%nx2 = %8.4f ", g);
System.out.printf("%nx3 = %8.4f ", j);
System.out.printf("%nx4 = %8.4f ", m);
System.out.printf("%nx5 = %8.4f ", p);
System.out.printf("%nx6 = %8.4f ", s);
System.out.printf("%nx7 = %8.4f ", v);
System.out.printf("%nx8 = %8.4f ", y);
System.out.printf("%nx9 = %8.4f ", ab);
}
All you need to do is set d to 2.0 outside the loop. Then use d in place of 2.0 inside the loop. The loop index of i is also used to name the iterations (x0, x1, x2, ...) when printing.
double d = 2.0; // set d to 2.0 here
for (int i = 0; i < 10; i++) {
double a = S / d; // use d here, the modified value will be used again
double b = S / a;
double c = a + b;
d = 0.5 * c;
System.out.printf("x%d = %8.4f%n", i, a);
}
prints the following for the input value of 50
x0 = 25.0000
x1 = 3.7037
x2 = 5.8127
x3 = 6.9374
x4 = 7.0698
x5 = 7.0711
x6 = 7.0711
x7 = 7.0711
x8 = 7.0711
x9 = 7.0711
Here is an exercise. Compare the current computed value to the last. If they are equal (or their difference is small), then you can exit the loop since repeated iterations won't improve the accuracy very much.

Drawing triangles with java using trigonometry

What I'm trying to do is create a program which take a side length and two angles and produces a triangle drawn using the AWT library.
I'm having trouble working out the logic to use the trigonometric ratios to produce the x and y points of the polygon.
for example, given two angles and a side, I'm attempting to calculate the next x and y points to draw the lines to.
Currently, I've just got some arbitrary points defined to draw a triangle at the moment.
the code block below the graphics is the math for working out all the sides to the triangle
Could anybody be of assistance?
Here is my code. It is badly written. It's mostly just me experimenting and learning more about java.
import javax.swing.*;
import java.awt.*;
import java.math.*;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
public class program{
public static void main (String[] args) {
JFrame frame = new JFrame();
CustomPaintComponent c = new CustomPaintComponent();
frame.add(c);
frame.setSize(1000,1000);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setTitle("Triangle");
frame.setVisible(true);
}
}
class CustomPaintComponent extends Component {
public void paint(Graphics g){
Graphics2D G2D = (Graphics2D)g;
int[] xpoints = { 500, 750 , 1000 , 500};
int[] ypoints = { 500 , 250 , 500 , 500};
G2D.drawPolygon(xpoints,ypoints,4);
}
public Triangle calc(){
double s1,a1,a2;
s1 = Integer.parseInt(JOptionPane.showInputDialog("Please enter side 1"));
a1 = Integer.parseInt(JOptionPane.showInputDialog("Please enter angle 1"));
a2 = Integer.parseInt(JOptionPane.showInputDialog("Please enter angle 2"));
double s2 = ((s1/Math.sin(Math.toRadians(a1))) * Math.sin(Math.toRadians(a2)));
System.out.println(s1/Math.sin(a1));
System.out.println(Math.sin(a2));
double a3 = 180 - (a1 + a2);
double s3 = Math.pow(s2, 2) + Math.pow(s1, 2) - (2 * s2 * s1 * Math.cos(Math.toRadians(a3)));
s3 = Math.sqrt(s3);
Math.toDegrees(a1);
Math.toDegrees(a2);
Math.toDegrees(a3);
System.out.println("side 1 is " + s1 + "side 2 is " + s2 + " and the third angle is: " + a3 + " and the third side length is: " + s3);
Triangle Triangle = new Triangle(s1,s2,s3,a1,a2,a3);
return Triangle;
}
}
class Triangle{
double s1,s2,s3,a1,a2,a3;
Triangle(double s1, double s2, double s3, double a1, double a2, double a3){
this.s1 = s1;
this.s2 = s2;
this.s3 = s3;
this.a1 = a1;
this.a2 = a2;
this.a3 = a3;
}
}
The three rules that a triangle must satisfy:
The angles always add to 180°
A + B + C = 180 degrees
Law of Sines (The Sine Rule) a/sin(A) = b/sin(B) = c/sin(C)
Note: Angle A is opposite to side a, B is opposite to side b, and C is opposite to side c.
Law of Cosines (The Cosine Rule) c^2 = a^2 + b^2 − 2ab*cos(C)
So, let's say you have a triangle XYZ.
The angle opposite to side x = X (=YXZ), the angle opposite to side y = Y (=XYZ), and the angle opposite to side z = Z (=XZY).
The input given by the user is the two angles and the side in between them.
Let the input be:
Angle X = 76 degrees
Angle Y = 34 degrees
Side z = 9 cm
First, find the third angle Z by using the first property.
Angle Z = 180 - X - Y
= 180 - 76 - 34
= 70 degrees
Now, using the Law of Sines, find the sides x and y.
x/sin(X) = z/sin(Z)
=> x/sin(76°) = 9/sin(70°)
=> x = (9/sin(70°)) × sin(76°)
=> x = 9.29 cm
y/sin(Y) = z/sin(Z)
=> y/sin(34°) = 9/sin(70°)
=> y = (9/sin(70°)) × sin(34°)
=> y = 5.36 cm
To code it:
static void printSidesOfTriangle(double side3, double angle1, double angle2){
// The sum of all the angles of triangle is 180 degrees
double angle3 = 180 - angle1 - angle2;
// Converting the angles from degrees to radians
angle1 = Math.toRadians(angle1);
angle2 = Math.toRadians(angle2);
angle3 = Math.toRadians(angle3);
double ratio = side3/(Math.sin(angle3));
double side1 = ratio*(Math.sin(angle1));
double side2 = ratio*(Math.sin(angle2));
System.out.println("The sides of the traingle are: " +
String.valueOf(side1) + ", " +
String.valueOf(side2) + ", and " +
String.valueOf(side3) + ".");
}
And to get the x and y coordinates of each point of the triangle, you need to have some more information as there can be multiple triangles possible with 3 sides on a 2D plane.
Else, you may assume one of the coordinates to be (0,0) and find slopes of both sides.
This way, you will get the x and y coordinates of the remaining point as you have the lengths of these two segments.
Let's assume:
Angle X = 76 degrees
Angle Y = 34 degrees
Angle Z = 70 degrees
Side x = 9.29 cm
Side y = 5.36 cm
Side z = 9.00 cm
Assume three vertices to be (x1,y1), (x2,y2), and (x3,y3).
Check out this LINK
In this way, you can get the x and y coordinates of the remaining vertex.
To code it:
//printVerticesOfTriangle(5.35,9.29,9.0,34,76,70);
//printVerticesOfTriangle(3,4,5,37,53,90);
static void printVerticesOfTriangle(double side1, double side2, double side,
double angle1, double angle2, double angle3)
{
// side1 opposite to angle1
// side2 opposite to angle2
// side3 opposite to angle3
// The vertices are (x1,y1), (x2,y2) and (x3,y3)
double x1 = 0;
double y1 = 0;
double x2 = 0;
double y2 = 0;
double x3 = 0;
double y3 = 0;
// If an angle is 90 degrees, keep that vertex as the origin.
if(angle1==90){
x1 = 0;
y1 = 0;
x2 = side2;
y2 = 0;
x3 = 0;
y3 = side3;
}
else if(angle2==90){
x2 = 0;
y2 = 0;
x1 = side1;
y1 = 0;
x3 = 0;
y3 = side3;
}
else if(angle3==90){
x3 = 0;
y3 = 0;
x1 = side1;
y1 = 0;
x2 = 0;
y2 = side2;
}
// If it is not a right-angled triangle
else{
// Converting the angles from degrees to radians
angle1 = Math.toRadians(angle1);
angle2 = Math.toRadians(angle2);
// For the slope, angle with the positive x-axis is considered
angle3 = Math.toRadians(180-angle3);
x1 = 0;
y1 = 0;
x3 = side2;
y3 = 0;
// Vertex (x2,y2) has to be calculated
x2 = x3*Math.tan(angle3)/(Math.tan(angle1)-Math.tan(angle2));
y2 = x2*Math.tan(angle1);
}
System.out.println("The vertices of the triangle are: " +
"(" + String.format("%.2f",x1) + "," + String.format("%.2f",y1) + "), " +
"(" + String.format("%.2f",x2) + "," + String.format("%.2f",y2) + "), " +
"(" + String.format("%.2f",x3) + "," + String.format("%.2f",y3) + ")");
}

Calculating the area of a triangle

I am new to Java. I am trying to calculate the area of a triangle using the formula:
s = (side 1 + side 2 + side 3)/2
area = square root (side (side - side 1)(side - side2)(side - side3).
If the user enter the three point as:
1.5 -3.4 4.6 5 9.5 -3.4 then the area of the triangle should be 33.6. However, my program runs, but it's giving me an incorrect answer. Below is my code.
// Import Java Scanner
import java.util.Scanner;
import java.lang.Math;
public class Ex_2_19 {
public static void main(String[] args) {
//Create a Scanner object
Scanner input = new Scanner(System.in);
float side = 0;
float area1 = 0;
float area2 = 0;
float area3 = 0;
float area4 = 0;
float calculatedarea = 0;
//Prompt the user to enter three points of a triangle
System.out.println("Enter point x1:");
System.out.println("Enter point y1:");
System.out.println("Enter point x2:");
System.out.println("Enter point y2:");
System.out.println("Enter point x3:");
System.out.println("Enter point y3:");
//Define the variables
float Pointx1 = input.nextFloat();
float Pointy1 = input.nextFloat();
float Pointx2 = input.nextFloat();
float Pointy2 = input.nextFloat();
float Pointx3 = input.nextFloat();
float Pointy3 = input.nextFloat();
//Formula to calculate the area of a triangle
side = (Pointx1 + Pointy1 + Pointx2 + Pointy2 + Pointx3 + Pointy3) / 2;
area1 = side - (Pointx1 + Pointy1);
area2 = side - (Pointx2 + Pointy2);
area3 = side - (Pointx3 + Pointy3);
area4 = side * area1 * (area2) * (area3);
calculatedarea = (float) (Math.sqrt(area4));
//calculatedarea = (float) (Math.sqrt(area1)*(area2) * (area3));
//Print result
System.out.println("The area of the triangle is " + calculatedarea);
}
}
You are trying Heron's Formula - note that a, b, c are the euclidean distance between the points, thus will need to be computed by sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)), etc., not just the sum of differences.

Result of Quaternion Multiplication not yielding expected Rotation of local coordinate system

I'm getting unexpected results when multiplying two quaternions and applying the resulting rotation to my local right-handed coordinate system. (X pointing forward, Y to the right and Z downward).
(See my Java SCCE below)
So I am trying to first apply a Z rotation by 90 degrees (yaw) and then a rotation of 90 degrees around the local X axis (roll).
I am trying to accomplish this by multiplying two quaternions representing these two rotations, creating a rotation Matrix from the result and applying it to the 3 unit vectors of my coordinate system but the results I am getting do not make sense. (i.e. they do not represent the coordinate system you should get from these two rotations.)
I have tried changing the quaternion multiplication order which did not help (see code lines that were commented out in the main method of the SCCE).
I have also tried creating the quaternion for the second rotation from global Y to simulate that it was created from the resulting local coordinate system after the first rotation.
For reference I am also calculating the result by applying the two individual rotation matrices (which works as expected).
What am I doing wrong?
import java.text.DecimalFormat;
import java.text.NumberFormat;
public class Quaternion {
public static final double NORMALIZATION_LOWER_TOLERANCE = 1 - 1e-4;
public static final double NORMALIZATION_UPPER_TOLERANCE = 1 + 1e-4;
private double w = 1.0;
private double x = 0.0;
private double y = 0.0;
private double z = 0.0;
public static void main(String[] args) {
Vector3D xVect = new Vector3D(1,0,0);
Vector3D yVect = new Vector3D(0,1,0);
Vector3D zVect = new Vector3D(0,0,1);
System.out.println("Initial Local Coordinate System: X:"+xVect+" / Y:"+yVect+ " / Z:"+zVect);
Quaternion rotZ = new Quaternion(Math.PI/2, zVect); // Yaw +90 deg
Quaternion rotY = new Quaternion(Math.PI/2, yVect); // Yaw +90 deg
Quaternion rotX = new Quaternion(Math.PI/2, xVect); // Then roll +90 deg
Matrix rotationMatrixZ = new Matrix(rotZ);
Vector3D localX = xVect.rotate(rotationMatrixZ);
Vector3D localY = yVect.rotate(rotationMatrixZ);
Vector3D localZ = zVect.rotate(rotationMatrixZ);
System.out.println("New Local Coordinate System after Yaw: X:"+localX+" / Y:"+localY+ " / Z:"+localZ); // Gives expected result
Quaternion localRotX = new Quaternion(Math.PI/2, localX);
Matrix localRotXMatrix = new Matrix(localRotX);
Vector3D rotatedX = localX.rotate(localRotXMatrix);
Vector3D rotatedY = localY.rotate(localRotXMatrix);
Vector3D rotatedZ = localZ.rotate(localRotXMatrix);
System.out.println("New Local Coordinate System two local rotations: X:"+rotatedX+" / Y:"+rotatedY+ " / Z:"+rotatedZ); // Gives expected result
Quaternion rotZX = rotZ.multiply(rotX);
// Quaternion rotZX = rotX.multiply(rotZ); // Tried both orders
// Quaternion rotZX = rotZ.multiply(rotY); // rotY is in fact the local rotX
// Quaternion rotZX = rotZ.multiply(rotY); // rotY is in fact the local rotX, tried both orders
rotZX.normalizeIfNeeded();
Matrix rotationXMatrixZX = new Matrix(rotZX);
rotatedX = xVect.rotate(rotationXMatrixZX);
rotatedY = localY.rotate(rotationXMatrixZX);
rotatedZ = localZ.rotate(rotationXMatrixZX);
System.out.println("New Local Coordinate System Quaternion Multiplication: X:"+rotatedX+" / Y:"+rotatedY+ " / Z:"+rotatedZ); // Expect same as above
}
public Quaternion() {
}
public Quaternion(double w, double x, double y, double z) {
this.w = w;
this.x = x;
this.y = y;
this.z = z;
}
public Quaternion(double angle, Vector3D vector){
double halfAngle = angle / 2;
double sin = Math.sin(halfAngle);
this.w = Math.cos(halfAngle);
this.x = vector.getX()*sin;
this.y = vector.getY()*sin;
this.z = vector.getZ()*sin;
}
public boolean normalizeIfNeeded() {
double sum = w * w + x * x + y * y + z * z;
if (NORMALIZATION_LOWER_TOLERANCE < sum && sum < NORMALIZATION_UPPER_TOLERANCE) {
return false;
}
double magnitude = Math.sqrt(sum);
w /= magnitude;
x /= magnitude;
y /= magnitude;
z /= magnitude;
return true;
}
public Quaternion multiply(Quaternion q2) {
Quaternion result = new Quaternion();
result.w = w * q2.w - x * q2.x - y * q2.y - z * q2.z;
result.x = w * q2.x + x * q2.w + y * q2.z - z * q2.y;
result.y = w * q2.y - x * q2.z + y * q2.w + z * q2.x;
result.z = w * q2.z + x * q2.y - y * q2.x + z * q2.w;
return result;
}
public Quaternion conjugate() {
return new Quaternion(w, -x, -y, -z);
}
public double getW() {
return w;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
#Override
public String toString() {
return "Quaternion [w=" + w + ", x=" + x + ", y=" + y + ", z=" + z + "]";
}
static class Vector3D {
double x=0;
double y=0;
double z=0;
public Vector3D(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3D rotate(Matrix rotationMatrix){
return rotationMatrix.multiply(this);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
#Override
public String toString() {
NumberFormat df = DecimalFormat.getNumberInstance();
return "[x=" + df.format(x) + ", y=" + df.format(y) + ", z=" + df.format(z) + "]";
}
}
static class Matrix {
private double[][] values;
public Matrix(int rowCount, int colCount) {
values = new double[rowCount][colCount];
}
public Matrix(Quaternion quaternionForRotationMatrix) {
this(3,3);
double w = quaternionForRotationMatrix.getW();
double x = quaternionForRotationMatrix.getX();
double y = quaternionForRotationMatrix.getY();
double z = quaternionForRotationMatrix.getZ();
double ww = w*w;
double wx = w*x;
double xx = x*x;
double xy = x*y;
double xz = x*z;
double wy = w*y;
double yy = y*y;
double yz = y*z;
double wz = w*z;
double zz = z*z;
values[0][0] = ww + xx - yy - zz;
values[0][1] = 2 * xy - 2 * wz;
values[0][2] = 2 * xz + 2 * wy;
values[1][0] = 2 * xy + 2 * wz;
values[1][1] = ww - xx + yy - zz;
values[1][2] = 2 * yz + 2 * wx;
values[2][0] = 2 * xz - 2 * wy;
values[2][1] = 2 * yz - 2 * wx;
values[2][2] = ww - xx - yy + zz;
}
public Vector3D multiply(Vector3D vector){
double [][] vect = new double [3][1];
vect[0][0] = vector.getX();
vect[1][0] = vector.getY();
vect[2][0] = vector.getZ();
double [][] result = multiplyMatrices(values, vect);
return new Vector3D(result[0][0], result[1][0], result[2][0]);
}
private double[][] multiplyMatrices(double[][] m1, double[][] m2) {
double[][] result = null;
if (m1[0].length == m2.length) {
int rowCount1 = m1.length;
int colCount1 = m1[0].length;
int rowCount2 = m2[0].length;
result = new double[rowCount1][rowCount2];
for (int i = 0; i < rowCount1; i++) {
for (int j = 0; j < rowCount2; j++) {
result[i][j] = 0;
for (int k = 0; k < colCount1; k++) {
result[i][j] += m1[i][k] * m2[k][j];
}
}
}
} else {
int rowCount = m1.length;
int colCount = m1[0].length;
result = new double[rowCount][colCount];
for (int i = 0; i < m1.length; i++) {
for (int j = 0; j < m1[0].length; j++) {
result[i][j] = 0;
}
}
}
return result;
}
#Override
public String toString() {
StringBuffer sb = new StringBuffer("Matrix = ");
for(int row = 0 ; row<values.length; row++){
sb.append ("[ ");
for(int col = 0 ; col<values[0].length; col++){
sb.append(Double.toString(values[row][col]));
if(col<values.length-1){
sb.append(" | ");
}
}
sb.append("] ");
}
return sb.toString();
}
}
}
Nevermind. Found it. I had an error in the formulas to build the rotation matrix. It now works as expected.
I am making a mental note to use formulas from Wikipedia in the future and not some random other site.
The respective part should be
values[0][0] = ww + xx - yy - zz;
values[0][1] = 2 * xy - 2 * wz;
values[0][2] = 2 * xz + 2 * wy;
values[1][0] = 2 * xy + 2 * wz;
values[1][1] = ww - xx + yy - zz;
values[1][2] = 2 * yz - 2 * wx; //CORRECTED SIGN
values[2][0] = 2 * xz - 2 * wy;
values[2][1] = 2 * yz + 2 * wx; //CORRECTED SIGN
values[2][2] = ww - xx - yy + zz;
At the end of the main method I was also using the wrong vectors for y and z:
Matrix rotationXMatrixZX = new Matrix(rotZX);
rotatedX = xVect.rotate(rotationXMatrixZX);
rotatedY = yVect.rotate(rotationXMatrixZX); // Corrected used y-vector
rotatedZ = zVect.rotate(rotationXMatrixZX); // Corrected used z-vector

Calculating Geometric median of 2D points

I am calculating Geometric median of some (x,y) points in java. To calculate Geometric median, first i am calculating centroid of all the points, then this centroid is used to calculate Geometric median. My code works fine, but sometimes it goes to an infinite loop (i think.). The problem is with my while condition. This while condition should be change according to input points, but i don't know how. Below I am putting the complete code.
import java.util.ArrayList;
public class GeometricMedian {
private static ArrayList<Point> points = new ArrayList<Point>();
private class Point {
private double x;
private double y;
Point(double a, double b) {
x = a;
y = b;
}
}
public static void main(String[] args) {
GeometricMedian gm = new GeometricMedian();
gm.addPoints();
Point centroid = gm.getCentroid();
Point geoMedian = gm.getGeoMedian(centroid);
System.out.println("GeometricMedian= {" + (float) geoMedian.x + ", "
+ (float) geoMedian.y + "}");
}
public void addPoints() {
points.add(new Point(0, 1));
points.add(new Point(2, 5));
points.add(new Point(3, 1));
points.add(new Point(4, 0));
}
public Point getCentroid() {
double cx = 0.0D;
double cy = 0.0D;
for (int i = 0; i < points.size(); i++) {
Point pt = points.get(i);
cx += pt.x;
cy += pt.y;
}
return new Point(cx / points.size(), cy / points.size());
}
public Point getGeoMedian(Point start) {
double cx = 0;
double cy = 0;
double centroidx = start.x;
double centroidy = start.y;
do {
double totalWeight = 0;
for (int i = 0; i < points.size(); i++) {
Point pt = points.get(i);
double weight = 1 / distance(pt.x, pt.y, centroidx, centroidy);
cx += pt.x * weight;
cy += pt.y * weight;
totalWeight += weight;
}
cx /= totalWeight;
cy /= totalWeight;
} while (Math.abs(cx - centroidx) > 0.5
|| Math.abs(cy - centroidy) > 0.5);// Probably this condition
// needs to change
return new Point(cx, cy);
}
private static double distance(double x1, double y1, double x2, double y2) {
x1 -= x2;
y1 -= y2;
return Math.sqrt(x1 * x1 + y1 * y1);
}
}
Please help me to fix the bug, also if there exitis any better way to calculate Geometric median of some 2D points, write here. Thank you.
I don't see why you need two loops. You only need the loop over all the points. What is the reason for the other one, in your view?
One way to solve this is to iterate certain number of times. This similar to K-Means method where it either converges to a specific threshold or stops after a predefined number of iterations.

Categories