带限制的C#绘图

带限制的C#绘图,c#,drawing,C#,Drawing,我正在处理一个从DXF文件(来自autocad或任何其他绘图程序的图形文件)中获取信息的项目。我从中获取信息,它显示面板的边框。在这个面板中,我需要设置线,但当面板外有坐标的线时,我不允许绘制它们 下面你可以看到一张图片,也许它能让你看得更清楚一点 所以白线是砖块,它们需要胶合线(黄色),海蓝线是轮廓线。在这条线之外,不允许画胶线(黄线) 正如您在NR 4BA87砖上看到的,它在面板外绘制胶合线 我需要一些检查,如果点在我的轮廓/面板内,我可以画它,否则就不画了。我该怎么做 编辑: 我从一个列

我正在处理一个从DXF文件(来自autocad或任何其他绘图程序的图形文件)中获取信息的项目。我从中获取信息,它显示面板的边框。在这个面板中,我需要设置线,但当面板外有坐标的线时,我不允许绘制它们

下面你可以看到一张图片,也许它能让你看得更清楚一点

所以白线是砖块,它们需要胶合线(黄色),海蓝线是轮廓线。在这条线之外,不允许画胶线(黄线)

正如您在NR 4BA87砖上看到的,它在面板外绘制胶合线

我需要一些检查,如果
在我的轮廓/面板内,我可以画它,否则就不画了。我该怎么做

编辑:

我从一个列表中画出这些线,如果我能从我的列表中删除(或不添加)面板外的胶粘线,那将是非常棒的

我有一个列表,其中的点是轮廓点:

public List<PointF> ListContourPoints = new List<PointF>();

您已经获得了组成面板角落的所有
点的位置数据。所以你需要做的就是找出组成面板的矩形,然后对线条进行位置检查

创建矩形的示例函数如下所示,但请注意,该函数是在假设面板与提供的示例形状相同的情况下创建的,创建包含所有变化的矩形还需要一些逻辑:

private static Rectangle[] SplitPointsIntoRectangles(Point[] pa)
{
    pa = pa.OrderBy(p => p.X).ToArray();
    Point[] leftmost = pa.Select(p => p).Where(p => p.X == pa[0].X).ToArray();
    Point[] rightmost = pa.Select(p => p).Where(p => p.X == pa[pa.Length - 1].X).ToArray();

    pa = pa.OrderBy(p => p.Y).ToArray();
    Point[] topmost = pa.Select(p => p).Where(p => p.Y == pa[0].Y).ToArray();
    Point[] bottommost = pa.Select(p => p).Where(p => p.Y == pa[pa.Length - 1].Y).ToArray();

    List<Point> edges = new List<Point>();
    edges.AddRange(leftmost);
    edges.AddRange(rightmost);
    edges.AddRange(topmost);
    edges.AddRange(bottommost);

    Point middlePixel = pa.FirstOrDefault(p => !edges.Contains(p));

    Rectangle[] ra = new Rectangle[2];
    ra[0] = new Rectangle(leftmost[0].X, leftmost.Min(p => p.Y), rightmost[0].X - leftmost[0].X, bottommost[0].Y - leftmost[0].Y);
    ra[1] = new Rectangle(topmost.Min(p => p.X), topmost[0].Y, rightmost[0].X - middlePixel.X, middlePixel.Y - topmost[0].Y);

    return ra;
}
如果以下函数返回一个空矩形,则两个矩形不相交,否则相交。注意:如果矩形部分相交,此函数将返回非空矩形

Rectangle intersectionRect = Rectangle.Intersect(MainRect, glueLineRect);
然后,可以将其扩展到在面板中包含的所有矩形上进行测试,如果在所有矩形上都失败,则粘合线位于面板外部


我创建这个答案是为了让您开始使用,
SplitPointsIntoRectangles
方法需要通用化。此外,还需要创建循环,以测试粘合线是否位于面板内部。

是否使用Windows窗体?如果是这样,只需在进行任何绘制之前设置区域。(WPF图形有一种等效的方法。)但是需要绘制砖块,即使砖块在面板外,所以我不能阻止所有的绘制,所以只需在绘制需要剪裁的元素时设置剪裁区域,然后再恢复。这可能是一种选择,但我实际上需要从列表中删除它们,我还使用此列表将这些行设置回DXF文件中,很抱歉没有设置。我假设您知道面板边缘的位置?当我使用你的代码时,
RectangleF intersectionRect2=RectangleF.Intersect(a_ContourRects[1],glueLineRect)
返回一个矩形,其中所有内容都处于
0
状态。还是要谢谢你的帮助我现在能弄明白一些事情了myself@Bart如果它返回一个空矩形,则表示该矩形不存在intersect@Bart如果这有助于您自由投票和/或将其标记为答案,以便未来的访问者可以看到
private static Rectangle[] SplitPointsIntoRectangles(Point[] pa)
{
    pa = pa.OrderBy(p => p.X).ToArray();
    Point[] leftmost = pa.Select(p => p).Where(p => p.X == pa[0].X).ToArray();
    Point[] rightmost = pa.Select(p => p).Where(p => p.X == pa[pa.Length - 1].X).ToArray();

    pa = pa.OrderBy(p => p.Y).ToArray();
    Point[] topmost = pa.Select(p => p).Where(p => p.Y == pa[0].Y).ToArray();
    Point[] bottommost = pa.Select(p => p).Where(p => p.Y == pa[pa.Length - 1].Y).ToArray();

    List<Point> edges = new List<Point>();
    edges.AddRange(leftmost);
    edges.AddRange(rightmost);
    edges.AddRange(topmost);
    edges.AddRange(bottommost);

    Point middlePixel = pa.FirstOrDefault(p => !edges.Contains(p));

    Rectangle[] ra = new Rectangle[2];
    ra[0] = new Rectangle(leftmost[0].X, leftmost.Min(p => p.Y), rightmost[0].X - leftmost[0].X, bottommost[0].Y - leftmost[0].Y);
    ra[1] = new Rectangle(topmost.Min(p => p.X), topmost[0].Y, rightmost[0].X - middlePixel.X, middlePixel.Y - topmost[0].Y);

    return ra;
}
Rectangle glueLineRect = new Rectangle(glueLineStartPoint.X, glueLineStartPoint.Y, glueLineEndPosition.X - glueLineStartPoint.X, 1);
Rectangle intersectionRect = Rectangle.Intersect(MainRect, glueLineRect);