AB4D Forum
Finding smallest distance between two 3D Objects - Printable Version

+- AB4D Forum (https://forum.ab4d.com)
+-- Forum: Products Forums (https://forum.ab4d.com/forumdisplay.php?fid=4)
+--- Forum: Ab3d.PowerToys (https://forum.ab4d.com/forumdisplay.php?fid=9)
+--- Thread: Finding smallest distance between two 3D Objects (/showthread.php?tid=4049)



Finding smallest distance between two 3D Objects - nherrmann - 11-09-2017

Hello,

I have a question, if the framework has any "comparison" functions where you can give in two 3D Objects and it will calculate one 3D Point of each 3D Object which defines the smallest distance between them?

Something like this:
Tuple<Point3D, Point3D> CalculateSmallestDistance(ModelVisual3D model1, ModelVisual3D model2)

[attachment=80]

Or like in the image I want to compare the yellow 3D Object with the blue, orange and green one.
What I want to know is, which Visual is closest to the yellow Visual?


Best Regards,
Nick


RE: Finding smallest distance between two 3D Objects - abenedik - 11-10-2017

There is no such thing as getting the smallest distance between two objects in Ab3d.PowerToys library.

But if you have ModelVisual3D objects with child models, it could help you to use model iterator to the library - for example Ab3d.Utilities.ModelIterator.IterateGeometryModel3DObjects method takes a ModelVisual3D and a callback delegate - it then iterates through all GeometryModel3D objects inside ModelVisual3D and for each call the delegate. The delegate also gets the transformation of all parent objects.

This can be used to generate a List of all Point3D positions from both ModelVisual3D objects. The following code does the trick:

Code:
var allPositions = new List<Point3D>();

ModelIterator.IterateGeometryModel3DObjects(modelVisual3D, delegate(GeometryModel3D geometryModel3D, Transform3D transform3D)
{
    // This code is called for each GeometryModel3D inside modelVisual3D

    var meshGeometry3D = (MeshGeometry3D)geometryModel3D.Geometry;

    if (transform3D == null || transform3D.Value.IsIdentity)
    {
        allPositions.AddRange(meshGeometry3D.Positions);
    }
    else
    {
        var transformedPositions = new Point3D[meshGeometry3D.Positions.Count];
        meshGeometry3D.Positions.CopyTo(transformedPositions, 0); // This is faster then .ToArray()

        transform3D.Transform(transformedPositions);

        allPositions.AddRange(transformedPositions);
    }
});


Then you can compare all positions from the array of the first ModelVisual3D to the second array and calculate the smallest distance (use LengthSquared to prevent calling sqrt). If you do not have very complex objects this should be done quickly (processors are insanely fast these days).

If you have very complex objects, then you will need to find some kind of data reduction technique to prevent comparing everything with everything.

Also note that if you will only compare positions, this will not always give you the smallest distance from two objects - for example in your image the gray and blue objects have the closest point that lies on the left vertical edge of the gray object. If you want to get such results, you will need to compare distances from all positions form first object to all triangles on the second object (see internet for formula). Then do the same for the second object - compare all positions with all triangles on the first object. This is much more intensive as checking only positions.

Your problem may be also solved with some object collision algorithm - check internet for more resources about that.


RE: Finding smallest distance between two 3D Objects - nherrmann - 11-15-2017

Thank you very much for the answer.
The problem is, that I have very complex Geometries. The most complex geometry has about 870000 positions.
I have some plans and methods how to reduce those points but I don't think it will give me always the correct smallest distance.

I have found a Method in your Library which sounds like it could solve the issue.
https://www.ab4d.com/help/PowerToys/html/M_Ab3d_Utilities_MathUtils_RayPlaneIntersection.htm

It is the RayPlaneIntersection Method of the MathUtils Class. But I don't understand how to use that method.
My thought was, if I take the Normal of a Point of e.g. the green geometry and send a Ray upwards I could find the the intersecting point of the yellow geometry.
Could you explain how to use the RayPlaneIntersection Method and what parameters I would have to use?

I had also troubles to find anything about the "point to triangle comparison" in the internet.

Best Regards
Nick


RE: Finding smallest distance between two 3D Objects - abenedik - 11-17-2017

The MathUtils.RayPlaneIntersection can be used to calculate an intersection point of a ray (can be created from mouse position and camera orientation) and a 3D plane - for example if you have a plane with normal (0,1,0) and a position (0,0,0) then you can use that method to calculate where the mouse hits this plane.

You can also see an example in the Ab3d.PowerToys main samples - check the "Cameras/Mouse 3D ray sample".


I am afraid that it will not help you in your case.