RhinoCommon MeshPlane intersection slower in Rhino 8?

We are using the MeshPlane intersection function ( Rhino.Geometry.Intersect.Intersection.MeshPlane) a lot
to display the contour curves of our model, using a DisplayConduit. I notice that since Rhino8 this function is
considerably slower than in Rhino 7. Setting a lower tolerance does not change much.
I notice a new argument MeshIntersectionCache, not sure how this could help ?

using the Mesh.CreateContourCurves does not solve the performance problem either.

Any ideas how to make this again as fast as in Rhino 7 ?

Hi @i-Shape,

Can you provide some sample code that demonstrates the slowness?

Note, the code behind Intersection.MeshPlane was replaced with a new, more modern mesh intersector in V8, due to some crashing issues reported by users.

Thanks,

– Dale

Hi Dale,

Thanks for your reply.

I wrote a little python script that demonstrates this.

Timing result on the same hardware : Rhino 7 : 0.533988952637, Rhino 8 : 13.2230682373,
ie about 25 times slower.

Thanks

import Rhino
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg
from Rhino.Input import RhinoGet
from Rhino.DocObjects import ObjectType
from Rhino.Commands import Result
from scriptcontext import doc
import time
 
def MeshContours():
    rc, objRef = RhinoGet.GetOneObject("Select mesh", True, ObjectType.Mesh )
    if rc != Result.Success:
        return rc
    mesh = objRef.Mesh()
    if None == mesh:
        return Result.Failure
    rs.UnselectAllObjects()
    
    start = time.time()
    for z in xrange(0,50):
        plane = Rhino.Geometry.Plane(rg.Point3d.Origin + z*rg.Vector3d.ZAxis,rg.Vector3d.ZAxis)
        sections = Rhino.Geometry.Intersect.Intersection.MeshPlane(mesh,plane)
        for line in sections:
            doc.Objects.AddPolyline(line)
        
    end = time.time()
    doc.Views.Redraw()
    print(end - start)
 
if( __name__ == "__main__" ):
    MeshContours()

meshcontours.py (1.1 KB)

model.3dm (8.9 MB)

Hi @i-Shape

the old MeshPlane() function in Rhino 7 has severe geometrical limitations and was storing intermediate information on the mesh that was being intersected. Therefore, it was not the same to call that function once, with the same parameters, or many times. This actually violated some constance contracts, but it was a clever hack.

We may add this feature/hack back at some point to add some default caching. But in general, the new mechanism allows the user to maintain precise cache data, and that is very advantageous if the mesh that is intersected is the same.

The new code requires minimal changes in your case. It also gives better results and runs faster.
meshcontours-ishape.py (1.2 KB)


Older computer, 3% faster on Rhino 8.

Newer computer, 15% faster on Rhino 8.

Please test this yourself and let me know how it goes. You are welcome!
Thanks,

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

Hi Giulio,

Thanks for the feedback. This works fine for us.
The only drawback is that we need to have a different code base for our plugin for V7 and V8, but that is not a big problem.

An other question, what is exactly the meaning of the tolerance argument ? I noticed that the larger you set the tolerance, the slower it runs, which seems counter-intuitive. Actually, i accidentally put a very large number, and then it completely blocked my computer.

Another ( probably cache related ) issue I encountered, is that when you run SplitDisjointMesh on a mesh with texture coordinates ( imported from an OBJ file), the texture gets messed up. After RebuildMesh, it is again correct. Did also not happen in V7.

Thanks,

Dirk

Hi Giulio,

Sorry to bother you again, but I was too early in my previous message to say that the speed problem is solved.

The new MeshPlane algorithm seems to work fine for section planes with a normal equal to the Z axis. With a random normal vector however, I still notice an important slowdown compared to V7.

normal is Z axis : V7 0.422004699707, V8 : 0.446144104004 ( equal speed)
random direction : V7 : 0.414001464844 , V8 : 3.35786437988 ( 8 times slower)

I modified the test script to demonstrate this.
So we should first Transform the mesh to align it with the section plane ?

Thanks,

Dirk

import Rhino
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg
from Rhino.Input import RhinoGet
from Rhino.DocObjects import ObjectType
from Rhino.Commands import Result
from scriptcontext import doc
import time
 
def MeshContours():
    rc, objRef = RhinoGet.GetOneObject("Select mesh", True, ObjectType.Mesh )
    if rc != Result.Success:
        return rc
    mesh = objRef.Mesh()
    if None == mesh:
        return Result.Failure
    rs.UnselectAllObjects()
    
    normal = rg.Vector3d(1,0.33,0.2)
    # comment this out for random normal 
    #normal = rg.Vector3d.ZAxis
    origin = rg.Point3d.Origin
    
    start = time.time()
    cache = rg.Intersect.MeshIntersectionCache()
    for z in xrange(0,50):
        plane = Rhino.Geometry.Plane(origin + z *normal,normal)
        #sections = Rhino.Geometry.Intersect.Intersection.MeshPlane(mesh,plane)
        sections = Rhino.Geometry.Intersect.Intersection.MeshPlane(mesh,cache,plane,1.0e-10)
        if None == sections:
            continue
        for line in sections:
            doc.Objects.AddPolyline(line)
        
    end = time.time()
    doc.Views.Redraw()
    print(end - start)

if( __name__ == "__main__" ):
    MeshContours()

Hi @Lian,

Can you provide a 3dm file with the geometry and the code you’re using to perform the intersection?

Thanks,

– Dale

I’m sorry, I apologize for my previous inappropriate comment. I rewrote some code to test it and it worked fine. And it doesn’t need to be on the Z axis.