From c0317efd53b7eee99fbd04c805cd95d42cc4559a Mon Sep 17 00:00:00 2001 From: Pierre Anquez Date: Thu, 5 Mar 2026 10:21:29 +0100 Subject: [PATCH 1/4] feat(Model_: add API helpers to compute unique vertices of models --- .../model/helpers/compute_unique_vertices.hpp | 37 ++++ src/geode/model/CMakeLists.txt | 2 + .../model/helpers/compute_unique_vertices.cpp | 173 ++++++++++++++++++ .../detail/surface_mesh_validity_fix.cpp | 2 + .../rectangular_cuboid_without_uv.og_brep | Bin 0 -> 12248 bytes tests/model/CMakeLists.txt | 7 + tests/model/test-compute-unique-vertices.cpp | 50 +++++ 7 files changed, 271 insertions(+) create mode 100644 include/geode/model/helpers/compute_unique_vertices.hpp create mode 100644 src/geode/model/helpers/compute_unique_vertices.cpp create mode 100644 tests/data/rectangular_cuboid_without_uv.og_brep create mode 100644 tests/model/test-compute-unique-vertices.cpp diff --git a/include/geode/model/helpers/compute_unique_vertices.hpp b/include/geode/model/helpers/compute_unique_vertices.hpp new file mode 100644 index 000000000..98bc18dda --- /dev/null +++ b/include/geode/model/helpers/compute_unique_vertices.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 - 2026 Geode-solutions + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#pragma once + +#include + +namespace geode +{ +} // namespace geode + +namespace geode +{ + template < typename Model > + void compute_model_unique_vertices( + const Model& model, typename Model::Builder& builder ); +} // namespace geode \ No newline at end of file diff --git a/src/geode/model/CMakeLists.txt b/src/geode/model/CMakeLists.txt index 78f7ca248..c616b1d64 100644 --- a/src/geode/model/CMakeLists.txt +++ b/src/geode/model/CMakeLists.txt @@ -29,6 +29,7 @@ add_geode_library( "helpers/component_mesh_polyhedra.cpp" "helpers/component_mesh_vertices.cpp" "helpers/component_mensurations.cpp" + "helpers/compute_unique_vertices.cpp" "helpers/convert_brep_section.cpp" "helpers/convert_model_meshes.cpp" "helpers/convert_to_mesh.cpp" @@ -108,6 +109,7 @@ add_geode_library( "helpers/component_mesh_polyhedra.hpp" "helpers/component_mesh_vertices.hpp" "helpers/component_mensurations.hpp" + "helpers/compute_unique_vertices.hpp" "helpers/convert_brep_section.hpp" "helpers/convert_model_meshes.hpp" "helpers/convert_to_mesh.hpp" diff --git a/src/geode/model/helpers/compute_unique_vertices.cpp b/src/geode/model/helpers/compute_unique_vertices.cpp new file mode 100644 index 000000000..f1d5d169e --- /dev/null +++ b/src/geode/model/helpers/compute_unique_vertices.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2019 - 2026 Geode-solutions + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template < typename Model > + std::vector< geode::Point< Model::dim > > get_all_points_base( + const Model& model ) + { + std::vector< geode::Point< Model::dim > > points; + for( const auto& corner : model.corners() ) + { + for( const auto v : geode::Range{ corner.mesh().nb_vertices() } ) + { + points.emplace_back( corner.mesh().point( v ) ); + } + } + for( const auto& line : model.lines() ) + { + for( const auto v : geode::Range{ line.mesh().nb_vertices() } ) + { + points.emplace_back( line.mesh().point( v ) ); + } + } + for( const auto& surface : model.surfaces() ) + { + for( const auto v : geode::Range{ surface.mesh().nb_vertices() } ) + { + points.emplace_back( surface.mesh().point( v ) ); + } + } + return points; + } + + std::vector< geode::Point2D > get_all_points( const geode::Section& model ) + { + return get_all_points_base< geode::Section >( model ); + } + + std::vector< geode::Point3D > get_all_points( const geode::BRep& model ) + { + auto points = get_all_points_base< geode::BRep >( model ); + for( const auto& block : model.blocks() ) + { + for( const auto v : geode::Range{ block.mesh().nb_vertices() } ) + { + points.emplace_back( block.mesh().point( v ) ); + } + } + return points; + } + + template < typename Model > + void set_unique_vertices_base( const Model& model, + typename Model::Builder& builder, + const geode::NNSearch< Model::dim >& unique_nns ) + { + for( const auto& corner : model.corners() ) + { + for( const auto v : geode::Range{ corner.mesh().nb_vertices() } ) + { + const auto& point = corner.mesh().point( v ); + builder.set_unique_vertex( { corner.component_id(), v }, + unique_nns.closest_neighbor( point ) ); + } + } + for( const auto& line : model.lines() ) + { + for( const auto v : geode::Range{ line.mesh().nb_vertices() } ) + { + const auto& point = line.mesh().point( v ); + builder.set_unique_vertex( { line.component_id(), v }, + unique_nns.closest_neighbor( point ) ); + } + } + for( const auto& surface : model.surfaces() ) + { + for( const auto v : geode::Range{ surface.mesh().nb_vertices() } ) + { + const auto& point = surface.mesh().point( v ); + builder.set_unique_vertex( { surface.component_id(), v }, + unique_nns.closest_neighbor( point ) ); + } + } + } + + void set_unique_vertices( const geode::Section& model, + geode::SectionBuilder& builder, + const geode::NNSearch2D& unique_nns ) + { + set_unique_vertices_base( model, builder, unique_nns ); + } + + void set_unique_vertices( const geode::BRep& model, + geode::BRepBuilder& builder, + const geode::NNSearch3D& unique_nns ) + { + set_unique_vertices_base( model, builder, unique_nns ); + for( const auto& block : model.blocks() ) + { + for( const auto v : geode::Range{ block.mesh().nb_vertices() } ) + { + const auto& point = block.mesh().point( v ); + builder.set_unique_vertex( { block.component_id(), v }, + unique_nns.closest_neighbor( point ) ); + } + } + } + +} // namespace + +namespace geode +{ + template < typename Model > + void compute_model_unique_vertices( + const Model& model, typename Model::Builder& builder ) + { + if( model.nb_unique_vertices() > 0 ) + { + return; + } + auto all_vertices = get_all_points( model ); + NNSearch< Model::dim > nns{ all_vertices }; + const auto colocated_info = + nns.colocated_index_mapping( GLOBAL_EPSILON ); + builder.create_unique_vertices( colocated_info.nb_unique_points() ); + NNSearch< Model::dim > unique_nns{ colocated_info.unique_points }; + set_unique_vertices( model, builder, unique_nns ); + } + + template void opengeode_model_api compute_model_unique_vertices( + const BRep&, BRepBuilder& ); + template void opengeode_model_api compute_model_unique_vertices( + const Section&, SectionBuilder& ); +} // namespace geode diff --git a/src/geode/model/helpers/detail/surface_mesh_validity_fix.cpp b/src/geode/model/helpers/detail/surface_mesh_validity_fix.cpp index cbc0c021b..b5c3a7758 100644 --- a/src/geode/model/helpers/detail/surface_mesh_validity_fix.cpp +++ b/src/geode/model/helpers/detail/surface_mesh_validity_fix.cpp @@ -29,6 +29,8 @@ #include +#include +#include #include #include diff --git a/tests/data/rectangular_cuboid_without_uv.og_brep b/tests/data/rectangular_cuboid_without_uv.og_brep new file mode 100644 index 0000000000000000000000000000000000000000..ad7212ae90b24e8b1e04e3af96d21a46b44680d7 GIT binary patch literal 12248 zcmeHNU2Ggz6`ni$>%aJ~mT%UXWUe7Z5K%!};#a?9SXf zyB=G%#e+wlz3aXAd}rp~^PO|<&+=j-eBz7 zLg~M#KK9p_=BcR-;x*j!gKdtD}eX7gT2D@^tvOYbIme&wNSFwYbJ4? zyhEHt7VGPHs!#mv-#@`qvEfr_G;g=r$Q*?Op+C9Zu!FKuXp-mS)9jg()iVG}PE8B| zC=vuj)REgsKxy{o(&0q_y>|BZX8{xo0*W)G-C+BPT2`I?Y5t$z0Lr)T{LeH{59;<7C+@Cn8S(=*QRJz67AYAfSGxw3C1`?AfI!Qvf=1+tXJ7G!O(d$dq;+ppw;U zS!)>bkI%k(3xkR~c*xUa(L+s4^V)GvV|=_(tgqU!L1z($ z#=2fHqaRRQ)q)!|P8_w}6*Xh5kF1E7D>ZJi=jIn*C2_4X_vv@2xIDzzkk5>i!D1|N zdc9FD8l1_VLXnkC&m$}QSw&X1Hjk|A_Y_%q4aFlX`;e|7 zc$}LTd9zS#fX4;IdVVQ(yE3w$MXMvC(TZqek8hB)HpJjCHKvO~)8Q`ZKX_954TYw| zeL5}ZH_=eH{jCm9OTVGe^gettT?A`g6q+sqD$_-T)HtKw{DB^F8kUWT23%cp&z$+%k zqkmEvfnuXk+$cE7Kp}1Szunr6{ez-!2^M_^rRXAb9eNw1fZjweqqp$>Xph%Kdz5I8 z675l5Kc(>VY$tdnREN4tgZQL0!yje6}w<@(( zGomKn%c!7ySA;aDnd^B;(tkx!bK!UIzHo!e8+R=Eq~zdkB{VG*ja65XQKufaAbNV3SFYaIv3wuVJoq>s|t3Aw{6 z7s(cuUPd+x_8GeiRY^DSqlAwa0bP8d?u<`*fCCZiq=sWCv*r_%igorKH% zKOUn#8)F(9r%o6dMQnU9ef0w9i94A8=em%$XykIKtYM}*r%06MVq`bl&I*!jOd>6EVg?*lO5B}EJT64a{l3D4!g_U06v5zZ-A)F7L>NX zqAxO)RMLkfuPW(N2);s@>@H$a4|hjLz}@p-%|8Nm;@%o}r^;!b%JR9H4tLABY;JaD zdT+SvMoTxowkhgXDBP7R+T3+3Tqsc?+xLFp4HJ0f#TX}d-d*mhbO=jbRWcNj0vI2b zx&fj-mF_>Xvj~X0f3GAS>&@M>UE;2ho|#Ey(-eH$Npq$+o0%!+%{_^`GU3|Xm7}Oq zu_>vA#6EYenm^$V!`;BC={|D{PL95V%zf?Jl`n&vxVIK{i*wUc6m|J@hq=>vK4qjc zd{3C`5;PnS;ly07yAtiFD?{x^-N31G80O0BN6yO6?s7MP4`IV@fT$byQ2zg9%)Y2= zXUs?5`O&kzqb_QLma1r4Yo@Zr8Bf%mnKg@fGoRTL?z&8L(_AIEZd%dit_&qA_Gi0W zJsEM8$g%u4!?+QS_(U(J5tZyR(We+6OPAcf-?@SVzZo(A6ks_puKtDzTgn zWme6*qTUt34!KEt#YlYGJN@?leMI~c6`wKj85f@kd7`zQML-x=d%23NRcvcxgBdgu z+sAN|J*lvJ>-u6EPM(Ao&PHg_dsG~u?D@2!WAILKZ%X6+Zg(KHU=b|A{q*NY9|ucu zFE27Z73mx>^_~$Gry59#&NOJh_&UnYaZ_2&dq@;rXkU=Sp+V<7sVw9@Lna1ANI~d3 z^bO}nu%#hOd51!8;}QYk2&9 zs)jHNXtD + +#include +#include + +#include +#include +#include +#include + +void test_brep() +{ + auto brep = geode::load_brep( absl::StrCat( + geode::DATA_PATH, "rectangular_cuboid_without_uv.og_brep" ) ); + geode::BRepBuilder brep_builder{ brep }; + geode::compute_model_unique_vertices( brep, brep_builder ); + OPENGEODE_EXCEPTION( brep.nb_unique_vertices() == 8, + "[Test] Wrong number of unique vertices" ); +} + +void test() +{ + geode::OpenGeodeModelLibrary::initialize(); + test_brep(); +} + +OPENGEODE_TEST( "convert-brep" ) \ No newline at end of file From d74622363034c557c5b79d312213a8b41588095b Mon Sep 17 00:00:00 2001 From: Pierre Anquez Date: Thu, 5 Mar 2026 10:22:20 +0100 Subject: [PATCH 2/4] feat(Model): add API helpers to compute unique vertices of models From e45b84e038a04525e6ff1b8c49eae798fd34532c Mon Sep 17 00:00:00 2001 From: Pierre Anquez Date: Fri, 6 Mar 2026 15:38:09 +0100 Subject: [PATCH 3/4] complete if there are already some UV --- .../model/helpers/compute_unique_vertices.cpp | 139 ++++++++++++++++-- 1 file changed, 123 insertions(+), 16 deletions(-) diff --git a/src/geode/model/helpers/compute_unique_vertices.cpp b/src/geode/model/helpers/compute_unique_vertices.cpp index f1d5d169e..ca28dab9e 100644 --- a/src/geode/model/helpers/compute_unique_vertices.cpp +++ b/src/geode/model/helpers/compute_unique_vertices.cpp @@ -88,63 +88,169 @@ namespace return points; } + template < typename Model > + const geode::Point< Model::dim >& get_point_base( + const Model& model, const geode::ComponentMeshVertex& cmv ) + { + if( cmv.component_id.type() + == geode::Surface< Model::dim >::component_type_static() ) + { + const auto& surface = model.surface( cmv.component_id.id() ); + return surface.mesh().point( cmv.vertex ); + } + if( cmv.component_id.type() + == geode::Line< Model::dim >::component_type_static() ) + { + const auto& line = model.line( cmv.component_id.id() ); + return line.mesh().point( cmv.vertex ); + } + if( cmv.component_id.type() + == geode::Corner< Model::dim >::component_type_static() ) + { + const auto& corner = model.corner( cmv.component_id.id() ); + return corner.mesh().point( cmv.vertex ); + } + throw geode::OpenGeodeException{ + "[compute_unique_vertices::get_point] Unknown component type: ", + cmv.component_id.string() + }; + const auto& corner = model.corner( cmv.component_id.id() ); + return corner.mesh().point( cmv.vertex ); + } + + const geode::Point2D& get_point( + const geode::Section& model, const geode::ComponentMeshVertex& cmv ) + { + return get_point_base< geode::Section >( model, cmv ); + } + + const geode::Point3D& get_point( + const geode::BRep& model, const geode::ComponentMeshVertex& cmv ) + { + if( cmv.component_id.type() + == geode::Block< 3 >::component_type_static() ) + { + const auto& block = model.block( cmv.component_id.id() ); + return block.mesh().point( cmv.vertex ); + } + return get_point_base< geode::BRep >( model, cmv ); + } + template < typename Model > void set_unique_vertices_base( const Model& model, typename Model::Builder& builder, + absl::Span< const geode::index_t > initial_uv_correspondance, const geode::NNSearch< Model::dim >& unique_nns ) { for( const auto& corner : model.corners() ) { for( const auto v : geode::Range{ corner.mesh().nb_vertices() } ) { + geode::ComponentMeshVertex cmv{ corner.component_id(), v }; + if( model.unique_vertex( { corner.component_id(), v } ) + != geode::NO_ID ) + { + continue; + } const auto& point = corner.mesh().point( v ); - builder.set_unique_vertex( { corner.component_id(), v }, - unique_nns.closest_neighbor( point ) ); + const auto unique_vertex_id = + unique_nns.closest_neighbor( point ); + builder.set_unique_vertex( + cmv, initial_uv_correspondance[unique_vertex_id] ); } } for( const auto& line : model.lines() ) { for( const auto v : geode::Range{ line.mesh().nb_vertices() } ) { + geode::ComponentMeshVertex cmv{ line.component_id(), v }; + if( model.unique_vertex( cmv ) != geode::NO_ID ) + { + continue; + } const auto& point = line.mesh().point( v ); - builder.set_unique_vertex( { line.component_id(), v }, - unique_nns.closest_neighbor( point ) ); + const auto unique_vertex_id = + unique_nns.closest_neighbor( point ); + builder.set_unique_vertex( + cmv, initial_uv_correspondance[unique_vertex_id] ); } } for( const auto& surface : model.surfaces() ) { for( const auto v : geode::Range{ surface.mesh().nb_vertices() } ) { + geode::ComponentMeshVertex cmv{ surface.component_id(), v }; + if( model.unique_vertex( cmv ) != geode::NO_ID ) + { + continue; + } const auto& point = surface.mesh().point( v ); - builder.set_unique_vertex( { surface.component_id(), v }, - unique_nns.closest_neighbor( point ) ); + const auto unique_vertex_id = + unique_nns.closest_neighbor( point ); + builder.set_unique_vertex( + cmv, initial_uv_correspondance[unique_vertex_id] ); } } } void set_unique_vertices( const geode::Section& model, geode::SectionBuilder& builder, + absl::Span< const geode::index_t > initial_uv_correspondance, const geode::NNSearch2D& unique_nns ) { - set_unique_vertices_base( model, builder, unique_nns ); + set_unique_vertices_base( + model, builder, initial_uv_correspondance, unique_nns ); } void set_unique_vertices( const geode::BRep& model, geode::BRepBuilder& builder, + absl::Span< const geode::index_t > initial_uv_correspondance, const geode::NNSearch3D& unique_nns ) { - set_unique_vertices_base( model, builder, unique_nns ); + set_unique_vertices_base( + model, builder, initial_uv_correspondance, unique_nns ); for( const auto& block : model.blocks() ) { for( const auto v : geode::Range{ block.mesh().nb_vertices() } ) { + geode::ComponentMeshVertex cmv{ block.component_id(), v }; + if( model.unique_vertex( cmv ) != geode::NO_ID ) + { + continue; + } const auto& point = block.mesh().point( v ); - builder.set_unique_vertex( { block.component_id(), v }, - unique_nns.closest_neighbor( point ) ); + const auto unique_vertex_id = + unique_nns.closest_neighbor( point ); + builder.set_unique_vertex( + cmv, initial_uv_correspondance[unique_vertex_id] ); } } } + template < typename Model > + std::vector< geode::index_t > compute_initial_uv_correspondance( + const Model& model, const geode::NNSearch< Model::dim >& unique_nns ) + { + std::vector< geode::index_t > initial_uv_correspondance( + unique_nns.nb_points(), geode::NO_ID ); + for( const auto uv : geode::Range{ model.nb_unique_vertices() } ) + { + const auto& cmv = model.component_mesh_vertices( uv ).front(); + const auto& point = get_point( model, cmv ); + initial_uv_correspondance[unique_nns.closest_neighbor( point )] = + uv; + } + geode::index_t new_uv = model.nb_unique_vertices(); + for( auto& uv : initial_uv_correspondance ) + { + if( uv == geode::NO_ID ) + { + uv = new_uv++; + } + } + return initial_uv_correspondance; + } + } // namespace namespace geode @@ -153,17 +259,18 @@ namespace geode void compute_model_unique_vertices( const Model& model, typename Model::Builder& builder ) { - if( model.nb_unique_vertices() > 0 ) - { - return; - } auto all_vertices = get_all_points( model ); NNSearch< Model::dim > nns{ all_vertices }; const auto colocated_info = nns.colocated_index_mapping( GLOBAL_EPSILON ); - builder.create_unique_vertices( colocated_info.nb_unique_points() ); + const auto nb_initial_unique_vertices = model.nb_unique_vertices(); NNSearch< Model::dim > unique_nns{ colocated_info.unique_points }; - set_unique_vertices( model, builder, unique_nns ); + const auto initial_uv_correspondance = + compute_initial_uv_correspondance( model, unique_nns ); + builder.create_unique_vertices( + colocated_info.nb_unique_points() - nb_initial_unique_vertices ); + set_unique_vertices( + model, builder, initial_uv_correspondance, unique_nns ); } template void opengeode_model_api compute_model_unique_vertices( From c76f5515d0581bc618095600ff59831e53097b34 Mon Sep 17 00:00:00 2001 From: panquez <32702237+panquez@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:38:49 +0000 Subject: [PATCH 4/4] Apply prepare changes --- .clang-tidy | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index c5d55af02..20868d455 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -8,6 +8,7 @@ Checks: > -fuchsia*, -llvmlibc*, -llvm-header-guard, + -llvm-prefer-static-over-anonymous-namespace, -misc-no-recursion, -modernize-use-trailing-return-type, -readability-redundant-access-specifiers, @@ -15,19 +16,19 @@ Checks: > -cppcoreguidelines-avoid-const-or-ref-data-members CheckOptions: - - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic - value: '1' + - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: "1" - key: readability-identifier-length.MinimumLoopCounterNameLength value: 1 - key: readability-identifier-length.IgnoredVariableNames - value: '^[defijkptuvw]$' + value: "^[defijkptuvw]$" # More options here: https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html - key: readability-identifier-naming.NamespaceCase value: lower_case - key: readability-identifier-naming.ClassCase - value: CamelCase + value: CamelCase - key: readability-identifier-naming.StructCase - value: CamelCase + value: CamelCase - key: readability-identifier-naming.FunctionCase value: lower_case - key: readability-identifier-naming.VariableCase @@ -51,14 +52,12 @@ CheckOptions: - key: readability-identifier-naming.GlobalFunctionCase value: lower_case - key: readability-identifier-naming.MemberConstantCase - value: CamelCase + value: CamelCase - key: readability-identifier-naming.StaticConstantCase - value: lower_case + value: lower_case - key: readability-function-cognitive-complexity.Threshold value: 10 - key: readability-function-size.ParameterThreshold value: 4 - key: misc-include-cleaner.IgnoreHeaders - value: utility;cstddef;geode/.*_export\.h;geode/.*/common\.h;geode/basic/types\.h;geode/basic/assert\.h; - - + value: utility;cstddef;geode/.*_export\.h;geode/.*/common\.h;geode/basic/types\.h;geode/basic/assert\.h;