WPF 自定义形状交替弧段

WPF Custom Shape Alternating Arc Segments

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

虽然我知道我可以使用椭圆并设置破折号数组来实现类似的效果 属性,但我需要处理不断变化的厚度和半径,即,我必须保持可见线段的数量不变,并且使用破折号数组 属性 会变得很困难,因为它与笔画粗细有关。

因此,我正在尝试创建一个类似于 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
    }
 }

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

为每个 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,每个 PathFigures 都有两条弧线和两条端线。

计算出合适的笔划破折号模式真的并不困难。

给定一个带有 EllipseGeometry 的路径(其中半径的定义比椭圆元素的定义更精确)

<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;