[英]How do I fix this JS function so it doesn't return false positives when checking if two line segments intersect?
I'm working on a mapping project (with the Google Maps SDK).我正在开发一个地图项目(使用 Google Maps SDK)。 Before drawing a line segment on the map I check to see if it intersects with any existing lines.
在地图上绘制线段之前,我会检查它是否与任何现有线相交。
I'm experiencing a situation where the code below is reporting the line segments are intersecting, but they're not.我遇到的情况是下面的代码报告线段相交,但事实并非如此。 Although, they do share an endpoint.
虽然,它们确实共享一个端点。
Perhaps this intersect()
function isn't meant to be used with Geo coordinates and I need a different function.也许这个
intersect()
函数不适合与地理坐标一起使用,我需要一个不同的函数。 I found this intersects() function here: Test if two lines intersect - JavaScript function我在这里找到了这个 intersects() 函数: Test if two lines intersect - JavaScript function
In this project I have about 150 lines and about 10-15 of them are detected as intersecting, and they're not (although they share a common endpoint with the line that is reported as intersecting).在这个项目中,我有大约 150 条线,其中大约 10-15 条被检测为相交,而它们不是(尽管它们与被报告为相交的线共享一个公共端点)。
Below is a screenshot of how the lines are drawn on Google Maps for a better visual.下面是如何在谷歌地图上绘制线条以获得更好的视觉效果的屏幕截图。 The red line is the second one passed to the
intersects()
function and is detected as intersecting the first line.红线是传递给
intersects()
函数的第二条线,并被检测为与第一条线相交。 Interestingly, if I reverse the lines passed to intersects()
it does not find them to be intersecting.有趣的是,如果我反转传递给
intersects()
的线,它不会发现它们相交。
let crosses = intersects( 39.018223, -76.75899, 39.018387, -76.758773, 39.018387, -76.758773, 39.019813, -76.757388, ); console.log('Intersects:', crosses); // returns true if the line from (a,b)->(c,d) intersects with (p,q)->(r,s) function intersects(a,b,c,d,p,q,r,s) { var det, gamma, lambda; det = (c - a) * (s - q) - (r - p) * (d - b); if (det === 0) { console.log('det is zero'); return false; } else { lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / det; gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / det; return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1); } };
You need to account for numerical precision.您需要考虑数值精度。 As mentioned in a comment of the post, you could test for endpoints but it would add a lot more computation.
正如帖子的评论中提到的,您可以测试端点,但它会增加更多的计算量。 Another method is to account for precision in the final test by adding an epsilon to the comparison:
另一种方法是通过在比较中添加一个 epsilon 来计算最终测试中的精度:
let epsilon = 1e-6;
return (epsilon < lambda && lambda < 1-epsilon) &&
(epsilon < gamma && gamma < 1-epsilon);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.