Bug in geometry Hit-Testing

心不动则不痛 提交于 2019-12-19 07:36:45

问题


I have a DrawingVisual element that rappresents a path which geometry is described by this 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"

To render the visual i use MyCanvas class, that provides hit-testing functionality:

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

When i draw my (red) path this is the result:

Where the size of the grid cells is 50x50. Now i try to get visuals for example in this region:

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

But MyPath is not in result, why? How i have to properly do hit-test? Thanks.


回答1:


It seems like hit-testing considers the position of the shapes to which was applied a reverse order of transformations. This would explain why my path is intersected only and not fully inside the RectangleGeometry argument of MyCanvas.GetVisuals method.

Waiting for a better response, i implemented the hit-test with a not hit-testing method, now part of MyCanvas class:

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

EDIT:

As Mike Danes (moderator on MSDN forum) explains in this thread:

"Is it really possible that this is a bug in geometry hit-testing?"

I'm 99% sure this is a bug. Drawing and hit testing should use the same transform order. The reason it works correctly with TransformGroup is because this way you only push only one transform in the drawing context and this avoids the wrong multiplication order in the hit test drawing context. Note that this has nothing to do with the fact that the order used in TranformGroup is different from the push order.



来源:https://stackoverflow.com/questions/10451066/bug-in-geometry-hit-testing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!