我使用下面的代码将线段扩展到矩形的边界,如果矩形内的点有效,但是如果矩形边界有一个点,它会失败
static void extend(Rectangle bounds, ref PointF start, ref PointF end)
{
if (start != end) // this to avoid small changes in orientation
{
float slope = (end.Y - start.Y) / (end.X - start.X);
if (Math.Round(start.Y, 2) == Math.Round(end.Y, 2) || Math.Abs(slope) <= 0.01d) // 0.01 is offset to check if the slope is very small
{
start.X = bounds.X;
start.Y = start.Y;
end.X = bounds.X + bounds.Width;
end.Y = end.Y;
return;
}
if (Math.Round(start.X, 2) == Math.Round(end.X, 2) || Math.Abs(slope) <= 0.01d)
{
start.X = start.X;
start.Y = bounds.Y;
end.X = end.X;
end.Y = bounds.Y + bounds.Height;
return;
}
// based on (y - y1) / (x - x1) == (y2 - y1) / (x2 - x1)
// => (y - y1) * (x2 - x1) == (y2 - y1) * (x - x1)
// y_for_xmin = y1 + (y2 - y1) * (xmin - x1) / (x2 - x1)
float y_for_xmin = start.Y + ((end.Y - start.Y) * (bounds.X - start.X) / (end.X - start.X));
// y_for_xmax = y1 + (y2 - y1) * (xmax - x1) / (x2 - x1)
float y_for_xmax = start.Y + ((end.Y - start.Y) * (bounds.X + bounds.Width - start.X) / (end.X - start.X));
// x_for_ymin = x1 + (x2 - x1) * (ymin - y1) / (y2 - y1)
float x_for_ymin = start.X + ((end.X - start.X) * (bounds.Y - start.Y) / (end.Y - start.Y));
//x_for_ymax = x1 + (x2 - x1) * (ymax - y1) / (y2 - y1)
float x_for_ymax = start.X + ((end.X - start.X) * (bounds.Y + bounds.Height - start.Y) / (end.Y - start.Y));
if ((bounds.Y <= y_for_xmin) && (y_for_xmin <= bounds.Y + bounds.Height))
{
if ((bounds.X <= x_for_ymax) && (bounds.X <= bounds.X + bounds.Width))
{
start.X = bounds.X;
start.Y = y_for_xmin;
end.X = x_for_ymax;
end.Y = bounds.Y + bounds.Height;
return;
}
if ((bounds.X <= x_for_ymin && x_for_ymin <= bounds.X + bounds.Width))
{
start.X = bounds.X;
start.Y = y_for_xmin;
end.X = x_for_ymin;
end.Y = bounds.Y;
return;
}
}
if ((bounds.Y <= y_for_xmax) && (bounds.Y <= bounds.Y + bounds.Height))
{
if ((bounds.X <= x_for_ymin) && (x_for_ymin <= bounds.X + bounds.Width))
{
start.X = x_for_ymin;
start.Y = bounds.Y;
end.X = bounds.X + bounds.Width;
end.Y = y_for_xmax;
return;
}
if ((bounds.X <= x_for_ymax) && (x_for_ymax <= bounds.X + bounds.Width))
{
start.X = x_for_ymax;
start.Y = bounds.Y + bounds.Height;
end.X = bounds.X + bounds.Width;
end.Y = y_for_xmax;
return;
}
}
}
}
任何想法如何解决矩形的线点
的情况答案 0 :(得分:1)
static bool intersection(PointF a1, PointF a2, PointF b1, PointF b2, ref PointF ans)
{
float x = ((a1.X*a2.Y - a1.Y*a2.X)*(b1.X - b2.X) - (a1.X - a2.X)*(b1.X*b2.Y - b1.Y*b2.X)) / ((a1.X - a2.X)*(b1.Y - b2.Y) - (a1.Y - a2.Y)*(b1.X - b2.X));
float y = ((a1.X*a2.Y - a1.Y*a2.X)*(b1.Y - b2.Y) - (a1.Y - a2.Y)*(b1.X*b2.Y - b1.Y*b2.X)) / ((a1.X - a2.X)*(b1.Y - b2.Y) - (a1.Y - a2.Y)*(b1.X - b2.X));
if(x == float.NaN || x == float.PositiveInfinity || x == float.NegativeInfinity || y == float.NaN || y == float.PositiveInfinity || y == float.NegativeInfinity)
{ // the lines are equal or never intersect
return false;
}
ans.X = x;
ans.Y = y;
return true;
}
static void extend(Rectangle bounds, ref PointF start, ref PointF end)
{
List<PointF> ansFinal = new List<PointF>();
PointF ansLeft = new PointF();
bool hitLeft = intersection(start, end, new PointF(bounds.X, bounds.Y), new PointF(bounds.X, bounds.Y + bounds.Height), ansLeft);
if(hitLeft && (ansLeft.Y < bounds.Y || ansLeft.Y > bounds.Y + bounds.Height)) hitLeft = false;
if(hitLeft) ansFinal.Add(ansLeft);
PointF ansTop = new PointF();
bool hitTop = intersection(start, end, new PointF(bounds.X, bounds.Y), new PointF(bounds.X + bounds.Width, bounds.Y), ansTop);
if(hitTop && (ansTop.X < bounds.X || ansTop.X > bounds.X + bounds.Width)) hitTop = false;
if(hitTop) ansFinal.Add(ansTop);
PointF ansRight = new PointF();
bool hitRight = intersection(start, end, new PointF(bounds.X + bounds.Width, bounds.Y), new PointF(bounds.X + bounds.Width, bounds.Y + bounds.Height), ansRight);
if(hitRight && (ansRight.Y < bounds.Y || ansRight.Y > bounds.Y + bounds.Height)) hitRight = false;
if(hitRight) ansFinal.Add(ansRight);
PointF ansBottom = new PointF();
bool hitBottom = intersection(start, end, new PointF(bounds.X, bounds.Y + bounds.Height), new PointF(bounds.X + bounds.Height, bounds.Y + bounds.Height), ansBottom);
if(hitBottom && (ansBottom.X < bounds.X || ansBottom.X > bounds.X + bounds.Width)) hitBottom = false;
if(hitBottom) ansFinal.Add(ansBottom);
if(!hitLeft && !hitTop && !hitRight && !hitBottom)
{
throw new Exception("No interections");
}
/*
// IF YOU HAD LINQ
PointF[] ans = ansFinal.Distinct().ToArray();
if(ans.Length < 2)
{
throw new Exception("Corner case *wink*");
}
start.X = ans[0].X; start.Y = ans[0].Y;
end.X = ans[1].X; end.Y = ans[1].Y;
*/
// the following is sufficient to cull out corner to corner, one corner
for(int x=ansFinal.Count-1; x>=1; x--)
if(ansFinal[x] == ansFinal[x-1])
ansFinal.RemoveAt(x);
if(ansFinal.Count < 2)
{
throw new Exception("Corner case *wink*");
}
start.X = ansFinal[0].X; start.Y = ansFinal[0].Y;
end.X = ansFinal[1].X; end.Y = ansFinal[1].Y;
}
编辑我在浏览器中写了这个,所以可能会有一些语法错误......
概念是您使用与矩形每边的线对线交点进行测试。如果存在交叉点,则确保它在矩形边(线段)的范围内。