From c872ee8844327987dc2331e30b9e08f8b87124f1 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 25 Aug 2020 15:01:07 +0200 Subject: [PATCH] Support writing SVG to scale --- src/ifcconvert/IfcConvert.cpp | 14 +++++++++++ src/serializers/SvgSerializer.cpp | 41 +++++++++++++++++++++++-------- src/serializers/SvgSerializer.h | 5 ++++ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 23cb3d921d..72bccb00fe 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -340,6 +340,7 @@ int main(int argc, char** argv) { #endif short precision; double section_height; + std::string svg_scale; po::options_description serializer_options("Serialization options"); serializer_options.add_options() @@ -351,6 +352,9 @@ int main(int argc, char** argv) { ("bounds", po::value(&bounds), "Specifies the bounding rectangle, for example 512x512, to which the " "output will be scaled. Only used when converting to SVG.") + ("scale", po::value(&svg_scale), + "Interprets SVG bounds in mm, centers layout and draw elements to scale. " + "Only used when converting to SVG. Example 1:100.") ("door-arcs", "Draw door openings arcs for IfcDoor elements") ("section-height", po::value(§ion_height), "Specifies the cut section height for SVG 2D geometry.") @@ -891,6 +895,16 @@ int main(int argc, char** argv) { if (vmap.count("door-arcs")) { static_cast(serializer.get())->setDrawDoorArcs(true); } + if (vmap.count("scale")) { + int s0, s1; + if (sscanf(svg_scale.c_str(), "%u:%u", &s0, &s1) == 2 && s0 > 0 && s1 > 0) { + static_cast(serializer.get())->setScale((double)s0 / s1); + } else { + cerr_ << "[Error] Invalid use of --scale" << std::endl; + print_options(serializer_options); + return EXIT_FAILURE; + } + } } if (convert_back_units) { diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index c6455b4e40..952700eada 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -706,17 +706,21 @@ void SvgSerializer::finalize() { const double dx = xmax - xmin; const double dy = ymax - ymin; - double sc = 1.; - - if (dx / width > dy / height) { - sc = width / dx; + double sc, cx, cy; + if (scale_) { + sc = (*scale_) * 1000; + cx = (xmax + xmin) / 2. * sc - width / 2.; + cy = (ymax + ymin) / 2. * sc - height / 2.; } else { - sc = height / dy; + if (dx / width > dy / height) { + sc = width / dx; + } else { + sc = height / dy; + } + cx = xmin * sc; + cy = ymin * sc; } - const double cx = xmin * sc; - const double cy = ymin * sc; - {std::vector< boost::shared_ptr >::const_iterator it; for (it = xcoords.begin(); it != xcoords.end(); ++it) { double& v = (*it)->value(); @@ -760,7 +764,15 @@ void SvgSerializer::finalize() { } void SvgSerializer::writeHeader() { - svg_file << "\n" + svg_file << "\n" " \n" " \n" " \n" @@ -774,7 +786,16 @@ void SvgSerializer::writeHeader() { " .IfcAnnotation path {\n" " marker-end: url(#arrowend);\n" " marker-start: url(#arrowstart);\n" - " }\n" + " }\n"; + + if (scale_) { + svg_file << + " text {\n" // (pt) (px) (in) (mm) + " font-size: 4;\n" // approx 12 / 0.75 / 96 * 25.4 + " }\n"; + } + + svg_file << " ]]>\n" " \n"; } diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index 5b623ed843..9ace5e748a 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -73,6 +73,7 @@ protected: std::ofstream svg_file; double xmin, ymin, xmax, ymax, width, height; boost::optional, IfcUtil::IfcBaseEntity*>>> section_heights; + boost::optional scale_; bool rescale, print_space_names_, print_space_areas_, draw_door_arcs_, with_section_heights_from_storey_; std::multimap paths; std::vector< boost::shared_ptr > xcoords; @@ -90,6 +91,9 @@ public: , ymax(-std::numeric_limits::infinity()) , with_section_heights_from_storey_(false) , rescale(false) + , print_space_names_(false) + , print_space_areas_(false) + , draw_door_arcs_(false) , file(0) , storey_(0) {} @@ -113,6 +117,7 @@ public: void setPrintSpaceNames(bool b) { print_space_names_ = b; } void setPrintSpaceAreas(bool b) { print_space_areas_ = b; } void setDrawDoorArcs(bool b) { draw_door_arcs_ = b; } + void setScale(double s) { scale_ = s; } std::string nameElement(const IfcUtil::IfcBaseEntity* storey, const IfcGeom::Element* elem); std::string nameElement(const IfcUtil::IfcBaseEntity* elem); std::string idElement(const IfcUtil::IfcBaseEntity* elem);