Distance point to solid

Distance point to solid

Anonymous
Not applicable
1,366 Views
3 Replies
Message 1 of 4

Distance point to solid

Anonymous
Not applicable

Hi forum,

I would like to ask the gurus here about the possibilities to perform the task of computing the distance of a point to an arbitrary solid.

 

My current approach is the following:

1. Try to get the correct transformation of the solid (which seems to be quite non-straight-forward depending on where the solid comes from -- GeometryElements, GeometryInstances, FamilyInstances, Pipes, Windows, whatever...)

2. Also restrict points to a BoundingBox to optimize, but BoundingBoxes are only axis-parallel for some of the instances I'm handling and so they are helping only in  a subset of cases.
3. Get all the faces, edges and vertices (Edge.GetEndPointReference) from the solid and store them for repeated distance requests with different points

4. For a given point calculate projective distances to the Faces, Edges and Vertices of the Solid (via XYZ.DistanceTo, Face.Project, Edge.Project, since this is the only working possibility I found in the API).

5. return the Minimum of all these distances.

 

This is working as expected but it is a lot of code and it is very slow - especially if one does repeated distance calculations with a lot of points, which I do.

 

So my question to you is:

Is there something better?

Does the API provide native means to speed up this process?

Is there maybe some Solid.DistanceTo method or similar hidden somewhere in the API?

I know of the ReferenceIntersector and I used it for an InsideCheck between point and Solid. Is there something similar that can be used for distance computation?

 

The ultimate problem we are facing is to find out, if a point has a certain distance r from the solid. So it would be possible to reformulate the problem as an intersection of the Solid and a Sphere of radius r around the given point. Is it possible to create a sphere through the API and intersect it with the solid? Are there any alternative approaches?

 

Any ideas and suggestions are highly appreciated.

 

Thanks a lot in advance and all the best,

Martin

0 Likes
1,367 Views
3 Replies
Replies (3)
Message 2 of 4

jeremytammik
Autodesk
Autodesk

Dear Martin,

 

Very nice question!

 

You can definitely create a sphere of any given radius r:

 

https://github.com/jeremytammik/the_building_coder_samples/blob/master/BuildingCoder/BuildingCoder/U...

 

    /// <summary>
    /// Create and return a solid sphere 
    /// with a given radius and centre point.
    /// </summary>
    static public Solid CreateSphereAt(
      XYZ centre,
      double radius )
    {
      // Use the standard global coordinate system 
      // as a frame, translated to the sphere centre.

      Frame frame = new Frame( centre, XYZ.BasisX,
        XYZ.BasisY, XYZ.BasisZ );

      // Create a vertical half-circle loop 
      // that must be in the frame location.

      Arc arc = Arc.Create(
        centre - radius * XYZ.BasisZ,
        centre + radius * XYZ.BasisZ,
        centre + radius * XYZ.BasisX );

      Line line = Line.CreateBound(
        arc.GetEndPoint( 1 ),
        arc.GetEndPoint( 0 ) );

      CurveLoop halfCircle = new CurveLoop();
      halfCircle.Append( arc );
      halfCircle.Append( line );

      List<CurveLoop> loops = new List<CurveLoop>( 1 );
      loops.Add( halfCircle );

      return GeometryCreationUtilities
        .CreateRevolvedGeometry( frame, loops,
          0, 2 * Math.PI );
    }

  

Furthermore, you can calculate its Boolean intersection with the solid using the ExecuteBooleanOperation method:

 

https://apidocs.co/apps/revit/2019/89cb7975-cc76-65ba-b996-bcb78d12161a.htm

 

I would hope that there is some more efficient solution, though.

 

Is your solid completely arbitrary, with curved surfaces, or (better) polyhedral, or, (better still) convex?

 

Even if it has curved surfaces, you can get a pretty good polyhedral approximation using the Revit API tessellation functionality... 

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 3 of 4

Anonymous
Not applicable

Hi Jeremy,

 

Thank you for your reply. I'll definitely look into the sphere creation and the tessellation approach also sounds interesting.

Unfortunately the input to this function is very general. I can't make any assumptions on well-behavedness of the solids in question. But now I have some new leads to investigate.

 

Best,
Martin

0 Likes
Message 4 of 4

Anonymous
Not applicable

Hi list,

Unfortunately the Solid-Intersection-Approach does not work as expected, since the call to

 

BooleanOperationsUtils.ExecuteBooleanOperation(sphere, theSolid, BooleanOperationsType.Difference);

 

can lead to an exception:

 

"Failed to perform the Boolean operation for the two solids. This may be due to geometric inaccuracies in the solids, such as slightly misaligned faces or edges. If so, eliminating the inaccuracies by making sure the solids are accurately aligned may solve the problem. This also may be due to one or both solids having complexities such as more than two faces geometrically meeting along a single edge, or two coincident edges, etc. Eliminating such conditions, or performing a sequence of Boolean operations in an order that avoids such conditions, may solve the problem. "

 

It is not really clear to me, why this exception is thrown, because in the case I catch it, no complicated solids were present (just one solid consisting of two rectangular boxed and the sphere). The sphere is defined straight forward:

XYZ profileArcPlus = center + new XYZ(0, 0, radius);
XYZ profileArcMid = center + new XYZ(radius, 0, 0);
XYZ profileArcMinus = center - new XYZ(0, 0, radius);

 

Frame frame = new Frame(center, XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ);

 

List<Curve> profile = new List<Curve>();
profile.Add(Line.CreateBound(profileArcPlus, profileArcMinus));
profile.Add(Arc.Create(profileArcMinus, profileArcPlus, profileArcMid));

 

CurveLoop curveLoop = CurveLoop.Create(profile);

 

SolidOptions options = new SolidOptions(ElementId.InvalidElementId,
ElementId.InvalidElementId);

 

Solid sphere = GeometryCreationUtilities.CreateRevolvedGeometry(frame, new CurveLoop[] { curveLoop }, 0, 2 * Math.PI, options);

0 Likes