WPF自定义形状交替弧段

时间:2019-06-04 16:38:08

标签: wpf custom-controls

我正在尝试使用一系列弧段在WPF中创建自定义形状。该形状本质上是一个带有折断线段的圆形,类似这样

enter image description here

虽然我知道我可以使用Ellipse并设置破折号数组属性来实现类似的效果,但是我需要处理厚度和半径的变化,即我必须保持可见段的数量不变,并且使用破折号变得很困难数组属性,因为它相对于笔触厚度。

因此,我尝试创建类似于SO问题here的自定义形状。该答案中描述的形状仅与绘制单个弧有关,而我需要绘制之间具有间隙的一系列弧。这就是我正在尝试的

 for ( int i = 1; i <= Segments; i++ )
 {
    var endpoint = PolarToCartesian(sweepAngle * i, Radius);    
    var drawArcSegment = i % 2 == 0;

    if (drawArcSegment)
    {
        var arcSegment = new ArcSegment
        {
           Point = endpoint,
           Size = new Size(Radius, Radius),
           IsLargeArc = false,
           SweepDirection = SweepDirection.Clockwise
        };
    }
    else
    {
        // WHAT TO DO HERE?
        // Need to either draw an arc segment that can't be seen but I can't apply
        // style properties to an arc segment OR need to move the current point of the
        // parent path figure to a new point that is the start of the following segment
    }
 }

这可能吗?我以正确的方式来处理这个问题吗?

2 个答案:

答案 0 :(得分:3)

计算适当的笔划破折号并不困难,

给出一个具有EllipseGeometry的路径(半径比Ellipse元素定义得更精确)

<Path x:Name="path" StrokeThickness="20" Stroke="Black">
    <Path.Data>
        <EllipseGeometry RadiusX="100" RadiusY="100"/>
    </Path.Data>
</Path>

您可以像这样计算StrokeDashArrayStrokeDashOffset属性:

var ellipse = (EllipseGeometry)path.Data;
var strokeLength = 2 * Math.PI * ellipse.RadiusX / path.StrokeThickness;

var numSegments = 8;
var relativeSegmentLength = 0.75;

var segmentLength = strokeLength / numSegments * relativeSegmentLength;
var gapLength = strokeLength / numSegments * (1 - relativeSegmentLength);

path.StrokeDashArray = new DoubleCollection { segmentLength, gapLength };
path.StrokeDashOffset = -gapLength / 2;

答案 1 :(得分:2)

为每个ArcSegment启动一个新的PathFigure,因此路径不必是连续的。

或者使用Clemens的答案,效果更好。

public PathGeometry CreateGeometry(int segmentCount, double radius)
{
    double sweepAngle = 360.0 / (double)segmentCount;
    double segmentAngle = sweepAngle / 2;

    double startAngleOffset = segmentAngle * 0.3;
    double endAngleOffset = segmentAngle * 1.7;

    var pg = new PathGeometry();

    for (int i = 0; i < segmentCount; ++i)
    {
        double currentSegmentAngle = i * sweepAngle;

        pg.Figures.Add(new PathFigure
        {
            StartPoint = PolarToCartesian(currentSegmentAngle + startAngleOffset, radius),
            Segments = {
                new ArcSegment{
                    Size = new Size(radius, radius),
                    SweepDirection = SweepDirection.Clockwise,
                    IsLargeArc = false,
                    Point = PolarToCartesian(currentSegmentAngle + endAngleOffset, radius)
                }
            }
        });
    }

    return pg;
}

笔触粗细与您的笔触粗细并不相同,但是您可以弄清楚。此中的线帽为半径。在您的人中,他们不是:您的人就像是在半径上抹掉一条宽线。如果需要的话,就不能让笔画为您完成工作。您将必须绘制封闭且填充的PathFigures,每个都有两个弧和两个结束线。

enter image description here