【问题标题】:Long lines don't render correctly长线无法正确渲染
【发布时间】:2012-02-04 06:23:10
【问题描述】:

我有一个带有画布的项目,用户可以使用鼠标进行缩放和平移。原点用穿过画布的蓝色十字标记。当用户放大标记时,标记的线宽会减小,以使它们在屏幕上保持大约 1 个像素宽。然而,在放大大约 10 倍后,原点线突然消失了。在应用缩放变换之前,渲染引擎似乎决定线条太小而无法显示。

奇怪的是,当我对矩形而不是直线执行相同的操作时,我得到了预期的行为(请参阅下面代码中的 ScaleBox 矩形对象)。欢迎任何关于导致问题的原因以及如何解决问题的想法。

这里是相关的 XAML:

    <Canvas x:Name="MouseCapture" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="WhiteSmoke" >
    <Canvas x:Name="ZoomPan">
        <Canvas.RenderTransform >
            <MatrixTransform x:Name="_zoomPanTransform" />
        </Canvas.RenderTransform>
        <Rectangle x:Name="ScaleBox" Width="100" Height="100" Canvas.Left="-50" Canvas.Top="-50" Stroke="Black"/>
        <Line x:Name="YOrigin" X1="-5000" X2="5000" Y1="0" Y2="0" Stroke="Blue" />
        <Line x:Name="XOrigin" X1="0" X2="0" Y1="-5000" Y2="5000" Stroke="Blue" />
    </Canvas>
</Canvas>

以及背后的代码:

Private Sub ZoomControl_PreviewMouseWheel(sender As Object, e As System.Windows.Input.MouseWheelEventArgs) Handles MouseCapture.PreviewMouseWheel
    Dim scale As Double
    If e.Delta > 0 Then
        scale = 0.95
    Else
        scale = 1 / 0.95
    End If
    Dim center As Point = e.GetPosition(MouseCapture)
    Dim zoom As New ScaleTransform(scale, scale, center.X, center.Y)
    _zoomPanTransform.Matrix *= zoom.Value
    UpdateLineWidth()
End Sub

Private Sub UpdateLineWidth()
    ScaleBox.StrokeThickness = 1 / _zoomPanTransform.Matrix.M11
    XOrigin.StrokeThickness = 1 / _zoomPanTransform.Matrix.M11
    YOrigin.StrokeThickness = 1 / _zoomPanTransform.Matrix.M11
End Sub

这是一切正常时的屏幕截图。

这是 10 倍缩放的屏幕截图。原点线突然消失了,但黑框仍然按预期显示。 (请注意,只有一侧的黑框是可见的,因为由于缩放,其余的都在可见区域之外。)

编辑:我发现问题见下文

【问题讨论】:

  • 你确定你的原点在屏幕上吗?似乎是视而不见。向左平移一点就知道了。
  • @MD.Unicorn 是的,这条线肯定在屏幕上

标签: .net wpf vb.net wpftoolkit


【解决方案1】:

我不太明白你为什么要把这些十字准线放在转换后的画布中。

与其将它们绘制到转换后的画布中并在每次转换更改时固定其有效线宽,不如将它们简单地放置在另一个未转换的画布中,例如在父 Canvas 中:

<Canvas x:Name="MouseCapture" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="WhiteSmoke" >
    <Canvas x:Name="ZoomPan">
        <Canvas.RenderTransform >
            <MatrixTransform x:Name="_zoomPanTransform" />
        </Canvas.RenderTransform>
        <Rectangle x:Name="ScaleBox" Width="100" Height="100" Canvas.Left="-50" Canvas.Top="-50" Stroke="Black"/>
    </Canvas>
    <Line x:Name="YOrigin" X1="-5000" X2="5000" Y1="0" Y2="0" Stroke="Blue" />
    <Line x:Name="XOrigin" X1="0" X2="0" Y1="-5000" Y2="5000" Stroke="Blue" />
</Canvas>

一般来说,当您想要在保持笔触粗细的同时变换几何形状,您应该使用Path 元素并将Path.Data 设置为Geometry,并使用适当的Geometry.Transform,如下例所示.请注意,转换被定义为静态资源(键为GlobalTransform),因此可以被多个几何体重用。

<Path Stroke="Blue">
    <Path.Data>
        <LineGeometry StartPoint="0,-100" EndPoint="0,100" Transform="{StaticResource GlobalTransform}"/>
    </Path.Data>
</Path>

【讨论】:

  • 感谢您的回复。将十字线放在自己的画布上的好主意。大声笑,我没有想到这一点。在缩放(围绕一个点)和平移时需要一些棘手的数学来保持一切对齐,但应该是可行的。另外,请注意路径和线都通过覆盖 DefiningGeometry 属性从形状派生,因此路径和线在内部是等效的。
  • 但是,如果您渲染-转换一条线或转换一条路径的 LineGeometry,它会产生很大的不同。
【解决方案2】:

问题是线路太长了。如果我动态地减少原点线的长度,使它们与画布的长度大致相同,那么一切都会按预期显示。如果线条比画布长 100 倍左右,它们就会突然消失。这可能是由于一些舍入错误或优化方案造成的。

【讨论】:

  • 只有当线条也很细时才会发生这种情况。如果您不减少笔画粗细,则线条不会消失。同样,拥有始终调整笔画粗细的渲染转换线并不是一个好主意。您应该考虑在您的绘图区域准确地绘制一个未缩放的十字准线,即在 (mouse-x, 0..height) 处的一条线,在 (0..width, mouse-y) 处的另一条线。
  • @Clemens 谢谢,这就是我最终要做的。完美运行。
猜你喜欢
  • 1970-01-01
  • 2019-07-21
  • 2015-03-10
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多