mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Store drawing location in SVG
This commit is contained in:
@@ -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) + "\"";
|
||||
}
|
||||
Reference in New Issue
Block a user