Cleaning up Inside Meshes - Speedup Contest

have you turned on optimizaiton in VS?

Yes. On the Release build. Still ~20ms.

But, then I also tried to modify the code a little, in VS2022. For example, I originally had two loops with Parallel.For, like so:

Parallel.For( /* Traversing Mesh Vertices */ )
{
    Parallel.For( )   // <-- skipped this one
    {
         // PointInCylinder test.
    }
}

Removing the inner Parallel.For reduced execution time almost 10 seconds…

Then in the PointInclusion method, I also tried make local variables of the signature parameter properties, and for 3 of them it reduced execution time with 1-2 seconds each(!). That was surprising.

So now I’m less than 10 sec on my old 6/12 i7-3930K (lowest was around 7.5 sec).

image

public static bool GetPointsInsideOrganPipeIndices(Point3d cylinderBase, Vector3d cylinderAxis, double cylinderRadius, Point3d[] points, double tolerance, out int[] pointInclusionIndices)
{
   //pointStatus, whether a points[i] is inside the cylinder
   var point_status = new int[points.Length];

   var cyl_axis = cylinderAxis;
   var cyl_length = cylinderAxis.Length;
   cyl_axis.Unitize(); // cyl_axis should be already unit size vector, but for just to be certain ...

   var cyl_base = cylinderBase;

   var radius_with_tolerance = cylinderRadius + tolerance;
   var square_radius_with_tolerance = radius_with_tolerance * radius_with_tolerance;

   var t_C1 = 0.0;
   var t_C2 = cyl_length;
   t_C1 = t_C1 - tolerance;
   t_C2 = t_C2 + tolerance;

   //Parallel.For(0, points.Length, i =>  // <-- Skipped Parallel in this "inner" loop
   for (int i = 0; i < points.Length; i++)
   {
       var ptX = points[i].X; // <-- #
       var ptY = points[i].Y; // <-- #
       var ptZ = points[i].Z; // <-- #

       var cylax_x = cyl_axis.X; // <-- #
       var cylax_y = cyl_axis.Y; // <-- #
       var cylax_z = cyl_axis.Z; // <-- #

       var cylbase_x = cyl_base.X; // <-- #
       var cylbase_y = cyl_base.Y; // <-- #
       var cylbase_z = cyl_base.Z; // <-- #

       //var t = cylax_x * (points[i].X - cyl_base.X) + cyl_axis.Y * (points[i].Y - cyl_base.Y) + cyl_axis.Z * (points[i].Z - cyl_base.Z);
       var t  = cylax_x * (ptX - cylbase_x) + cylax_y * (ptY - cylbase_y)+ cylax_z * (ptZ - cylbase_z); 

       var TX = cylbase_x + t * cylax_x;
       var TY = cylbase_y + t * cylax_y;
       var TZ = cylbase_z + t * cylax_z;

       var square_distance_pt = (ptX - TX) * (ptX - TX) +
                                (ptY - TY) * (ptY - TY) +
                                (ptZ - TZ) * (ptZ - TZ);
       
       if (t < t_C1 || t > t_C2 || square_distance_pt > square_radius_with_tolerance)
       {
           point_status[i] = -1; //point is NOT inside the cylinder
       }
       else
       {
           point_status[i] = i;
       }
   }
   //);

   pointInclusionIndices = (from index in point_status
                            where index > -1
                            orderby index descending
                            select index).ToArray();

   return pointInclusionIndices.Length > 0;
}

This small modification meant almost 3 sec shorter execution time, which I really didn’t expect.

Of course I also pasted in the code above into the ScriptComponent, and that gave me yet another positive surprise (3.2 sec!):

image

Would be nice to get similar speed in the VS2022 version as well.

//Rolf

Edit: Latest optimized ScriptComponent version (1.7.3):
MeshCleanByOrganPipe 2024 R7-1.7.3.gh (1.8 MB)

MeshCleanByOrganPipe 2024 R7-1.7.3-Gan.gh (1.8 MB)

Newer versions of .NET put it under 1s with Rhino 8.

image

1 Like

Something might be wrong with your VS configuration.

We’ll see, I will try in VS2022 tonight. Looks good on your side!

Very nice code you wrote. :+1:

//Rolf

I didn’t write much. You write very nice code. :wink:

Ok, now we’re talking! I updated the VS2022 code with your modifications, and off we go. I arrived at 1.4 sec also with VS2022.

Absolutely stunning speed! Thank you very much @gankeyu , I knew you would squeeze this thing, pushing it to its limits.

:+1: :sunglasses:

//Rolf

1 Like

A final version, based on @gankeyu 's very efficient code. With some added functionality when the final removal of the Vertices “inside” is done either inside the component (see option Cleanup == true) or if connecting a Wire to the Filter output, the cleanup can be done outside the Component (the code check’s if a wire is connected). Same thing with the “Meshes” output: Sometimes you want to deal with the DisJointed mesh parts separately.

So here we go: Version 1.8.0 dedicated to @gankeyu (“1.8.0-Gan”):

MeshCleanByOrganPipe 2024 R7-1.8.0-Gan.gh (1.8 MB)

Have a nice one,

//Rolf

3 Likes