Determining the positional relationship (intersection) between two line segments in a plane and solving the intersection

Source: Internet
Author: User
Concept

The determination of the positional relationship between two line segments in a plane is widely used in many fields, such as games, CAD, and graphic processing.AlgorithmAn important part. This article will describe a mainstream and high-performance judgment Algorithm in a popular language as much as possible.

Outer product, also known as cross product, is a concept in vector algebra (analytic ry. Two Dimensional Vectors V1 (x1, Y1) and V2 (X2, Y2) of the outer product V1 x v2 = x1y2-y1x2. If the rotation is clockwise from V1 to V2, the outer product is negative, and the reverse is positive. 0 indicates that the two directions are the same (parallel ). In addition, this article involves the concepts of line examples and equations. For more information, see linear algebra.

For convenient calculation, the size of coordinate points is defined as follows: the vertices with larger X coordinates are large, the coordinates of X are equal, but those with larger y coordinates are large, vertices x and y are equal. The smaller end of a line segment is the start point, and the larger end is the end point.

 

Problem

Specify the endpoint coordinates of the two line segments, obtain the positional relationship, and obtain the intersection (if any ).

 

Analysis

The Positional relationships between two line segments can be divided into three types: overlapping, non-overlapping, but intersection, and non-intersection. To avoid precision problems, we must first exclude all overlapping situations.

Coincidence can be divided into three types: Full coincidence, end coincidence, and partial coincidence. Obviously, the start and end points of the two line segments are the same, that is, they are completely overlapped. Only the starting point is the same or only the end point is the same as the end point. (Note: when the end point of a line segment with smaller coordinates is the same as the start point of a line segment with larger coordinates, it must be considered as intersection ). To determine whether part of overlap exists, you must first determine whether parallelism exists. Set line segments L1 (P1-> P2) and L2 (P3-> P4), where p1 (x1, Y1) is the start point of the first line segment, P2 (X2, Y2) it is the end point of the first line segment, P3 (X3, Y3) is the start point of the second line segment, and P4 (X4, Y4) is the end point of the second line segment. Therefore, two vectors can be constructed:

    • V1 (x2-x1, y2-y1), V2 (x4-x3, y4-y3)

If the outer product V1 x V2 of V1 and V2 is 0, the two line segments are parallel, and some overlap may exist. Then, determine whether two parallel lines are in the same line. The method is to use one end of L1 and the other end of L2 to form the vector Vs and make an outer product with V2, if Vs and v2 are parallel, the two line segments are collocated (three points are collocated ). If the end point of a line segment with a smaller starting point is greater than the start point of a line segment with a larger starting point, the result is partially overlapped.

If there is no coincidence, it is necessary to determine whether the two lines are intersecting. The main algorithm still relies on the outer product. However, the calculation overhead of the outer product is relatively large. If there are many non-intersecting conditions, you can first quickly exclude the experiment: consider the two line segments as the diagonal lines of the two rectangles and construct the two rectangles. If the two rectangles do not overlap (X-coordinate or Y-coordinate), the two rectangles are considered as non-intersecting.

Then perform a cross-site test. The two overlapping line segments are bound to cross-border. Simply put, P1 and P2 are located on both sides of L2 and P3 and P4 are located on both sides of L1, so that the outer product can be used to make a judgment. Construct the S1 (P3, P1), S2 (P3, P2) vectors, respectively ), if S1 × V2 and S2 × v2 are different (S1-> V2 and S2-> V2 rotate in the opposite direction), P1 and P2 are on both sides of L2. Similarly, you can determine whether P3. If either of the above four cross points is equal to 0, it means that the endpoint of a line segment is on another line.

After determining the intersection of two line segments, you can solve the intersection. Of course, you can use the plane ry method to calculate the intersection point, and use the column-point oblique equation. However, this will make it difficult to deal with the special case where the slope is 0, and there will be multiple Division operations in the operation, it is difficult to ensure accuracy. The vector method is used for solving the problem.

If the intersection is (x0, y0), the following equations must be true:

    1. X0-x1 = K1 (x2-x1)
    2. Y0-y1 = K1 (y2-y1)
    3. X0-x3 = k2 (x4-x3)
    4. Y0-y3 = k2 (y4-y3)

Where K1 and K2 are any constants not 0 (if it is 0, it indicates that there is a coincidence endpoint, which has been excluded ). Link 1 to 2, and Connect 3 to 4. Remove K1 and K2:

    1. X0 (y2-y1)-x1 (y2-y1) = y0 (x2-x1)-y1 (x2-x1)
    2. X0 (y4-y3)-X3 (y4-y3) = y0 (x4-x3)-Y3 (x4-x3)

Move the items containing unknown x0 and Y0 to the left, and the constant to the right:

    1. (Y2-y1) x0 + (x1-x2) Y0 = (y2-y1) X1 + (x1-x2) Y1
    2. (Y4-y3) x0 + (x3-x4) Y0 = (y4-y3) X3 + (x3-x4) Y3

Set two constant items to B1 and B2:

    • B1 = (y2-y1) X1 + (x1-x2) Y1
    • B2 = (y4-y3) X3 + (x3-x4) Y3

The coefficient determine factor is d, the coefficient obtained by replacing x0 with B1 and B2 is D1, and the coefficient obtained by replacing y0 is D2:

    • | D | = (x2-x1) (y4-y3)-(x4-x3) (y2-y1)
    • | D1 | = B2 (x2-x1)-B1 (x4-x3)
    • | D2 | = B2 (y2-y1)-B1 (y4-y3)

Therefore, the coordinates of the intersection point can be obtained as follows:

    • X0 = | d1 |/| d |, Y0 = | D2 |/| d |

Complete.

 

C ++/STL implementation
# Include <iostream> # include <cmath> using namespace STD; struct pointf {float X; float y ;}; bool equal (float F1, float F2) {return (ABS (F1-F2) <1e-4f);} // determine whether two points are equal bool operator = (const pointf & P1, const pointf & p2) {return (equal (p1.x, p2.x) & Equal (p1.y, p2.y) ;}// compare the two-point coordinate values. First, compare the X coordinate values, if they are the same, compare the Y coordinate bool operator> (const pointf & P1, const pointf & p2) {return (p1.x> p2.x | (equal (p1.x, p2.x) & p1.y> p2.y )) ;} // Calculate the two-vector outer product float operator ^ (const pointf & P1, const pointf & p2) {return (p1.x * p2.y-p1.y * p2.x );} // determine the relationship between the two line segments and obtain the intersection (if any ). The return values are listed as follows: // [overlapped] Completely overlapped (6). One endpoint is overlapped and co-linear (5), and some overlap (4) // [no coincidence] intersection of two vertices (3), online (2), orthogonal (1), zero (0), parameter error (-1) int intersection (pointf P1, pointf P2, pointf P3, pointf P4, pointf & INT) {// ensure parameter P1! = P2, P3! = P4if (p1 = P2 | P3 = P4) {return-1; // return-1 indicates that at least one line segment is overlapped at the beginning and end, cannot constitute a line segment} // to facilitate calculation, ensure that the start point of each line segment is before and the end point is behind. If (P1> P2) {swap (P1, P2) ;}if (P3> P4) {swap (P3, P4 );} // determine whether the two line segments completely overlap if (p1 = P3 & p2 = P4) {return 6 ;} // obtain the outer product of two vectors, such as pointf V1 = {p2.x-p1.x, p2.y-p1.y}, V2 = {p4.x-p3.x, p4.y-p3.y}. // obtain the outer product of two vectors, when parallel is used, the outer product is 0 float corss = V1 ^ V2; // If the starting point is overlapped if (p1 = P3) {Int = p1; // The starting point is coincident and is collocated (parallel) return 5; if not parallel, it is handed over to the endpoint. Return 3 return (equal (corss, 0 )? 5: 3);} // if the end point is overlapped if (P2 = P4) {Int = P2; // if the end point is overlapped and the end point is collocated (parallel), return 5; if it is not parallel, it is handed over to the endpoint and 3 return (equal (corss, 0 )? 5: 3);} // if the two ends are connected at the beginning and end if (p1 = P4) {Int = p1; return 3;} If (P2 = P3) {Int = P2; return 3;} // After the above judgment, the first and last vertices are all out of phase duplicates. // The line segments are sorted by the start and end vertices. If the starting point of Line Segment 1 is large, the two line segments are exchanged if (P1> P3) {swap (P1, P3); swap (P2, P4 ); // update the previously calculated vector and its outer product swap (V1, V2); corss = V1 ^ V2;} // process parallel conditions of two line segments if (equal (corss, 0 )) {// perform the outer product of the vectors V1 (P1, P2) and vs (P1, P3) to determine whether or not pointf Vs = {p3.x-p1.x, p3.y-p1.y} Are collocated }; // if the outer product is 0, the two parallel lines are in the same line. If (equal (V1 ^ vs, 0 )) {// If (P2> P3) {Int = P3; return 4; // return value 4 indicates that the part of the line segment is overlapped} // if the three points are not collocated, the two parallel lines are not collocated. // Returns 0 if there are no parallel lines that are not collocated or collocated but do not overlap.} // if the following are not parallel lines, perform the fast Rejection Test first. // The X coordinate is ordered, can be directly compared. The Y coordinate must first calculate the maximum and minimum float Ymax1 = p1.y, ymin1 = p2.y, ymax2 = p3.y, ymin2 = p4.y; If (Ymax1 <ymin1) {swap (Ymax1, ymin1) ;}if (ymax2 <ymin2) {swap (ymax2, ymin2) ;}// if the rectangle with two linelines as diagonal lines does not intersection, if (p1.x> p4.x | p2.x <p3.x | Ymax1 <ymin2 | ymin1> ymax2) {return 0 ;} // The following cross-site test pointf VS1 = {p1.x-p3.x, p1.y-p3.y}, vs2 = {p2.x-p3.x, p2.y-p3.y}, pointf vt1 = {p3.x-p1.x, p3.y-p1.y}, VT2 = {p4.x-p1.x, p4.y-p1.y}; float s1v2, s2v2, t1v1, t2v1; // determine whether to submit the data to the online if (equal (s1v2 = VS1 ^ V2, 0) & P4> P1 & P1> P3) {Int = p1; return 2;} If (equal (s2v2 = vs2 ^ V2, 0) & P4> P2 & P2> P3) {Int = P2; return 2 ;} if (equal (t1v1 = vt1 ^ V1, 0) & P2> P3 & P3> P1) {Int = P3; return 2 ;} if (equal (t2v1 = VT2 ^ V1, 0) & P2> P4 & P4> P1) {Int = P4; return 2 ;}// not submitted online, determine whether to intersection if (s1v2 * s2v2> 0 | t1v1 * t2v1> 0) {return 0;} // The following conditions are intersection, for details about the algorithm, see the document // two constant terms for calculating the Second-Order Determinant float ConA = p1.x * v1.y-p1.y * v1.x; float Conb = p3.x * v2.y-p3.y * v2.x; // calculate the value of the determine factors D1 and D2, divide by the value of the coefficient determine, get the intersection coordinate Int. X = (Conb * v1.x-ConA * v2.x)/corss; Int. y = (Conb * v1.y-ConA * v2.y)/corss; // returns 1 return 1 orthogonal;} // The main function int main (void) {// generate 100 random test data for (INT I = 0; I <100; ++ I) {pointf P1, P2, P3, P4, int; p1.x = (float) (RAND () % 10); p1.y = (float) (RAND () % 10); p2.x = (float) (RAND () % 10 ); p2.y = (float) (RAND () % 10); p3.x = (float) (RAND () % 10); p3.y = (float) (RAND () % 10 ); p4.x = (float) (RAND () % 10); p4.y = (float) (RAND () % 10); int Nr = intersection (P1, P2, P3, P4, INT); cout <"[("; cout <(INT) p1.x <',' <(INT) p1.y <"),("; cout <(INT) p2.x <',' <(INT) p2.y <")] -- [("; cout <(INT) p3.x <', '<(INT) p3.y <"), ("; cout <(INT) p4.x <', '<(INT) p4.y <")]: "; cout <NR; If (NR> 0) {cout <'(' <Int. x <',' <Int. Y <')';} cout <Endl;} return 0 ;}

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.