使用 PointCollection C# WPF 透支时在 canvas 上扩展多段线

Polylines extended on canvas while overdrawing with use of PointCollection C# WPF

我正在创建 autocad 插件,它从现有几何体中获取点,将其传递给另一个 windows 并在 canvas 上创建与折线具有相同几何体的对象。 Autocad对象是多段线所以有些点(顶点)必须透支。

我从 autocad 收集点、顶点长度并将其转换为 canvas 上真实坐标中的中心对象。然后当我画它时,我得到这个:

我收集的点是正确的,它们是相似的。 canvas 上的绘制代码在这里:

 private void drawOnCanvas(List<Point> points)
    {
        // Create a black Brush
        SolidColorBrush blackBrush = new SolidColorBrush();
        blackBrush.Color = Colors.Black;

        // Create a polyline
        Polyline poly = new Polyline();
        poly.Stroke = blackBrush;
        poly.StrokeThickness = 4;

        // Create a collection of points for a polyline
        PointCollection polygonPoints = new PointCollection();
        for (int i = 0; i < points.Count-1; i++)
        {
            polygonPoints.Add(points[i]);
        }

        // Set Polyline.Points properties
        poly.Points = polygonPoints;

        // Add polyline to the page
        canvas.Children.Add(poly);
    }

当我进入调试器时,点显示如下:

如您所见,点的定义方式正确。

private void canvas_MouseMove(object sender, MouseEventArgs e)
    {
        Point p = Mouse.GetPosition(canvas);
        coords.Content = p.ToString();
    }

当我用 mouseMove 读取坐标时,延伸的边长了大约一半长度 (50/2)。

为什么会发生这种情况以及如何解决这个问题?

更新的解决方案:

 for (int i = 0; i < points.Count - 1; i += 2)
                {
                    pathGeometry = pathGeometry + "M" + points[i].X.ToString("F2") + " " + points[i].Y.ToString("F2") + " " + "L" + points[i + 1].X.ToString("F2") + " " + points[i + 1].Y.ToString("F2") + " ";
                }

                canvas.Children.Add(new Path { Stroke = Brushes.Brown, StrokeThickness = 3, Data = Geometry.Parse(pathGeometry) });

更新解决方案 2:(更好的解决方案)

PathFigure figures = new PathFigure();
figures.StartPoint = points[0];
points.RemoveAt(0);
figures.Segments = new PathSegmentCollection(points.Select((p, i) => new LineSegment(p, i % 2 == 0)));
PathGeometry pg = new PathGeometry();
pg.Figures.Add(figures);
canvas.Children.Add(new Path { Stroke = Brushes.Brown, StrokeThickness = 3, Data = pg });

我认为这是因为当你从右上角转到中上角时,多边形的绘制超出了实际的点,形成了一种尖锐的顶点。但我认为你在 window 中绘制时 y 轴向下,所以你必须将我的右上角视为底部 :-) 这意味着它是正确的短边。

解决方案是使用不同的线或路径几何:

<Path Data="M10 5 L60 5 M35 5 L35 65 M10 65 L60 65" Stroke="Black" StrokeThickness="5"  />

更新:

参考上面第一张图,其实是按照这个顺序画的:5-6-4-3-1-2。 (因为y轴向下)。

如果将下面的两个形状插入到 Canvas 中,您将看到多段线和路径的渲染之间的区别。如果您将折线中的值 20 更改为另一个值,您将看到折线(根据设计)呈现的效果 - 与路径相比。我在多段线和路径中的点都是任意的,你应该使用你的 ACad 点。

<Polyline Name="Poly" Points="10 5, 60 5, 35, 20 35, 65, 10, 65 60, 65" Stroke="Blue" StrokeThickness="5">
</Polyline>

<Path Name="MyPath" Data="M10 5 L60 5 M35 5 L35 65 M10 65 L60 65" Stroke="Black" StrokeThickness="5">
  <Path.RenderTransform>
    <TranslateTransform X="0" Y="100" />
  </Path.RenderTransform>
</Path>

如果您想了解有关 Path 的更多信息,请查看 here

更新二:

在后面的代码中,将路径数据构造为字符串可能会非常混乱。相反,您可能想要使用相应的类型:

  PathFigure figures = new PathFigure(new Point(10, 5),
    new PathSegment[]
    {
      new LineSegment(new Point(60,5), true),
      new LineSegment(new Point(35,5), false),
      new LineSegment(new Point(35,65), true),
      new LineSegment(new Point(10,65), false),
      new LineSegment(new Point(60,65), true),
    }, false);

  PathGeometry pg = new PathGeometry();
  pg.Figures.Add(figures);
  MyPath.Data = pg;

或者可以从一系列点来完成:

  Point[] points =
  {
    new Point(60, 5),
    new Point(35, 5),
    new Point(35, 65),
    new Point(10, 65),
    new Point(60, 65),
  };

  PathFigure figures = new PathFigure();
  figures.StartPoint = new Point(10, 5);
  figures.Segments = new PathSegmentCollection(points.Select((p, i) => new LineSegment(p, i % 2 == 0)));
  PathGeometry pg = new PathGeometry();
  pg.Figures.Add(figures);
  MyPath.Data = pg;

以上与 MyPath 中的数据字符串相同。

在这两种情况下,您都需要知道点代表哪种形状,以便您可以相应地设置 isStroked,或者使用其他类型的线段,如弧等。

我最近在使用折线时遇到了同样的问题。通过设置正确的连接类型,我能够摆脱行中不必要的扩展。

您可以将折线的 StrokeLineJoin 属性 设置为 PenLineJoin.Bevel 或 'PenLineJoin.Round'。

poly.StrokeLineJoin = PenLineJoin.Bevel;

或者

poly.StrokeLineJoin = PenLineJoin.Round;

当多段线以锐角转弯时,这将删除锐角。