Store drawing location in SVG

This commit is contained in:
Thomas Krijnen
2020-12-31 11:31:05 +01:00
parent a5adb01dff
commit c3d4ce8f51
2 changed files with 85 additions and 27 deletions
+73 -24
View File
@@ -24,6 +24,7 @@
#include <cstdio>
#include <limits>
#include <algorithm>
#include <numeric>
#include <gp_Pln.hxx>
#include <gp_Trsf.hxx>
@@ -292,16 +293,18 @@ void SvgSerializer::write(path_object& p, const TopoDS_Wire& wire) {
p.second.push_back(path);
}
SvgSerializer::path_object& SvgSerializer::start_path(IfcUtil::IfcBaseEntity* storey, const std::string& id) {
SvgSerializer::path_object& SvgSerializer::start_path(const gp_Pln& pln, IfcUtil::IfcBaseEntity* storey, const std::string& id) {
auto key = std::make_pair(std::make_pair(storey, ""), path_object());
SvgSerializer::path_object& p = paths.insert(key)->second;
drawing_metadata[key.first].pln_3d = pln;
p.first = id;
return p;
}
SvgSerializer::path_object& SvgSerializer::start_path(const std::string& drawing_name, const std::string& id) {
SvgSerializer::path_object& SvgSerializer::start_path(const gp_Pln& pln, const std::string& drawing_name, const std::string& id) {
auto key = std::make_pair(std::make_pair(nullptr, drawing_name), path_object());
SvgSerializer::path_object& p = paths.insert(key)->second;
drawing_metadata[key.first].pln_3d = pln;
p.first = id;
return p;
}
@@ -633,6 +636,15 @@ void SvgSerializer::write(const geometry_data& data) {
cut_z = zmin + 1.;
}
gp_Pln pln;
if (variant.which() < 2) {
pln = gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ());
}
else {
const auto& section = boost::get<vertical_section>(variant);
pln = section.plane;
}
gp_Vec bbmin(x1, y1, zmin);
gp_Vec bbmax(x2, y2, zmax);
auto bbdif = bbmax - bbmin;
@@ -641,9 +653,9 @@ void SvgSerializer::write(const geometry_data& data) {
if (data.product->declaration().is("IfcAnnotation") && (proj.Magnitude() > 1.e-5) && zmin >= range.first && zmin <= range.second) {
if (po == nullptr) {
if (storey) {
po = &start_path(storey, data.svg_name);
po = &start_path(pln, storey, data.svg_name);
} else {
po = &start_path(drawing_name, data.svg_name);
po = &start_path(pln, drawing_name, data.svg_name);
}
}
@@ -717,20 +729,12 @@ void SvgSerializer::write(const geometry_data& data) {
if (po == nullptr) {
if (storey) {
po = &start_path(storey, data.svg_name);
po = &start_path(pln, storey, data.svg_name);
} else {
po = &start_path(drawing_name, data.svg_name);
po = &start_path(pln, drawing_name, data.svg_name);
}
}
// Create a horizontal cross section 1 meter above the bottom point of the shape
gp_Pln pln;
if (variant.which() < 2) {
pln = gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ());
} else {
const auto& section = boost::get<vertical_section>(variant);
pln = section.plane;
}
TopoDS_Shape result = BRepAlgoAPI_Section(subshape, pln);
if (variant.which() == 2) {
@@ -889,7 +893,10 @@ void SvgSerializer::setBoundingRectangle(double width, double height) {
this->rescale = true;
}
void SvgSerializer::resize() {
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) {
// Scale the resulting image to a bounding rectangle specified by command line arguments
const double dx = xmax - xmin;
@@ -918,6 +925,8 @@ void SvgSerializer::resize() {
cy = ymin * sc;
}
m = {{ {{sc,0,-cx}},{{0,sc,-cy}},{{0,0,1}} }};
float_item_list::const_iterator it;
for (it = xcoords.begin() + xcoords_begin; it != xcoords.end(); ++it, ++xcoords_begin) {
double& v = (*it)->value();
@@ -931,6 +940,8 @@ void SvgSerializer::resize() {
(*it)->value() *= sc;
}
}
return m;
}
void SvgSerializer::resetScale() {
@@ -944,7 +955,12 @@ void SvgSerializer::resetScale() {
}
void SvgSerializer::finalize() {
resize();
auto m = resize();
// Update the paper space scale matrices
for (auto& p : paths) {
drawing_metadata[p.first].matrix_3 = m;
}
if (!deferred_section_data_.is_initialized() && (auto_section_ || auto_elevation_)) {
deferred_section_data_.emplace();
@@ -987,21 +1003,20 @@ void SvgSerializer::finalize() {
{
gp_Pln pln(gp_Ax3(
gp_Pnt((xmin + xmax) / 2., -(ymax + 1.e-1), 0.),
gp_Dir(0, -1, 0),
gp_Dir(0, 1, 0),
gp_Dir(1, 0, 0)));
deferred_section_data_->push_back(vertical_section{ pln , "Elevation North", true });
}
{
gp_Pln pln(gp_Ax3(
gp_Pnt(xmin - 1.e-1, (ymin + ymax) / -2., 0.),
gp_Dir(-1, 0, 0),
gp_Dir(0, -1, 0)));
gp_Dir(1, 0, 0),
gp_Dir(0, 1, 0)));
deferred_section_data_->push_back(vertical_section{ pln , "Elevation West", true });
}
}
resetScale();
if (deferred_section_data_ && deferred_section_data_->size() && element_buffer_.size()) {
@@ -1059,7 +1074,7 @@ void SvgSerializer::finalize() {
exp.Init(hlr_compound, TopAbs_EDGE);
BRep_Builder B;
auto& po = start_path(drawing_name, "class=\"projection\"");
auto& po = start_path(section.plane, drawing_name, "class=\"projection\"");
for (; exp.More(); exp.Next()) {
TopoDS_Wire w;
B.MakeWire(w);
@@ -1070,7 +1085,11 @@ void SvgSerializer::finalize() {
}
}
resize();
auto m3 = resize();
auto k = std::make_pair(nullptr, drawing_name);
drawing_metadata[k].matrix_3 = m3;
resetScale();
if (use_hlr) {
@@ -1089,11 +1108,11 @@ void SvgSerializer::finalize() {
}
std::ostringstream oss;
if (it->first.first) {
svg_file << " <g " << nameElement(it->first.first) << ">\n";
svg_file << " <g " << nameElement(it->first.first) << " " << writeMetadata(drawing_metadata[it->first]) << ">\n";
} else {
auto n = it->first.second;
IfcUtil::escape_xml(n);
svg_file << " <g " << namespace_prefix_ << "name=\"" << n << "\" class=\"section\">\n";
svg_file << " <g " << namespace_prefix_ << "name=\"" << n << "\" class=\"section\" " << writeMetadata(drawing_metadata[it->first]) << ">\n";
}
}
svg_file << " <g " << it->second.first << ">\n";
@@ -1285,3 +1304,33 @@ void SvgSerializer::setSectionHeightsFromStoreys(double offset) {
section_data_->push_back(horizontal_plan_at_element{});
}
}
namespace {
std::string array_to_string(double v) {
return std::to_string(v);
}
template <typename T>
std::string array_to_string(const T& v) {
return "[" + std::accumulate(
++v.begin(), v.end(),
array_to_string(v.front()),
[](const std::string& accum, auto const & item) {
return accum + "," + array_to_string(item);
}) + "]";
}
}
std::string SvgSerializer::writeMetadata(const drawing_meta& m) {
gp_Trsf trsf;
trsf.SetTransformation(m.pln_3d.Position(), gp::XOY());
auto m43 = IfcGeom::Matrix<real_t>(IfcGeom::ElementSettings(IfcGeom::IteratorSettings(), 1., ""), trsf).data();
std::array<std::array<double, 4>, 4> m4 = {{
{{ (double)m43[0], (double)m43[3], (double)m43[6], (double)m43[9] }},
{{ (double)m43[1], (double)m43[4], (double)m43[7], (double)m43[10] }},
{{ (double)m43[2], (double)m43[5], (double)m43[8], (double)m43[11] }},
{{ 0, 0, 0, 1 }}
}};
return namespace_prefix_ + "plane=\""+ array_to_string(m4) +"\" " +
namespace_prefix_ + "matrix3=\"" + array_to_string(m.matrix_3) + "\"";
}