You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中如何添加不随缩放变大的点几何图形?

问题描述

我正在创建由线条和椭圆构成的几何图形,现在想为该几何图形添加点,目前通过创建小半径椭圆来实现此需求。但问题是我会对该几何图形应用变换,当执行平移和缩放操作时,这些点会变得很大。请问如何添加点才能让它们在缩放时不会变大?

现有代码

public static Path PointsGeometry(List<Point> Locations, Transform transform)
{
    GeometryGroup geometries = new GeometryGroup();
    foreach (Point Location in Locations)
    {
        geometries.Children.Add(new EllipseGeometry
            {
                Center = Location,
                RadiusX = .5,
                RadiusY = .5,
            }
        );
    }

    geometries.Transform = transform;

    Path path = new Path
    {
        Fill = Brushes.WhiteSmoke,
        Data = geometries,
    };

    return path;
}
解决方案

核心思路是让点的大小不受缩放变换的影响,下面提供几种可行的实现方式:

方式一:用Canvas放置固定尺寸的Ellipse作为点

把主几何图形和点都放在同一个Canvas中,主图形应用完整的平移+缩放变换,而点仅应用平移变换,保持自身尺寸固定:

public static void AddFixedSizePoints(Canvas canvas, List<Point> locations, Transform mainTransform)
{
    // 从主变换中提取平移分量
    TranslateTransform translate = null;
    if (mainTransform is TransformGroup group)
    {
        translate = group.Children.OfType<TranslateTransform>().FirstOrDefault();
    }
    else if (mainTransform is TranslateTransform tt)
    {
        translate = tt;
    }

    foreach (Point loc in locations)
    {
        Ellipse point = new Ellipse
        {
            Width = 2,
            Height = 2,
            Fill = Brushes.WhiteSmoke,
        };
        // 定位点的位置,抵消自身尺寸的偏移
        double offset = 1;
        Canvas.SetLeft(point, loc.X - offset);
        Canvas.SetTop(point, loc.Y - offset);
        // 应用平移变换(如果主变换包含平移)
        if (translate != null)
        {
            point.RenderTransform = translate;
        }
        canvas.Children.Add(point);
    }
}

这种方式下,点的尺寸固定,不会随主图形的缩放而变大。

方式二:修改原有代码,抵消缩放对几何图形的影响

如果坚持用Path绘制点,可以对几何图形应用逆缩放变换,抵消主变换中的缩放效果:

public static Path PointsGeometry(List<Point> Locations, Transform transform)
{
    GeometryGroup geometries = new GeometryGroup();
    foreach (Point Location in Locations)
    {
        geometries.Children.Add(new EllipseGeometry
            {
                Center = Location,
                RadiusX = .5,
                RadiusY = .5,
            }
        );
    }

    // 提取主变换的矩阵,生成逆缩放矩阵(保留平移)
    Matrix matrix = transform.Value;
    Matrix inverseScaleMatrix = new Matrix(
        1 / matrix.M11, 
        0, 
        0, 
        1 / matrix.M22, 
        matrix.OffsetX, 
        matrix.OffsetY
    );
    geometries.Transform = new MatrixTransform(inverseScaleMatrix);

    Path path = new Path
    {
        Fill = Brushes.WhiteSmoke,
        Data = geometries,
    };

    return path;
}

通过将主变换的缩放分量取倒数,让点的几何图形在缩放时反向缩放,最终呈现的大小保持不变。

方式三:在自定义控件的OnRender中直接绘制点

如果是自定义控件,可重写OnRender方法,根据当前缩放比例动态调整点的绘制大小:

private List<Point> _points = new List<Point>();

protected override void OnRender(DrawingContext dc)
{
    base.OnRender(dc);
    // 获取当前控件的缩放变换比例
    Matrix transform = this.RenderTransform.Value;
    double scale = Math.Max(Math.Abs(transform.M11), Math.Abs(transform.M22));
    // 确保点的实际显示大小固定为2px
    double pointRadius = scale > 0 ? 1 / scale : 1;

    foreach (Point loc in _points)
    {
        dc.DrawEllipse(Brushes.WhiteSmoke, null, loc, pointRadius, pointRadius);
    }
}

这种方式直接根据当前缩放比例动态调整绘制参数,保证点的显示大小始终一致。

内容的提问来源于stack exchange,提问作者Harxish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 08:10:25