C# WPF路径在某个大小时消失

C# WPF路径在某个大小时消失,c#,wpf,C#,Wpf,我在缩放图形时遇到了这个问题,它是在GIS控件Greatmap上绘制的。但一个简单的实验让我相信,问题在WPF中更深层 考虑简单的WPF应用程序: 这是MainWindow.xaml <Grid> <StackPanel> <Slider ValueChanged="Size_Changed" Minimum="0" Maximum="300000"/> <TextBox x:Name="Value"><

我在缩放图形时遇到了这个问题,它是在GIS控件Greatmap上绘制的。但一个简单的实验让我相信,问题在WPF中更深层

考虑简单的WPF应用程序:

这是MainWindow.xaml

<Grid>
    <StackPanel>
        <Slider ValueChanged="Size_Changed" Minimum="0" Maximum="300000"/>
        <TextBox x:Name="Value"></TextBox>
    </StackPanel>
    <Canvas>
        <Path x:Name="MyPath" Stroke="Black" StrokeThickness="2" />
    </Canvas>
</Grid>

这就是它背后的代码

private void Size_Changed(object sender,
        RoutedPropertyChangedEventArgs<double> e)
    {
        if (MyPath == null) return;

        var g = new StreamGeometry();
        using (var s = g.Open())
        {
            var pointA = new Point(0, 200);

            s.BeginFigure(pointA, false, false);

            var pointB = new Point(e.NewValue, 200);

            s.PolyLineTo(new[] {pointB}, true, true);

            Value.Text = $"zoom = {e.NewValue:0.0} ;  pointA = {pointA.X:#,0} ; pointB = {pointB.X:#,0}";
        }

        g.Freeze();

        MyPath.Data = g;
    }
private void Size\u已更改(对象发送方,
RoutedPropertyChangedEventArgs(e)
{
if(MyPath==null)返回;
var g=新的StreamGeometry();
使用(var s=g.Open())
{
var pointA=新点(0,200);
s、 beginigure(pointA、false、false);
var pointB=新点(例如,新值,200);
s、 PolyLineTo(new[]{pointB},true,true);
Value.Text=$“zoom={e.NewValue:0.0};pointA={pointA.X:#,0};pointB={pointB.X:#,0}”;
}
g、 冻结();
MyPath.Data=g;
}
当我将滑块从0拖动到249999时,一切正常。我能在我的视野中看到这条线。但此时滑块的值变为250000–直线消失


WPF有什么限制吗?

我看不出WPF有什么限制。对我来说,它看起来像是渲染中的WPF错误

我只能提供一个解决方案,但我不知道为什么在250000之后会出现问题。 我不知道这个变通方法是否适用于你的真实案例。其思想是使用
LayoutTransform
绘制一条水平线:

private void Size_Changed(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (MyPath == null) return;

    var g = new StreamGeometry();
    using (var s = g.Open())
    {
        var pointA = new Point(0, 200);

        s.BeginFigure(pointA, false, false);

        var pointB = new Point(1, 200);

        s.PolyLineTo(new[] { pointB }, true, true);

        MyPath.LayoutTransform = new ScaleTransform(e.NewValue, 1);

        Value.Text = $"zoom = {e.NewValue:0.0} ;  pointA = {pointA.X:#,0} ; pointB = {pointB.X:#,0}";
    }

    g.Freeze();

    MyPath.Data = g;
}
private void Size\u已更改(对象发送方,RoutedPropertyChangedEventArgs e)
{
if(MyPath==null)返回;
var g=新的StreamGeometry();
使用(var s=g.Open())
{
var pointA=新点(0,200);
s、 beginigure(pointA、false、false);
var pointB=新点(1200);
s、 PolyLineTo(new[]{pointB},true,true);
MyPath.LayoutTransform=新的ScaleTransform(e.NewValue,1);
Value.Text=$“zoom={e.NewValue:0.0};pointA={pointA.X:#,0};pointB={pointB.X:#,0}”;
}
g、 冻结();
MyPath.Data=g;
}

非常令人兴奋的问题,我想这一定是个bug。 如果您将pointA更改如下:

var pointA = new Point(1, 200);

然后它就会工作…:-)

出于某种原因,底层算法(可能是Direct2D或其祖先)考虑了比率
StrokeThickness/Geometry
范围,并确定笔划在某个点不可见(1对125000)。在另一个问题中也提到了这一点:

但是笔划是一个笔刷,因此您可以像这样使用自定义笔刷欺骗系统,例如在本例中:

// use pen size instead of StrokeThickness
var geo = new GeometryDrawing(null, new Pen(Brushes.Black, 2), 
              new RectangleGeometry(new Rect(0, 0, e.NewValue, 1))); // use desired width for the geometry
var brush = new DrawingBrush(geo);
brush.Stretch = Stretch.None; // use this brush size, don't stretch to stroke thickness
brush.Freeze();
MyPath.Stroke = brush;

// choose a big number (more than desired thickness * 125000) to fool WPF or its friends
MyPath.StrokeThickness = 1000;

这似乎与下文所述的问题有关

在WPF中,似乎存在一个与图形渲染方式相关的最大长度与笔划宽度与长度比率,这可能由图形渲染决定。 如果笔划宽度发生变化,则可以观察到以下情况:

  • 如果笔划宽度为1:允许的最大长度为125000
  • 如果 笔划宽度为2:允许的最大长度为250000
  • 如果笔划宽度为3:允许的最大长度为375000

这可能与您选择的数据类型有关吗?也许你可以试着用十进制或浮点变量来代替,看看问题是否仍然存在。不,我肯定只使用了double。顺便说一下,刚才在谷歌地球上遇到了非常相似的事情。我把路径在40、40和50、50之间,比我在这条路径的中间开始放大,在某个尺度上有一半的路径消失了。我不知道Google Earth使用了什么技术,但它是fanny。它实际上与路径/多边形线的厚度和长度之间的比例有关。对于冲程厚度,3条线在长度375000处塌陷;对于笔划厚度4,它在长度500000处塌陷,以此类推,对于厚度/长度,它以1/125000的比例塌陷,对于完美的水平线,也就是说,但它为什么塌陷?而且只有
点(0200)
,而
点(0.0000001200)
则不然,比如浮点数学的危害。WPF在尺寸和位置上使用double是设计师们的一厢情愿,后端仍然停留在浮动区。所有图形引擎都在这里漫游。非常好的演示。它甚至适用于
点(0.000000000001200)
,但不适用于
点(0.200)
。好主意!但如何处理任意(不是水平或垂直)路径?@mli-我还没想过。我不认为在所有情况下都有好的解决办法。我还使用UWP应用程序+Win2D测试了Direct2D,没有发现任何问题。请注意,这里也发布了一个问题:有一个报告连接的bug,但是现在连接已经消失了,我找不到bug报告中说了什么。无论如何,这表明微软意识到了这一点,所以这更多的是设计上的限制,而不是一个bug。。。