Search code examples
c#geometrylineline-segment

How to move the end points of a line to keep its length but make it parallel to another line (C# preferably!)


I have a line segment whose end points I know

Line1 (X1,Y1) (X2,Y2)

I have a second line

Line2 (X3,Y3) (X4,Y4)

I want to calculate new end points for line 1 such that the resulting line is parallel to Line2, and Line1's centre point remains at the same coordinates.

i.e. such that Line1 simply rotates so it is parallel to Line2

I know I can calculate each line's angle

var line1Angle = (Mathf.Atan2(x2 - x1, y2 - y1));
var line2Angle = (Mathf.Atan2(x4 - x3, y4 - y3));

I can also calculate the lengths

var len1 = Math.Sqrt((x2-x1)*(x2-x1)+ (y2-y1) * (y2-y1));
var len2 = Math.Sqrt((x4-x3)*(x4-x3)+ (y4-y3) * (y4-y3));

but everything I have tried seems to fail - either not rotating correctly, or rotating but with the incorrect length.

The closest code I have (below) rotates correctly, but the length of Line1 is not retained.

The code uses an 'offset' which was used by the code this version is based on as it simply drew a parallel line 'offset' pixels from the destination line - I have set it to an arbitrary value but I believe should be the distance of Line1's centre point from the closest point on Line2.

I'd love it if someone could supply a code version, rather than an explanation (or as well as!) as I've read and tried so many non-code solutions, and evidently my understanding / translation to code is flawed!


float len1 = (float)Math.Sqrt((x2-x1)*(x2-x1)+ (y2-y1) * (y2-y1));
float len2 = (float)Math.Sqrt((x4-x3)*(x4-x3)+ (y4-y3) * (y4-y3));

float offset = 3.0f; // This should be the dist from our center to the closest wall but I"m compromising for now!
float newX1 = x3 + offset * (y4 - y3) * (len1 / len2);
float newX2 = x4 + offset * (y4 - y3) * (len1 / len2);
float newY1 = y3 + offset * (x3 - x4) * (len1 / len2);
float newY2 = y4 + offset * (x3 - x4) * (len1 / len2); 

Solution

  • Approach without angles: you know segment lengths, and can just form new segment ends with the same direction as line2 defines

    dx1 = x2 - x1
    dy1 = y2 - y1
    dx2 = x4 - x3
    dy2 = y4 - y3
    len1 = hypot(dx1, dy1)
    len2 = hypot(dx2, dy2)
    midx = (x1 + x2) / 2
    midy = (y1 + y2) / 2
    coeff = 0.5 * len1 / len2
    
    //now we make a vector with direction of line2
    //and length of half of line1
    
    newx1 = midx - dx2 * coeff  
    newy1 = midy - dy2 * coeff
    newx2 = midx + dx2 * coeff
    newy2 = midy + dy2 * coeff