- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这个问题是关于:
但是请注意,一个有趣的子问题在大多数解决方案中都被完全掩盖了,即使存在三个子情况,它们也只是为重合情况返回 null:
例如,我们可以像这样设计一个 C# 函数:
public static PointF[] Intersection(PointF a1, PointF a2, PointF b1, PointF b2)
其中 (a1,a2) 是一条线段,(b1,b2) 是另一条线段。
此函数需要涵盖大多数实现或解释所掩盖的所有奇怪情况。为了解决重合线的奇怪问题,该函数可以返回一个 PointF 数组:
最佳答案
// port of this JavaScript code with some changes:
// http://www.kevlindev.com/gui/math/intersection/Intersection.js
// found here:
// http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect/563240#563240
public class Intersector
{
static double MyEpsilon = 0.00001;
private static float[] OverlapIntervals(float ub1, float ub2)
{
float l = Math.Min(ub1, ub2);
float r = Math.Max(ub1, ub2);
float A = Math.Max(0, l);
float B = Math.Min(1, r);
if (A > B) // no intersection
return new float[] { };
else if (A == B)
return new float[] { A };
else // if (A < B)
return new float[] { A, B };
}
// IMPORTANT: a1 and a2 cannot be the same, e.g. a1--a2 is a true segment, not a point
// b1/b2 may be the same (b1--b2 is a point)
private static PointF[] OneD_Intersection(PointF a1, PointF a2, PointF b1, PointF b2)
{
//float ua1 = 0.0f; // by definition
//float ua2 = 1.0f; // by definition
float ub1, ub2;
float denomx = a2.X - a1.X;
float denomy = a2.Y - a1.Y;
if (Math.Abs(denomx) > Math.Abs(denomy))
{
ub1 = (b1.X - a1.X) / denomx;
ub2 = (b2.X - a1.X) / denomx;
}
else
{
ub1 = (b1.Y - a1.Y) / denomy;
ub2 = (b2.Y - a1.Y) / denomy;
}
List<PointF> ret = new List<PointF>();
float[] interval = OverlapIntervals(ub1, ub2);
foreach (float f in interval)
{
float x = a2.X * f + a1.X * (1.0f - f);
float y = a2.Y * f + a1.Y * (1.0f - f);
PointF p = new PointF(x, y);
ret.Add(p);
}
return ret.ToArray();
}
private static bool PointOnLine(PointF p, PointF a1, PointF a2)
{
float dummyU = 0.0f;
double d = DistFromSeg(p, a1, a2, MyEpsilon, ref dummyU);
return d < MyEpsilon;
}
private static double DistFromSeg(PointF p, PointF q0, PointF q1, double radius, ref float u)
{
// formula here:
//http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
// where x0,y0 = p
// x1,y1 = q0
// x2,y2 = q1
double dx21 = q1.X - q0.X;
double dy21 = q1.Y - q0.Y;
double dx10 = q0.X - p.X;
double dy10 = q0.Y - p.Y;
double segLength = Math.Sqrt(dx21 * dx21 + dy21 * dy21);
if (segLength < MyEpsilon)
throw new Exception("Expected line segment, not point.");
double num = Math.Abs(dx21 * dy10 - dx10 * dy21);
double d = num / segLength;
return d;
}
// this is the general case. Really really general
public static PointF[] Intersection(PointF a1, PointF a2, PointF b1, PointF b2)
{
if (a1.Equals(a2) && b1.Equals(b2))
{
// both "segments" are points, return either point
if (a1.Equals(b1))
return new PointF[] { a1 };
else // both "segments" are different points, return empty set
return new PointF[] { };
}
else if (b1.Equals(b2)) // b is a point, a is a segment
{
if (PointOnLine(b1, a1, a2))
return new PointF[] { b1 };
else
return new PointF[] { };
}
else if (a1.Equals(a2)) // a is a point, b is a segment
{
if (PointOnLine(a1, b1, b2))
return new PointF[] { a1 };
else
return new PointF[] { };
}
// at this point we know both a and b are actual segments
float ua_t = (b2.X - b1.X) * (a1.Y - b1.Y) - (b2.Y - b1.Y) * (a1.X - b1.X);
float ub_t = (a2.X - a1.X) * (a1.Y - b1.Y) - (a2.Y - a1.Y) * (a1.X - b1.X);
float u_b = (b2.Y - b1.Y) * (a2.X - a1.X) - (b2.X - b1.X) * (a2.Y - a1.Y);
// Infinite lines intersect somewhere
if (!(-MyEpsilon < u_b && u_b < MyEpsilon)) // e.g. u_b != 0.0
{
float ua = ua_t / u_b;
float ub = ub_t / u_b;
if (0.0f <= ua && ua <= 1.0f && 0.0f <= ub && ub <= 1.0f)
{
// Intersection
return new PointF[] {
new PointF(a1.X + ua * (a2.X - a1.X),
a1.Y + ua * (a2.Y - a1.Y)) };
}
else
{
// No Intersection
return new PointF[] { };
}
}
else // lines (not just segments) are parallel or the same line
{
// Coincident
// find the common overlapping section of the lines
// first find the distance (squared) from one point (a1) to each point
if ((-MyEpsilon < ua_t && ua_t < MyEpsilon)
|| (-MyEpsilon < ub_t && ub_t < MyEpsilon))
{
if (a1.Equals(a2)) // danger!
return OneD_Intersection(b1, b2, a1, a2);
else // safe
return OneD_Intersection(a1, a2, b1, b2);
}
else
{
// Parallel
return new PointF[] { };
}
}
}
}
测试代码如下:
public class IntersectTest
{
public static void PrintPoints(PointF[] pf)
{
if (pf == null || pf.Length < 1)
System.Console.WriteLine("Doesn't intersect");
else if (pf.Length == 1)
{
System.Console.WriteLine(pf[0]);
}
else if (pf.Length == 2)
{
System.Console.WriteLine(pf[0] + " -- " + pf[1]);
}
}
public static void TestIntersect(PointF a1, PointF a2, PointF b1, PointF b2)
{
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("Does " + a1 + " -- " + a2);
System.Console.WriteLine("intersect " + b1 + " -- " + b2 + " and if so, where?");
System.Console.WriteLine("");
PointF[] result = Intersect.Intersection(a1, a2, b1, b2);
PrintPoints(result);
}
public static void Main()
{
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("line segments intersect");
TestIntersect(new PointF(0, 0),
new PointF(100, 100),
new PointF(100, 0),
new PointF(0, 100));
TestIntersect(new PointF(5, 17),
new PointF(100, 100),
new PointF(100, 29),
new PointF(8, 100));
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("");
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("just touching points and lines cross");
TestIntersect(new PointF(0, 0),
new PointF(25, 25),
new PointF(25, 25),
new PointF(100, 75));
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("");
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("parallel");
TestIntersect(new PointF(0, 0),
new PointF(0, 100),
new PointF(100, 0),
new PointF(100, 100));
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("");
System.Console.WriteLine("----");
System.Console.WriteLine("lines cross but segments don't intersect");
TestIntersect(new PointF(50, 50),
new PointF(100, 100),
new PointF(0, 25),
new PointF(25, 0));
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("");
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("coincident but do not overlap!");
TestIntersect(new PointF(0, 0),
new PointF(25, 25),
new PointF(75, 75),
new PointF(100, 100));
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("");
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("touching points and coincident!");
TestIntersect(new PointF(0, 0),
new PointF(25, 25),
new PointF(25, 25),
new PointF(100, 100));
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("");
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("overlap/coincident");
TestIntersect(new PointF(0, 0),
new PointF(75, 75),
new PointF(25, 25),
new PointF(100, 100));
TestIntersect(new PointF(0, 0),
new PointF(100, 100),
new PointF(0, 0),
new PointF(100, 100));
System.Console.WriteLine("----------------------------------------------------------");
System.Console.WriteLine("");
while (!System.Console.KeyAvailable) { }
}
}
这是输出:
----------------------------------------------------------line segments intersect----------------------------------------------------------Does {X=0, Y=0} -- {X=100, Y=100}intersect {X=100, Y=0} -- {X=0, Y=100} and if so, where?{X=50, Y=50}----------------------------------------------------------Does {X=5, Y=17} -- {X=100, Y=100}intersect {X=100, Y=29} -- {X=8, Y=100} and if so, where?{X=56.85001, Y=62.30054}--------------------------------------------------------------------------------------------------------------------just touching points and lines cross----------------------------------------------------------Does {X=0, Y=0} -- {X=25, Y=25}intersect {X=25, Y=25} -- {X=100, Y=75} and if so, where?{X=25, Y=25}--------------------------------------------------------------------------------------------------------------------parallel----------------------------------------------------------Does {X=0, Y=0} -- {X=0, Y=100}intersect {X=100, Y=0} -- {X=100, Y=100} and if so, where?Doesn't intersect--------------------------------------------------------------lines cross but segments don't intersect----------------------------------------------------------Does {X=50, Y=50} -- {X=100, Y=100}intersect {X=0, Y=25} -- {X=25, Y=0} and if so, where?Doesn't intersect--------------------------------------------------------------------------------------------------------------------coincident but do not overlap!----------------------------------------------------------Does {X=0, Y=0} -- {X=25, Y=25}intersect {X=75, Y=75} -- {X=100, Y=100} and if so, where?Doesn't intersect--------------------------------------------------------------------------------------------------------------------touching points and coincident!----------------------------------------------------------Does {X=0, Y=0} -- {X=25, Y=25}intersect {X=25, Y=25} -- {X=100, Y=100} and if so, where?{X=25, Y=25}--------------------------------------------------------------------------------------------------------------------overlap/coincident----------------------------------------------------------Does {X=0, Y=0} -- {X=75, Y=75}intersect {X=25, Y=25} -- {X=100, Y=100} and if so, where?{X=25, Y=25} -- {X=75, Y=75}----------------------------------------------------------Does {X=0, Y=0} -- {X=100, Y=100}intersect {X=0, Y=0} -- {X=100, Y=100} and if so, where?{X=0, Y=0} -- {X=100, Y=100}----------------------------------------------------------
关于c# - 检测两条重合线段的重合子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2255842/
有没有办法将多个线段视为 1 条线? IE:我将鼠标悬停在其中一个上,两者都会突出显示,并且切换图例中的可见性将隐藏这两个部分。 http://jsfiddle.net/rayholland/HSvB
有没有办法将多条线段视为一条线? IE:我将鼠标悬停在一个上,两个都突出显示,切换图例中的可见性将隐藏两个部分。 http://jsfiddle.net/rayholland/HSvBj/2/ ser
我正在尝试解决有关使用箭头键绘制线条的练习。当按下任一箭头键时,该线从中心开始向东、西、北或南绘制。该代码仅在东或西方向有效,而在北或南方向无效,这是我的问题!! 有人可以给我关于这件事的想法吗?谢谢
给定每条线的起点和终点的 XYZ 坐标,如何确定两条 3D 线段是否相交?如果它们确实相交,在什么 XYZ 位置? 我只能找到 2D 的答案:How do you detect where two l
给定每条线的起点和终点的 XYZ 坐标,如何确定两条 3D 线段是否相交?如果它们确实相交,在什么 XYZ 位置? 我只能找到 2D 的答案:How do you detect where two l
我正在使用适用于 ios 的 google map sdk 来提供当前用户位置和结束位置之间的方向。到目前为止,我已经使用下面的代码在当前用户位置和结束位置之间绘制了一条 GMSPolyline,并且
我是 Qt 的新手,我想使用 Qt 使用 CGAL 制作交互式几何程序。我希望用户使用鼠标输入点、线段,然后按下按钮让 CGAL 算法处理输入。 我的环境是 CGAL 4.5、Qt 5.6 和 QtC
我有两条线段:X1,Y1,Z1 - X2,Y2,Z2 和 X3,Y3,Z3 - X4,Y4,Z4 我试图找到两个线段之间的最短距离。 几个小时以来,我一直在寻找解决方案,但所有这些解决方案似乎都适用于
我正在尝试在 WPF 中创建铁路轨道和带有边界和标签的街道等效果。如何向线段添加边框和沿线段的标签?我试过 Border 类,但它创建了一个矩形边框。 对于标签,我尝试了 Text on a path
我正在做一个小项目来显示基于路线段重叠的路线效率低下。 例如,我在这里放了一个 JSFIDDLE,显示 D 和 E 之间有一条粉红色和蓝色的线重叠。我如何确定这段路在它们的路线上有重叠? 路线将由用户
我想绘制三组数据。具体来说,我想显示单个数据点,包括三组的均值。这是我到目前为止所拥有的: library(ggplot2) df <- data.frame(group=rep(c("A", "B"
我想绘制三组数据。具体来说,我想显示单个数据点,包括三组的均值。这是我到目前为止所拥有的: library(ggplot2) df <- data.frame(group=rep(c("A", "B"
<line> 元素可以用来画线段 SVG 线段 <line> <line> 元素可以用来画线段 线段的起始坐标可以用 x1 和 y1 来定义 线段的终点坐标可
我正在我的游戏中编写 C++ 碰撞检测程序,并试图提出一种算法:我有一个由两个中心点(C1、C2)、长度和半径定义的胶囊。然后我有一条用两点(R1,R2)定义的射线。我已经知道它们相交了。我只需要找到
我正在创建一个包含多变量数据的 PCA 双图。 有没有办法在 ggbiplot 中指定线段的颜色/透明度/位置?此命令的所有参数均未提供此选项。 我知道 ggbiplot 是基于 ggplot - 它
最近学了下 python opencv,分享下使用 opencv 在图片上绘制常用图形的方法。 案例中实现了在图片中添加线段、圆形、矩形、椭圆形以及添加文字的方法,使用 opencv2 实现的
我在应用 rgl 3d 绘图包时遇到了一些问题。 我正在尝试绘制一些线段。我的数据被安排在一个名为“标记”的数据框中,它有六列,一列代表起始 x、y 和 z 值,一列代表结束 x、y 和 z 值。 s
我必须使用 matplotlib 库绘制多条“曲线”,每条曲线由水平线段(甚至点)组成。 我通过 NaNs 分隔片段达到了这个目标。这是我的示例(工作)代码: from pylab import ar
我是一名优秀的程序员,十分优秀!