mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
SVG text annotation descriptions
This commit is contained in:
@@ -1569,7 +1569,133 @@ void SvgSerializer::resetScale() {
|
||||
ymax = -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
void SvgSerializer::addTextAnnotations(const drawing_key& k) {
|
||||
auto& meta = drawing_metadata[k];
|
||||
|
||||
boost::optional<std::pair<double, double>> range;
|
||||
|
||||
if (k.first && section_data_) {
|
||||
for (auto& sd : *section_data_) {
|
||||
if (sd.which() == 0) {
|
||||
const auto& plan = boost::get<horizontal_plan>(sd);
|
||||
if (k.first == plan.storey) {
|
||||
range = std::make_pair(plan.elevation, plan.next_elevation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto annotations = file->instances_by_type("IfcAnnotation");
|
||||
for (auto& ann_ : *annotations) {
|
||||
auto ann = (IfcUtil::IfcBaseEntity*) ann_;
|
||||
|
||||
auto ot = ann->get("ObjectType");
|
||||
auto nm = ann->get("Name");
|
||||
auto ds = ann->get("Description");
|
||||
auto pl = ann->get("ObjectPlacement");
|
||||
|
||||
if (!ot->isNull() && !nm->isNull() && !ds->isNull() && !pl->isNull()) {
|
||||
auto object_type = (std::string) *ot;
|
||||
auto name = (std::string) *nm;
|
||||
auto desc = (std::string) *ds;
|
||||
|
||||
if (object_type == "Text") {
|
||||
IfcGeom::Kernel kernel(file);
|
||||
gp_Trsf trsf;
|
||||
if (kernel.convert_placement(*pl, trsf)) {
|
||||
|
||||
auto v = trsf.TranslationPart();
|
||||
if (k.first) {
|
||||
v.ChangeCoord(1) *= -1.;
|
||||
trsf.SetTranslationPart(v);
|
||||
}
|
||||
|
||||
if (!range || (v.Z() >= range->first && v.Z() < range->second)) {
|
||||
|
||||
if (meta.pln_3d.Position().Direction().Dot(gp_Dir(trsf.HVectorialPart().Column(3))) > 0.99) {
|
||||
auto svg_name = nameElement(ann);
|
||||
path_object* po;
|
||||
if (k.first) {
|
||||
po = &start_path(meta.pln_3d, k.first, svg_name);
|
||||
} else {
|
||||
po = &start_path(meta.pln_3d, k.second, svg_name);
|
||||
}
|
||||
|
||||
if (object_type.size()) {
|
||||
// postfix the object_type for CSS matching
|
||||
boost::replace_all(svg_name, "class=\"IfcAnnotation\"", "class=\"IfcAnnotation " + object_type + "\"");
|
||||
}
|
||||
|
||||
boost::optional<double> font_size;
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, name, boost::is_any_of("_"));
|
||||
if (tokens.size() == 2) {
|
||||
try {
|
||||
font_size = boost::lexical_cast<double>(tokens.back());
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
// @todo column or row?
|
||||
double z_rotation = gp_Dir(trsf.HVectorialPart().Column(1)).AngleWithRef(gp_Dir(1., 0., 0.), gp_Dir(0., 0., 1.));
|
||||
z_rotation *= 180. / M_PI;
|
||||
|
||||
util::string_buffer path;
|
||||
// dominant-baseline="central" is not well supported in IE.
|
||||
// so we add a 0.35 offset to the dy of the tspans
|
||||
path.add(" <text text-anchor=\"left\" x=\"");
|
||||
xcoords.push_back(path.add(v.X()));
|
||||
path.add("\" y=\"");
|
||||
ycoords.push_back(path.add(v.Y()));
|
||||
|
||||
path.add("\" transform=\"rotate(");
|
||||
path.add(z_rotation);
|
||||
path.add(" ");
|
||||
xcoords.push_back(path.add(v.X()));
|
||||
path.add(" ");
|
||||
ycoords.push_back(path.add(v.Y()));
|
||||
path.add(")\"");
|
||||
|
||||
if (font_size) {
|
||||
path.add(" font-size=\"");
|
||||
path.add(*font_size);
|
||||
path.add("\"");
|
||||
}
|
||||
path.add(">");
|
||||
|
||||
std::vector<std::string> labels{ desc };
|
||||
|
||||
for (auto lit = labels.begin(); lit != labels.end(); ++lit) {
|
||||
const auto& l = *lit;
|
||||
double dy = labels.begin() == lit
|
||||
? 0.0 // align bottom
|
||||
: 1.0; // <- dy is relative to the previous text element, so
|
||||
// always 1 for successive spans.
|
||||
path.add("<tspan x=\"");
|
||||
xcoords.push_back(path.add(v.X()));
|
||||
path.add("\" dy=\"");
|
||||
path.add(boost::lexical_cast<std::string>(dy));
|
||||
path.add("em\">");
|
||||
path.add(l);
|
||||
path.add("</tspan>");
|
||||
}
|
||||
|
||||
path.add("</text>");
|
||||
|
||||
po->second.push_back(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SvgSerializer::finalize() {
|
||||
for (auto& p : drawing_metadata) {
|
||||
addTextAnnotations(p.first);
|
||||
}
|
||||
|
||||
for (auto& p : storey_hlr) {
|
||||
draw_hlr(drawing_metadata[{p.first, ""}].pln_3d, { p.first, "" });
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ public:
|
||||
void setDrawDoorArcs(bool b) { draw_door_arcs_ = b; }
|
||||
void setStoreyHeightLineLength(double d) { storey_height_line_length_ = d; }
|
||||
void setSpaceNameTransform(const std::string& v) { space_name_transform_ = v; }
|
||||
void addTextAnnotations(const drawing_key& k);
|
||||
|
||||
std::array<std::array<double, 3>, 3> resize();
|
||||
void resetScale();
|
||||
|
||||
Reference in New Issue
Block a user