Skip to content

Commit 3ebd07d

Browse files
committed
decribe_components() zero() plane()
1 parent 1b455eb commit 3ebd07d

File tree

4 files changed

+167
-23
lines changed

4 files changed

+167
-23
lines changed

json_logger.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ namespace {
4141
}
4242
}
4343

44+
std::string json_logger::to_json_string(const meta_data& m) {
45+
boost::property_tree::ptree pt;
46+
for (auto& p : m) {
47+
ptree_writer vis{ pt, p.first };
48+
boost::apply_visitor(vis, p.second);
49+
}
50+
std::ostringstream oss;
51+
boost::property_tree::write_json(oss, pt, false);
52+
return oss.str();
53+
}
54+
4455
void json_logger::message(severity s, const std::string & message, const std::map<std::string, meta_data>& meta)
4556
{
4657
static const std::array<const std::string, 6> severity_strings = { "", "debug", "notice", "warning", "error", "fatal" };

json_logger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class json_logger {
1414
typedef enum { FMT_TEXT, FMT_JSON } format;
1515
typedef boost::variant<long, double, std::string> meta_value;
1616
typedef std::map<std::string, meta_value> meta_data;
17+
static std::string to_json_string(const meta_data&);
1718
private:
1819
static std::vector<std::pair<format, std::ostream*>> log_output;
1920
static severity severity_;

voxec.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ voxel_operation_map::map_t& voxel_operation_map::map() {
3636
m.insert(std::make_pair(std::string("collapse"), &instantiate<op_collapse>));
3737
m.insert(std::make_pair(std::string("collapse_count"), &instantiate<op_collapse_count>));
3838
m.insert(std::make_pair(std::string("print_components"), &instantiate<op_print_components>));
39+
m.insert(std::make_pair(std::string("describe_components"), &instantiate<op_describe_components>));
3940
m.insert(std::make_pair(std::string("keep_components"), &instantiate<op_keep_components>));
4041
m.insert(std::make_pair(std::string("dump_surfaces"), &instantiate<op_dump_surfaces>));
4142
m.insert(std::make_pair(std::string("json_stats"), &instantiate<op_json_stats>));
@@ -47,6 +48,8 @@ voxel_operation_map::map_t& voxel_operation_map::map() {
4748
m.insert(std::make_pair(std::string("filter_attributes"), &instantiate<op_create_attr_filter>));
4849
m.insert(std::make_pair(std::string("filter_properties"), &instantiate<op_create_prop_filter>));
4950
#endif
51+
m.insert(std::make_pair(std::string("zeros"), &instantiate<op_zeros>));
52+
m.insert(std::make_pair(std::string("plane"), &instantiate<op_plane>));
5053
m.insert(std::make_pair(std::string("mesh"), &instantiate<op_mesh>));
5154
initialized = true;
5255
}

voxec.h

Lines changed: 152 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ struct filtered_files_t {};
3939
#include <BRepBndLib.hxx>
4040
#include <BRep_Builder.hxx>
4141
#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>
4247

4348
#include <set>
4449
#include <map>
@@ -155,6 +160,29 @@ class voxel_operation {
155160
virtual ~voxel_operation() {}
156161
};
157162

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+
158186
#ifdef WITH_IFC
159187
class op_parse_ifc_file : public voxel_operation {
160188
public:
@@ -537,6 +565,32 @@ class op_print_components : public voxel_operation {
537565
}
538566
};
539567

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+
540594
class op_keep_components : public voxel_operation {
541595
public:
542596
const std::vector<argument_spec>& arg_names() const {
@@ -559,27 +613,6 @@ class op_keep_components : public voxel_operation {
559613
};
560614

561615
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-
583616
template <typename Fn, typename Fn2>
584617
void revoxelize_and_check_overlap(abstract_voxel_storage* voxels, const geometry_collection_t& surfaces, Fn fn, Fn2 fn2) {
585618
BRep_Builder B;
@@ -899,6 +932,101 @@ class op_offset : public voxel_operation {
899932
}
900933
};
901934

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+
9021030
class op_offset_xy : public voxel_operation {
9031031
public:
9041032
const std::vector<argument_spec>& arg_names() const {
@@ -1315,7 +1443,7 @@ class op_create_prop_filter : public voxel_operation {
13151443
class op_mesh : public voxel_operation {
13161444
public:
13171445
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"} };
13191447
return nm_;
13201448
}
13211449
symbol_value invoke(const scope_map& scope) const {
@@ -1324,7 +1452,8 @@ class op_mesh : public voxel_operation {
13241452
auto filename = scope.get_value<std::string>("filename");
13251453
std::ofstream ofs(filename.c_str());
13261454
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);
13281457
} else {
13291458
((regular_voxel_storage*)voxels)->obj_export(ofs, use_value != 1, use_value == 1);
13301459
}

0 commit comments

Comments
 (0)