【问题标题】:Bug in geometry Hit-Testing几何命中测试中的错误
【发布时间】:2012-05-04 14:44:44
【问题描述】:

我有一个 DrawingVisual 元素,它表示一条路径,该路径由 syntax 描述:

"m106,59.3c0-1.98,0,0-4.95,0.989-3.96,0.989-13.8,3.96-20.8,4.95-6.92,0-14.8-3.96-17.8-3.96-1.98,2.97,3.96,10.9 ,7.91,13.8,2.97,1.98,9.89,3.96,14.8,3.96,4.95-0.989,10.9-2.97,13.8-6.92,2.97-2.97,5.93-10.9,6.92-12.9z"

为了呈现视觉效果,我使用了 MyCanvas 类,它提供了命中测试功能:

public class MyCanvas : Panel
{
   public List<Visual> Visuals = new List<Visual>();
   private List<DrawingVisual> Hits = new List<DrawingVisual>();

   public void AddVisual(Visual Visual)
   {
       this.Visuals.Add(Visual);
       base.AddVisualChild(Visual);
       base.AddLogicalChild(Visual);
   }

   public List<DrawingVisual> GetVisuals(Geometry Region)
   {
       GeometryHitTestParameters Parameters = new GeometryHitTestParameters(Region);
       this.Hits.Clear();
       HitTestResultCallback Callback = new HitTestResultCallback(this.HitTestCallBack);
       VisualTreeHelper.HitTest(this, null, Callback, Parameters);

       return this.Hits;
   }

   private HitTestResultBehavior HitTestCallBack(HitTestResult Result)
   {
        GeometryHitTestResult GeometryRes = (GeometryHitTestResult)Result;
        DrawingVisual DVisual = Result.VisualHit as DrawingVisual;

        if (DVisual != null && GeometryRes.IntersectionDetail == IntersectionDetail.FullyInside) 
            this.Hits.Add(DVisual);     

       return HitTestResultBehavior.Continue;
   }

   protected override Visual GetVisualChild(int Index)
   { return this.Visuals[Index]; }

   protected override int VisualChildrenCount {
        get { return this.Visuals.Count; }
   }
}

当我绘制我的(红色)路径时,结果如下:

网格单元的大小为 50x50。现在我尝试在这个区域获得视觉效果:

MyCanvas my_canvas = new MyCanvas();
RectangleGeometry MyRegion = new RectangleGeometry(new Rect(50, 50, 250, 250));
DrawingVisual MyPath = new DrawingVisual();

using (DrawingContext context = MyPath.RenderOpen()) {
   context.PushTransform(new TranslateTransform(50, 50));
   context.PushTransform(new ScaleTransform(2, 2));
   context.DrawGeometry(Brushes.Red, new Pen(), MyGeometry);
}

my_canvas.AddVisual(MyPath);
List<DrawingVisual> result = my_canvas.GetVisuals(MyRegion);

但是 MyPath 不在结果中,为什么?我如何正确地进行命中测试? 谢谢。

【问题讨论】:

  • 您是否在 HitTestCallback 中检查过 Path 是否被命中(设置断点)?如果是,IntersectionDetail 有什么值?
  • 我还是编辑了问题(我忘记了转换):IntersectionDetail.Intersect
  • @Clemens 我可能找到了something

标签: .net wpf drawing hittest


【解决方案1】:

似乎 hit-testing 考虑了应用reverse order of transformations 的形状的位置。这可以解释为什么我的路径仅与 fully inside 相交,而不是 MyCanvas.GetVisuals 方法的 RectangleGeometry 参数。

等待更好的响应,我用 not hit-testing 方法实现了 hit-test,现在是 MyCanvas 类的一部分:

public List<DrawingVisual> GetVisuals(Rect Area)
{
   this.Hits.Clear();

   foreach (DrawingVisual DVisual in this.Visuals) {
       if (Area.Contains(DVisual.DescendantBounds))
           this.Hits.Add(DVisual);
   }

   return this.Hits;
}

编辑:

正如 Mike Danes(MSDN 论坛的版主)在 this 线程中解释的那样:

“这真的有可能是几何命中测试中的错误吗?”

我 99% 确定这是一个错误。绘图和命中测试应使用相同的变换顺序。它与 TransformGroup 一起正常工作的原因是因为这样您只在绘图上下文中推送一个变换,这避免了命中测试绘图上下文中的错误乘法顺序。 请注意,这与TranformGroup中使用的顺序与推送顺序不同的事实无关。

【讨论】:

  • 你能把这个错误提交给微软吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 2016-02-02
  • 2021-10-13
  • 2015-06-14
  • 1970-01-01
  • 2016-02-16
相关资源
最近更新 更多