From 3c90378955137582441a11d81d95d9837ff872e4 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:20:50 +0200 Subject: [PATCH 01/19] feat: add a component to crop point clouds --- src/gh/components/DF_crop_cloud/code.py | 50 +++++++ src/gh/components/DF_crop_cloud/icon.png | Bin 0 -> 723 bytes src/gh/components/DF_crop_cloud/metadata.json | 124 ++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 src/gh/components/DF_crop_cloud/code.py create mode 100644 src/gh/components/DF_crop_cloud/icon.png create mode 100644 src/gh/components/DF_crop_cloud/metadata.json diff --git a/src/gh/components/DF_crop_cloud/code.py b/src/gh/components/DF_crop_cloud/code.py new file mode 100644 index 00000000..9d11bcc3 --- /dev/null +++ b/src/gh/components/DF_crop_cloud/code.py @@ -0,0 +1,50 @@ +from diffCheck import df_cvt_bindings as df_cvt + +import numpy as np + +import Rhino +from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML + +from ghpythonlib.componentbase import executingcomponent as component + +class DFCloudCrop(component): + def __init__(self): + super(DFCloudCrop, self).__init__() + def RunScript(self, + i_cloud: Rhino.Geometry.PointCloud, + i_box: Rhino.Geometry.Brep, + i_x_min: float, + i_y_min: float, + i_z_min: float, + i_x_max: float, + i_y_max: float, + i_z_max: float): + if i_cloud is None: + ghenv.Component.AddRuntimeMessage(RML.Warning, "No point cloud provided. Please connect a point cloud to the input.") # noqa: F821 + return None + + if i_box is not None: + bbox = i_box.GetBoundingBox(True) + bb_min_as_array = np.asarray([bbox.Min.X, bbox.Min.Y, bbox.Min.Z]) + bb_max_as_array = np.asarray([bbox.Max.X, bbox.Max.Y, bbox.Max.Z]) + + ghenv.Component.AddRuntimeMessage(RML.Remark, "A box is provided and is used to crop the point cloud, all other inputs neglected. To use min/max values, disconnect the box") # noqa: F821 + else: + if i_x_min is None: + i_x_min = -np.inf + if i_y_min is None: + i_y_min = -np.inf + if i_z_min is None: + i_z_min = -np.inf + if i_x_max is None: + i_x_max = np.inf + if i_y_max is None: + i_y_max = np.inf + if i_z_max is None: + i_z_max = np.inf + bb_min_as_array = np.asarray([i_x_min, i_y_min, i_z_min]) + bb_max_as_array = np.asarray([i_x_max, i_y_max, i_z_max]) + df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud) + df_cloud.crop(bb_min_as_array, bb_max_as_array) + rh_cloud = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) + return [rh_cloud] diff --git a/src/gh/components/DF_crop_cloud/icon.png b/src/gh/components/DF_crop_cloud/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2d21368a2c48587afc9ebf9ea022ee0f3ac85965 GIT binary patch literal 723 zcmV;^0xbQBP)EX>4Tx04R}tkv&MmKpe$iQ?()$5j%)DWT-A$5EXHhDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRU4&4rtTK|Hf* z>74h8L#!w%#OK8023?T&k?XR{Z=4Gb3p_Jqq?7Z+A!4!6#&R38qM;H`6NeR5qkJLb zvch?bvs$jQ<~{ifgE?&_#dVs)h+zqFBp^aY6(y8mAwsK0iisrcM?L&Qjz2*znOr3> zax9<%6_Voz|AXJ%n)#_oHz^neI$v!2V+0870*#t&e;?a+;{@ zj20++-Q(Te?Y;ebrrF;Q$^LT6;wD4z00006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=>`!DG!QlYKSuxn02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{0065=L_t(Y$JJHI4Z|=DlL8HwY5494eRG;@=e}$Njg!c7 zRG@tMq-0u$N(UrM9RpBtqIb_Cgd^vzw>aYU-MvMUvA0+ Date: Tue, 17 Jun 2025 15:21:54 +0200 Subject: [PATCH 02/19] feat: add cropping capability to DFPointCloud --- src/diffCheck/geometry/DFPointCloud.cc | 15 +++++++++++++++ src/diffCheck/geometry/DFPointCloud.hh | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/src/diffCheck/geometry/DFPointCloud.cc b/src/diffCheck/geometry/DFPointCloud.cc index d00fac65..748245de 100644 --- a/src/diffCheck/geometry/DFPointCloud.cc +++ b/src/diffCheck/geometry/DFPointCloud.cc @@ -216,6 +216,21 @@ namespace diffCheck::geometry this->Normals.push_back(normal); } + void DFPointCloud::Crop(const Eigen::Vector3d &minBound, const Eigen::Vector3d &maxBound) + { + auto O3DPointCloud = this->Cvt2O3DPointCloud(); + auto O3DPointCloudCropped = O3DPointCloud->Crop(open3d::geometry::AxisAlignedBoundingBox(minBound, maxBound)); + this->Points.clear(); + for (auto &point : O3DPointCloudCropped->points_) + this->Points.push_back(point); + this->Colors.clear(); + for (auto &color : O3DPointCloudCropped->colors_) + this->Colors.push_back(color); + this->Normals.clear(); + for (auto &normal : O3DPointCloudCropped->normals_) + this->Normals.push_back(normal); + } + void DFPointCloud::UniformDownsample(int everyKPoints) { auto O3DPointCloud = this->Cvt2O3DPointCloud(); diff --git a/src/diffCheck/geometry/DFPointCloud.hh b/src/diffCheck/geometry/DFPointCloud.hh index b3f0a3be..14d441fb 100644 --- a/src/diffCheck/geometry/DFPointCloud.hh +++ b/src/diffCheck/geometry/DFPointCloud.hh @@ -89,6 +89,14 @@ namespace diffCheck::geometry */ void RemoveStatisticalOutliers(int nbNeighbors, double stdRatio); + /** + * @brief Crop the point cloud to a bounding box defined by the min and max bounds + * + * @param minBound the minimum bound of the bounding box as an Eigen::Vector3d + * @param maxBound the maximum bound of the bounding box as an Eigen::Vector3d + */ + void Crop(const Eigen::Vector3d &minBound, const Eigen::Vector3d &maxBound); + public: ///< Downsamplers /** * @brief Downsample the point cloud with voxel grid From f07431f181972670f52f11bd8d49486dc2c25c72 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Tue, 17 Jun 2025 21:21:27 +0200 Subject: [PATCH 03/19] feat: add binding for cropping capability of point cloud --- src/diffCheckBindings.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/diffCheckBindings.cc b/src/diffCheckBindings.cc index 434f5da2..f32b04b8 100644 --- a/src/diffCheckBindings.cc +++ b/src/diffCheckBindings.cc @@ -54,6 +54,8 @@ PYBIND11_MODULE(diffcheck_bindings, m) { .def("remove_statistical_outliers", &diffCheck::geometry::DFPointCloud::RemoveStatisticalOutliers, py::arg("nb_neighbors"), py::arg("std_ratio")) + .def("crop", &diffCheck::geometry::DFPointCloud::Crop, + py::arg("min_bound"), py::arg("max_bound")) .def("load_from_PLY", &diffCheck::geometry::DFPointCloud::LoadFromPLY) .def("save_to_PLY", &diffCheck::geometry::DFPointCloud::SaveToPLY) From a0289fcb62994d6ad21734db1297bdaccad39d0d Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:55:51 +0200 Subject: [PATCH 04/19] fix: simplify cropping component --- src/gh/components/DF_crop_cloud/code.py | 25 +----- src/gh/components/DF_crop_cloud/metadata.json | 76 +------------------ 2 files changed, 5 insertions(+), 96 deletions(-) diff --git a/src/gh/components/DF_crop_cloud/code.py b/src/gh/components/DF_crop_cloud/code.py index 9d11bcc3..4bbe38f4 100644 --- a/src/gh/components/DF_crop_cloud/code.py +++ b/src/gh/components/DF_crop_cloud/code.py @@ -12,13 +12,7 @@ def __init__(self): super(DFCloudCrop, self).__init__() def RunScript(self, i_cloud: Rhino.Geometry.PointCloud, - i_box: Rhino.Geometry.Brep, - i_x_min: float, - i_y_min: float, - i_z_min: float, - i_x_max: float, - i_y_max: float, - i_z_max: float): + i_box: Rhino.Geometry.Brep): if i_cloud is None: ghenv.Component.AddRuntimeMessage(RML.Warning, "No point cloud provided. Please connect a point cloud to the input.") # noqa: F821 return None @@ -28,22 +22,9 @@ def RunScript(self, bb_min_as_array = np.asarray([bbox.Min.X, bbox.Min.Y, bbox.Min.Z]) bb_max_as_array = np.asarray([bbox.Max.X, bbox.Max.Y, bbox.Max.Z]) - ghenv.Component.AddRuntimeMessage(RML.Remark, "A box is provided and is used to crop the point cloud, all other inputs neglected. To use min/max values, disconnect the box") # noqa: F821 else: - if i_x_min is None: - i_x_min = -np.inf - if i_y_min is None: - i_y_min = -np.inf - if i_z_min is None: - i_z_min = -np.inf - if i_x_max is None: - i_x_max = np.inf - if i_y_max is None: - i_y_max = np.inf - if i_z_max is None: - i_z_max = np.inf - bb_min_as_array = np.asarray([i_x_min, i_y_min, i_z_min]) - bb_max_as_array = np.asarray([i_x_max, i_y_max, i_z_max]) + ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide a box to crop the point cloud with") # noqa: F821 + df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud) df_cloud.crop(bb_min_as_array, bb_max_as_array) rh_cloud = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) diff --git a/src/gh/components/DF_crop_cloud/metadata.json b/src/gh/components/DF_crop_cloud/metadata.json index 9962b083..b0f7f30c 100644 --- a/src/gh/components/DF_crop_cloud/metadata.json +++ b/src/gh/components/DF_crop_cloud/metadata.json @@ -17,7 +17,7 @@ "name": "i_cloud", "nickname": "i_cloud", "description": "The point cloud to crop.", - "optional": true, + "optional": false, "allowTreeAccess": true, "showTypeHints": true, "scriptParamAccess": "item", @@ -29,85 +29,13 @@ "name": "i_box", "nickname": "i_box", "description": "The brep box to crop the point cloud with.", - "optional": true, + "optional": false, "allowTreeAccess": true, "showTypeHints": true, "scriptParamAccess": "item", "wireDisplay": "default", "sourceCount": 0, "typeHintID": "brep" - }, - { - "name": "i_x_min", - "nickname": "i_x_min", - "description": "The minimum x value to crop the point cloud with.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "float" - }, - { - "name": "i_y_min", - "nickname": "i_y_min", - "description": "The minimum y value to crop the point cloud with.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "float" - }, - { - "name": "i_z_min", - "nickname": "i_z_min", - "description": "The minimum z value to crop the point cloud with.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "float" - }, - { - "name": "i_x_max", - "nickname": "i_x_max", - "description": "The maximum x value to crop the point cloud with.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "float" - }, - { - "name": "i_y_max", - "nickname": "i_y_max", - "description": "The maximum y value to crop the point cloud with.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "float" - }, - { - "name": "i_z_max", - "nickname": "i_z_max", - "description": "The maximum z value to crop the point cloud with.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "float" } ], "outputParameters": [ From a98b80fc3ef24a3f98f5a8619d78744b0cc898ea Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:56:01 +0200 Subject: [PATCH 05/19] feat: add point cloud subtraction method and implement it in component --- src/diffCheck/geometry/DFPointCloud.cc | 44 ++++++++++++ src/diffCheck/geometry/DFPointCloud.hh | 9 +++ src/diffCheckBindings.cc | 3 + src/gh/components/DF_cloud_subtractor/code.py | 25 +++++++ .../components/DF_cloud_subtractor/icon.png | Bin 0 -> 12377 bytes .../DF_cloud_subtractor/metadata.json | 64 ++++++++++++++++++ 6 files changed, 145 insertions(+) create mode 100644 src/gh/components/DF_cloud_subtractor/code.py create mode 100644 src/gh/components/DF_cloud_subtractor/icon.png create mode 100644 src/gh/components/DF_cloud_subtractor/metadata.json diff --git a/src/diffCheck/geometry/DFPointCloud.cc b/src/diffCheck/geometry/DFPointCloud.cc index 748245de..4b14c500 100644 --- a/src/diffCheck/geometry/DFPointCloud.cc +++ b/src/diffCheck/geometry/DFPointCloud.cc @@ -273,6 +273,50 @@ namespace diffCheck::geometry return bboxPts; } + void DFPointCloud::SubtractPoints(const DFPointCloud &pointCloud, double distanceThreshold) + { + if (this->Points.size() == 0 || pointCloud.Points.size() == 0) + throw std::invalid_argument("One of the point clouds is empty."); + + auto O3DSourcePointCloud = this->Cvt2O3DPointCloud(); + auto O3DTargetPointCloud = std::make_shared(pointCloud)->Cvt2O3DPointCloud(); + auto O3DResultPointCloud = std::make_shared(); + + open3d::geometry::KDTreeFlann threeDTree; + threeDTree.SetGeometry(*O3DTargetPointCloud); + std::vector indices; + std::vector distances; + for (const auto &point : O3DSourcePointCloud->points_) + { + threeDTree.SearchRadius(point, distanceThreshold, indices, distances); + if (indices.empty()) + { + O3DResultPointCloud->points_.push_back(point); + if (O3DSourcePointCloud->HasColors()) + { + O3DResultPointCloud->colors_.push_back(O3DSourcePointCloud->colors_[&point - &O3DSourcePointCloud->points_[0]]); + } + if (O3DSourcePointCloud->HasNormals()) + { + O3DResultPointCloud->normals_.push_back(O3DSourcePointCloud->normals_[&point - &O3DSourcePointCloud->points_[0]]); + } + } + } + this->Points.clear(); + for (auto &point : O3DResultPointCloud->points_) + this->Points.push_back(point); + if (O3DResultPointCloud->HasColors()) + { + this->Colors.clear(); + for (auto &color : O3DResultPointCloud->colors_){this->Colors.push_back(color);}; + } + if (O3DResultPointCloud->HasNormals()) + { + this->Normals.clear(); + for (auto &normal : O3DResultPointCloud->normals_){this->Normals.push_back(normal);}; + } + } + void DFPointCloud::ApplyTransformation(const diffCheck::transformation::DFTransformation &transformation) { auto O3DPointCloud = this->Cvt2O3DPointCloud(); diff --git a/src/diffCheck/geometry/DFPointCloud.hh b/src/diffCheck/geometry/DFPointCloud.hh index 14d441fb..42deba0a 100644 --- a/src/diffCheck/geometry/DFPointCloud.hh +++ b/src/diffCheck/geometry/DFPointCloud.hh @@ -144,6 +144,15 @@ namespace diffCheck::geometry * /// */ std::vector GetTightBoundingBox(); + + public: ///< Point cloud subtraction + /** + * @brief Subtract the points, colors and normals from another point cloud when they are too close to the points of another point cloud. + * + * @param pointCloud the other point cloud to subtract from this one + * @param distanceThreshold the distance threshold to consider a point as too close. Default is 0.01. + */ + void SubtractPoints(const DFPointCloud &pointCloud, double distanceThreshold = 0.01); public: ///< Transformers /** diff --git a/src/diffCheckBindings.cc b/src/diffCheckBindings.cc index f32b04b8..ce89972b 100644 --- a/src/diffCheckBindings.cc +++ b/src/diffCheckBindings.cc @@ -41,6 +41,9 @@ PYBIND11_MODULE(diffcheck_bindings, m) { .def("downsample_by_size", &diffCheck::geometry::DFPointCloud::DownsampleBySize, py::arg("target_size")) + .def("subtract_points", &diffCheck::geometry::DFPointCloud::SubtractPoints, + py::arg("point_cloud"), py::arg("distance_threshold")) + .def("apply_transformation", &diffCheck::geometry::DFPointCloud::ApplyTransformation, py::arg("transformation")) diff --git a/src/gh/components/DF_cloud_subtractor/code.py b/src/gh/components/DF_cloud_subtractor/code.py new file mode 100644 index 00000000..423ca2b1 --- /dev/null +++ b/src/gh/components/DF_cloud_subtractor/code.py @@ -0,0 +1,25 @@ +from diffCheck import df_cvt_bindings as df_cvt + +import Rhino +from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML + +from ghpythonlib.componentbase import executingcomponent as component + +class DFCloudSubtract(component): + def __init__(self): + super(DFCloudSubtract, self).__init__() + def RunScript(self, + i_cloud_subtract_from: Rhino.Geometry.PointCloud, + i_cloud_subtract_with: Rhino.Geometry.PointCloud, + i_distance_threshold: float): + df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_subtract_from) + df_cloud_substract = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_subtract_with) + if i_distance_threshold is None: + ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold not defined. 0.01 used as default value.")# noqa: F821 + i_distance_threshold = 0.01 + if i_distance_threshold <= 0: + ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold must be greater than 0. Please provide a valid distance threshold.")# noqa: F821 + return None + df_cloud.subtract_points(df_cloud_substract, i_distance_threshold) + rh_cloud = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) + return [rh_cloud] diff --git a/src/gh/components/DF_cloud_subtractor/icon.png b/src/gh/components/DF_cloud_subtractor/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1bcd01ff2a4f212c87192a0500dd585f0add6401 GIT binary patch literal 12377 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 literal 0 HcmV?d00001 diff --git a/src/gh/components/DF_cloud_subtractor/metadata.json b/src/gh/components/DF_cloud_subtractor/metadata.json new file mode 100644 index 00000000..4a3b1545 --- /dev/null +++ b/src/gh/components/DF_cloud_subtractor/metadata.json @@ -0,0 +1,64 @@ +{ + "name": "DFSubtractCloud", + "nickname": "Subtract", + "category": "diffCheck", + "subcategory": "Cloud", + "description": "Subtracts points from a point cloud based on a distance threshold.", + "exposure": 4, + "instanceGuid": "9ef299aa-76dc-4417-9b95-2a374e2b36af", + "ghpython": { + "hideOutput": true, + "hideInput": true, + "isAdvancedMode": true, + "marshalOutGuids": true, + "iconDisplay": 2, + "inputParameters": [ + { + "name": "i_cloud_subtract_from", + "nickname": "i_cloud_subtract_from", + "description": "The point cloud to subtract from.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud" + }, + { + "name": "i_cloud_subtract_with", + "nickname": "i_cloud_subtract_with", + "description": "The point cloud to subtract with.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud" + }, + { + "name": "i_distance_threshold", + "nickname": "i_distance_threshold", + "description": "The distance threshold to consider a point as too close.", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "brep" + } + ], + "outputParameters": [ + { + "name": "o_cloud", + "nickname": "o_cloud", + "description": "The resulting cloud after subtraction.", + "optional": false, + "sourceCount": 0, + "graft": false + } + ] + } +} \ No newline at end of file From fcc1936e981058138f0e8b56b13bf9bc4333b6d7 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:26:50 +0200 Subject: [PATCH 06/19] feat: add point cloud duplication for python binding --- src/diffCheck/geometry/DFPointCloud.cc | 5 +++++ src/diffCheck/geometry/DFPointCloud.hh | 7 +++++++ src/diffCheckBindings.cc | 3 +++ 3 files changed, 15 insertions(+) diff --git a/src/diffCheck/geometry/DFPointCloud.cc b/src/diffCheck/geometry/DFPointCloud.cc index 4b14c500..160f55e4 100644 --- a/src/diffCheck/geometry/DFPointCloud.cc +++ b/src/diffCheck/geometry/DFPointCloud.cc @@ -231,6 +231,11 @@ namespace diffCheck::geometry this->Normals.push_back(normal); } + DFPointCloud DFPointCloud::Duplicate() const + { + return DFPointCloud(this->Points, this->Colors, this->Normals); + } + void DFPointCloud::UniformDownsample(int everyKPoints) { auto O3DPointCloud = this->Cvt2O3DPointCloud(); diff --git a/src/diffCheck/geometry/DFPointCloud.hh b/src/diffCheck/geometry/DFPointCloud.hh index 42deba0a..a8779313 100644 --- a/src/diffCheck/geometry/DFPointCloud.hh +++ b/src/diffCheck/geometry/DFPointCloud.hh @@ -97,6 +97,13 @@ namespace diffCheck::geometry */ void Crop(const Eigen::Vector3d &minBound, const Eigen::Vector3d &maxBound); + /** + * @brief Get the duplicate of the point cloud. This is mainly used in the python bindings + * + * @return DFPointCloud a copy of the point cloud + */ + diffCheck::geometry::DFPointCloud Duplicate() const; + public: ///< Downsamplers /** * @brief Downsample the point cloud with voxel grid diff --git a/src/diffCheckBindings.cc b/src/diffCheckBindings.cc index ce89972b..65426909 100644 --- a/src/diffCheckBindings.cc +++ b/src/diffCheckBindings.cc @@ -57,9 +57,12 @@ PYBIND11_MODULE(diffcheck_bindings, m) { .def("remove_statistical_outliers", &diffCheck::geometry::DFPointCloud::RemoveStatisticalOutliers, py::arg("nb_neighbors"), py::arg("std_ratio")) + .def("crop", &diffCheck::geometry::DFPointCloud::Crop, py::arg("min_bound"), py::arg("max_bound")) + .def("duplicate", &diffCheck::geometry::DFPointCloud::Duplicate) + .def("load_from_PLY", &diffCheck::geometry::DFPointCloud::LoadFromPLY) .def("save_to_PLY", &diffCheck::geometry::DFPointCloud::SaveToPLY) From d65fb17cd2117289e9184040d239fadac629c115 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:29:44 +0200 Subject: [PATCH 07/19] feat: add capacity to crop with any brep, and keep trace of in and out points --- src/gh/components/DF_crop_cloud/code.py | 34 ++++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/gh/components/DF_crop_cloud/code.py b/src/gh/components/DF_crop_cloud/code.py index 4bbe38f4..9e08f98d 100644 --- a/src/gh/components/DF_crop_cloud/code.py +++ b/src/gh/components/DF_crop_cloud/code.py @@ -1,3 +1,4 @@ +"""Crops a point cloud by giving the bounding box or a brep.""" from diffCheck import df_cvt_bindings as df_cvt import numpy as np @@ -7,25 +8,44 @@ from ghpythonlib.componentbase import executingcomponent as component +TOL = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance + class DFCloudCrop(component): def __init__(self): super(DFCloudCrop, self).__init__() + def RunScript(self, i_cloud: Rhino.Geometry.PointCloud, - i_box: Rhino.Geometry.Brep): + i_box: Rhino.Geometry.Brep, + i_brep: Rhino.Geometry.Brep): if i_cloud is None: - ghenv.Component.AddRuntimeMessage(RML.Warning, "No point cloud provided. Please connect a point cloud to the input.") # noqa: F821 + ghenv.Component.AddRuntimeMessage(RML.Warning,"No point cloud provided. Please connect a point cloud to the input.")# noqa: F821 return None if i_box is not None: bbox = i_box.GetBoundingBox(True) bb_min_as_array = np.asarray([bbox.Min.X, bbox.Min.Y, bbox.Min.Z]) bb_max_as_array = np.asarray([bbox.Max.X, bbox.Max.Y, bbox.Max.Z]) + df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud) + df_cloud_copy = df_cloud.duplicate() + df_cloud.crop(bb_min_as_array, bb_max_as_array) + df_cloud_copy.subtract_points(df_cloud, TOL) + o_pts_out = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud_copy) + o_pts_in = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) + + elif i_brep is not None: + pts_in = [] + pts_out = [] + for pc_item in i_cloud: + point = Rhino.Geometry.Point3d(pc_item.X, pc_item.Y, pc_item.Z) + if i_brep.IsPointInside(point, TOL, True): + pts_in.append(point) + else: + pts_out.append(point) + o_pts_in = Rhino.Geometry.PointCloud(pts_in) + o_pts_out = Rhino.Geometry.PointCloud(pts_out) else: - ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide a box to crop the point cloud with") # noqa: F821 + ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide a box to crop the point cloud with") # noqa: F821 - df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud) - df_cloud.crop(bb_min_as_array, bb_max_as_array) - rh_cloud = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) - return [rh_cloud] + return [o_pts_in, o_pts_out] From 10d19437b13e1ad4a35d00995126389c2e3353f2 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Wed, 30 Jul 2025 14:47:33 +0200 Subject: [PATCH 08/19] feat: add point cloud intersection calculation --- src/diffCheckBindings.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/diffCheckBindings.cc b/src/diffCheckBindings.cc index 65426909..6436cfad 100644 --- a/src/diffCheckBindings.cc +++ b/src/diffCheckBindings.cc @@ -43,6 +43,9 @@ PYBIND11_MODULE(diffcheck_bindings, m) { .def("subtract_points", &diffCheck::geometry::DFPointCloud::SubtractPoints, py::arg("point_cloud"), py::arg("distance_threshold")) + + .def("intersect", &diffCheck::geometry::DFPointCloud::Intersect, + py::arg("point_cloud"), py::arg("distance_threshold")) .def("apply_transformation", &diffCheck::geometry::DFPointCloud::ApplyTransformation, py::arg("transformation")) From 02b47561349c44a29c17eeb3e8fdc0e62b527799 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Wed, 30 Jul 2025 14:48:28 +0200 Subject: [PATCH 09/19] feat: add point cloud intersection calculation component --- src/gh/components/DF_cloud_intersect/code.py | 25 +++++++ src/gh/components/DF_cloud_intersect/icon.png | Bin 0 -> 15224 bytes .../DF_cloud_intersect/metadata.json | 64 ++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/gh/components/DF_cloud_intersect/code.py create mode 100644 src/gh/components/DF_cloud_intersect/icon.png create mode 100644 src/gh/components/DF_cloud_intersect/metadata.json diff --git a/src/gh/components/DF_cloud_intersect/code.py b/src/gh/components/DF_cloud_intersect/code.py new file mode 100644 index 00000000..76247329 --- /dev/null +++ b/src/gh/components/DF_cloud_intersect/code.py @@ -0,0 +1,25 @@ +from diffCheck import df_cvt_bindings as df_cvt + +import Rhino +from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML + +from ghpythonlib.componentbase import executingcomponent as component + +class DFCloudIntersect(component): + def __init__(self): + super(DFCloudIntersect, self).__init__() + def RunScript(self, + i_cloud_intersect_from: Rhino.Geometry.PointCloud, + i_cloud_intersect_with: Rhino.Geometry.PointCloud, + i_distance_threshold: float): + df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_intersect_from) + df_cloud_intersect = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_intersect_with) + if i_distance_threshold is None: + ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold not defined. 0.01 used as default value.")# noqa: F821 + i_distance_threshold = 0.01 + if i_distance_threshold <= 0: + ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold must be greater than 0. Please provide a valid distance threshold.")# noqa: F821 + return None + df_intersection = df_cloud.intersect(df_cloud_intersect, i_distance_threshold) + rh_cloud = df_cvt.cvt_dfcloud_2_rhcloud(df_intersection) + return [rh_cloud] diff --git a/src/gh/components/DF_cloud_intersect/icon.png b/src/gh/components/DF_cloud_intersect/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6eeb70e5d57952be1ef6df01883d20618cbad9b4 GIT binary patch literal 15224 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 XKaw4tEkgbm#@O@q literal 0 HcmV?d00001 diff --git a/src/gh/components/DF_cloud_intersect/metadata.json b/src/gh/components/DF_cloud_intersect/metadata.json new file mode 100644 index 00000000..e95370c9 --- /dev/null +++ b/src/gh/components/DF_cloud_intersect/metadata.json @@ -0,0 +1,64 @@ +{ + "name": "DFSubtractCloud", + "nickname": "Subtract", + "category": "diffCheck", + "subcategory": "Cloud", + "description": "Subtracts points from a point cloud based on a distance threshold.", + "exposure": 4, + "instanceGuid": "b1a87021-dc4d-4844-86e0-8dcf55965ac6", + "ghpython": { + "hideOutput": true, + "hideInput": true, + "isAdvancedMode": true, + "marshalOutGuids": true, + "iconDisplay": 2, + "inputParameters": [ + { + "name": "i_cloud_intersect_from", + "nickname": "i_cloud_intersect_from", + "description": "The point cloud to intersect from.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud" + }, + { + "name": "i_cloud_intersect_with", + "nickname": "i_cloud_intersect_with", + "description": "The point cloud to intersect with.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud" + }, + { + "name": "i_distance_threshold", + "nickname": "i_distance_threshold", + "description": "The distance threshold to consider a point as too close.", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "float" + } + ], + "outputParameters": [ + { + "name": "o_cloud", + "nickname": "o_cloud", + "description": "The resulting cloud after intersection.", + "optional": false, + "sourceCount": 0, + "graft": false + } + ] + } +} \ No newline at end of file From bbbee0704413dbd8474913eaf56405f41fcefa3b Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Wed, 30 Jul 2025 14:49:33 +0200 Subject: [PATCH 10/19] feat: add point cloud merge component --- src/gh/components/DF_cloud_merge/code.py | 27 ++++++++++++ src/gh/components/DF_cloud_merge/icon.png | Bin 0 -> 15210 bytes .../components/DF_cloud_merge/metadata.json | 41 ++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/gh/components/DF_cloud_merge/code.py create mode 100644 src/gh/components/DF_cloud_merge/icon.png create mode 100644 src/gh/components/DF_cloud_merge/metadata.json diff --git a/src/gh/components/DF_cloud_merge/code.py b/src/gh/components/DF_cloud_merge/code.py new file mode 100644 index 00000000..c0948e5e --- /dev/null +++ b/src/gh/components/DF_cloud_merge/code.py @@ -0,0 +1,27 @@ +"""Merges point clouds together.""" +import diffCheck +from diffCheck.diffcheck_bindings import dfb_geometry as df_geometry +import Rhino + +import System + +from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML + +from ghpythonlib.componentbase import executingcomponent as component + +TOL = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance + +class DFMergeAssemblies(component): + def RunScript(self, + i_clouds: System.Collections.Generic.List[Rhino.Geometry.PointCloud]): + if i_clouds is None or len(i_clouds) == 0: + ghenv.Component.AddRuntimeMessage(RML.Warning, "No point clouds provided. Please connect point clouds to the input.") # noqa: F821 + return None + + merged_cloud = df_geometry.DFPointCloud() + for cloud in i_clouds: + df_cloud = diffCheck.df_cvt_bindings.cvt_rhcloud_2_dfcloud(cloud) + merged_cloud.add_points(df_cloud) + + o_cloud = diffCheck.df_cvt_bindings.cvt_dfcloud_2_rhcloud(merged_cloud) + return [o_cloud] diff --git a/src/gh/components/DF_cloud_merge/icon.png b/src/gh/components/DF_cloud_merge/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bda1f58c544d019981fe7bb2a8309ad54942e81d GIT binary patch literal 15210 zcmeHuWl&t(wl40$5=0Xw-DSNf(LhZcerHlBm305 zRj*FHd*83qRjb!pbAIESV|-)GHG5Uf4p&iU;17V@~>CU(IChO^j{O;A>o3Q$v)UgiV&mp_S zBJo>~)5A-bs9Q&O(b3cUWi7l}tb9HjH-|?e3LZ;OC!Tli{&yuOYWFUmITi_S%UCCl z-?cp7TuHy9a=2$(LZ7@6UtA#A_w;wkyU5W!y<#|bZfVJC8E8!!eV?0Iv2Ao!v-C*H zQN&AibutXJedt(vY~Ib7*5YbDk=V37x{w}VCGnj*yNix32l(pcjXW_@%@SK&@1^-v z^lvF&9<}hc=rMi20zTGBDP=7^-Fh0YEtNPVKF(!GxcfS^Jo*5&4#Rx(yuA;E2810= z@PX8cpr%i^$^AFsSI#z{^$0qCj(xiMpih}4k|2UuM)tkkt9$&0)2as3(VAqxddQ|> z_zH|Hfnh_GbkkP9a(@FonbF{F+$T8iu}Sj27$?~0kD3W|%`&dos=XlEoG-E4GIuYk z(tpEpT=tagd*|PThn5)jq|em7k&d4R?sd3Ls{`XSEJ=Md^%r@(f6Ut7tuUNmWRhe= zpF5)QsD3ZI9Q|3yHqxtw-R#VZwH4QXuh%dv(6A!)VwCm{vQ=5b3~3Yn_*sBlzXy&- znwKaCeUZ*eE!}2Frc%h(dGy4x;|P|M8ONJ)6Aj;jkSQqaXJALKiJAr%ekR2Qo4OVyCH5oT2_#uIjh|}{ ze;j?58CM%=I-i|u^_C{I&xw^Ga<1O_mbKjThI52t&uV~0-#i#kOV>R?Lu>B)?4?O4 zsq3tJl7Z`8^{nO8bD-!&Gt(A_+VZx8S(| z=mz>sl$|A|oG>{0O~(6;wAq;VR%^*?IS+N!6Yt9QO&qSfY!08M9i+eAB_-aC+xS+^ zsuL6U81bUj7mrDkGj zvMjq^={rveYL((k7Sa^gOrIL_oSg|hj_b{nBzuM~mAy~hvp&e%!kz1_P(Ff-(6-dY zV5Es2weHbrUGIkTtnzqm=t=YuS~h(71C0z;uxj6@me53}aZ&S#>K3YoTwWu{n6tR#%~r zsS9g*r4v4BN^KK>uG?AbeY@qFT$@I|aKvwFv%sW)(FAl&&#}^6p7+_1u}tNy2iuz3 zk2HC#Y~4&u_~RTVV|e zR%+@uP7W0`*&y9I?^CLCac-4V+fH05;$+f(FH=(`7@0}9?S={8p7#328T+JpLaYh*&= zu>s8JRBr%rAIlSYkOXP{li|{|IdHf??er%&)c5LEx_vjM9mI`!A-g%O{$65@u!(2x zo>5>f1o;Y;9xiBpfOtyni7AEPP3TMR5I1n}#miztVo|7X0Ge8%`rG#3R<^x}o6XJxVb@;Rhc3L5;*)BTX(p&mOQmB$UZ6T>@)52kP45SfQ z#RN|?j_b4`4Pz|B*Yx=vmv$5yh9SaEA-|-TPlfM=w?yIpm4FNt%V?hey5T#o!-P-y zPOk_0s-91pSzN*kK~BdSJ(o+9z=awm*szOBy=4-oSqZEn9yd3TC7hD2oT z{DNbqzc!AqQV?OIqL4z^jhQ3Ly=gQbl$L!t$0MJ7|i|= z9o?{EUSbU4Iesn(FTq^+L0IV_Hc? z5d$WXg?pGoJE=rb0q_+0`%!K9!*J)TFmBcAusiNCAVcy`DR8eRJ?!6=s=k~8tQ+|F z39#@Q2TLgF=_t9Lig~MGkzi8GFxrSS_WBARN}Vc|h~!X>NT%suC$f0GB|9!kb9Y# zyX8_K$IF}Jw2T5y3Y8<1;5&Mq{$Bt|dg>L-`mR_jON{j(98H`fd0_n%i$(zktPDqV zw-psV#z=vWHUUy*=ojapmpTdlzEMQQVoFn^pPdpZ8i>vjJHj?4kXyU=REA8Dx%#Q? z$_37CS5k0#0(AhuQMN1{i*SwX*xqTk9Q(CSWuLXYds|gF{jjbYlnbGp!K!!P0TUyY z=Tzx8v?(0NdMh|>Ok;7dS6VIJDj0_+FdgAs{*M-+A&O_s$vSj~(Zz~(Ba{areY{-J z3=@^ahg_m+p=q@D(}>|t*Sz0nfS0_w17B(odbft5_F2d0TVp@$1$R8^A5n!{h4J!| zQOI5d2dcYx;&3?8|HPM#5GmJG9MXV=6wdX>%H03@a?Q_Dhtjv$Qe!+}-Xcm|G;s#W{$kyg}5T@glb}B>` z*qo3Ni1$-l+w^>)UNWAu5B%1N5QnncPRRX*$qZ%d_%6Ig=(I=y1z(}0x!G||P_U^> zBRT6JkBG(_6~=8`O@9Bg5VqZ}2|~th`n4Cx!2|4N*VdhPCt03rxgElgHYeDmvdcn-R~d`fcDa5 zSNfOD73TcH$bK}+2|ucLX9q0vlG`meZY1U~$YKqMVSljWfiuqku~J@3h(YZ`L*?oR zi8;h9qg9X=hQBk{^peB~$*!Om4I{t5y_2Qt^qSEi)Tp$b7)}M3&(;HRT!-m#jceZ-Il`g@arjcoM>F}7jv}$G&i0iQ4!c-%sE*Zh&}|qvv%66qz37b%bmilza}fSSs7Y#)wd)OhD`S#oz&3~3~&QUJ?2==eJc&uK>U z=CfyKkmJZtnW#n1uLAE2_s_6wb=D>V6KS6A#NrG1AT)U24}eH35xFAydFHs7)CUY$ zKsWkE&8|XOH1Rk2sr3}7Y22&iu$Oomx!ChXt!w`@gDbG8jm34cq{VTI6j-GGfs3vM z!(2*(EcYJMXr01XPOU&+<`v&Bren?BBp-N8=6CXb*LXVb^nKY;akvk3_3#wjq;kMXEtHUk1z>%VZNKhO0$K z8DdAd9DPG#4-lMQSt6747cY3EamZx6S9L$oVz7%BZJul@gVVXw1gO!VdlmMUf9J$b zm2;S!*Pw1_M5H0a;3X3UE>;8HYM%LEHrUwlQd|=(8GMFskY!O0d(~C-p4t%~@nsx- zZ~;X{X)#uIB-Ux!YV0V#XpU_-O)CxlS;s+#julDGKtdNW$!p9Dhxh8%TUXQV?am4m zyqLa@a(hN`xoLNooIcddwxO$z1;N+GMB#dJUmp?hejGEK{cvIE@#r7waJyvSOC@KF zDlX^`V+D5qRQm~k-v-7;7q&x1d4(X8P6+eq(3RnxLCfi6)m!I>;f57h3_7PB`R{ND z0NMi7ZC7m_)ysBVujDs-9dU5t5ru@fUwKeS=>sq$68f4hs~#O6XI-YzAl>upxA%s` zvk5V;mofMA)~onk6U6W!8Z!krUcit9d7Rcg6BMOyNRMs##y0*1H(H^Byi46`(e2Xg zoYae_%15nCh9Y-6#TInpe11|u-L`^Uj zXGZZO=^p~r2EE+h|1^Ra{K9*KvhF4rn~WNja;Y|gzn ztRM@MA2cmc8wH?sr|C-;`suLV7TI5wL^e$q&6t7Dq7l7am}e-i;^~&FrZLn9 z`TTu!88%u$xJq1XhdAnOG55?#sAnQ+Snt~9)TB+>{D(>xvI9!oGCd}<^MUsx#s*B+ z2xBBjAMm@r)+SfgmY7z<;F2A{cSFnW1k*-|t#t+uUK&!^HsA`T?OJurl? z=pCt-W2ZbFBp!!14dPCusbn{4^H%4XS_G8u?}w`x8gQdEX6&oX`e%8yv-TxLe!&W) zI!(%sr;bSa8se=E?bT6~93;wB76&NEo%bq4Z?}=hrpYU8_7JoYxBRT>_gKHrPq%$< zjnM-~1yVXycVax5A1WEa*x)kZwX4eKo=M9lduY~O)S^ozVeH1x;Guzq&oPeW_QT?| zpPBt&;lY?tw7jUnW6C$@F8x;hJJw2KkWYbjOPW8mT(aLy#u9H0I{IcD8O7d^ zZEdWwK9=a{xLX3y+S^+m|Ck$wCFU~}0an~4I3|u2#8o}R;8E1Dh}x1_F|AZRE6tdl&Fy=@9mJUA!t-aqTlg!F1^aqyqp#=p%*J zOPXufBQ(D5SdC>)#zI60S}}}RK1@)XL|)8gl5Wo9gj$v&OuK?^j9;(V>6K0Y+O;DW z_HoX`+Z@c^b@JXdB?-`kk9?xZ`=OJ*^U`&~YXizqv5PMScw6RU>SB6gnis7^%N{Xv z6x+`E#BViTAssG(b2F$F0#u#hlkEzrCn1D2ruY)UxT`P+v|StaDejff4IZMYjZfqh z?*tAU!nt1RM}A}MBH?(!p?f!=QbBd*Z*qhdQ7mo?4uFiX6E>BHVr<^c#HHlXj)}-q zhRD7SOOO(m-dm=D(~D~!=Y!Exjk_E=0A}h;nqZ}p>wP|7TGe5T=`gLOcKzp6T!zObm^opWzQ_1H(W?0XbPaIhXLOd~hKz01htKMu(>MAa@J z7B&N2uM;$4JkSnrjUbmT;Q+r{kXV|JzSPmbz&bT4TxX%|!p=`LH4#nIuUgiEiZWxoFWSdP0UH#N4iGw*MR5G=3298!C@B1<1O z7X{N;K;o~!6Ass^_=sKYIq`{;aZ!0v5z}|w6<8U>EOLmxF0jb@N#o|{2I?}AAhXFD zi4b7aP|y{I>Eu?MFYnS2Wg~*2+5x6nwZeL2JZy0Xs2!npg8rC1u=GZJ!8Tj(6LWwL ztv=F1*$Zn8BswP>bfQ3>uvW$S+=D=6B&jZ|yvYzkoL*$$x^86U5w^`9oI|n{T_H6d zQJRpvz0U-F9VBNI>0G1q*vTg1HlD?~lMTYS z3@utt3rn)z^PzmP!ASlkUFLQe^;k6G*)aQF#?1gRa;>L#D|Q`&sx90>{DIl>V^sZ@9O6%E<<-}plKo}R+Y0ln*zBjI0ft88 z)}E!N?_@71YwWXjV}k00a`)*B`nKi^NK2x%-o`+bk-T=zUi1{rhN|yNu&R>=(Oh35 z2Vu{$7i8r`c621AFn<^e;+eFaw`>CAhH1Rzc~6FG+N75}B+c%G>wYi0zA^PV@dj29 zpk62n#ff3D} zaagm-Ev+x=H4Bp=t#^~&B(jAFB|HvUUqA4MaisRkttR0~FGv2MMWK$#DOCQsbf6#3 zWhm8o9)H1GSgD}lk1lriYf@fHpg<{_v;3D`>Ovm}TTtK|ZgEzPfx(=5sB;#mcb%gB zT=V;f;Cv5Pe>EfS3>S-DFa<_^jA^Ic_n;KH&g?3eqb4eb1bCX1?-oD9e`4pliJz02 zd<6wwS`Ci3qiMIUk{8GBe^qq2xNbGP1m>ELuqYO#hBoUtzhkcX8Uv$3Wyj42QA^+p z-aQtK5Pp#lntCOV1yoxLK)w(%2p=ThH}Rzj%%DH&iLx$Z*^e4D z?&%<)ESdH&60RqPZp344&3i#?U8Xx~)+LH(SPaG{lQoUJrWbz z{>$$dvl@r!xiDF@CTl4ID!Q|q+0}Lby6@}(4{3i%W6)~1SYUt9M%5d>1wGmzh-eRX zbz$LkzLIZEGtvP{^dO^qmHN=#+fpuT#ix!Ul0{FD`-F}wV|8eUWMllV?w9qf!a>@# zYx`Ey#XLeqC8yD)ZIMu=GJQPmGn4D$O|?#%-F^K)46XKQmas|T5y88I-IbR}C55-m zgA`w(GleN7EEJ_X**B;TOzb_1F)`!EUGuG#a5%!5fs7&!kn{wYystH3>=5lUpuL|Y>x_HiP>932DhK$2%t_`Rnmg@&%qrJ1btOwIIk zmR3oZN#YMd3XkvOb|*mc$I%$1xEQ4xv7vdf6Ky)t?bESZgYm_R*z303$=r8o-rWsn zh_Z~9fn0}#+b-f87cSymbuZDr3q#LeN2*c5vXnQvnDewJ{xpizMD%ND^Q0M}pd&66 z!pkqA+_1J+O;LS~s~nw|&}iMdVzt{|js#~CViOBD9BaBC4=XlW{BEIumXq7PcDymm zFE*F>BfRa2VbDB&ok4_GzKOz9kcyR-wPsj>CJ=jkD=-;Zq|d6(ei*{B;0iNUYa1&i zR*LwvLs^oS!kqrmTJUaRD4%ah1Igl;+jQ#-KApG0{ejnQ@pl?7JXO$r(<=U3fqD3c za1Z}m_C_^!N{gD0NGakG8qq#_nhW{IV{(9vf|4OzUzk@CgwtGHMo+=?1niF?w7$)! zl;Qjq+b`uRiG^WKcN6DlTpvuwIRg8$Y|Kns?T$m=8%Ty!}lk1=~`Cv#)vBgVw?c zDCLHym&r2||HdOUqqp zl`mp$%xhx@8q+SRH0?GFb;29_3-d$oY6wD59TA`bsk^EDQ|=4i9EvS;-FjR8$|p~Ix;QZ+~^<#=~eq7o&%-OI7BB_i^rO=+51OAYXr`7CG$AxW9<+O@qhp3_|DFZn)w~4 zj%pbhwET&dQcJ8_dGX}xrP!vg04|pXTo(sxg{L~pr$Jy{*W7O9@uJy1diiDT;(I@D zo4p6vU*}?1&N`Yh@jT5=iz2(f@XvHY3d&C2$|>#{Bei0Y5ss&77Ze^B`;E2O@3{3l zVpFMd?UE%<2Y`E(=_P&C_a1sJ9$IJo3h`~u_+O)-P3YqLBjgCAS0ZX7xMF?@&Nfo` zCQu|uK;tQBhX-$UVuM{|IYr=>d`$yJV*J>Du{>6Yfp_phM+1B-ly1C+^KEb2oI5|= zx*NumdWZ`O*+G-Rq+C`(A*b0uR{DIjHUF0FjdS4$5!co#x=O?@rZAnh=>Dh;`IYBk ze%V}C{rt}A{>otvWyuf-sJ`)9O6Aul1vy8Fi;rm0szA{fCM~Z)sk36MoZ;NlrTMS> zoTzrTZx?$9m`Ev`?jpWWKCkCZ<-JssoNe7eXFWP5iIb>Tw%s zrr-e*(psFdwdNXez)Ym(;H_4=oy+#T@_}d~* z1*E$BF~||lq|G!H%cMCM5BR`29lnBf#voza?O*0gj$qD_FWB-D;WTv8GqqP=m&J

F8h)fwO#_q{sW+%T)gFp&r4%Z5$F{TwBl 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 B{F49x literal 0 HcmV?d00001 diff --git a/src/gh/components/DF_cloud_merge/metadata.json b/src/gh/components/DF_cloud_merge/metadata.json new file mode 100644 index 00000000..8e9a323c --- /dev/null +++ b/src/gh/components/DF_cloud_merge/metadata.json @@ -0,0 +1,41 @@ +{ + "name": "DFMergeClouds", + "nickname": "DFMergeClouds", + "category": "diffCheck", + "subcategory": "Cloud", + "description": "This component merges a series of point clouds into a unique point cloud.", + "exposure": 4, + "instanceGuid": "1e5e3ce8-1eb8-4227-9456-016f3cedd235", + "ghpython": { + "hideOutput": true, + "hideInput": true, + "isAdvancedMode": true, + "marshalOutGuids": true, + "iconDisplay": 2, + "inputParameters": [ + { + "name": "i_clouds", + "nickname": "i_clouds", + "description": "The point clouds to merge.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "list", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud", + "flatten": true + } + ], + "outputParameters": [ + { + "name": "o_cloud", + "nickname": "o_cloud", + "description": "The merged point cloud.", + "optional": false, + "sourceCount": 0, + "graft": false + } + ] + } +} \ No newline at end of file From 718a3a683fc7398ee8e19a312194d6e5ae392cee Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Wed, 30 Jul 2025 14:51:02 +0200 Subject: [PATCH 11/19] feat: add point cloud intersection calculation to DFPointCloud --- src/diffCheck/geometry/DFPointCloud.cc | 36 ++++++++++++++++++++++++++ src/diffCheck/geometry/DFPointCloud.hh | 11 +++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/diffCheck/geometry/DFPointCloud.cc b/src/diffCheck/geometry/DFPointCloud.cc index 160f55e4..1ae12fb5 100644 --- a/src/diffCheck/geometry/DFPointCloud.cc +++ b/src/diffCheck/geometry/DFPointCloud.cc @@ -322,6 +322,42 @@ namespace diffCheck::geometry } } + diffCheck::geometry::DFPointCloud DFPointCloud::Intersect(const DFPointCloud &pointCloud, double distanceThreshold) + { + if (this->Points.size() == 0 || pointCloud.Points.size() == 0) + throw std::invalid_argument("One of the point clouds is empty."); + + auto O3DSourcePointCloud = this->Cvt2O3DPointCloud(); + auto O3DTargetPointCloud = std::make_shared(pointCloud)->Cvt2O3DPointCloud(); + auto O3DResultPointCloud = std::make_shared(); + + open3d::geometry::KDTreeFlann threeDTree; + threeDTree.SetGeometry(*O3DTargetPointCloud); + std::vector indices; + std::vector distances; + for (const auto &point : O3DSourcePointCloud->points_) + { + threeDTree.SearchRadius(point, distanceThreshold, indices, distances); + if (!indices.empty()) + { + O3DResultPointCloud->points_.push_back(point); + if (O3DSourcePointCloud->HasColors()) + { + O3DResultPointCloud->colors_.push_back(O3DSourcePointCloud->colors_[&point - &O3DSourcePointCloud->points_[0]]); + } + if (O3DSourcePointCloud->HasNormals()) + { + O3DResultPointCloud->normals_.push_back(O3DSourcePointCloud->normals_[&point - &O3DSourcePointCloud->points_[0]]); + } + } + } + diffCheck::geometry::DFPointCloud result; + result.Points = O3DResultPointCloud->points_; + result.Colors = O3DResultPointCloud->colors_; + result.Normals = O3DResultPointCloud->normals_; + return result; + } + void DFPointCloud::ApplyTransformation(const diffCheck::transformation::DFTransformation &transformation) { auto O3DPointCloud = this->Cvt2O3DPointCloud(); diff --git a/src/diffCheck/geometry/DFPointCloud.hh b/src/diffCheck/geometry/DFPointCloud.hh index a8779313..773fd839 100644 --- a/src/diffCheck/geometry/DFPointCloud.hh +++ b/src/diffCheck/geometry/DFPointCloud.hh @@ -152,7 +152,7 @@ namespace diffCheck::geometry */ std::vector GetTightBoundingBox(); - public: ///< Point cloud subtraction + public: ///< Point cloud subtraction and intersection /** * @brief Subtract the points, colors and normals from another point cloud when they are too close to the points of another point cloud. * @@ -161,6 +161,15 @@ namespace diffCheck::geometry */ void SubtractPoints(const DFPointCloud &pointCloud, double distanceThreshold = 0.01); + /** + * @brief Intersect the points, colors and normals from another point cloud when they are close enough to the points of another point cloud. Is the point cloud interpretation of a boolean intersection. + * + * @param pointCloud the other point cloud to intersect with this one + * @param distanceThreshold the distance threshold to consider a point as too close. Default is 0.01. + * @return diffCheck::geometry::DFPointCloud the intersected point cloud + */ + diffCheck::geometry::DFPointCloud Intersect(const DFPointCloud &pointCloud, double distanceThreshold = 0.01); + public: ///< Transformers /** * @brief Apply a transformation to the point cloud From e7dad06adce135f7bf0c94159213489da9737ee4 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:02:55 +0200 Subject: [PATCH 12/19] fix: rename SubstractCloud to CloudDifference and fix mistakes in metadata --- src/gh/components/DF_cloud_difference/code.py | 25 +++++++ .../components/DF_cloud_difference/icon.png | Bin 0 -> 15464 bytes .../DF_cloud_difference/metadata.json | 64 ++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 src/gh/components/DF_cloud_difference/code.py create mode 100644 src/gh/components/DF_cloud_difference/icon.png create mode 100644 src/gh/components/DF_cloud_difference/metadata.json diff --git a/src/gh/components/DF_cloud_difference/code.py b/src/gh/components/DF_cloud_difference/code.py new file mode 100644 index 00000000..de67465b --- /dev/null +++ b/src/gh/components/DF_cloud_difference/code.py @@ -0,0 +1,25 @@ +from diffCheck import df_cvt_bindings as df_cvt + +import Rhino +from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML + +from ghpythonlib.componentbase import executingcomponent as component + +class DFCloudDifference(component): + def __init__(self): + super(DFCloudDifference, self).__init__() + def RunScript(self, + i_cloud_A: Rhino.Geometry.PointCloud, + i_cloud_B: Rhino.Geometry.PointCloud, + i_distance_threshold: float): + df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_A) + df_cloud_substract = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_B) + if i_distance_threshold is None: + ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold not defined. 0.01 used as default value.")# noqa: F821 + i_distance_threshold = 0.01 + if i_distance_threshold <= 0: + ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold must be greater than 0. Please provide a valid distance threshold.")# noqa: F821 + return None + df_cloud.subtract_points(df_cloud_substract, i_distance_threshold) + rh_cloud = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) + return [rh_cloud] diff --git a/src/gh/components/DF_cloud_difference/icon.png b/src/gh/components/DF_cloud_difference/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cba0ffbf4c10e3a0a49832bcd64765d3d5c3903b GIT binary patch literal 15464 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 literal 0 HcmV?d00001 diff --git a/src/gh/components/DF_cloud_difference/metadata.json b/src/gh/components/DF_cloud_difference/metadata.json new file mode 100644 index 00000000..ce6b6984 --- /dev/null +++ b/src/gh/components/DF_cloud_difference/metadata.json @@ -0,0 +1,64 @@ +{ + "name": "DFCloudDifference", + "nickname": "Difference", + "category": "diffCheck", + "subcategory": "Cloud", + "description": "Subtracts points from a point cloud based on a distance threshold.", + "exposure": 4, + "instanceGuid": "9ef299aa-76dc-4417-9b95-2a374e2b36af", + "ghpython": { + "hideOutput": true, + "hideInput": true, + "isAdvancedMode": true, + "marshalOutGuids": true, + "iconDisplay": 2, + "inputParameters": [ + { + "name": "i_cloud_A", + "nickname": "i_cloud_A", + "description": "The point cloud to subtract from.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud" + }, + { + "name": "i_cloud_subtract_with", + "nickname": "i_cloud_subtract_with", + "description": "The point cloud to subtract with.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud" + }, + { + "name": "i_distance_threshold", + "nickname": "i_distance_threshold", + "description": "The distance threshold to consider a point as too close.", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "float" + } + ], + "outputParameters": [ + { + "name": "o_cloud_in", + "nickname": "o_cloud", + "description": "The resulting cloud after subtraction.", + "optional": false, + "sourceCount": 0, + "graft": false + } + ] + } +} \ No newline at end of file From 5308e44f73f1923d359c5ec755ceb1ca914264ee Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:06:26 +0200 Subject: [PATCH 13/19] fix: rename MergeCloud to CloudUnion and fix mistakes in metadata --- src/gh/components/DF_cloud_union/code.py | 27 ++++++++++++ src/gh/components/DF_cloud_union/icon.png | Bin 0 -> 15210 bytes .../components/DF_cloud_union/metadata.json | 41 ++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/gh/components/DF_cloud_union/code.py create mode 100644 src/gh/components/DF_cloud_union/icon.png create mode 100644 src/gh/components/DF_cloud_union/metadata.json diff --git a/src/gh/components/DF_cloud_union/code.py b/src/gh/components/DF_cloud_union/code.py new file mode 100644 index 00000000..c0948e5e --- /dev/null +++ b/src/gh/components/DF_cloud_union/code.py @@ -0,0 +1,27 @@ +"""Merges point clouds together.""" +import diffCheck +from diffCheck.diffcheck_bindings import dfb_geometry as df_geometry +import Rhino + +import System + +from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML + +from ghpythonlib.componentbase import executingcomponent as component + +TOL = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance + +class DFMergeAssemblies(component): + def RunScript(self, + i_clouds: System.Collections.Generic.List[Rhino.Geometry.PointCloud]): + if i_clouds is None or len(i_clouds) == 0: + ghenv.Component.AddRuntimeMessage(RML.Warning, "No point clouds provided. Please connect point clouds to the input.") # noqa: F821 + return None + + merged_cloud = df_geometry.DFPointCloud() + for cloud in i_clouds: + df_cloud = diffCheck.df_cvt_bindings.cvt_rhcloud_2_dfcloud(cloud) + merged_cloud.add_points(df_cloud) + + o_cloud = diffCheck.df_cvt_bindings.cvt_dfcloud_2_rhcloud(merged_cloud) + return [o_cloud] diff --git a/src/gh/components/DF_cloud_union/icon.png b/src/gh/components/DF_cloud_union/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bda1f58c544d019981fe7bb2a8309ad54942e81d GIT binary patch literal 15210 zcmeHuWl&t(wl40$5=0Xw-DSNf(LhZcerHlBm305 zRj*FHd*83qRjb!pbAIESV|-)GHG5Uf4p&iU;17V@~>CU(IChO^j{O;A>o3Q$v)UgiV&mp_S zBJo>~)5A-bs9Q&O(b3cUWi7l}tb9HjH-|?e3LZ;OC!Tli{&yuOYWFUmITi_S%UCCl z-?cp7TuHy9a=2$(LZ7@6UtA#A_w;wkyU5W!y<#|bZfVJC8E8!!eV?0Iv2Ao!v-C*H zQN&AibutXJedt(vY~Ib7*5YbDk=V37x{w}VCGnj*yNix32l(pcjXW_@%@SK&@1^-v z^lvF&9<}hc=rMi20zTGBDP=7^-Fh0YEtNPVKF(!GxcfS^Jo*5&4#Rx(yuA;E2810= z@PX8cpr%i^$^AFsSI#z{^$0qCj(xiMpih}4k|2UuM)tkkt9$&0)2as3(VAqxddQ|> z_zH|Hfnh_GbkkP9a(@FonbF{F+$T8iu}Sj27$?~0kD3W|%`&dos=XlEoG-E4GIuYk z(tpEpT=tagd*|PThn5)jq|em7k&d4R?sd3Ls{`XSEJ=Md^%r@(f6Ut7tuUNmWRhe= zpF5)QsD3ZI9Q|3yHqxtw-R#VZwH4QXuh%dv(6A!)VwCm{vQ=5b3~3Yn_*sBlzXy&- znwKaCeUZ*eE!}2Frc%h(dGy4x;|P|M8ONJ)6Aj;jkSQqaXJALKiJAr%ekR2Qo4OVyCH5oT2_#uIjh|}{ ze;j?58CM%=I-i|u^_C{I&xw^Ga<1O_mbKjThI52t&uV~0-#i#kOV>R?Lu>B)?4?O4 zsq3tJl7Z`8^{nO8bD-!&Gt(A_+VZx8S(| z=mz>sl$|A|oG>{0O~(6;wAq;VR%^*?IS+N!6Yt9QO&qSfY!08M9i+eAB_-aC+xS+^ zsuL6U81bUj7mrDkGj zvMjq^={rveYL((k7Sa^gOrIL_oSg|hj_b{nBzuM~mAy~hvp&e%!kz1_P(Ff-(6-dY zV5Es2weHbrUGIkTtnzqm=t=YuS~h(71C0z;uxj6@me53}aZ&S#>K3YoTwWu{n6tR#%~r zsS9g*r4v4BN^KK>uG?AbeY@qFT$@I|aKvwFv%sW)(FAl&&#}^6p7+_1u}tNy2iuz3 zk2HC#Y~4&u_~RTVV|e zR%+@uP7W0`*&y9I?^CLCac-4V+fH05;$+f(FH=(`7@0}9?S={8p7#328T+JpLaYh*&= zu>s8JRBr%rAIlSYkOXP{li|{|IdHf??er%&)c5LEx_vjM9mI`!A-g%O{$65@u!(2x zo>5>f1o;Y;9xiBpfOtyni7AEPP3TMR5I1n}#miztVo|7X0Ge8%`rG#3R<^x}o6XJxVb@;Rhc3L5;*)BTX(p&mOQmB$UZ6T>@)52kP45SfQ z#RN|?j_b4`4Pz|B*Yx=vmv$5yh9SaEA-|-TPlfM=w?yIpm4FNt%V?hey5T#o!-P-y zPOk_0s-91pSzN*kK~BdSJ(o+9z=awm*szOBy=4-oSqZEn9yd3TC7hD2oT z{DNbqzc!AqQV?OIqL4z^jhQ3Ly=gQbl$L!t$0MJ7|i|= z9o?{EUSbU4Iesn(FTq^+L0IV_Hc? z5d$WXg?pGoJE=rb0q_+0`%!K9!*J)TFmBcAusiNCAVcy`DR8eRJ?!6=s=k~8tQ+|F z39#@Q2TLgF=_t9Lig~MGkzi8GFxrSS_WBARN}Vc|h~!X>NT%suC$f0GB|9!kb9Y# zyX8_K$IF}Jw2T5y3Y8<1;5&Mq{$Bt|dg>L-`mR_jON{j(98H`fd0_n%i$(zktPDqV zw-psV#z=vWHUUy*=ojapmpTdlzEMQQVoFn^pPdpZ8i>vjJHj?4kXyU=REA8Dx%#Q? z$_37CS5k0#0(AhuQMN1{i*SwX*xqTk9Q(CSWuLXYds|gF{jjbYlnbGp!K!!P0TUyY z=Tzx8v?(0NdMh|>Ok;7dS6VIJDj0_+FdgAs{*M-+A&O_s$vSj~(Zz~(Ba{areY{-J z3=@^ahg_m+p=q@D(}>|t*Sz0nfS0_w17B(odbft5_F2d0TVp@$1$R8^A5n!{h4J!| zQOI5d2dcYx;&3?8|HPM#5GmJG9MXV=6wdX>%H03@a?Q_Dhtjv$Qe!+}-Xcm|G;s#W{$kyg}5T@glb}B>` z*qo3Ni1$-l+w^>)UNWAu5B%1N5QnncPRRX*$qZ%d_%6Ig=(I=y1z(}0x!G||P_U^> zBRT6JkBG(_6~=8`O@9Bg5VqZ}2|~th`n4Cx!2|4N*VdhPCt03rxgElgHYeDmvdcn-R~d`fcDa5 zSNfOD73TcH$bK}+2|ucLX9q0vlG`meZY1U~$YKqMVSljWfiuqku~J@3h(YZ`L*?oR zi8;h9qg9X=hQBk{^peB~$*!Om4I{t5y_2Qt^qSEi)Tp$b7)}M3&(;HRT!-m#jceZ-Il`g@arjcoM>F}7jv}$G&i0iQ4!c-%sE*Zh&}|qvv%66qz37b%bmilza}fSSs7Y#)wd)OhD`S#oz&3~3~&QUJ?2==eJc&uK>U z=CfyKkmJZtnW#n1uLAE2_s_6wb=D>V6KS6A#NrG1AT)U24}eH35xFAydFHs7)CUY$ zKsWkE&8|XOH1Rk2sr3}7Y22&iu$Oomx!ChXt!w`@gDbG8jm34cq{VTI6j-GGfs3vM z!(2*(EcYJMXr01XPOU&+<`v&Bren?BBp-N8=6CXb*LXVb^nKY;akvk3_3#wjq;kMXEtHUk1z>%VZNKhO0$K z8DdAd9DPG#4-lMQSt6747cY3EamZx6S9L$oVz7%BZJul@gVVXw1gO!VdlmMUf9J$b zm2;S!*Pw1_M5H0a;3X3UE>;8HYM%LEHrUwlQd|=(8GMFskY!O0d(~C-p4t%~@nsx- zZ~;X{X)#uIB-Ux!YV0V#XpU_-O)CxlS;s+#julDGKtdNW$!p9Dhxh8%TUXQV?am4m zyqLa@a(hN`xoLNooIcddwxO$z1;N+GMB#dJUmp?hejGEK{cvIE@#r7waJyvSOC@KF zDlX^`V+D5qRQm~k-v-7;7q&x1d4(X8P6+eq(3RnxLCfi6)m!I>;f57h3_7PB`R{ND z0NMi7ZC7m_)ysBVujDs-9dU5t5ru@fUwKeS=>sq$68f4hs~#O6XI-YzAl>upxA%s` zvk5V;mofMA)~onk6U6W!8Z!krUcit9d7Rcg6BMOyNRMs##y0*1H(H^Byi46`(e2Xg zoYae_%15nCh9Y-6#TInpe11|u-L`^Uj zXGZZO=^p~r2EE+h|1^Ra{K9*KvhF4rn~WNja;Y|gzn ztRM@MA2cmc8wH?sr|C-;`suLV7TI5wL^e$q&6t7Dq7l7am}e-i;^~&FrZLn9 z`TTu!88%u$xJq1XhdAnOG55?#sAnQ+Snt~9)TB+>{D(>xvI9!oGCd}<^MUsx#s*B+ z2xBBjAMm@r)+SfgmY7z<;F2A{cSFnW1k*-|t#t+uUK&!^HsA`T?OJurl? z=pCt-W2ZbFBp!!14dPCusbn{4^H%4XS_G8u?}w`x8gQdEX6&oX`e%8yv-TxLe!&W) zI!(%sr;bSa8se=E?bT6~93;wB76&NEo%bq4Z?}=hrpYU8_7JoYxBRT>_gKHrPq%$< zjnM-~1yVXycVax5A1WEa*x)kZwX4eKo=M9lduY~O)S^ozVeH1x;Guzq&oPeW_QT?| zpPBt&;lY?tw7jUnW6C$@F8x;hJJw2KkWYbjOPW8mT(aLy#u9H0I{IcD8O7d^ zZEdWwK9=a{xLX3y+S^+m|Ck$wCFU~}0an~4I3|u2#8o}R;8E1Dh}x1_F|AZRE6tdl&Fy=@9mJUA!t-aqTlg!F1^aqyqp#=p%*J zOPXufBQ(D5SdC>)#zI60S}}}RK1@)XL|)8gl5Wo9gj$v&OuK?^j9;(V>6K0Y+O;DW z_HoX`+Z@c^b@JXdB?-`kk9?xZ`=OJ*^U`&~YXizqv5PMScw6RU>SB6gnis7^%N{Xv z6x+`E#BViTAssG(b2F$F0#u#hlkEzrCn1D2ruY)UxT`P+v|StaDejff4IZMYjZfqh z?*tAU!nt1RM}A}MBH?(!p?f!=QbBd*Z*qhdQ7mo?4uFiX6E>BHVr<^c#HHlXj)}-q zhRD7SOOO(m-dm=D(~D~!=Y!Exjk_E=0A}h;nqZ}p>wP|7TGe5T=`gLOcKzp6T!zObm^opWzQ_1H(W?0XbPaIhXLOd~hKz01htKMu(>MAa@J z7B&N2uM;$4JkSnrjUbmT;Q+r{kXV|JzSPmbz&bT4TxX%|!p=`LH4#nIuUgiEiZWxoFWSdP0UH#N4iGw*MR5G=3298!C@B1<1O z7X{N;K;o~!6Ass^_=sKYIq`{;aZ!0v5z}|w6<8U>EOLmxF0jb@N#o|{2I?}AAhXFD zi4b7aP|y{I>Eu?MFYnS2Wg~*2+5x6nwZeL2JZy0Xs2!npg8rC1u=GZJ!8Tj(6LWwL ztv=F1*$Zn8BswP>bfQ3>uvW$S+=D=6B&jZ|yvYzkoL*$$x^86U5w^`9oI|n{T_H6d zQJRpvz0U-F9VBNI>0G1q*vTg1HlD?~lMTYS z3@utt3rn)z^PzmP!ASlkUFLQe^;k6G*)aQF#?1gRa;>L#D|Q`&sx90>{DIl>V^sZ@9O6%E<<-}plKo}R+Y0ln*zBjI0ft88 z)}E!N?_@71YwWXjV}k00a`)*B`nKi^NK2x%-o`+bk-T=zUi1{rhN|yNu&R>=(Oh35 z2Vu{$7i8r`c621AFn<^e;+eFaw`>CAhH1Rzc~6FG+N75}B+c%G>wYi0zA^PV@dj29 zpk62n#ff3D} zaagm-Ev+x=H4Bp=t#^~&B(jAFB|HvUUqA4MaisRkttR0~FGv2MMWK$#DOCQsbf6#3 zWhm8o9)H1GSgD}lk1lriYf@fHpg<{_v;3D`>Ovm}TTtK|ZgEzPfx(=5sB;#mcb%gB zT=V;f;Cv5Pe>EfS3>S-DFa<_^jA^Ic_n;KH&g?3eqb4eb1bCX1?-oD9e`4pliJz02 zd<6wwS`Ci3qiMIUk{8GBe^qq2xNbGP1m>ELuqYO#hBoUtzhkcX8Uv$3Wyj42QA^+p z-aQtK5Pp#lntCOV1yoxLK)w(%2p=ThH}Rzj%%DH&iLx$Z*^e4D z?&%<)ESdH&60RqPZp344&3i#?U8Xx~)+LH(SPaG{lQoUJrWbz z{>$$dvl@r!xiDF@CTl4ID!Q|q+0}Lby6@}(4{3i%W6)~1SYUt9M%5d>1wGmzh-eRX zbz$LkzLIZEGtvP{^dO^qmHN=#+fpuT#ix!Ul0{FD`-F}wV|8eUWMllV?w9qf!a>@# zYx`Ey#XLeqC8yD)ZIMu=GJQPmGn4D$O|?#%-F^K)46XKQmas|T5y88I-IbR}C55-m zgA`w(GleN7EEJ_X**B;TOzb_1F)`!EUGuG#a5%!5fs7&!kn{wYystH3>=5lUpuL|Y>x_HiP>932DhK$2%t_`Rnmg@&%qrJ1btOwIIk zmR3oZN#YMd3XkvOb|*mc$I%$1xEQ4xv7vdf6Ky)t?bESZgYm_R*z303$=r8o-rWsn zh_Z~9fn0}#+b-f87cSymbuZDr3q#LeN2*c5vXnQvnDewJ{xpizMD%ND^Q0M}pd&66 z!pkqA+_1J+O;LS~s~nw|&}iMdVzt{|js#~CViOBD9BaBC4=XlW{BEIumXq7PcDymm zFE*F>BfRa2VbDB&ok4_GzKOz9kcyR-wPsj>CJ=jkD=-;Zq|d6(ei*{B;0iNUYa1&i zR*LwvLs^oS!kqrmTJUaRD4%ah1Igl;+jQ#-KApG0{ejnQ@pl?7JXO$r(<=U3fqD3c za1Z}m_C_^!N{gD0NGakG8qq#_nhW{IV{(9vf|4OzUzk@CgwtGHMo+=?1niF?w7$)! zl;Qjq+b`uRiG^WKcN6DlTpvuwIRg8$Y|Kns?T$m=8%Ty!}lk1=~`Cv#)vBgVw?c zDCLHym&r2||HdOUqqp zl`mp$%xhx@8q+SRH0?GFb;29_3-d$oY6wD59TA`bsk^EDQ|=4i9EvS;-FjR8$|p~Ix;QZ+~^<#=~eq7o&%-OI7BB_i^rO=+51OAYXr`7CG$AxW9<+O@qhp3_|DFZn)w~4 zj%pbhwET&dQcJ8_dGX}xrP!vg04|pXTo(sxg{L~pr$Jy{*W7O9@uJy1diiDT;(I@D zo4p6vU*}?1&N`Yh@jT5=iz2(f@XvHY3d&C2$|>#{Bei0Y5ss&77Ze^B`;E2O@3{3l zVpFMd?UE%<2Y`E(=_P&C_a1sJ9$IJo3h`~u_+O)-P3YqLBjgCAS0ZX7xMF?@&Nfo` zCQu|uK;tQBhX-$UVuM{|IYr=>d`$yJV*J>Du{>6Yfp_phM+1B-ly1C+^KEb2oI5|= zx*NumdWZ`O*+G-Rq+C`(A*b0uR{DIjHUF0FjdS4$5!co#x=O?@rZAnh=>Dh;`IYBk ze%V}C{rt}A{>otvWyuf-sJ`)9O6Aul1vy8Fi;rm0szA{fCM~Z)sk36MoZ;NlrTMS> zoTzrTZx?$9m`Ev`?jpWWKCkCZ<-JssoNe7eXFWP5iIb>Tw%s zrr-e*(psFdwdNXez)Ym(;H_4=oy+#T@_}d~* z1*E$BF~||lq|G!H%cMCM5BR`29lnBf#voza?O*0gj$qD_FWB-D;WTv8GqqP=m&J

F8h)fwO#_q{sW+%T)gFp&r4%Z5$F{TwBl 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 B{F49x literal 0 HcmV?d00001 diff --git a/src/gh/components/DF_cloud_union/metadata.json b/src/gh/components/DF_cloud_union/metadata.json new file mode 100644 index 00000000..da4d63cc --- /dev/null +++ b/src/gh/components/DF_cloud_union/metadata.json @@ -0,0 +1,41 @@ +{ + "name": "DFCloudUnion", + "nickname": "DFCloudUnion", + "category": "diffCheck", + "subcategory": "Cloud", + "description": "This component merges a series of point clouds into a unique point cloud.", + "exposure": 4, + "instanceGuid": "1e5e3ce8-1eb8-4227-9456-016f3cedd235", + "ghpython": { + "hideOutput": true, + "hideInput": true, + "isAdvancedMode": true, + "marshalOutGuids": true, + "iconDisplay": 2, + "inputParameters": [ + { + "name": "i_clouds", + "nickname": "i_clouds", + "description": "The point clouds to merge.", + "optional": false, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "list", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "pointcloud", + "flatten": true + } + ], + "outputParameters": [ + { + "name": "o_cloud", + "nickname": "o_cloud", + "description": "The merged point clouds.", + "optional": false, + "sourceCount": 0, + "graft": false + } + ] + } +} \ No newline at end of file From 164ef82112feb1d568aa7c68b9cb8e4738660800 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Mon, 4 Aug 2025 18:08:47 +0200 Subject: [PATCH 14/19] fix: metadata in CropCloud and IntersectCloud --- .../components/DF_cloud_intersect/metadata.json | 16 ++++++++-------- src/gh/components/DF_crop_cloud/metadata.json | 14 +++++++++++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/gh/components/DF_cloud_intersect/metadata.json b/src/gh/components/DF_cloud_intersect/metadata.json index e95370c9..6e044686 100644 --- a/src/gh/components/DF_cloud_intersect/metadata.json +++ b/src/gh/components/DF_cloud_intersect/metadata.json @@ -1,9 +1,9 @@ { - "name": "DFSubtractCloud", - "nickname": "Subtract", + "name": "DFIntersectCloud", + "nickname": "Intersect", "category": "diffCheck", "subcategory": "Cloud", - "description": "Subtracts points from a point cloud based on a distance threshold.", + "description": "Intersects points from two point clouds based on a distance threshold.", "exposure": 4, "instanceGuid": "b1a87021-dc4d-4844-86e0-8dcf55965ac6", "ghpython": { @@ -14,8 +14,8 @@ "iconDisplay": 2, "inputParameters": [ { - "name": "i_cloud_intersect_from", - "nickname": "i_cloud_intersect_from", + "name": "i_cloud_A", + "nickname": "i_cloud_A", "description": "The point cloud to intersect from.", "optional": false, "allowTreeAccess": true, @@ -26,8 +26,8 @@ "typeHintID": "pointcloud" }, { - "name": "i_cloud_intersect_with", - "nickname": "i_cloud_intersect_with", + "name": "i_cloud_B", + "nickname": "i_cloud_B", "description": "The point cloud to intersect with.", "optional": false, "allowTreeAccess": true, @@ -40,7 +40,7 @@ { "name": "i_distance_threshold", "nickname": "i_distance_threshold", - "description": "The distance threshold to consider a point as too close.", + "description": "The distance threshold to consider a point as close enough.", "optional": true, "allowTreeAccess": true, "showTypeHints": true, diff --git a/src/gh/components/DF_crop_cloud/metadata.json b/src/gh/components/DF_crop_cloud/metadata.json index b0f7f30c..78a00782 100644 --- a/src/gh/components/DF_crop_cloud/metadata.json +++ b/src/gh/components/DF_crop_cloud/metadata.json @@ -40,9 +40,17 @@ ], "outputParameters": [ { - "name": "o_cloud", - "nickname": "o_cloud", - "description": "The downsampled cloud.", + "name": "o_cloud_inside", + "nickname": "o_cloud_inside", + "description": "the points inside the cropping object.", + "optional": false, + "sourceCount": 0, + "graft": false + }, + { + "name": "o_cloud_outside", + "nickname": "o_cloud_outside", + "description": "the points outside the cropping object.", "optional": false, "sourceCount": 0, "graft": false From 1baf875efbe9c4238669091410c9344a6cf226af Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Mon, 4 Aug 2025 20:23:05 +0200 Subject: [PATCH 15/19] fix: small typos again in the metadata --- .../DF_cloud_difference/metadata.json | 4 ++-- src/gh/components/DF_cloud_intersect/code.py | 8 ++++---- src/gh/components/DF_crop_cloud/metadata.json | 17 +++++++++++++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/gh/components/DF_cloud_difference/metadata.json b/src/gh/components/DF_cloud_difference/metadata.json index ce6b6984..ec7dfd40 100644 --- a/src/gh/components/DF_cloud_difference/metadata.json +++ b/src/gh/components/DF_cloud_difference/metadata.json @@ -26,8 +26,8 @@ "typeHintID": "pointcloud" }, { - "name": "i_cloud_subtract_with", - "nickname": "i_cloud_subtract_with", + "name": "i_cloud_B", + "nickname": "i_cloud_B", "description": "The point cloud to subtract with.", "optional": false, "allowTreeAccess": true, diff --git a/src/gh/components/DF_cloud_intersect/code.py b/src/gh/components/DF_cloud_intersect/code.py index 76247329..f7d6548e 100644 --- a/src/gh/components/DF_cloud_intersect/code.py +++ b/src/gh/components/DF_cloud_intersect/code.py @@ -9,11 +9,11 @@ class DFCloudIntersect(component): def __init__(self): super(DFCloudIntersect, self).__init__() def RunScript(self, - i_cloud_intersect_from: Rhino.Geometry.PointCloud, - i_cloud_intersect_with: Rhino.Geometry.PointCloud, + i_cloud_A: Rhino.Geometry.PointCloud, + i_cloud_B: Rhino.Geometry.PointCloud, i_distance_threshold: float): - df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_intersect_from) - df_cloud_intersect = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_intersect_with) + df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_A) + df_cloud_intersect = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_B) if i_distance_threshold is None: ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold not defined. 0.01 used as default value.")# noqa: F821 i_distance_threshold = 0.01 diff --git a/src/gh/components/DF_crop_cloud/metadata.json b/src/gh/components/DF_crop_cloud/metadata.json index 78a00782..202e8a79 100644 --- a/src/gh/components/DF_crop_cloud/metadata.json +++ b/src/gh/components/DF_crop_cloud/metadata.json @@ -28,14 +28,27 @@ { "name": "i_box", "nickname": "i_box", - "description": "The brep box to crop the point cloud with.", - "optional": false, + "description": "The brep box to crop the point cloud with. Can only be a box.", + "optional": true, "allowTreeAccess": true, "showTypeHints": true, "scriptParamAccess": "item", "wireDisplay": "default", "sourceCount": 0, "typeHintID": "brep" + }, + { + "name": "i_brep", + "nickname": "i_brep", + "description": "The brep to crop the point cloud with. This is slower than the box, but accommodates any Brep.", + "optional": true, + "allowTreeAccess": true, + "showTypeHints": true, + "scriptParamAccess": "item", + "wireDisplay": "default", + "sourceCount": 0, + "typeHintID": "brep", + "flatten": false } ], "outputParameters": [ From 8cdd175defdfdb37df2e9de30042482de1e46704 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:35:07 +0200 Subject: [PATCH 16/19] feat: add possibility to crop pc with any box --- src/diffCheck/geometry/DFPointCloud.cc | 18 ++++++++++++++++++ src/diffCheck/geometry/DFPointCloud.hh | 6 ++++++ src/diffCheckBindings.cc | 9 ++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/diffCheck/geometry/DFPointCloud.cc b/src/diffCheck/geometry/DFPointCloud.cc index 1ae12fb5..5b016eda 100644 --- a/src/diffCheck/geometry/DFPointCloud.cc +++ b/src/diffCheck/geometry/DFPointCloud.cc @@ -231,6 +231,24 @@ namespace diffCheck::geometry this->Normals.push_back(normal); } + void DFPointCloud::Crop(const std::vector &corners) + { + if (corners.size() != 8) + throw std::invalid_argument("The corners vector must contain exactly 8 points."); + open3d::geometry::OrientedBoundingBox obb = open3d::geometry::OrientedBoundingBox::CreateFromPoints(corners); + auto O3DPointCloud = this->Cvt2O3DPointCloud(); + auto O3DPointCloudCropped = O3DPointCloud->Crop(obb); + this->Points.clear(); + for (auto &point : O3DPointCloudCropped->points_) + this->Points.push_back(point); + this->Colors.clear(); + for (auto &color : O3DPointCloudCropped->colors_) + this->Colors.push_back(color); + this->Normals.clear(); + for (auto &normal : O3DPointCloudCropped->normals_) + this->Normals.push_back(normal); + } + DFPointCloud DFPointCloud::Duplicate() const { return DFPointCloud(this->Points, this->Colors, this->Normals); diff --git a/src/diffCheck/geometry/DFPointCloud.hh b/src/diffCheck/geometry/DFPointCloud.hh index 773fd839..8a65d380 100644 --- a/src/diffCheck/geometry/DFPointCloud.hh +++ b/src/diffCheck/geometry/DFPointCloud.hh @@ -97,6 +97,12 @@ namespace diffCheck::geometry */ void Crop(const Eigen::Vector3d &minBound, const Eigen::Vector3d &maxBound); + /** + * @brief Crop the point cloud to a bounding box defined by the 8 corners of the box + * @param corners the 8 corners of the bounding box as a vector of Eigen::Vector3d + */ + void Crop(const std::vector &corners); + /** * @brief Get the duplicate of the point cloud. This is mainly used in the python bindings * diff --git a/src/diffCheckBindings.cc b/src/diffCheckBindings.cc index 6436cfad..1e5ad07e 100644 --- a/src/diffCheckBindings.cc +++ b/src/diffCheckBindings.cc @@ -61,9 +61,16 @@ PYBIND11_MODULE(diffcheck_bindings, m) { .def("remove_statistical_outliers", &diffCheck::geometry::DFPointCloud::RemoveStatisticalOutliers, py::arg("nb_neighbors"), py::arg("std_ratio")) - .def("crop", &diffCheck::geometry::DFPointCloud::Crop, + .def("crop", + (void (diffCheck::geometry::DFPointCloud::*)(const Eigen::Vector3d&, const Eigen::Vector3d&)) + &diffCheck::geometry::DFPointCloud::Crop, py::arg("min_bound"), py::arg("max_bound")) + .def("crop", + (void (diffCheck::geometry::DFPointCloud::*)(const std::vector&)) + &diffCheck::geometry::DFPointCloud::Crop, + py::arg("corners")) + .def("duplicate", &diffCheck::geometry::DFPointCloud::Duplicate) .def("load_from_PLY", &diffCheck::geometry::DFPointCloud::LoadFromPLY) From 3eebaa567eb9c90caa23cbdb3f3f405930c1fadd Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:39:40 +0200 Subject: [PATCH 17/19] feat: improve cropping component following @eleniv3d 's comments --- src/gh/components/DF_crop_cloud/code.py | 25 ++++++------------- src/gh/components/DF_crop_cloud/metadata.json | 23 ++++------------- 2 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/gh/components/DF_crop_cloud/code.py b/src/gh/components/DF_crop_cloud/code.py index 9e08f98d..e57a8eec 100644 --- a/src/gh/components/DF_crop_cloud/code.py +++ b/src/gh/components/DF_crop_cloud/code.py @@ -4,7 +4,6 @@ import numpy as np import Rhino -from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML from ghpythonlib.componentbase import executingcomponent as component @@ -16,36 +15,28 @@ def __init__(self): def RunScript(self, i_cloud: Rhino.Geometry.PointCloud, - i_box: Rhino.Geometry.Brep, - i_brep: Rhino.Geometry.Brep): - if i_cloud is None: - ghenv.Component.AddRuntimeMessage(RML.Warning,"No point cloud provided. Please connect a point cloud to the input.")# noqa: F821 - return None - - if i_box is not None: - bbox = i_box.GetBoundingBox(True) - bb_min_as_array = np.asarray([bbox.Min.X, bbox.Min.Y, bbox.Min.Z]) - bb_max_as_array = np.asarray([bbox.Max.X, bbox.Max.Y, bbox.Max.Z]) + i_boundary: Rhino.Geometry.Brep): + + if i_boundary.IsBox(): + vertices = i_boundary.Vertices + bb_as_array = [np.asarray([vertice.Location.X, vertice.Location.Y, vertice.Location.Z]) for vertice in vertices] df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud) df_cloud_copy = df_cloud.duplicate() - df_cloud.crop(bb_min_as_array, bb_max_as_array) + df_cloud.crop(bb_as_array) df_cloud_copy.subtract_points(df_cloud, TOL) o_pts_out = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud_copy) o_pts_in = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) - elif i_brep is not None: + else: pts_in = [] pts_out = [] for pc_item in i_cloud: point = Rhino.Geometry.Point3d(pc_item.X, pc_item.Y, pc_item.Z) - if i_brep.IsPointInside(point, TOL, True): + if i_boundary.IsPointInside(point, TOL, True): pts_in.append(point) else: pts_out.append(point) o_pts_in = Rhino.Geometry.PointCloud(pts_in) o_pts_out = Rhino.Geometry.PointCloud(pts_out) - else: - ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide a box to crop the point cloud with") # noqa: F821 - return [o_pts_in, o_pts_out] diff --git a/src/gh/components/DF_crop_cloud/metadata.json b/src/gh/components/DF_crop_cloud/metadata.json index 202e8a79..877249c2 100644 --- a/src/gh/components/DF_crop_cloud/metadata.json +++ b/src/gh/components/DF_crop_cloud/metadata.json @@ -3,7 +3,7 @@ "nickname": "Crop", "category": "diffCheck", "subcategory": "Cloud", - "description": "Crops a point cloud by giving the bounding box or limit values.", + "description": "Crops a point cloud by giving a boundary volume.", "exposure": 4, "instanceGuid": "f0461287-b1aa-47ec-87c4-0f03924cea24", "ghpython": { @@ -26,29 +26,16 @@ "typeHintID": "pointcloud" }, { - "name": "i_box", - "nickname": "i_box", - "description": "The brep box to crop the point cloud with. Can only be a box.", - "optional": true, + "name": "i_boundary", + "nickname": "i_boundary", + "description": "The brep boundary to crop the point cloud with. If a box is provided, computation will be faster. If a generic brep is provided, it will be used but may be slower.", + "optional": false, "allowTreeAccess": true, "showTypeHints": true, "scriptParamAccess": "item", "wireDisplay": "default", "sourceCount": 0, "typeHintID": "brep" - }, - { - "name": "i_brep", - "nickname": "i_brep", - "description": "The brep to crop the point cloud with. This is slower than the box, but accommodates any Brep.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "brep", - "flatten": false } ], "outputParameters": [ From bc42fe2c9b822f474695ac999ca022086d0daef1 Mon Sep 17 00:00:00 2001 From: DamienGilliard <127743632+DamienGilliard@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:55:43 +0200 Subject: [PATCH 18/19] fix: rename CloudCrop to CloudSplit --- src/gh/components/DF_cloud_merge/code.py | 27 -------- src/gh/components/DF_cloud_merge/icon.png | Bin 15210 -> 0 bytes .../components/DF_cloud_merge/metadata.json | 41 ----------- .../{DF_crop_cloud => DF_cloud_split}/code.py | 4 +- .../icon.png | Bin .../metadata.json | 14 ++-- src/gh/components/DF_cloud_subtractor/code.py | 25 ------- .../components/DF_cloud_subtractor/icon.png | Bin 12377 -> 0 bytes .../DF_cloud_subtractor/metadata.json | 64 ------------------ 9 files changed, 9 insertions(+), 166 deletions(-) delete mode 100644 src/gh/components/DF_cloud_merge/code.py delete mode 100644 src/gh/components/DF_cloud_merge/icon.png delete mode 100644 src/gh/components/DF_cloud_merge/metadata.json rename src/gh/components/{DF_crop_cloud => DF_cloud_split}/code.py (95%) rename src/gh/components/{DF_crop_cloud => DF_cloud_split}/icon.png (100%) rename src/gh/components/{DF_crop_cloud => DF_cloud_split}/metadata.json (75%) delete mode 100644 src/gh/components/DF_cloud_subtractor/code.py delete mode 100644 src/gh/components/DF_cloud_subtractor/icon.png delete mode 100644 src/gh/components/DF_cloud_subtractor/metadata.json diff --git a/src/gh/components/DF_cloud_merge/code.py b/src/gh/components/DF_cloud_merge/code.py deleted file mode 100644 index c0948e5e..00000000 --- a/src/gh/components/DF_cloud_merge/code.py +++ /dev/null @@ -1,27 +0,0 @@ -"""Merges point clouds together.""" -import diffCheck -from diffCheck.diffcheck_bindings import dfb_geometry as df_geometry -import Rhino - -import System - -from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML - -from ghpythonlib.componentbase import executingcomponent as component - -TOL = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance - -class DFMergeAssemblies(component): - def RunScript(self, - i_clouds: System.Collections.Generic.List[Rhino.Geometry.PointCloud]): - if i_clouds is None or len(i_clouds) == 0: - ghenv.Component.AddRuntimeMessage(RML.Warning, "No point clouds provided. Please connect point clouds to the input.") # noqa: F821 - return None - - merged_cloud = df_geometry.DFPointCloud() - for cloud in i_clouds: - df_cloud = diffCheck.df_cvt_bindings.cvt_rhcloud_2_dfcloud(cloud) - merged_cloud.add_points(df_cloud) - - o_cloud = diffCheck.df_cvt_bindings.cvt_dfcloud_2_rhcloud(merged_cloud) - return [o_cloud] diff --git a/src/gh/components/DF_cloud_merge/icon.png b/src/gh/components/DF_cloud_merge/icon.png deleted file mode 100644 index bda1f58c544d019981fe7bb2a8309ad54942e81d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15210 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

F8h)fwO#_q{sW+%T)gFp&r4%Z5$F{TwBl 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 B{F49x diff --git a/src/gh/components/DF_cloud_merge/metadata.json b/src/gh/components/DF_cloud_merge/metadata.json deleted file mode 100644 index 8e9a323c..00000000 --- a/src/gh/components/DF_cloud_merge/metadata.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "DFMergeClouds", - "nickname": "DFMergeClouds", - "category": "diffCheck", - "subcategory": "Cloud", - "description": "This component merges a series of point clouds into a unique point cloud.", - "exposure": 4, - "instanceGuid": "1e5e3ce8-1eb8-4227-9456-016f3cedd235", - "ghpython": { - "hideOutput": true, - "hideInput": true, - "isAdvancedMode": true, - "marshalOutGuids": true, - "iconDisplay": 2, - "inputParameters": [ - { - "name": "i_clouds", - "nickname": "i_clouds", - "description": "The point clouds to merge.", - "optional": false, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "list", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "pointcloud", - "flatten": true - } - ], - "outputParameters": [ - { - "name": "o_cloud", - "nickname": "o_cloud", - "description": "The merged point cloud.", - "optional": false, - "sourceCount": 0, - "graft": false - } - ] - } -} \ No newline at end of file diff --git a/src/gh/components/DF_crop_cloud/code.py b/src/gh/components/DF_cloud_split/code.py similarity index 95% rename from src/gh/components/DF_crop_cloud/code.py rename to src/gh/components/DF_cloud_split/code.py index e57a8eec..6ceddb1d 100644 --- a/src/gh/components/DF_crop_cloud/code.py +++ b/src/gh/components/DF_cloud_split/code.py @@ -9,9 +9,9 @@ TOL = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance -class DFCloudCrop(component): +class DFCloudSplit(component): def __init__(self): - super(DFCloudCrop, self).__init__() + super(DFCloudSplit, self).__init__() def RunScript(self, i_cloud: Rhino.Geometry.PointCloud, diff --git a/src/gh/components/DF_crop_cloud/icon.png b/src/gh/components/DF_cloud_split/icon.png similarity index 100% rename from src/gh/components/DF_crop_cloud/icon.png rename to src/gh/components/DF_cloud_split/icon.png diff --git a/src/gh/components/DF_crop_cloud/metadata.json b/src/gh/components/DF_cloud_split/metadata.json similarity index 75% rename from src/gh/components/DF_crop_cloud/metadata.json rename to src/gh/components/DF_cloud_split/metadata.json index 877249c2..c4ca6852 100644 --- a/src/gh/components/DF_crop_cloud/metadata.json +++ b/src/gh/components/DF_cloud_split/metadata.json @@ -1,9 +1,9 @@ { - "name": "DFCropCloud", - "nickname": "Crop", + "name": "DFCloudSplit", + "nickname": "Split", "category": "diffCheck", "subcategory": "Cloud", - "description": "Crops a point cloud by giving a boundary volume.", + "description": "Splits a point cloud using a boundary volume.", "exposure": 4, "instanceGuid": "f0461287-b1aa-47ec-87c4-0f03924cea24", "ghpython": { @@ -16,7 +16,7 @@ { "name": "i_cloud", "nickname": "i_cloud", - "description": "The point cloud to crop.", + "description": "The point cloud to split.", "optional": false, "allowTreeAccess": true, "showTypeHints": true, @@ -28,7 +28,7 @@ { "name": "i_boundary", "nickname": "i_boundary", - "description": "The brep boundary to crop the point cloud with. If a box is provided, computation will be faster. If a generic brep is provided, it will be used but may be slower.", + "description": "The brep boundary to split the point cloud with. If a box is provided, computation will be faster. If a generic brep is provided, it will be used but may be slower.", "optional": false, "allowTreeAccess": true, "showTypeHints": true, @@ -42,7 +42,7 @@ { "name": "o_cloud_inside", "nickname": "o_cloud_inside", - "description": "the points inside the cropping object.", + "description": "the points inside the splitting region.", "optional": false, "sourceCount": 0, "graft": false @@ -50,7 +50,7 @@ { "name": "o_cloud_outside", "nickname": "o_cloud_outside", - "description": "the points outside the cropping object.", + "description": "the points outside the splitting region.", "optional": false, "sourceCount": 0, "graft": false diff --git a/src/gh/components/DF_cloud_subtractor/code.py b/src/gh/components/DF_cloud_subtractor/code.py deleted file mode 100644 index 423ca2b1..00000000 --- a/src/gh/components/DF_cloud_subtractor/code.py +++ /dev/null @@ -1,25 +0,0 @@ -from diffCheck import df_cvt_bindings as df_cvt - -import Rhino -from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML - -from ghpythonlib.componentbase import executingcomponent as component - -class DFCloudSubtract(component): - def __init__(self): - super(DFCloudSubtract, self).__init__() - def RunScript(self, - i_cloud_subtract_from: Rhino.Geometry.PointCloud, - i_cloud_subtract_with: Rhino.Geometry.PointCloud, - i_distance_threshold: float): - df_cloud = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_subtract_from) - df_cloud_substract = df_cvt.cvt_rhcloud_2_dfcloud(i_cloud_subtract_with) - if i_distance_threshold is None: - ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold not defined. 0.01 used as default value.")# noqa: F821 - i_distance_threshold = 0.01 - if i_distance_threshold <= 0: - ghenv.Component.AddRuntimeMessage(RML.Warning, "Distance threshold must be greater than 0. Please provide a valid distance threshold.")# noqa: F821 - return None - df_cloud.subtract_points(df_cloud_substract, i_distance_threshold) - rh_cloud = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) - return [rh_cloud] diff --git a/src/gh/components/DF_cloud_subtractor/icon.png b/src/gh/components/DF_cloud_subtractor/icon.png deleted file mode 100644 index 1bcd01ff2a4f212c87192a0500dd585f0add6401..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12377 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 diff --git a/src/gh/components/DF_cloud_subtractor/metadata.json b/src/gh/components/DF_cloud_subtractor/metadata.json deleted file mode 100644 index 4a3b1545..00000000 --- a/src/gh/components/DF_cloud_subtractor/metadata.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "DFSubtractCloud", - "nickname": "Subtract", - "category": "diffCheck", - "subcategory": "Cloud", - "description": "Subtracts points from a point cloud based on a distance threshold.", - "exposure": 4, - "instanceGuid": "9ef299aa-76dc-4417-9b95-2a374e2b36af", - "ghpython": { - "hideOutput": true, - "hideInput": true, - "isAdvancedMode": true, - "marshalOutGuids": true, - "iconDisplay": 2, - "inputParameters": [ - { - "name": "i_cloud_subtract_from", - "nickname": "i_cloud_subtract_from", - "description": "The point cloud to subtract from.", - "optional": false, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "pointcloud" - }, - { - "name": "i_cloud_subtract_with", - "nickname": "i_cloud_subtract_with", - "description": "The point cloud to subtract with.", - "optional": false, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "pointcloud" - }, - { - "name": "i_distance_threshold", - "nickname": "i_distance_threshold", - "description": "The distance threshold to consider a point as too close.", - "optional": true, - "allowTreeAccess": true, - "showTypeHints": true, - "scriptParamAccess": "item", - "wireDisplay": "default", - "sourceCount": 0, - "typeHintID": "brep" - } - ], - "outputParameters": [ - { - "name": "o_cloud", - "nickname": "o_cloud", - "description": "The resulting cloud after subtraction.", - "optional": false, - "sourceCount": 0, - "graft": false - } - ] - } -} \ No newline at end of file From a1d52666714c50096a260cf609fb97ba49d13d4f Mon Sep 17 00:00:00 2001 From: eleniv3d <43600924+eleniv3d@users.noreply.github.com> Date: Thu, 2 Oct 2025 15:50:23 +0200 Subject: [PATCH 19/19] FIX minor cosmetic changes --- src/gh/components/DF_cloud_difference/code.py | 2 ++ .../code.py | 6 ++++-- .../icon.png | Bin .../metadata.json | 4 ++-- src/gh/components/DF_cloud_split/code.py | 2 +- src/gh/components/DF_cloud_union/code.py | 3 ++- 6 files changed, 11 insertions(+), 6 deletions(-) rename src/gh/components/{DF_cloud_intersect => DF_cloud_intersection}/code.py (92%) rename src/gh/components/{DF_cloud_intersect => DF_cloud_intersection}/icon.png (100%) rename src/gh/components/{DF_cloud_intersect => DF_cloud_intersection}/metadata.json (96%) diff --git a/src/gh/components/DF_cloud_difference/code.py b/src/gh/components/DF_cloud_difference/code.py index de67465b..0d54f9e1 100644 --- a/src/gh/components/DF_cloud_difference/code.py +++ b/src/gh/components/DF_cloud_difference/code.py @@ -5,9 +5,11 @@ from ghpythonlib.componentbase import executingcomponent as component + class DFCloudDifference(component): def __init__(self): super(DFCloudDifference, self).__init__() + def RunScript(self, i_cloud_A: Rhino.Geometry.PointCloud, i_cloud_B: Rhino.Geometry.PointCloud, diff --git a/src/gh/components/DF_cloud_intersect/code.py b/src/gh/components/DF_cloud_intersection/code.py similarity index 92% rename from src/gh/components/DF_cloud_intersect/code.py rename to src/gh/components/DF_cloud_intersection/code.py index f7d6548e..8ebe1b4e 100644 --- a/src/gh/components/DF_cloud_intersect/code.py +++ b/src/gh/components/DF_cloud_intersection/code.py @@ -5,9 +5,11 @@ from ghpythonlib.componentbase import executingcomponent as component -class DFCloudIntersect(component): + +class DFCloudIntersection(component): def __init__(self): - super(DFCloudIntersect, self).__init__() + super(DFCloudIntersection, self).__init__() + def RunScript(self, i_cloud_A: Rhino.Geometry.PointCloud, i_cloud_B: Rhino.Geometry.PointCloud, diff --git a/src/gh/components/DF_cloud_intersect/icon.png b/src/gh/components/DF_cloud_intersection/icon.png similarity index 100% rename from src/gh/components/DF_cloud_intersect/icon.png rename to src/gh/components/DF_cloud_intersection/icon.png diff --git a/src/gh/components/DF_cloud_intersect/metadata.json b/src/gh/components/DF_cloud_intersection/metadata.json similarity index 96% rename from src/gh/components/DF_cloud_intersect/metadata.json rename to src/gh/components/DF_cloud_intersection/metadata.json index 6e044686..e12fd3ff 100644 --- a/src/gh/components/DF_cloud_intersect/metadata.json +++ b/src/gh/components/DF_cloud_intersection/metadata.json @@ -1,6 +1,6 @@ { - "name": "DFIntersectCloud", - "nickname": "Intersect", + "name": "DFCloudIntersection", + "nickname": "Intersection", "category": "diffCheck", "subcategory": "Cloud", "description": "Intersects points from two point clouds based on a distance threshold.", diff --git a/src/gh/components/DF_cloud_split/code.py b/src/gh/components/DF_cloud_split/code.py index 6ceddb1d..263136cb 100644 --- a/src/gh/components/DF_cloud_split/code.py +++ b/src/gh/components/DF_cloud_split/code.py @@ -28,7 +28,7 @@ def RunScript(self, o_pts_in = df_cvt.cvt_dfcloud_2_rhcloud(df_cloud) else: - pts_in = [] + pts_in = [] pts_out = [] for pc_item in i_cloud: point = Rhino.Geometry.Point3d(pc_item.X, pc_item.Y, pc_item.Z) diff --git a/src/gh/components/DF_cloud_union/code.py b/src/gh/components/DF_cloud_union/code.py index c0948e5e..2c341023 100644 --- a/src/gh/components/DF_cloud_union/code.py +++ b/src/gh/components/DF_cloud_union/code.py @@ -11,7 +11,8 @@ TOL = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance -class DFMergeAssemblies(component): + +class DFCloudUnion(component): def RunScript(self, i_clouds: System.Collections.Generic.List[Rhino.Geometry.PointCloud]): if i_clouds is None or len(i_clouds) == 0: