Adding a capability to Line2D

Hi all.

I found myself several times wishing that Line2D could do this specific thing, so I made it do that thing. I called the new class Line2DPlus. The new thing it does is this: it has a method called getClosestPt which returns the point on the line that is closest to any given point.

Here’s the code for the getClosestPt method:

           
            public Point2D.Float getClosestPt ( Point2D.Float targetPoint ) {
                  
                  // Find the distance from the line to the point:
                  
                  double ptLineDist = ptLineDist ( targetPoint ) ;
                  
                  // Find the distance from the line's beginning to the point:
                  
                  double endPtDist = getP1 ().distance ( targetPoint ) ;
                  
                  // Calculating the length of the line segment that runs from the line's 
                  // beginning to the point on the line that is closest to the targetPoint:
                  
                  double segmentLength = 
                        Math.sqrt ( ( endPtDist * endPtDist ) - ( ptLineDist * ptLineDist ) ) ;
                        
                  // Finding the change in x and y between the endpoints of the line:
                  
                  double changeX = getP1 ().getX () - getP2 ().getX () ;
                  
                  double changeY = getP1 ().getY () - getP2 ().getY () ;
                  
                  // Finding the length of the line:
                  
                  double length = getP1 ().distance ( getP2 () ) ;
                  
                  // Determining the change in X and Y for the new segment:
                  
                  double newX = segmentLength * changeX / length ;
                  
                  double newY = segmentLength * changeY / length ;
                  
                  // Finding the end point of the new segment:
                  
                  Point2D.Float newEnd = 
                        new Point2D.Float ( ( float ) ( getP1 ().getX () + newX ) , 
                                                      ( float ) ( getP1 ().getY () + newY ) ) ;
                                                      
                  // Returning that point:
                  
                  return newEnd ;
                  
            }     

Any comments? Specifically, I’m curious if anybody can see a better way to do the same thing.

After working with this code for a little while, and having it not work correctly, and staring at it for a long time, I finally realized there’s an error in it. Since no one else caught it, I thought I’d post it myself:


                  // Finding the change in x and y between the endpoints of the line: 
                   
                  double changeX = getP1 ().getX () - getP2 ().getX () ; 
                   
                  double changeY = getP1 ().getY () - getP2 ().getY () ; 


and


                  // Finding the end point of the new segment: 
                   
                  Point2D.Float newEnd =  
                        new Point2D.Float ( ( float ) ( getP1 ().getX () + newX ) ,  
                                                      ( float ) ( getP1 ().getY () + newY ) ) ; 
           

add up to the new line segment heading away from the target point, not towards it. To correct this, either the first snippet needs to be changed to


                  // Finding the change in x and y between the endpoints of the line: 
                   
                  double changeX = getP2 ().getX () - getP1 ().getX () ; 
                   
                  double changeY = getP2 ().getY () - getP1 ().getY () ; 


which will result in the positivity/negativity of the changeX and changeY being reversed, or


                  // Finding the end point of the new segment: 
                   
                  Point2D.Float newEnd =  
                        new Point2D.Float ( ( float ) ( getP1 ().getX () - newX ) ,  
                                                      ( float ) ( getP1 ().getY () - newY ) ) ; 
           

which does almost the same thing.

Clear as mud? Well, I tried.