我需要获得矩形和直线的交点。 在矩形(矩形的中心)内有B点,在外面有A点。我需要在一个矩形边框上找到C点。 我也得到矩形的宽度和高度。
所有这些都是 WPF 应用程序,所以如果任何功能构建我会非常高兴。
答案 0 :(得分:3)
这是基本的数学求解线 - 线交叉,检查tutorial
的topcoderLine-Line Intersection最多的一个 您将在几何中找到的常见任务 问题是线路交叉。尽管 这是如此常见,很多事实 编码员仍然遇到麻烦。 第一个问题是,形式是什么 我们给出了线条和形式 我们会喜欢他们吗?理想情况下,每个 我们的线路将以形式出现 Ax + By = C,其中A,B和C是 定义该行的数字。 但是,我们很少有线 这种格式,但我们可以轻松 从两个生成这样的方程式 点。说我们有两个不同的 点,(x1,y1)和(x2,y2),和 想要找到A,B和C. 上面的等式。我们可以这样做 设置A = y2-y1 B = x1-x2 C = A * X1 + B * Y1
答案 1 :(得分:3)
在不知道WPF或其任何功能的情况下,我就是这样做的:
答案 2 :(得分:2)
使用ax和ay坐标为A和bx,坐标为B,并假设宽度为w且高度为h的矩形的中心为{0,0},则以下情况应该有效
IntersectionRectangleLine[{ax_, ay_}, {bx_, by_}, h_, w_] :=
Module[{\[Mu]r, \[Mu]l, \[Mu]t, \[Mu]b},
{\[Mu]r, \[Mu]l, \[Mu]t, \[Mu]b} = {-((-2 ay bx + 2 ax by - ax w +
bx w)/((ay - by) h)), -((-2 ay bx + 2 ax by + ax w -
bx w)/((ay - by) h)), -((
2 ay bx - 2 ax by - ay h + by h)/((ax - bx) w)), -((
2 ay bx - 2 ax by + ay h - by h)/((ax - bx) w))};
Which[
-1 <= \[Mu]r <= 1, {0, w/2} + \[Mu]r {h/2, 0},
-1 <= \[Mu]l <= 1, {0, -w/2} + \[Mu]l {h/2, 0},
-1 <= \[Mu]t <= 1, {h/2, 0} + \[Mu]t {0, w/2},
-1 <= \[Mu]b <= 1, {-h/2, 0} + \[Mu]b {0, w/2}
]
]
这基于构成三角形的四条线的交叉点的解决方案
In[114]:= Solve[Thread[\[Lambda] ({bx, by} - {ax, ay}) + {ax, ay} == {0, w/2} + \[Mu] {h/2, 0}], \[Mu], {\[Lambda]}]
Out[114]= {{\[Mu] -> -((-2 ay bx + 2 ax by - ax w + bx w)/((ay - by) h))}}
(这里以第一行为例)。
对于Evgeny来说,这就是它在我的屏幕上的样子。相当多可读性。
答案 3 :(得分:2)
C#,WPF的解决方案:
/// <summary>
/// Get Intersection point
/// </summary>
/// <param name="a1">a1 is line1 start</param>
/// <param name="a2">a2 is line1 end</param>
/// <param name="b1">b1 is line2 start</param>
/// <param name="b2">b2 is line2 end</param>
/// <returns></returns>
public static Vector? Intersects(Vector a1, Vector a2, Vector b1, Vector b2)
{
Vector b = a2 - a1;
Vector d = b2 - b1;
var bDotDPerp = b.X * d.Y - b.Y * d.X;
// if b dot d == 0, it means the lines are parallel so have infinite intersection points
if (bDotDPerp == 0)
return null;
Vector c = b1 - a1;
var t = (c.X * d.Y - c.Y * d.X) / bDotDPerp;
if (t < 0 || t > 1)
{
return null;
}
var u = (c.X * b.Y - c.Y * b.X) / bDotDPerp;
if (u < 0 || u > 1)
{
return null;
}
return a1 + t * b;
}
修改强> 找到Link来回答上述问题的答案。
答案 4 :(得分:1)
如果你知道矩形的尺寸,我假设你做“
rX
矩形宽度rY
矩形高度Ay
A的Y位置Ax
A的X位置By
B的Y位置Bx
B的X位置Cy
C的Y位置Cx
C的X位置 Cy = By + rY / 2
C位置位于矩形的顶部,因此它是By位置+ rY位置的一半
然后我们只需计算Cx
位置。
Cx = (Bx + ((Ax - Bx) / (Ay - By)) * Cy)
您可以使用Point
答案 5 :(得分:1)
希望它 100% 有效
我也遇到了同样的问题。所以经过两天的努力,我终于创建了这个方法,
主方法,
// Tuple<entryPoint, exitPoint, lineStatus>
private Tuple<Point, Point, Line> GetIntersectionPoint(Point a, Point b, Rectangle rect)
{
if (IsWithinRectangle(a, rect) && IsWithinRectangle(b, rect))
{
// Can't set null to Point that's why I am returning just empty object
return new Tuple<Point, Point, Line>(new Point(), new Point(), Line.InsideTheRectangle);
}
else if (!IsWithinRectangle(a, rect) && !IsWithinRectangle(b, rect))
{
if (!LineIntersectsRectangle(a, b, rect))
{
// Can't set null to Point that's why I am returning just empty object
return new Tuple<Point, Point, Line>(new Point(), new Point(), Line.NoIntersection);
}
Point entryPoint = new Point();
Point exitPoint = new Point();
bool entryPointFound = false;
// Top Line of Chart Area
if (LineIntersectsLine(a, b, new Point(0, 0), new Point(rect.Width, 0)))
{
entryPoint = GetPointFromYValue(a, b, 0);
entryPointFound = true;
}
// Right Line of Chart Area
if (LineIntersectsLine(a, b, new Point(rect.Width, 0), new Point(rect.Width, rect.Height)))
{
if (entryPointFound)
exitPoint = GetPointFromXValue(a, b, rect.Width);
else
{
entryPoint = GetPointFromXValue(a, b, rect.Width);
entryPointFound = true;
}
}
// Bottom Line of Chart
if (LineIntersectsLine(a, b, new Point(0, rect.Height), new Point(rect.Width, rect.Height)))
{
if (entryPointFound)
exitPoint = GetPointFromYValue(a, b, rect.Height);
else
{
entryPoint = GetPointFromYValue(a, b, rect.Height);
}
}
// Left Line of Chart
if (LineIntersectsLine(a, b, new Point(0, 0), new Point(0, rect.Height)))
{
exitPoint = GetPointFromXValue(a, b, 0);
}
return new Tuple<Point, Point, Line>(entryPoint, exitPoint, Line.EntryExit);
}
else
{
Point entryPoint = GetEntryIntersectionPoint(rect, a, b);
return new Tuple<Point, Point, Line>(entryPoint, new Point(), Line.Entry);
}
}
支持方法,
enum Line
{
// Inside the Rectangle so No Intersection Point(Both Entry Point and Exit Point will be Null)
InsideTheRectangle,
// One Point Inside the Rectangle another Point Outside the Rectangle. So it has only Entry Point
Entry,
// Both Point Outside the Rectangle but Intersecting. So It has both Entry and Exit Point
EntryExit,
// Both Point Outside the Rectangle and not Intersecting. So doesn't has both Entry and Exit Point
NoIntersection
}
private Point GetEntryIntersectionPoint(Rectangle rect, Point a, Point b)
{
// For top line of the rectangle
if (LineIntersectsLine(new Point(0, 0), new Point(rect.Width, 0), a, b))
{
return GetPointFromYValue(a, b, 0);
}
// For right side line of the rectangle
else if (LineIntersectsLine(new Point(rect.Width, 0), new Point(rect.Width, rect.Height), a, b))
{
return GetPointFromXValue(a, b, rect.Width);
}
// For bottom line of the rectangle
else if (LineIntersectsLine(new Point(0, rect.Height), new Point(rect.Width, rect.Height), a, b))
{
return GetPointFromYValue(a, b, rect.Height);
}
// For left side line of the rectangle
else
{
return GetPointFromXValue(a, b, 0);
}
}
public bool LineIntersectsRectangle(Point p1, Point p2, Rectangle r)
{
return LineIntersectsLine(p1, p2, new Point(r.X, r.Y), new Point(r.X + r.Width, r.Y)) ||
LineIntersectsLine(p1, p2, new Point(r.X + r.Width, r.Y), new Point(r.X + r.Width, r.Y + r.Height)) ||
LineIntersectsLine(p1, p2, new Point(r.X + r.Width, r.Y + r.Height), new Point(r.X, r.Y + r.Height)) ||
LineIntersectsLine(p1, p2, new Point(r.X, r.Y + r.Height), new Point(r.X, r.Y)) ||
(r.Contains(p1) && r.Contains(p2));
}
private bool LineIntersectsLine(Point l1p1, Point l1p2, Point l2p1, Point l2p2)
{
float q = (l1p1.Y - l2p1.Y) * (l2p2.X - l2p1.X) - (l1p1.X - l2p1.X) * (l2p2.Y - l2p1.Y);
float d = (l1p2.X - l1p1.X) * (l2p2.Y - l2p1.Y) - (l1p2.Y - l1p1.Y) * (l2p2.X - l2p1.X);
if (d == 0)
{
return false;
}
float r = q / d;
q = (l1p1.Y - l2p1.Y) * (l1p2.X - l1p1.X) - (l1p1.X - l2p1.X) * (l1p2.Y - l1p1.Y);
float s = q / d;
if (r < 0 || r > 1 || s < 0 || s > 1)
{
return false;
}
return true;
}
// For Large values, processing with integer is not working properly
// So I here I am dealing only with double for high accuracy
private Point GetPointFromYValue(Point a, Point b, double y)
{
double x1 = a.X, x2 = b.X, y1 = a.Y, y2 = b.Y;
double x = (((y - y1) * (x2 - x1)) / (y2 - y1)) + x1;
return new Point((int)x, (int)y);
}
// For Large values, processing with integer is not working properly
// So here I am dealing only with double for high accuracy
private Point GetPointFromXValue(Point a, Point b, double x)
{
double x1 = a.X, x2 = b.X, y1 = a.Y, y2 = b.Y;
double y = (((x - x1) * (y2 - y1)) / (x2 - x1)) + y1;
return new Point((int)x, (int)y);
}
// rect.Contains(point) is not working properly in some cases.
// So here I created my own method
private bool IsWithinRectangle(Point a, Rectangle rect)
{
return a.X >= rect.X && a.X <= rect.X + rect.Width && a.Y >= rect.Y && a.Y <= rect.Y + rect.Height;
}