Reputation: 1595
Hi I am writing an application with java. In my application I need a method to connect each point to its two closest point between many different points (draw a line from a point to its two closest points). At first I created this method so as to connect each point to its closest point:
public void connectingPoints()
{
ArrayList<Point> externals = new ArrayList<Point>();
for(int i = 0; i<externals.size(); i++)
{
Point point = externals.get(i);
Point minPoint = externals.get(i+1);
int minXDistance = minPoint.x-point.x;
int minYDistance = minPoint.y-point.y;
for(int j = 1; j<externals.size();i++)
{
if((externals.get(j+1).x-point.x<minXDistance)&&(externals.get(j+1).y-point.y<minYDistance))
{
minPoint = externals.get(j+1);
}
}
getGraphics().drawLine(point.x, point.y, minPoint.x, minPoint.y);
repaint();
}
}
}
but this method doesnt work at all. why? where is the problem? And how can i connect a point to its 2 closest point.
Upvotes: 0
Views: 1834
Reputation: 3096
I think you have several issues. It looks like you have a class like this:
public class Point {
public double x;
public double y;
}
You should probably add a method to your class that looks like this:
public double distance(Point p) {
return Math.hypot(this.x - p.x, this.y - p.y);
}
And another one:
public Point getClosestPoint(List<Point> pts) {
double minDistSoFar = Double.MAX_VALUE;
Point rval = null;
for (Point p : pts) {
if (p.x == this.x && p.y == this.y) {
continue;
}
double pDist = this.distance(p);
if (pDist < minDistSoFar) {
minDistSoFar = pDist;
rval = p;
}
}
}
Now your algorithm can become this:
public void connectingPoints()
{
ArrayList<Point> externals = new ArrayList<Point>();
for(Point p : externals) {
Point minPoint = p.getClosestPoint(externals);
getGraphics().drawLine(point.x, point.y, minPoint.x, minPoint.y);
repaint();
}
}
EDIT: Your original problem is probably that you index "i" in your loop examining the value of j. Also, here is a rewrite with a simple (and workable) rewrite of your code.
public void connectingPoints()
{
ArrayList<Point> externals = new ArrayList<Point>();
for(int i = 0; i<externals.size(); i++)
{
Point point = externals.get(i);
Point minPoint = externals.get((i+1) % externals.size());
int minXDistance = minPoint.x-point.x;
int minYDistance = minPoint.y-point.y;
double minDist = Math.hypot(minXDistance, minYDistance);
for(int j = 0; j < externals.size(); j++) // <- you had i++ here!
{
if (i == j) {
continue;
}
Point testPt = externals.get(j);
double dist = Math.hypot(point.x - testPt.x, point.y - testPt.y);
if (dist < minDist)
{
minDist = dist;
minPoint = testPt;
}
}
getGraphics().drawLine(point.x, point.y, minPoint.x, minPoint.y);
repaint();
}
}
Upvotes: 1
Reputation: 15870
Problem 1: You're not computing distance, you're computing distance in X + distance in Y.
distance = sqrt( x^2 + y^2)
The good news is that for comparison purposes, you can drop the square root. You CANNOT drop the "square x" and "square y" portion. Very Important.
Problem 2: You're finding the nearest point twice, not the nearest two points. Here's a quick-n-dirty algorithm that'll work, though it certainly leaves room for improvement:
For each point
calculate and store distances to all the other points
// use a sorted map for the above.
grab the closest two points and draw your lines.
Note that this will cause quite a bit of recalculation, thus the room for improvement.
Also note that this will NOT create a path through all your points.
Upvotes: 1
Reputation: 6317
That's not really checking the distance between the points. Calculate the distance between the points using the pythagorean theorem and then pick the lowest and second lowest result. Square the distance between X values, add the square of the distance between the Y values, and then take square root.
Upvotes: 2