To find the intersection of two line segments ZZ

Source: Internet
Author: User
Tags dashed line

the "intersection of segments" is a very basic geometric calculation that will be used in many games.

I now learn to sell the recent learned some of the "line intersection" algorithm said, I hope to help you.
The content of this article is very elementary, mainly for the same as I beginners, so please the algorithm Teijin Pat AH Quack

Refer to the known Segment 1 (A, b) and Segment 2 (C,D), where a B c d is the endpoint, the segment intersection p. (parallel or collinear as disjoint)



===============================
algorithm one: to find the intersection of two line segments, and then determine whether the intersection is on two segments.

We can find the line intersection by the general equation of the straight line ax+by+c=0 (the ABC in the equation is the coefficient, not the endpoint mentioned above, but also the point oblique equation and the oblique-cut equation, here for the time being).
It then determines whether the intersection is on the segment based on the position of the intersection with the end of the segment. Formulas such as:



The implementation code is as follows:

  1. function Segmentsintr (A, B, C, D) {
  2. /** 1 solve the linear equations, and find the intersection of line segments. **/
  3. If the denominator is 0 parallel or collinear, does not intersect
  4. var denominator = (b.y-a.y) * (d.x-c.x)-(a.x-b.x) * (C.Y-D.Y);
  5. if (denominator==0) {
  6. return false;
  7. }
  8. Intersection coordinates of the line where the segment is located (x, y)
  9. var x = ((b.x-a.x) * (d.x-c.x) * (C.Y-A.Y)
  10. + (B.Y-A.Y) * (d.x-c.x) * a.x
  11. -(D.Y-C.Y) * (b.x-a.x) * c.x)/denominator;
  12. var y =-((B.Y-A.Y) * (D.Y-C.Y) * (c.x-a.x)
  13. + (b.x-a.x) * (D.Y-C.Y) * A.Y
  14. -(d.x-c.x) * (B.Y-A.Y) * c.y)/denominator;
  15. /** 2 Determine if the intersection is on two segments **/
  16. if (
  17. //intersection on line 1
  18. (x-a.x) * (x-b.x) <= 0 && (Y-A.Y) * (Y-B.Y) <= 0
  19. //And the intersection is also on line 2
  20. && (x-c.x) * (x-d.x) <= 0 && (Y-C.Y) * (Y-D.Y) <= 0
  21. ){
  22. //Return intersection P
  23. return {
  24. X:x,
  25. Y:y
  26. }
  27. }
  28. //Do not intersect otherwise
  29. return false
  30. }

                    the

algorithm is relatively clear and understandable, but its performance is not high. Since it is not sure whether the intersection is valid (on the line segment), it takes more time to calculate the intersection.  
If the intersection is found to be invalid, then the previous calculation will be wasted. And the whole computational process is complicated.  
So is there a way of thinking that we can first determine if there is a valid intersection, and then calculate it?  
Obviously the answer is yes. Then there are some of the following algorithms.  


=============================== 
algorithm two: To determine whether the two endpoints of each segment are on either side of the other, or to find the intersection of the lines where the two segments are located, otherwise they do not intersect.  

The first step is to determine whether two points are on either side of a segment, usually using a projection method:  ,

to find the normal vector of the line segment, then projecting the point onto the normal, and finally judging the relationship between the point and the segment according to the position of the projection. See  

 

Point A and point B are projected on the CD normals of the segment, and we also make a projection of the segment CD on its own normal (select point C or one of Point D).  
is mainly used for reference.  
The midpoint a projection and point B projection are on both sides of the point C projection, indicating that the end of the segment AB is on both sides of the segment CD.  

Similarly, determine if the CD is on both sides of the line ab.  

Ask for normals, projection what sounds complicated, In fact, it was really complicated for me, and a few months ago I would not have forgotten the geometry of my Study: ' () '  
but fortunately, learning and implementation is not complicated, there are formulas to follow:  


to find the normals of line AB:  

    1. var nx=b.y-a.y,
    2. ny=a.x-b.x;
    3. var normalline = {x:nx, y:ny};



Note: The geometric meaning of normalline.x and normalline.y represents the direction of the normals, not the coordinates.


Find the projection position of C on the normals:

    1. var dist= normalline.x*c.x + normalline.y*c.y;



Note: the "projection position" here is a scalar that represents the distance to the normal origin, not the coordinates of the projection point.
It is usually enough to know the distance.

When we put a projection (Dista), point B projection (DISTB), point C projection (DISTC), we can easily determine the relative position according to their size.

Two lines collinear when DISTA==DISTB==DISTC
Two line segments parallel when DISTA==DISTB!=DISTC
When the Dista and Distb are on the same side of the DISTC, the two segments do not intersect.
Dista and Distb on the DISTC side, whether the two line segments intersect need to judge the relationship between Point C D and Line AB.

The preceding steps simply implement "judging if the segments intersect", and when the result is true, we also need to seek further intersections.
After the process of finding the intersection, let's look at the complete implementation of the algorithm:

  1. function Segmentsintr (A, B, C, D) {
  2. //Line AB normal N1
  3. var nx1 = (b.y-a.y), NY1 = (a.x-b.x);
  4. //Segment CD normal N2
  5. var nx2 = (d.y-c.y), Ny2 = (c.x-d.x);
  6. //Two normals do cross-multiply, if the result is 0, the segment AB and segment CD are parallel or collinear, disjoint
  7. var denominator = nx1*ny2-ny1*nx2;
  8. if (denominator==0) {
  9. return false;
  10. }
  11. //projection on the normal N2
  12. var distc_n2=nx2 * c.x + ny2 * C.Y;
  13. var dista_n2=nx2 * a.x + ny2 * A.Y-DISTC_N2;
  14. var distb_n2=nx2 * b.x + ny2 * B.Y-DISTC_N2;
  15. //Point a projection and point B projection on the same side of the point C projection (in the case of points on the segment, this example is treated as disjoint);
  16. if (dista_n2*distb_n2>=0) {
  17. return false;
  18. }
  19. //  
  20. //Judgment point C point D and Line ab relationship, principle ibid.
  21. //  
  22. //projection on the normal N1
  23. var dista_n1=nx1 * a.x + NY1 * A.Y;
  24. var distc_n1=nx1 * c.x + NY1 * C.Y-DISTA_N1;
  25. var distd_n1=nx1 * d.x + NY1 * D.Y-DISTA_N1;
  26. if (distc_n1*distd_n1>=0) {
  27. return false;
  28. }
  29. //Calculate intersection coordinates
  30. var fraction= dista_n2/denominator;
  31. var dx= fraction * NY1,
  32. dy=-fraction * NX1;
  33. return {x:a.x + dx, y:a.y + dy};
  34. }

The method used by the



to find the intersection coordinates is a bit strange, a feeling that is not in the mind.  
In fact, it is similar to the algorithm inside the algorithm, but the inside of a lot of computing items have been calculated in advance.  
in other words, In the algorithm two, the part of the intersection coordinate is also used in the straight line of the linear equations.  

Now a simple rough and very unscientific comparison of algorithm one and algorithm two:  
1 in the best case, the complexity of the two algorithms is the same  
2 worst case , the computation of algorithm one and algorithm two is almost  
3 But the algorithm II provides more "early termination conditions", so on average, the algorithm two should be better.  

Actually, the actual test is true.  

The previous two algorithms are basically more common and can handle most situations. But there is actually a better algorithm.  
This is also I recently learned the new (I now learn to sell, we do not mind ah ...)  

=============================== 
algorithm Three: Determine whether each segment of the two endpoints are on the other side of the line, is to find out the line of two segments where the intersection point, Otherwise, it does not intersect.  

(eh?) How does it feel like the algorithm two? Don't doubt it's the same ...  
the so-called algorithm three, in fact, is only a refinement of the algorithm two, the improvement of the place is mainly:  
does not judge the position of points and segments by the normal projection, but is judged by the triangular area of points and segments.  

First, review the Triangle area formula: A known triangle three points a (x, y) b (x, Y) c (x, y), the Triangle area is:  

    1. var triarea= ((a.x-c.x) * (B.Y-C.Y)-(A.Y-C.Y) * (b.x-c.x))/2;



The above formula is not difficult to understand because the two vector forks multiply by = = Two vectors of the parallelogram (with two vectors as the neighboring edge).
And because the vector is a direction, so the area is also a direction, usually we have to counter-clockwise, clockwise is negative.

The key points of the improved algorithm are:
If the Triangle area consisting of line AB and point C is different from the positive and negative sign of the triangle area formed by the segment AB and the Triangle area of Point D,
Then point C and Point D are on both sides of the line AB. As shown in the following:



The triangle shown in the dashed line, the winding direction (the three-side definition order) is different, so the positive and negative signs of the area are different.


Here's a look at the code first:
Since we just have to judge the symbol, we don't need to divide the next 2 by the Triangle area formula.

  1. function Segmentsintr (A, B, C, D) {
  2. //twice times the triangle ABC area
  3. var area_abc = (a.x-c.x) * (B.Y-C.Y)-(A.Y-C.Y) * (b.x-c.x);
  4. twice times the area of the Triangle Abd
  5. var area_abd = (a.x-d.x) * (B.Y-D.Y)-(A.Y-D.Y) * (b.x-d.x);
  6. //Area symbol same as two points on the same side of the line, disjoint (in the case of points on the line segment, this example is treated as disjoint);
  7. if (area_abc*area_abd>=0) {
  8. return false;
  9. }
  10. //twice times the area of the triangular CDA
  11. var area_cda = (c.x-a.x) * (D.Y-A.Y)-(C.Y-A.Y) * (d.x-a.x);
  12. twice times the area of the triangular CDB
  13. //Note: There is a small optimization here. It is not necessary to use the formula to calculate the area, but to add and subtract from the known three areas.
  14. var area_cdb = area_cda + area_abc-area_abd;
  15. if (AREA_CDA * area_cdb >= 0) {
  16. return false;
  17. }
  18. //Calculate intersection coordinates
  19. var t = area_cda/(AREA_ABD-AREA_ABC);
  20. var dx= t* (b.x-a.x),
  21. dy= t* (B.Y-A.Y);
  22. return {x:a.x + dx, y:a.y + dy};
  23. }




Finally, the part of intersection coordinates and the algorithm two are the same.


Algorithm three on the basis of the second algorithm, greatly simplifying the calculation steps, the code is also more streamlined. It can be said that there are three kinds of algorithms, the best. The actual test results are also true.

Of course, it's important to be honest, in JavaScript, the time complexity of the three algorithms is almost the same (especially under the V8 engine) for normal computing.
My test case is also a perverted million-level segment intersection test to pull the gap between the three algorithms.

But in terms of excellence and learning attitude, the pursuit of a better algorithm, always has its positive significance.


All right, no more nagging, let's get here.
Now learn to sell things, inevitably have errors, but also please everyone treatise. Thank you first.

Article Source: http://fins.iteye.com/blog/1522259

To find the intersection of two line segments ZZ

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.