Work towards #1153

This commit is contained in:
Thomas Krijnen
2021-03-28 12:48:20 +02:00
parent ce03742aab
commit 88f26eaead
2 changed files with 85 additions and 20 deletions
+79 -16
View File
@@ -79,6 +79,7 @@
#include "../ifcparse/IfcGlobalId.h" #include "../ifcparse/IfcGlobalId.h"
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/tokenizer.hpp>
#include "SvgSerializer.h" #include "SvgSerializer.h"
@@ -422,6 +423,36 @@ namespace {
return box_t{ {{x0, y0, z0}}, {{x1, y1, z1}} }; return box_t{ {{x0, y0, z0}}, {{x1, y1, z1}} };
} }
struct string_property {
std::string pset_name, prop_name, value;
};
template <typename It>
void enumerate_string_properties(IfcUtil::IfcBaseEntity* product, It output_it) {
auto rels = product->get_inverse("IsDefinedBy");
for (auto& rel : *rels) {
if (rel->declaration().is("IfcRelDefinesByProperties")) {
auto pset = (IfcUtil::IfcBaseEntity*) (IfcUtil::IfcBaseClass*) *((IfcUtil::IfcBaseEntity*) rel)->get("RelatingPropertyDefinition");
std::string pset_name;
if (!pset->get("Name")->isNull()) {
pset_name = *pset->get("Name");
}
IfcEntityList::ptr props = *pset->get("HasProperties");
for (auto& prop : *props) {
if (prop->declaration().is("IfcPropertySingleValue")) {
std::string name = *((IfcUtil::IfcBaseEntity*) prop)->get("Name");
IfcUtil::IfcBaseClass* v = *((IfcUtil::IfcBaseEntity*) prop)->get("NominalValue");
auto value = v->data().getArgument(0);
if (value->type() == IfcUtil::Argument_STRING) {
std::string v_str = *value;
*output_it++ = string_property{ pset_name, name, v_str };
}
}
}
}
}
}
} }
void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* brep_obj) { void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* brep_obj) {
@@ -443,6 +474,9 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* brep_obj) {
// (When determinant < 0, copy is implied and the input is not mutated.) // (When determinant < 0, copy is implied and the input is not mutated.)
auto compound_unmirrored = make_transform_global.Shape(); auto compound_unmirrored = make_transform_global.Shape();
boost::optional<double> scale;
boost::optional<std::pair<double, double>> size;
auto e = edge_from_compound(compound_unmirrored); auto e = edge_from_compound(compound_unmirrored);
boost::optional<gp_Pln> pln; boost::optional<gp_Pln> pln;
if (e) { if (e) {
@@ -457,8 +491,39 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* brep_obj) {
pln = gp_Pln(gp_Ax3(P, N, V)); pln = gp_Pln(gp_Ax3(P, N, V));
} }
} }
else if (box_from_compound(compound_local)) { else if (boost::optional<box_t> b = box_from_compound(compound_local)) {
pln = gp_Pln().Transformed(trsf); pln = gp_Pln().Transformed(trsf);
size = std::make_pair(
b->second[0] - b->first[0],
b->second[1] - b->first[1]
);
}
std::vector<string_property> props;
enumerate_string_properties(brep_obj->product(), std::back_inserter(props));
std::map<std::string, std::string> prop_map;
for (auto& p : props) {
prop_map[p.pset_name + "." + p.prop_name] = p.value;
}
auto pit = prop_map.find("EPset_Drawing.Scale");
if (pit != prop_map.end()) {
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
tokenizer tok{ pit->second };
auto tokit = tok.begin();
std::string num, denum;
if (tokit != tok.end()) {
num = *tokit++;
}
tokit++;
if (tokit != tok.end()) {
denum = *tokit++;
}
if (num.size() && denum.size()) {
try {
scale = (float) boost::lexical_cast<int>(num) / boost::lexical_cast<int>(denum);
}
catch (boost::bad_lexical_cast&) {}
}
} }
if (pln) { if (pln) {
@@ -477,10 +542,10 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* brep_obj) {
name = boost::lexical_cast<std::string>(brep_obj->id()); name = boost::lexical_cast<std::string>(brep_obj->id());
} }
if (is_section) { if (is_section) {
deferred_section_data_->push_back(vertical_section{ *pln , "Section " + name, false }); deferred_section_data_->push_back(vertical_section{ *pln , "Section " + name, false, scale, size });
} }
if (is_elevation) { if (is_elevation) {
deferred_section_data_->push_back(vertical_section{ *pln , "Elevation " + name, true }); deferred_section_data_->push_back(vertical_section{ *pln , "Elevation " + name, true, scale, size });
} }
} }
@@ -1233,16 +1298,14 @@ void SvgSerializer::write(const geometry_data& data) {
} }
void SvgSerializer::setBoundingRectangle(double width, double height) { void SvgSerializer::setBoundingRectangle(double width, double height) {
this->width = width; size_ = std::make_pair(width, height);
this->height = height;
this->rescale = true;
} }
std::array<std::array<double, 3>, 3> SvgSerializer::resize() { std::array<std::array<double, 3>, 3> SvgSerializer::resize() {
// identity matrix; // identity matrix;
std::array<std::array<double, 3>, 3> m = {{ {{1,0,0}},{{0,1,0}},{{0,0,1}} }}; std::array<std::array<double, 3>, 3> m = {{ {{1,0,0}},{{0,1,0}},{{0,0,1}} }};
if (rescale) { if (size_) {
// Scale the resulting image to a bounding rectangle specified by command line arguments // Scale the resulting image to a bounding rectangle specified by command line arguments
const double dx = xmax - xmin; const double dx = xmax - xmin;
const double dy = ymax - ymin; const double dy = ymax - ymin;
@@ -1250,19 +1313,19 @@ std::array<std::array<double, 3>, 3> SvgSerializer::resize() {
double sc, cx, cy; double sc, cx, cy;
if (scale_) { if (scale_) {
sc = (*scale_) * 1000; sc = (*scale_) * 1000;
cx = (xmax + xmin) / 2. * sc - width * center_x_.get_value_or(0.5); cx = (xmax + xmin) / 2. * sc - size_->first * center_x_.get_value_or(0.5);
cy = (ymax + ymin) / 2. * sc - height * center_y_.get_value_or(0.5); cy = (ymax + ymin) / 2. * sc - size_->second * center_y_.get_value_or(0.5);
} }
else { else {
if (calculated_scale_) { if (calculated_scale_) {
sc = *calculated_scale_; sc = *calculated_scale_;
} }
else { else {
if (dx / width > dy / height) { if (dx / size_->first > dy / size_->second) {
sc = width / dx; sc = size_->first / dx;
} }
else { else {
sc = height / dy; sc = size_->second / dy;
} }
calculated_scale_ = sc; calculated_scale_ = sc;
} }
@@ -1609,11 +1672,11 @@ void SvgSerializer::writeHeader() {
if (use_namespace_) { if (use_namespace_) {
svg_file << " xmlns:ifc=\"http://www.ifcopenshell.org/ns\""; svg_file << " xmlns:ifc=\"http://www.ifcopenshell.org/ns\"";
} }
if (scale_) { if (scale_ && size_) {
svg_file << svg_file <<
" width=\"" << width << "mm\"" " width=\"" << size_->first << "mm\""
" height=\"" << height << "mm\"" << " height=\"" << size_->second << "mm\"" <<
" viewBox=\"0 0 " << width << " " << height << "\""; " viewBox=\"0 0 " << size_->first << " " << size_->second << "\"";
} }
svg_file << ">\n" svg_file << ">\n"
+6 -4
View File
@@ -97,6 +97,8 @@ struct vertical_section {
gp_Pln plane; gp_Pln plane;
std::string name; std::string name;
bool with_projection; bool with_projection;
boost::optional<double> scale;
boost::optional<std::pair<double, double>> size;
}; };
typedef boost::variant<horizontal_plan, horizontal_plan_at_element, vertical_section> section_data; typedef boost::variant<horizontal_plan, horizontal_plan_at_element, vertical_section> section_data;
@@ -130,12 +132,13 @@ public:
}; };
protected: protected:
std::ofstream svg_file; std::ofstream svg_file;
double xmin, ymin, xmax, ymax, width, height; double xmin, ymin, xmax, ymax;
boost::optional<std::vector<section_data>> section_data_; boost::optional<std::vector<section_data>> section_data_;
boost::optional<std::vector<section_data>> deferred_section_data_; boost::optional<std::vector<section_data>> deferred_section_data_;
boost::optional<double> scale_, calculated_scale_, center_x_, center_y_; boost::optional<double> scale_, calculated_scale_, center_x_, center_y_, scale_backup_;
boost::optional<std::pair<double, double>> size_, size_backup_;
bool with_section_heights_from_storey_, rescale, print_space_names_, print_space_areas_; bool with_section_heights_from_storey_, print_space_names_, print_space_areas_;
storey_height_display_types storey_height_display_; storey_height_display_types storey_height_display_;
bool draw_door_arcs_, is_floor_plan_; bool draw_door_arcs_, is_floor_plan_;
bool auto_section_, auto_elevation_; bool auto_section_, auto_elevation_;
@@ -173,7 +176,6 @@ public:
, xmax(-std::numeric_limits<double>::infinity()) , xmax(-std::numeric_limits<double>::infinity())
, ymax(-std::numeric_limits<double>::infinity()) , ymax(-std::numeric_limits<double>::infinity())
, with_section_heights_from_storey_(false) , with_section_heights_from_storey_(false)
, rescale(false)
, print_space_names_(false) , print_space_names_(false)
, print_space_areas_(false) , print_space_areas_(false)
, draw_door_arcs_(false) , draw_door_arcs_(false)