diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 18810b9b1e..c3eb82e2c9 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -344,7 +344,7 @@ int main(int argc, char** argv) { #endif short precision; double section_height; - std::string svg_scale; + std::string svg_scale, svg_center; std::string section_ref, elevation_ref; po::options_description serializer_options("Serialization options"); @@ -360,6 +360,9 @@ int main(int argc, char** argv) { ("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.") + ("center", po::value(&svg_center), + "When using --scale, specifies the location in the range [0 1]x[0 1] around which" + "to center the drawings. Example 0.5x0.5 (default).") ("section-ref", po::value(§ion_ref), "Element at which vertical cross sections should be created") ("elevation-ref", po::value(&elevation_ref), @@ -526,8 +529,8 @@ int main(int argc, char** argv) { } } - boost::optional bounding_width; - boost::optional bounding_height; + boost::optional bounding_width, bounding_height, relative_center_x, relative_center_y; + if (vmap.count("bounds") == 1) { int w, h; if (sscanf(bounds.c_str(), "%ux%u", &w, &h) == 2 && w > 0 && h > 0) { @@ -540,6 +543,18 @@ int main(int argc, char** argv) { } } + if (vmap.count("center") == 1) { + double cx, cy; + if (sscanf(svg_center.c_str(), "%lfx%lf", &cx, &cy) == 2 && cx >= 0. && cy >= 0. && cx <= 1. && cy <= 1.) { + relative_center_x = cx; + relative_center_y = cy; + } else { + cerr_ << "[Error] Invalid use of --bounds" << std::endl; + print_options(serializer_options); + return EXIT_FAILURE; + } + } + const path_t input_filename = vmap["input-file"].as(); if (!file_exists(IfcUtil::path::to_utf8(input_filename))) { cerr_ << "[Error] Input file '" << input_filename << "' does not exist" << std::endl; @@ -925,6 +940,9 @@ int main(int argc, char** argv) { if (vmap.count("elevation-ref")) { static_cast(serializer.get())->setElevationRef(elevation_ref); } + if (relative_center_x && relative_center_y) { + static_cast(serializer.get())->setDrawingCenter(*relative_center_x, *relative_center_y); + } } if (convert_back_units) { diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index da9608d2ee..0fd71c7709 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -863,8 +863,8 @@ void SvgSerializer::resize() { double sc, cx, cy; if (scale_) { sc = (*scale_) * 1000; - cx = (xmax + xmin) / 2. * sc - width / 2.; - cy = (ymax + ymin) / 2. * sc - height / 2.; + 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); } else { if (calculated_scale_) { sc = *calculated_scale_; diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index 07ee49d2b3..382b059088 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -116,7 +116,7 @@ protected: double xmin, ymin, xmax, ymax, width, height; boost::optional> section_data_; boost::optional> deferred_section_data_; - boost::optional scale_, calculated_scale_; + boost::optional scale_, calculated_scale_, center_x_, center_y_; bool rescale, print_space_names_, print_space_areas_, draw_door_arcs_; bool with_section_heights_from_storey_, buffer_elements_; @@ -186,6 +186,9 @@ public: buffer_elements_ = true; } void setScale(double s) { scale_ = s; } + void setDrawingCenter(double x, double y) { + center_x_ = x; center_y_ = y; + } 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);