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 <boost/format.hpp>
#include <boost/tokenizer.hpp>
#include "SvgSerializer.h"
@@ -422,6 +423,36 @@ namespace {
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) {
@@ -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.)
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);
boost::optional<gp_Pln> pln;
if (e) {
@@ -457,8 +491,39 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* brep_obj) {
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);
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) {
@@ -477,10 +542,10 @@ void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* brep_obj) {
name = boost::lexical_cast<std::string>(brep_obj->id());
}
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) {
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) {
this->width = width;
this->height = height;
this->rescale = true;
size_ = std::make_pair(width, height);
}
std::array<std::array<double, 3>, 3> SvgSerializer::resize() {
// identity matrix;
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
const double dx = xmax - xmin;
const double dy = ymax - ymin;
@@ -1250,19 +1313,19 @@ std::array<std::array<double, 3>, 3> SvgSerializer::resize() {
double sc, cx, cy;
if (scale_) {
sc = (*scale_) * 1000;
cx = (xmax + xmin) / 2. * sc - width * center_x_.get_value_or(0.5);
cy = (ymax + ymin) / 2. * sc - height * center_y_.get_value_or(0.5);
cx = (xmax + xmin) / 2. * sc - size_->first * center_x_.get_value_or(0.5);
cy = (ymax + ymin) / 2. * sc - size_->second * center_y_.get_value_or(0.5);
}
else {
if (calculated_scale_) {
sc = *calculated_scale_;
}
else {
if (dx / width > dy / height) {
sc = width / dx;
if (dx / size_->first > dy / size_->second) {
sc = size_->first / dx;
}
else {
sc = height / dy;
sc = size_->second / dy;
}
calculated_scale_ = sc;
}
@@ -1609,11 +1672,11 @@ void SvgSerializer::writeHeader() {
if (use_namespace_) {
svg_file << " xmlns:ifc=\"http://www.ifcopenshell.org/ns\"";
}
if (scale_) {
if (scale_ && size_) {
svg_file <<
" width=\"" << width << "mm\""
" height=\"" << height << "mm\"" <<
" viewBox=\"0 0 " << width << " " << height << "\"";
" width=\"" << size_->first << "mm\""
" height=\"" << size_->second << "mm\"" <<
" viewBox=\"0 0 " << size_->first << " " << size_->second << "\"";
}
svg_file << ">\n"
+6 -4
View File
@@ -97,6 +97,8 @@ struct vertical_section {
gp_Pln plane;
std::string name;
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;
@@ -130,12 +132,13 @@ public:
};
protected:
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>> 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_;
bool draw_door_arcs_, is_floor_plan_;
bool auto_section_, auto_elevation_;
@@ -173,7 +176,6 @@ public:
, xmax(-std::numeric_limits<double>::infinity())
, ymax(-std::numeric_limits<double>::infinity())
, with_section_heights_from_storey_(false)
, rescale(false)
, print_space_names_(false)
, print_space_areas_(false)
, draw_door_arcs_(false)