Nevron Open Vision Documentation
Hit Testing

 
Hit Testing Overview

The DOM is hit-tested by specific visitors that derive from the NDisplayVisitor class, and thus inherit the transform and clip management provided by it, as explained in the The Visual Tree topic. There are generally two types of hit tests that can be performed upon the visual tree:

Both types of hit-tests can be performed in two variations:

Hit-testing is performed by different static methods of the NVisualTreeHelpers static class.

Hit-Testing Visual Subtrees

As mentioned, hit-testing is performed by different static methods of the NVisualTreeHelpers static class. A common requirement for all hit-test methods is that they must receive a valid NVisual instance, which to consider as root for the subtree hit-test. The following code performs a visual subtree tree hit-test by point:

My First Hit-Test
Copy Code
// hit test the visual subtree, rooted by sutreeRootVisual by point
// the point is considered to be in sutreeRootVisual coordinates
NVisual topMostHit = NVisualTreeHelpers.HitTestTopMostByPoint(sutreeRootVisual, new NPoint(10, 10));

The following table summarizes the hit test static methods exposed by the NVisualTreeHelpers static class

Method Description

Top Most - By Point

NVisual HitTestTopMostByPoint(NVisual visualRoot, NPoint pointInRoot)

Hit tests the visual tree rooted by visualRoot by point and returns the top-most hit visual.

NVisual HitTestTopMostByPoint(NVisual visualRoot, NPoint pointInRoot, INFilter<NVisual> filter)

Hit tests the visual tree rooted by visualRoot by point and returns the top-most hit visual. Optionally you can specify a filter (see filter and clip comments below).

NVisual HitTestTopMostByPoint(NVisual visualRoot, NPoint pointInRoot, INFilter<NVisual> filter, NRegion clipInRoot)

Hit tests the visual tree rooted by visualRoot by point and returns the top-most hit visual. Optionally you can specify a filter and clip (see filter and clip comments below).

Top Most - By Region

NVisual HitTestTopMostByRegion(NVisual visualRoot, NRegion regionInRoot)

Hit tests the visual tree rooted by visualRoot by the region defined by the regionInRoot graphics path and returns the top-most hit visual.

NVisual HitTestTopMostByRegion(NVisual visualRoot, NRegion regionInRoot, INFilter<NVisual> filter)

Hit tests the visual tree rooted by visualRoot by the region defined by the regionInRoot graphics path and returns the top-most hit visual. Optionally you can specify a filter (see filter and clip comments below).

NVisual HitTestTopMostByRegion(NVisual visualRoot, NRegion regionInRoot, INFilter<NVisual> filter, NRegion clipInRoot)

Hit tests the visual tree rooted by visualRoot by the region defined by the regionInRoot graphics path and returns the top-most hit visual. Optionally you can specify a filter and clip (see filter and clip comments below).

All - By Point

NList<NVisual> HitTestAllByPoint(NVisual visualRoot, NPoint pointInRoot)

Hit tests all visuals that reside in the visual tree rooted by visualRoot and returns the hit ones.

NList<NVisual> HitTestAllByPoint(NVisual visualRoot, NPoint pointInRoot, INFilter<NVisual> filter)

Hit tests all visuals that reside in the visual tree rooted by visualRoot and returns the hit ones. Optionally you can specify a filter (see filter and clip comments below).

NList<NVisual> HitTestAllByPoint(NVisual visualRoot, NPoint pointInRoot, INFilter<NVisual> filter, NRegion clipInRoot)

Hit tests all visuals that reside in the visual tree rooted by visualRoot and returns the hit ones. Optionally you can specify a filter and clip (see filter and clip comments below).

All - By Region

NList<NVisual> HitTestAllByRegion(NVisual visualRoot, NRegion regionInRoot)

Hit tests all visuals that reside in the visual tree rooted by visualRoot by the region defined by the regionInRoot graphics path and returns the hit ones.

NList<NVisual> HitTestAllByRegion(NVisual visualRoot, NRegion regionInRoot, INFilter<NVisual> filter)

Hit tests all visuals that reside in the visual tree rooted by visualRoot by the region defined by the regionInRoot graphics path and returns the hit ones. Optionally you can specify a filter (see filter and clip comments below).

NList<NVisual> HitTestAllByRegion(NVisual visualRoot, NRegion regionInRoot, INFilter<NVisual> filter, NRegion clipInRoot)

Hit tests all visuals that reside in the visual tree rooted by visualRoot by the region defined by the regionInRoot graphics path and returns the hit ones. Optionally you can specify a filter and clip (see filter and clip comments below).

As seen from the API table, each hit-test method has two overloads that allow you to optionally specify a filter and a clipping region:

Filter - the filter is used to determine which visuals should at all be hit-tested. A value of null means that the hit-test is not filtered and hence all visuals that reside in the visualRoot need to be hit-tested. If a valid filter is provided, the respective hit test will only hit-test the visuals that pass the filter (e.g. the Filter method for this visuals returns true - see Filters for more information).

Clip Region - the clip region is used to additionally limit the area from the visualRoot coordinate space that should be hit-tested. A value of null means that the hit-tested area of the visualRoot coordinate space is not additionally limited. When a hit-test visitor traverses the visual tree it automatically takes into account the currently accumulated clip, as described in the The Visual Tree topic.

Implementing HitTest Methods

In order for a visual to be hit by a point or region hit test, its respective HitTest method must return true, if the visual is hit by a point or region respectively. By default a NVisual does not provide an implementation for these methods (they simply return false) - so it is up to derived classes to override the respective HitTest methods, if they need to be hit-tested by point or by region. The rest of this section gives you some tips on how to implement/override the HitTest methods:

Implementing Point Hit-Test

As mentioned the bool HitTest(NPointHitTestVisitor visitor) method is called during top-most or all point hit tests. The passed NPointHitTestVisitor instance derives from NDisplayVisitor, and the hit-test point is available in two coordinate systems - local and scene, via the LocalHitTestPoint and SceneHitTestPoint properties respectively. In most cases you will use the point in local coordinates to perform a point hit test over a region in local coordinates. The following code hit-tests a graphics path that represents a doughnut shape by point:

Implementing Point Hit Test
Copy Code
public class MyFirstVisual : NVisual
{
...
 public override bool HitTest(NPointHitTestVisitor visitor)
 {
  NGraphicsPath path = new NGraphicsPath();
  path.AddEllipse(0, 0, 100, 100);
  path.AddEllipse(10, 10, 80, 80);
  return path.Contains(visitor.LocalHitTestPoint, ENFillRule.EvenOdd);
 }
...
}

The path is hit-tested via its Contains method. The point used is the LocalHitTestPoint, which is in local coordinates for the current visual. Nearly all graphics objects and primitives  (NRectangle, NQuadrangle, NPolygon, NRegion, NGraphicsPath etc. implement a Contains methods). 

Implementing Region Hit-Test

As mentioned the bool HitTest(NRegionHitTestVisitor visitor) method is called during top-most or all region hit tests. The passed NRegionHitTestVisitor instance derives from NDisplayVisitor, and the hit-test region is available in two coordinate systems - local and scene, via the LocalHitTestRegion and SceneHitTestRegion properties respectively. In most cases you will use the region in local coordinates to perform a region hit test over a region in local coordinates. The following code hit-tests a graphics path that represents a doughnut shape by region:

Implementing Region Hit Test
Copy Code
public class MyFirstVisual : NVisual
{
 public override bool HitTest(NRegionHitTestVisitor visitor)
 {
  NGraphicsPath path = new NGraphicsPath();
  path.AddEllipse(0, 0, 100, 100);
  path.AddEllipse(10, 10, 80, 80);
  NRegion pathRegion = NRegion.FromPath(path, ENFillRule.EvenOdd);
  return pathRegion.IntersectsWith(visitor.LocalHitTestRegion);
 }
}

The region constructed from the path is hit-tested via its IntersectsWith method. The region used is the LocalHitTestRegion, which is in local coordinates for the current visual.

The possibility to create a NRegion from a path (as well as other graphics objects) and to query whether it intersects with other regions, means that the region hit-test can be used for all types of area related hit-tests - from rectangular selection to lasso selection as well as all types of selection that are based on arbitrary geometry.

 

See Also
Send Feedback