wpf c#在顶点周围创建多边形

时间:2016-02-16 09:29:54

标签: c# wpf rounded-corners

在我的WPF项目中,我想绘制一些多边形或折线。它们需要是具有圆角的多边形,这些多边形在给定的顶点之外传递,如下图所示: image sample

还需要在第一个点(多边形的左上角)中有一个钩子,但主要问题是关于在给定点之外传递。

例如,如果点具有给定的坐标:

P1(10,10)

P2(10100)

P3(100,100)

P4(100,10)

如何创建多边形?

我找到了一个例子here但是给出的顶点在形状之外而不在其中。

有没有办法在WPF中构建这种形状?无论是图书馆还是本地代码。

1 个答案:

答案 0 :(得分:1)

似乎你应该实现某种等距算法。假设多边形线与每个顶点的距离 d 。算法步骤是:

  1. d 的每个多边形线从其原始位置
  2. 偏移
  3. 对于每个顶点绘制一个弧段,其中弧的中心是顶点,起点和终点是关节线段的点。
  4. Algorithm for the first step

    <强>更新

    创建示例代码以说明algorythm。

    <强> XAML

        <Canvas Name="canvas">
            <Polygon Name="poly" Stroke="Black" >
                <Polygon.Points>
                    <Point X="110" Y="110" />
                    <Point X="110" Y="200" />
                    <Point X="200" Y="200" />
                    <Point X="300" Y="110" />
                    <Point X="200" Y="110" />
                </Polygon.Points>
            </Polygon>
        </Canvas>
    

    <强> C#

        double _distance = 10.0;
    
        Line CreateLine(Point pointStart, Point pointEnd)
        {
            Line line = new Line();
    
            line.Stroke = Brushes.Red;
            line.X1 = pointStart.X;
            line.Y1 = pointStart.Y;
            line.X2 = pointEnd.X;
            line.Y2 = pointEnd.Y;
    
            return line;
        }
    
        Path CreateArc(Point pointStart, Point pointEnd, double radius)
        {
            ArcSegment arc = new ArcSegment();
            arc.Point = pointEnd;
            arc.Size = new Size(radius, radius);
    
    
            var pathFigure = new PathFigure(pointStart, new PathSegment[] { arc }, false);
            Path path = new Path();
            path.Data = new PathGeometry(new PathFigure[] { pathFigure });
            path.Stroke = Brushes.Red;
    
            return path;
        }
    
        private void CreateDrawing()
        {
    
            for (int i = 0; i < poly.Points.Count; i++)
            {
                int lastPointIndex = (i > 0) ? i - 1 : poly.Points.Count - 1;
                int nextPointIndex = (i < poly.Points.Count - 1) ? i + 1 : 0;
    
    
                var pointsPair = GetPerpendicularPoint(poly.Points[i].X, poly.Points[i].Y, poly.Points[nextPointIndex].X, poly.Points[nextPointIndex].Y, _distance);
                var lastPointsPair = GetPerpendicularPoint(poly.Points[lastPointIndex].X, poly.Points[lastPointIndex].Y, poly.Points[i].X, poly.Points[i].Y, _distance);
    
                canvas.Children.Add(CreateLine(pointsPair.Item1, pointsPair.Item2));
                canvas.Children.Add(CreateArc(lastPointsPair.Item2, pointsPair.Item1, _distance));
            }
    
        }
    
        private Tuple<Point, Point> GetPerpendicularPoint(double startX, double startY, double stopX, double stopY, double distance)
        {
            Point p = new Point(startX - stopX, startY - stopY);
            Point n = new Point(p.Y, -p.X);
            double norm_length = Math.Sqrt((n.X * n.X) + (n.Y * n.Y));
            n.X /= norm_length;
            n.Y /= norm_length;
            return new Tuple<Point, Point>(new Point(startX + (distance * n.X), startY + (distance * n.Y)), new Point(stopX + (distance * n.X), stopY + (distance * n.Y)));
        }
    

    <强>结果

    simple equidistant

    非凸多边形的更新

    如果多边形是非凸的,则不应添加弧。为了检查是否添加弧,我们可以使用凸多边形的特征,它的所有顶点都在2D平面的一侧除以线,由每两个相邻顶点定义。 因此,如果以时钟顺序给出多边形顶点,那么我们必须检查下一个点是否在右侧,并且仅在这种情况下绘制弧。

    代码:

    if (IsRight(poly.Points[lastPointIndex], poly.Points[i], poly.Points[nextPointIndex]))
    {
        canvas.Children.Add(CreateArc(lastPointsPair.Item2, pointsPair.Item1, _distance));
    }
    

    ...

    public bool IsRight(Point a, Point b, Point c)
    {
        return ((b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X)) > .0;
    }