wpf c# 在顶点周围创建多边形
wpf c# create polygons around vertex points
在我的 WPF 项目中,我想绘制一些多边形或折线。它们需要是具有圆角的多边形,这些圆角在给定的顶点之外传递,如下图示例:
还需要第一个点(多边形的左上角)有一个钩子,但主要问题是关于给定点之外的传递。
例如,如果点具有给定的坐标:
p1(10,10)
p2(10,100)
p3(100,100)
p4(100,10)
如何创建多边形?
我找到了一个示例 here 但是给定的顶点在形状外部而不是内部。
有没有办法在 WPF 中构建这种形状?无论是库还是本机代码。
看来您应该实施某种等距算法。假设多边形线与每个顶点的距离为 d。算法步骤为:
- 将每条多边形线从其原始位置d偏移
- 对每个顶点画一条弧线段,圆弧中心为顶点,起点和终点为关节线段的点。
更新
创建了用于说明算法的示例代码。
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)));
}
结果
更新非凸多边形
如果多边形是非凸的,则不应添加圆弧。要检查是否添加圆弧,我们可以使用凸多边形的特征,它的所有顶点都在 2D 平面的一侧,由线划分,由每 2 个相邻顶点定义。
因此,如果多边形顶点按顺时针顺序给出,那么我们必须检查下一个点是否在右侧,并且只有在这种情况下才绘制弧线。
代码:
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;
}
在我的 WPF 项目中,我想绘制一些多边形或折线。它们需要是具有圆角的多边形,这些圆角在给定的顶点之外传递,如下图示例:
还需要第一个点(多边形的左上角)有一个钩子,但主要问题是关于给定点之外的传递。
例如,如果点具有给定的坐标:
p1(10,10)
p2(10,100)
p3(100,100)
p4(100,10)
如何创建多边形?
我找到了一个示例 here 但是给定的顶点在形状外部而不是内部。
有没有办法在 WPF 中构建这种形状?无论是库还是本机代码。
看来您应该实施某种等距算法。假设多边形线与每个顶点的距离为 d。算法步骤为:
- 将每条多边形线从其原始位置d偏移
- 对每个顶点画一条弧线段,圆弧中心为顶点,起点和终点为关节线段的点。
更新
创建了用于说明算法的示例代码。
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)));
}
结果
更新非凸多边形
如果多边形是非凸的,则不应添加圆弧。要检查是否添加圆弧,我们可以使用凸多边形的特征,它的所有顶点都在 2D 平面的一侧,由线划分,由每 2 个相邻顶点定义。 因此,如果多边形顶点按顺时针顺序给出,那么我们必须检查下一个点是否在右侧,并且只有在这种情况下才绘制弧线。
代码:
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;
}