mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 19:27:10 +00:00
Support writing SVG to scale
This commit is contained in:
@@ -340,6 +340,7 @@ int main(int argc, char** argv) {
|
|||||||
#endif
|
#endif
|
||||||
short precision;
|
short precision;
|
||||||
double section_height;
|
double section_height;
|
||||||
|
std::string svg_scale;
|
||||||
|
|
||||||
po::options_description serializer_options("Serialization options");
|
po::options_description serializer_options("Serialization options");
|
||||||
serializer_options.add_options()
|
serializer_options.add_options()
|
||||||
@@ -351,6 +352,9 @@ int main(int argc, char** argv) {
|
|||||||
("bounds", po::value<std::string>(&bounds),
|
("bounds", po::value<std::string>(&bounds),
|
||||||
"Specifies the bounding rectangle, for example 512x512, to which the "
|
"Specifies the bounding rectangle, for example 512x512, to which the "
|
||||||
"output will be scaled. Only used when converting to SVG.")
|
"output will be scaled. Only used when converting to SVG.")
|
||||||
|
("scale", po::value<std::string>(&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")
|
("door-arcs", "Draw door openings arcs for IfcDoor elements")
|
||||||
("section-height", po::value<double>(§ion_height),
|
("section-height", po::value<double>(§ion_height),
|
||||||
"Specifies the cut section height for SVG 2D geometry.")
|
"Specifies the cut section height for SVG 2D geometry.")
|
||||||
@@ -891,6 +895,16 @@ int main(int argc, char** argv) {
|
|||||||
if (vmap.count("door-arcs")) {
|
if (vmap.count("door-arcs")) {
|
||||||
static_cast<SvgSerializer*>(serializer.get())->setDrawDoorArcs(true);
|
static_cast<SvgSerializer*>(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<SvgSerializer*>(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) {
|
if (convert_back_units) {
|
||||||
|
|||||||
@@ -706,17 +706,21 @@ void SvgSerializer::finalize() {
|
|||||||
const double dx = xmax - xmin;
|
const double dx = xmax - xmin;
|
||||||
const double dy = ymax - ymin;
|
const double dy = ymax - ymin;
|
||||||
|
|
||||||
double sc = 1.;
|
double sc, cx, cy;
|
||||||
|
if (scale_) {
|
||||||
if (dx / width > dy / height) {
|
sc = (*scale_) * 1000;
|
||||||
sc = width / dx;
|
cx = (xmax + xmin) / 2. * sc - width / 2.;
|
||||||
|
cy = (ymax + ymin) / 2. * sc - height / 2.;
|
||||||
} else {
|
} 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<util::string_buffer::float_item> >::const_iterator it;
|
{std::vector< boost::shared_ptr<util::string_buffer::float_item> >::const_iterator it;
|
||||||
for (it = xcoords.begin(); it != xcoords.end(); ++it) {
|
for (it = xcoords.begin(); it != xcoords.end(); ++it) {
|
||||||
double& v = (*it)->value();
|
double& v = (*it)->value();
|
||||||
@@ -760,7 +764,15 @@ void SvgSerializer::finalize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SvgSerializer::writeHeader() {
|
void SvgSerializer::writeHeader() {
|
||||||
svg_file << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"
|
svg_file << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"";
|
||||||
|
if (scale_) {
|
||||||
|
svg_file <<
|
||||||
|
" width=\"" << width << "mm\""
|
||||||
|
" height=\"" << height << "mm\"" <<
|
||||||
|
" viewBox=\"0 0 " << width << " " << height << "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
svg_file << ">\n"
|
||||||
" <defs>\n"
|
" <defs>\n"
|
||||||
" <marker id=\"arrowend\" markerWidth=\"10\" markerHeight=\"7\" refX=\"10\" refY=\"3.5\" orient=\"auto\">\n"
|
" <marker id=\"arrowend\" markerWidth=\"10\" markerHeight=\"7\" refX=\"10\" refY=\"3.5\" orient=\"auto\">\n"
|
||||||
" <polygon points=\"0 0, 10 3.5, 0 7\" />\n"
|
" <polygon points=\"0 0, 10 3.5, 0 7\" />\n"
|
||||||
@@ -774,7 +786,16 @@ void SvgSerializer::writeHeader() {
|
|||||||
" .IfcAnnotation path {\n"
|
" .IfcAnnotation path {\n"
|
||||||
" marker-end: url(#arrowend);\n"
|
" marker-end: url(#arrowend);\n"
|
||||||
" marker-start: url(#arrowstart);\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"
|
||||||
" </style>\n";
|
" </style>\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ protected:
|
|||||||
std::ofstream svg_file;
|
std::ofstream svg_file;
|
||||||
double xmin, ymin, xmax, ymax, width, height;
|
double xmin, ymin, xmax, ymax, width, height;
|
||||||
boost::optional<std::vector<std::pair<std::pair<double, double>, IfcUtil::IfcBaseEntity*>>> section_heights;
|
boost::optional<std::vector<std::pair<std::pair<double, double>, IfcUtil::IfcBaseEntity*>>> section_heights;
|
||||||
|
boost::optional<double> scale_;
|
||||||
bool rescale, print_space_names_, print_space_areas_, draw_door_arcs_, with_section_heights_from_storey_;
|
bool rescale, print_space_names_, print_space_areas_, draw_door_arcs_, with_section_heights_from_storey_;
|
||||||
std::multimap<IfcUtil::IfcBaseEntity*, path_object, storey_sorter> paths;
|
std::multimap<IfcUtil::IfcBaseEntity*, path_object, storey_sorter> paths;
|
||||||
std::vector< boost::shared_ptr<util::string_buffer::float_item> > xcoords;
|
std::vector< boost::shared_ptr<util::string_buffer::float_item> > xcoords;
|
||||||
@@ -90,6 +91,9 @@ public:
|
|||||||
, ymax(-std::numeric_limits<double>::infinity())
|
, ymax(-std::numeric_limits<double>::infinity())
|
||||||
, with_section_heights_from_storey_(false)
|
, with_section_heights_from_storey_(false)
|
||||||
, rescale(false)
|
, rescale(false)
|
||||||
|
, print_space_names_(false)
|
||||||
|
, print_space_areas_(false)
|
||||||
|
, draw_door_arcs_(false)
|
||||||
, file(0)
|
, file(0)
|
||||||
, storey_(0)
|
, storey_(0)
|
||||||
{}
|
{}
|
||||||
@@ -113,6 +117,7 @@ public:
|
|||||||
void setPrintSpaceNames(bool b) { print_space_names_ = b; }
|
void setPrintSpaceNames(bool b) { print_space_names_ = b; }
|
||||||
void setPrintSpaceAreas(bool b) { print_space_areas_ = b; }
|
void setPrintSpaceAreas(bool b) { print_space_areas_ = b; }
|
||||||
void setDrawDoorArcs(bool b) { draw_door_arcs_ = 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<real_t>* elem);
|
std::string nameElement(const IfcUtil::IfcBaseEntity* storey, const IfcGeom::Element<real_t>* elem);
|
||||||
std::string nameElement(const IfcUtil::IfcBaseEntity* elem);
|
std::string nameElement(const IfcUtil::IfcBaseEntity* elem);
|
||||||
std::string idElement(const IfcUtil::IfcBaseEntity* elem);
|
std::string idElement(const IfcUtil::IfcBaseEntity* elem);
|
||||||
|
|||||||
Reference in New Issue
Block a user