@@ -39,6 +39,11 @@ struct filtered_files_t {};
39
39
#include < BRepBndLib.hxx>
40
40
#include < BRep_Builder.hxx>
41
41
#include < BRepTools.hxx>
42
+ #include < ProjLib.hxx>
43
+ #include < TopExp_Explorer.hxx>
44
+ #include < BRepPrimAPI_MakeBox.hxx>
45
+ #include < BRepBuilderAPI_MakeFace.hxx>
46
+ #include < BRepAlgoAPI_Common.hxx>
42
47
43
48
#include < set>
44
49
#include < map>
@@ -155,6 +160,29 @@ class voxel_operation {
155
160
virtual ~voxel_operation () {}
156
161
};
157
162
163
+ namespace {
164
+ json_logger::meta_data dump_info (abstract_voxel_storage* voxels) {
165
+ if (dynamic_cast <abstract_chunked_voxel_storage*>(voxels)) {
166
+ auto left = dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->grid_offset ();
167
+ auto nc = dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->num_chunks ();
168
+ auto right = (left + nc.as <long >()) - (decltype (left)::element_type)1 ;
169
+ auto sz = dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->voxel_size ();
170
+ auto szl = (long )dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->chunk_size ();
171
+ auto left_world = ((voxels->bounds ()[0 ].as <long >() + left * szl).as <double >() * sz);
172
+ auto right_world = ((voxels->bounds ()[1 ].as <long >() + left * szl).as <double >() * sz);
173
+
174
+ return {
175
+ {" count" , (long )voxels->count ()},
176
+ {" grid" , left.format () + " - " + right.format ()},
177
+ {" bounds" , voxels->bounds ()[0 ].format () + " - " + voxels->bounds ()[1 ].format ()},
178
+ {" world" , left_world.format () + " - " + right_world.format ()},
179
+ {" bits" , (long )voxels->value_bits ()}
180
+ };
181
+ }
182
+ return {};
183
+ }
184
+ }
185
+
158
186
#ifdef WITH_IFC
159
187
class op_parse_ifc_file : public voxel_operation {
160
188
public:
@@ -537,6 +565,32 @@ class op_print_components : public voxel_operation {
537
565
}
538
566
};
539
567
568
+ class op_describe_components : public voxel_operation {
569
+ public:
570
+ const std::vector<argument_spec>& arg_names () const {
571
+ static std::vector<argument_spec> nm_ = { { true , " output_path" , " string" }, { true , " input" , " voxels" } };
572
+ return nm_;
573
+ }
574
+ symbol_value invoke (const scope_map& scope) const {
575
+ const std::string output_path = scope.get_value <std::string>(" output_path" );
576
+ std::ofstream ofs (output_path.c_str ());
577
+ ofs << " [" ;
578
+ bool first = true ;
579
+ abstract_voxel_storage* voxels = scope.get_value <abstract_voxel_storage*>(" input" );
580
+ connected_components ((regular_voxel_storage*)voxels, [&ofs, &first](regular_voxel_storage* c) {
581
+ if (!first) {
582
+ ofs << " ," ;
583
+ }
584
+ auto info = dump_info (c);
585
+ ofs << json_logger::to_json_string (info);
586
+ first = false ;
587
+ });
588
+ ofs << " ]" ;
589
+ symbol_value v;
590
+ return v;
591
+ }
592
+ };
593
+
540
594
class op_keep_components : public voxel_operation {
541
595
public:
542
596
const std::vector<argument_spec>& arg_names () const {
@@ -559,27 +613,6 @@ class op_keep_components : public voxel_operation {
559
613
};
560
614
561
615
namespace {
562
- json_logger::meta_data dump_info (abstract_voxel_storage* voxels) {
563
- if (dynamic_cast <abstract_chunked_voxel_storage*>(voxels)) {
564
- auto left = dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->grid_offset ();
565
- auto nc = dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->num_chunks ();
566
- auto right = (left + nc.as <long >()) - (decltype (left)::element_type)1 ;
567
- auto sz = dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->voxel_size ();
568
- auto szl = (long )dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->chunk_size ();
569
- auto left_world = ((voxels->bounds ()[0 ].as <long >() + left * szl).as <double >() * sz);
570
- auto right_world = ((voxels->bounds ()[1 ].as <long >() + left * szl).as <double >() * sz);
571
-
572
- return {
573
- {" count" , (long )voxels->count ()},
574
- {" grid" , left.format () + " - " + right.format ()},
575
- {" bounds" , voxels->bounds ()[0 ].format () + " - " + voxels->bounds ()[1 ].format ()},
576
- {" world" , left_world.format () + " - " + right_world.format ()},
577
- {" bits" , (long )voxels->value_bits ()}
578
- };
579
- }
580
- return {};
581
- }
582
-
583
616
template <typename Fn, typename Fn2>
584
617
void revoxelize_and_check_overlap (abstract_voxel_storage* voxels, const geometry_collection_t & surfaces, Fn fn, Fn2 fn2) {
585
618
BRep_Builder B;
@@ -899,6 +932,101 @@ class op_offset : public voxel_operation {
899
932
}
900
933
};
901
934
935
+ class op_zeros : public voxel_operation {
936
+ public:
937
+ const std::vector<argument_spec>& arg_names () const {
938
+ static std::vector<argument_spec> nm_ = { { true , " input" , " voxels" } };
939
+ return nm_;
940
+ }
941
+ symbol_value invoke (const scope_map& scope) const {
942
+ abstract_voxel_storage* voxels = scope.get_value <abstract_voxel_storage*>(" input" );
943
+ // @todo also implement empty_copy_as() here.
944
+ return voxels->empty_copy ();
945
+ }
946
+ };
947
+
948
+ class op_plane : public voxel_operation {
949
+ public:
950
+ const std::vector<argument_spec>& arg_names () const {
951
+ static std::vector<argument_spec> nm_ = { { true , " input" , " voxels" }, {true , " a" , " real" }, {true , " b" , " real" }, {true , " c" , " real" }, {true , " d" , " real" } };
952
+ return nm_;
953
+ }
954
+ symbol_value invoke (const scope_map& scope) const {
955
+ abstract_voxel_storage* v = scope.get_value <abstract_voxel_storage*>(" input" );
956
+
957
+ auto voxels = dynamic_cast <abstract_chunked_voxel_storage*>(v);
958
+ if (voxels == nullptr ) {
959
+ throw std::runtime_error (" expected chunked storage" );
960
+ }
961
+
962
+ auto result = voxels->empty_copy ();
963
+
964
+ if (voxels->count () == 0 ) {
965
+ return result;
966
+ }
967
+
968
+ gp_Pln pln (
969
+ scope.get_value <double >(" a" ),
970
+ scope.get_value <double >(" b" ),
971
+ scope.get_value <double >(" c" ),
972
+ scope.get_value <double >(" d" )
973
+ );
974
+
975
+ auto left = voxels->grid_offset ();
976
+ auto sz = dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->voxel_size ();
977
+ auto szl = (long )dynamic_cast <abstract_chunked_voxel_storage*>(voxels)->chunk_size ();
978
+ auto left_world = ((voxels->bounds ()[0 ].as <long >() + left * szl).as <double >() * sz);
979
+ auto right_world = ((voxels->bounds ()[1 ].as <long >() + left * szl).as <double >() * sz);
980
+
981
+ BRepPrimAPI_MakeBox mb (gp_Pnt (
982
+ left_world.get <0 >(),
983
+ left_world.get <1 >(),
984
+ left_world.get <2 >()
985
+ ), gp_Pnt (
986
+ right_world.get <0 >(),
987
+ right_world.get <1 >(),
988
+ right_world.get <2 >()
989
+ ));
990
+
991
+ auto box = mb.Solid ();
992
+ static double inf = std::numeric_limits<double >::infinity ();
993
+ std::array<std::array<double , 2 >, 2 > uv_min_max = {{ {{+inf, +inf}}, {{-inf,-inf}} }};
994
+
995
+ TopExp_Explorer exp (box, TopAbs_VERTEX);
996
+ for (; exp.More (); exp.Next ()) {
997
+ auto p = BRep_Tool::Pnt (TopoDS::Vertex (exp.Current ()));
998
+ auto p2d = ProjLib::Project (pln, p);
999
+ for (int i = 0 ; i < 2 ; ++i) {
1000
+ auto v = p2d.ChangeCoord ().ChangeCoord (i + 1 );
1001
+ auto & min_v = uv_min_max[0 ][i];
1002
+ auto & max_v = uv_min_max[1 ][i];
1003
+ if (v < min_v) min_v = v;
1004
+ if (v > max_v) max_v = v;
1005
+ }
1006
+ }
1007
+
1008
+ auto face = BRepBuilderAPI_MakeFace (pln,
1009
+ uv_min_max[0 ][0 ], uv_min_max[1 ][0 ],
1010
+ uv_min_max[0 ][1 ], uv_min_max[1 ][1 ]
1011
+ );
1012
+
1013
+ auto face_inside = BRepAlgoAPI_Common (face, box).Shape ();
1014
+ TopoDS_Compound C;
1015
+ if (face_inside.ShapeType () == TopAbs_COMPOUND) {
1016
+ C = TopoDS::Compound (face_inside);
1017
+ } else {
1018
+ BRep_Builder B;
1019
+ B.MakeCompound (C);
1020
+ B.Add (C, face_inside);
1021
+ }
1022
+
1023
+ BRepMesh_IncrementalMesh (C, 0.001 );
1024
+
1025
+ geometry_collection_t * single = new geometry_collection_t { { 0 , C} };
1026
+ return single;
1027
+ }
1028
+ };
1029
+
902
1030
class op_offset_xy : public voxel_operation {
903
1031
public:
904
1032
const std::vector<argument_spec>& arg_names () const {
@@ -1315,7 +1443,7 @@ class op_create_prop_filter : public voxel_operation {
1315
1443
class op_mesh : public voxel_operation {
1316
1444
public:
1317
1445
const std::vector<argument_spec>& arg_names () const {
1318
- static std::vector<argument_spec> nm_ = { { true , " input" , " voxels" }, { true , " filename" , " string" }, {false , " use_value" , " integer" } };
1446
+ static std::vector<argument_spec> nm_ = { { true , " input" , " voxels" }, { true , " filename" , " string" }, {false , " use_value" , " integer" }, { false , " with_components " , " integer " } };
1319
1447
return nm_;
1320
1448
}
1321
1449
symbol_value invoke (const scope_map& scope) const {
@@ -1324,7 +1452,8 @@ class op_mesh : public voxel_operation {
1324
1452
auto filename = scope.get_value <std::string>(" filename" );
1325
1453
std::ofstream ofs (filename.c_str ());
1326
1454
if (voxels->value_bits () == 1 ) {
1327
- ((regular_voxel_storage*)voxels)->obj_export (ofs);
1455
+ auto with_components = scope.get_value_or <int >(" with_components" , -1 );
1456
+ ((regular_voxel_storage*)voxels)->obj_export (ofs, with_components != 0 );
1328
1457
} else {
1329
1458
((regular_voxel_storage*)voxels)->obj_export (ofs, use_value != 1 , use_value == 1 );
1330
1459
}
0 commit comments