Chapter 02-2: Calculate the distance between a point and a line



In this chapter the function calculates the shortest distance between a straight line and a given point. The function takes two arrays as arguments. The first array holds the xy-coordinates of the start and endpoints of the line and the second argument holds the xy-coordinate of the point. For example:
argument 1: line = newArray(start_x, start_y, end_x, end_y);
argument 2; point = newArray(point_x, point_y);
The return value for this function is the shortest distance between the line and the point. The function creates a perpendicular line to the given line, crossing the given point. This is supposed to be the shortest distance between a line and a point.


Step 01: The function distance_line_point(line, point)

function distance_line_point(line, point)     {
   
    // check for vertical line
    if(line[0]==line[2]) {    // both x-values are the same --> vertical line
                            distance = line[0]- point[0];
                         }
   
    // check for horizontal line
    if(line[1]==line[3]) {  // both y-values are the same --> horizontal line
                            distance = line[1] - point[1];
                         }
   
    // check for tilted line
    if((line[0]!=line[2]) && (line[1]!=line[3])) {    // tilted line --> x and y values of the start and endpoint are different
   
                            // calculate the gradient b = (y2-y1)/(x2-x1)
                            b = (line[3]-line[1])/(line[2]-line[0]);
                           
                            // calculate the centre distance a=y-bx
                            a = line[1] - ( b * line[0]);
                           
                            // calculate the angle of the 90° crossing line
                            angle_line90deg = (atan(b)*180/PI) + 90;
                           
                            // calculate the gradient b2 of the 90° intersection line
                            angle_line90rad = angle_line90deg / (180/PI);    // angle in rad
                            b2 = (tan(angle_line90rad));
                           
                            // calculate the centre distance a2 of the 90° intersection line
                            // a2 = y_point - b2 * x_point;
                            a2 = point[1] - b2 * point[0];
                           
                            // calculate the intersection of the two lines
                            ptx_intersection = (a2-a) / (b - b2);
                            pty_intersection = a + b * ptx_intersection;
                           
                            // calculate the distance between the point and the intersection of the two lines
                            dx = point[0] - ptx_intersection;
                            dy = point[1] - pty_intersection;
                            distance = sqrt(dx*dx + dy*dy);
                            if(distance<0.00001) distance = 0;
                         }
                         
    return distance;
}


The function checks the first argument whether it is a horizontal, vertical or tilted line. If it is a vertical or horizontal line the calculation is very simple. If it is a tilted line it first calculates the gradient b and the centre distance a of the given line. Both you need to calculate the angle of the line. Once you got the angle you also can calculate the angle of the perpendicular line. Then the function calculates the gradient b2 and the centre distance a2 of the perpendicular line. Now you got everything to calculate the intersection point of the given and the perpendicular line. At the end of the function it is a simple point ot  point calculation to get the distance to the line. If the line is tilted and the point is exactly located on the line, the function will return a very small number, because of rounding errors. That's why it will be clipped to zero if the distance is very small.

Step 02: Macro example with the distance_line_point function

Some simple code sample for the imagej macro language. Open any image, copy the code into a new imagej text window and run the macro.


//+++++++++++ STEP 01 DECLARATIONEN +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
    function distance_line_point(line, point);

//+++++++++++ STEP 02 MAIN PROGRAM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

line = newArray(50,50,300,150);
makeLine(line[0],line[1],line[2],line[3]);
roiManager("Add");
point = newArray(150,185);
makePoint(point[0],point[1]);
roiManager("Add");
setOption("Show All", true);
dist_line_point = distance_line_point(line,point);
print(dist_line_point);

//+++++++++++ STEP 03 Function: distance_line_point ++++++++++++++++++++++++++++++++++++++++++++++

function distance_line_point(line, point)     {
   
    // check for vertical line
    if(line[0]==line[2]) {    // both x-values are the same --> vertical line
                            distance = line[0]- point[0];
                         }
   
    // check for horizontal line
    if(line[1]==line[3]) {  // both y-values are the same --> horizontal line
                            distance = line[1] - point[1];
                         }
   
    // else tilted line
    if((line[0]!=line[2]) && (line[1]!=line[3])) {    // tilted line --> x and y values of the start and endpoint are different
   
                            // calculate the gradient b = (y2-y1)/(x2-x1)
                            b = (line[3]-line[1])/(line[2]-line[0]);
                           
                            // calculate the centre distance a=y-bx
                            a = line[1] - ( b * line[0]);
                           
                            // calculate the angle of the 90° crossing line
                            angle_line90deg = (atan(b)*180/PI) + 90;
                           
                            // calculate the gradient b2 of the 90° intersection line
                            angle_line90rad = angle_line90deg / (180/PI);    // angle in rad
                            b2 = (tan(angle_line90rad));
                           
                            // calculate the centre distance a2 of the 90° intersection line
                            // a2 = y_point - b2 * x_point;
                            a2 = point[1] - b2 * point[0];
                           
                            // calculate the intersection of the two lines
                            ptx_intersection = (a2-a) / (b - b2);
                            pty_intersection = a + b * ptx_intersection;
                           
                            // calculate the distance between the point and the intersection of the two lines
                            dx = point[0] - ptx_intersection;
                            dy = point[1] - pty_intersection;
                            distance = sqrt(dx*dx + dy*dy);
                            if(distance<0.00001) distance = 0;
                         }
                         
    return distance;
}



Step 03: Enjoy the results


chapter02-2_step03img01.gif     chapter02-2_step03img02.gif


The Log window shows you the distance in pixels. For realworld measurements you have to calibrate the pixelsize. For that it is important to know what format your pixel on the sensor has. You have to find out, whether it is square or rectangular shaped. The function can be implemented very easy in measuring programms.