简体   繁体   中英

connect a point to each two closest point between different points

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.

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.

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.

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM