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).
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!):
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.
We’ll see, I will try in VS2022 tonight. Looks good on your side!
Very nice code you wrote.
//Rolf
I didn’t write much. You write very nice code.
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.
//Rolf
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