The following sample code demonstrates two methods to find the closest feature to a 3D point in the scene using HOOPS Visualize (HPS). This code can be copied and pasted into the wpf_sandbox project (DemoUserCommands.cs) included in your HPS package.
Note: this sample code requires HOOPS Exchange as well and references a model provided in the Exchange download package. This was built with HNP 2024.
In the first method, a small simple sphere is defined and inserted into the scene. SelectByShell() is used to return all selections within that sphere. If this returns nothing, the sphere is deleted and a new, slightly larger sphere is created – this process repeats until a selection result is returned.
HPS.View myView = GetCanvas().GetAttachedLayout().GetFrontView();
myView.AttachModel(myModel);
// Insert a sample model to test:
try
{
string file_in = "<ExchangeInstallDirectory>/samples/data/pmi/PMI_Sample/CV5_Sample.CATPart";
HPS.Exchange.ImportOptionsKit iok = new HPS.Exchange.ImportOptionsKit();
iok.SetBRepMode(HPS.Exchange.BRepMode.BRepAndTessellation);
HPS.Exchange.ImportNotifier exchangeNotifier = HPS.Exchange.File.Import(file_in, iok);
exchangeNotifier.Wait();
HPS.Exchange.CADModel modelFile = exchangeNotifier.GetCADModel();
myModel = modelFile.GetModel();
myView.AttachModel(myModel);
HPS.SegmentKey myModelKey = myModel.GetSegmentKey();
myModelKey.InsertDistantLight(new HPS.Vector(1, 1, -1));
// Given a point in space, find the closest feature by iteratively increasing the size of a sphere
// with its center at that point until it hits a feature, then highlight that feature:
HPS.Point pointToTest = new HPS.Point(10, 0, 50);
bool isHit = false;
int upperBound = 1000; // Max distance the point can be from the model we're checking against
int i = 0;
while (!isHit && i<upperBound)
{
// Define the sphere we will use to perform a shell selection (collision check)
HPS.SphereKit mySphereKit= new HPS.SphereKit();
float radius = (float) (i + 1) / 2;
mySphereKit.SetCenter(pointToTest);
mySphereKit.SetRadius(radius);
mySphereKit.SetBasis(new HPS.Vector(0, 1, 0), new HPS.Vector(1, 0, 0)); // "axis" and "up" vectors
System.Diagnostics.Debug.Write("Radius:");
System.Diagnostics.Debug.WriteLine(radius);
// Create a reference sphere
HPS.SegmentKey referenceSphereSegKey = HPS.Database.CreateRootSegment();
HPS.SphereKey mySphereKey = referenceSphereSegKey.InsertSphere(mySphereKit);
// Insert the reference sphere into the scene
HPS.SegmentKey sphereSubSeg = myModelKey.Subsegment();
HPS.ShellKey mySphereShell = sphereSubSeg.InsertShellFromGeometry(mySphereKey);
// Perform a select by shell selection:
HPS.SelectionOptionsKit selectionOptions = new HPS.SelectionOptionsKit();
selectionOptions.SetAlgorithm(HPS.Selection.Algorithm.Analytic);
selectionOptions.SetLevel(HPS.Selection.Level.Subentity);
selectionOptions.SetProximity(0);
selectionOptions.SetScope(myModelKey);
HPS.SelectionResults selectionResults;
ulong numSelectedItems = GetCanvas().GetWindowKey().GetSelectionControl().SelectByShell(mySphereShell, selectionOptions, out selectionResults);
HPS.SelectionResultsIterator srIterator = selectionResults.GetIterator();
if (!srIterator.IsValid()) // If nothing is returned
{
System.Diagnostics.Debug.WriteLine("miss");
referenceSphereSegKey.Delete(); // Delete the offscreen root segment and its subsegments
sphereSubSeg.Delete(); // Delete the branch containing the sphere
i++;
}
else
{
isHit = true;
var highlightOptions = new HighlightOptionsKit("highlight_style");
highlightOptions.SetOverlay(Drawing.Overlay.InPlace);
while (srIterator.IsValid())
{
HPS.SelectionItem selectionItem = srIterator.GetItem();
var componentPath = modelFile.GetComponentPath(selectionItem);
if (!componentPath.Empty())
{
highlightOptions.SetNotification(true);
componentPath.Highlight(GetCanvas(), highlightOptions);
}
srIterator.Next();
}
}
myView.FitWorld();
GetCanvas().Update();
}
}
catch (HPS.IOException ioe)
{
System.Diagnostics.Debug.WriteLine(ioe.Message);
}
Sphere shown for reference - query point is at center of sphere. The highlighted face is the closest feature to the point.
In the second method, SelectByVolume() is used with a similar process. However, this method only allows for cuboid selection geometry, so it will not return a result as precise as a method using a sphere.
HPS.View myView = GetCanvas().GetAttachedLayout().GetFrontView();
myView.AttachModel(myModel);
// Insert a sample model to test:
try
{
string file_in = "<ExchangeInstallDirectory>/samples/data/pmi/PMI_Sample/CV5_Sample.CATPart";
HPS.Exchange.ImportOptionsKit iok = new HPS.Exchange.ImportOptionsKit();
iok.SetBRepMode(HPS.Exchange.BRepMode.BRepAndTessellation);
HPS.Exchange.ImportNotifier exchangeNotifier = HPS.Exchange.File.Import(file_in, iok);
exchangeNotifier.Wait();
HPS.Exchange.CADModel modelFile = exchangeNotifier.GetCADModel();
myModel = modelFile.GetModel();
myView.AttachModel(myModel);
HPS.SegmentKey myModelKey = myModel.GetSegmentKey();
myModelKey.InsertDistantLight(new HPS.Vector(1, 1, -1));
// Given a point in space, find the closest feature by iteratively increasing the size of a cuboid volume
// with its center at that point until it hits a feature, then highlight that feature:
HPS.Point pointToTest = new HPS.Point(35, 0, 30);
bool isHit = false;
int upperBound = 1000; // Max distance the point can be from the model we're checking against
int i = 1;
while (!isHit && i < upperBound)
{
// Define the cuboid for volumetric selection
HPS.SimpleCuboid boundingCuboid = new HPS.SimpleCuboid(new HPS.Point(-i + pointToTest.x, -i + pointToTest.y, -i + pointToTest.z), new HPS.Point(i + pointToTest.x, i + pointToTest.y, i + pointToTest.z));
System.Diagnostics.Debug.Write("Length: ");
System.Diagnostics.Debug.WriteLine(i*2);
// Perform a select by volume selection:
HPS.SelectionOptionsKit selectionOptions = new HPS.SelectionOptionsKit();
selectionOptions.SetAlgorithm(HPS.Selection.Algorithm.Analytic);
selectionOptions.SetLevel(HPS.Selection.Level.Subentity);
selectionOptions.SetScope(myModelKey);
HPS.SelectionResults selectionResults;
ulong numSelectedItems = GetCanvas().GetWindowKey().GetSelectionControl().SelectByVolume(boundingCuboid, selectionOptions, out selectionResults);
HPS.SelectionResultsIterator srIterator = selectionResults.GetIterator();
if (!srIterator.IsValid()) // If nothing is returned
{
System.Diagnostics.Debug.WriteLine("miss");
i++;
}
else
{
isHit = true;
var highlightOptions = new HighlightOptionsKit("highlight_style");
highlightOptions.SetOverlay(Drawing.Overlay.InPlace);
while (srIterator.IsValid())
{
HPS.SelectionItem selectionItem = srIterator.GetItem();
var componentPath = modelFile.GetComponentPath(selectionItem);
if (!componentPath.Empty())
{
highlightOptions.SetNotification(true);
componentPath.Highlight(GetCanvas(), highlightOptions);
}
srIterator.Next();
}
// Insert the cube for reference:
HPS.ShellKit myShellKit = new HPS.ShellKit();
HPS.Point[] shellPoints = {
new HPS.Point(-i + pointToTest.x, -i + pointToTest.y, -i + pointToTest.z),
new HPS.Point(i + pointToTest.x, -i + pointToTest.y, -i + pointToTest.z),
new HPS.Point(i + pointToTest.x, i + pointToTest.y, -i + pointToTest.z),
new HPS.Point(-i + pointToTest.x, i + pointToTest.y, -i + pointToTest.z),
new HPS.Point(-i + pointToTest.x, -i + pointToTest.y, i + pointToTest.z),
new HPS.Point(i + pointToTest.x, -i + pointToTest.y, i + pointToTest.z),
new HPS.Point(i + pointToTest.x, i + pointToTest.y, i + pointToTest.z),
new HPS.Point(-i + pointToTest.x, i + pointToTest.y, i + pointToTest.z)
};
int[] shellFaceList = {
4, 0, 1, 2, 3,
4, 1, 5, 6, 2,
4, 5, 4, 7, 6,
4, 4, 0, 3, 7,
4, 3, 2, 6, 7,
4, 0, 4, 5, 1
};
myShellKit.SetPoints(shellPoints);
myShellKit.SetFacelist(shellFaceList);
HPS.SegmentKey myShellSegKey = myModelKey.Subsegment();
HPS.ShellKey cubeShellKey = myShellSegKey.InsertShell(myShellKit);
}
myView.FitWorld();
GetCanvas().Update();
}
}
catch (HPS.IOException ioe)
{
System.Diagnostics.Debug.WriteLine(ioe.Message);
}
Cube shown for reference - query point is at center of cube. The highlighted face is the closest feature to the point.