mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
Add SvgSerializer developed in collaboration with ROOT B.V.
This commit is contained in:
@@ -166,6 +166,8 @@ ADD_EXECUTABLE(IfcConvert
|
||||
../src/ifcconvert/OpenCascadeBasedSerializer.cpp
|
||||
../src/ifcconvert/WavefrontObjSerializer.cpp
|
||||
../src/ifcconvert/XmlSerializer.cpp
|
||||
../src/ifcconvert/SvgSerializer.cpp
|
||||
../src/ifcconvert/util.cpp
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES (IfcConvert IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES})
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#include "../ifcconvert/StepSerializer.h"
|
||||
#include "../ifcconvert/WavefrontObjSerializer.h"
|
||||
#include "../ifcconvert/XmlSerializer.h"
|
||||
#include "../ifcconvert/SvgSerializer.h"
|
||||
|
||||
static std::string DEFAULT_EXTENSION = "obj";
|
||||
|
||||
void printVersion() {
|
||||
std::cerr << "IfcOpenShell IfcConvert " << IFCOPENSHELL_VERSION << std::endl;
|
||||
@@ -57,6 +60,7 @@ void printUsage(const boost::program_options::options_description& generic_optio
|
||||
std::cerr << " .stp STEP Standard for the Exchange of Product Data" << std::endl
|
||||
<< " .igs IGES Initial Graphics Exchange Specification" << std::endl
|
||||
<< " .xml XML Property definitions and decomposition tree" << std::endl
|
||||
<< " .svg SVG Scalable Vector Graphics (2d floor plan)" << std::endl
|
||||
<< std::endl
|
||||
<< "Command line options" << std::endl << generic_options << std::endl
|
||||
<< "Advanced options" << std::endl << geom_options << std::endl;
|
||||
@@ -86,6 +90,7 @@ int main(int argc, char** argv) {
|
||||
("input-file", boost::program_options::value<std::string>(), "input IFC file")
|
||||
("output-file", boost::program_options::value<std::string>(), "output geometry file");
|
||||
|
||||
std::string bounds;
|
||||
std::vector<std::string> entity_vector;
|
||||
boost::program_options::options_description geom_options;
|
||||
geom_options.add_options()
|
||||
@@ -123,6 +128,9 @@ int main(int argc, char** argv) {
|
||||
("disable-opening-subtractions",
|
||||
"Specifies whether to disable the boolean subtraction of "
|
||||
"IfcOpeningElement Representations from their RelatingElements.")
|
||||
("bounds", boost::program_options::value<std::string>(&bounds),
|
||||
"Specifies the bounding rectangle, for example 512x512, to which the "
|
||||
"output will be scaled. Only used when converting to SVG.")
|
||||
("include",
|
||||
"Specifies that the entities listed after --entities are to be included")
|
||||
("exclude",
|
||||
@@ -170,9 +178,21 @@ int main(int argc, char** argv) {
|
||||
const bool sew_shells = vmap.count("sew-shells") != 0;
|
||||
const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0;
|
||||
const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0;
|
||||
const bool include_entities = vmap.count("include") != 0;
|
||||
bool include_entities = vmap.count("include") != 0;
|
||||
const bool include_plan = vmap.count("plan") != 0;
|
||||
const bool include_model = vmap.count("model") != 0 || (!include_plan);
|
||||
boost::optional<int> bounding_width, bounding_height;
|
||||
if (vmap.count("bounds") == 1) {
|
||||
int w, h;
|
||||
if (sscanf(bounds.c_str(), "%ux%u", &w, &h) == 2) {
|
||||
bounding_width = w;
|
||||
bounding_height = h;
|
||||
} else {
|
||||
std::cerr << "[Error] Invalid use of --bounds" << std::endl;
|
||||
printUsage(generic_options, geom_options);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the set ifc types to be ignored from the command line.
|
||||
std::set<std::string> entities;
|
||||
@@ -183,19 +203,13 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
entities.insert(lowercase_type);
|
||||
}
|
||||
|
||||
// If no entities are specified these are the defaults to skip from output
|
||||
if (entity_vector.empty()) {
|
||||
entities.insert("ifcopeningelement");
|
||||
entities.insert("ifcspace");
|
||||
}
|
||||
|
||||
const std::string input_filename = vmap["input-file"].as<std::string>();
|
||||
// If no output filename is specified a Wavefront OBJ file will be output
|
||||
// to maintain backwards compatibility with the obsolete IfcObj executable.
|
||||
const std::string output_filename = vmap.count("output-file") == 1
|
||||
? vmap["output-file"].as<std::string>()
|
||||
: change_extension(input_filename, "obj");
|
||||
: change_extension(input_filename, DEFAULT_EXTENSION);
|
||||
|
||||
if (output_filename.size() < 5) {
|
||||
printUsage(generic_options, geom_options);
|
||||
@@ -207,6 +221,17 @@ int main(int argc, char** argv) {
|
||||
*c = tolower(*c);
|
||||
}
|
||||
|
||||
// If no entities are specified these are the defaults to skip from output
|
||||
if (entity_vector.empty()) {
|
||||
if (output_extension == ".svg") {
|
||||
entities.insert("ifcspace");
|
||||
include_entities = true;
|
||||
} else {
|
||||
entities.insert("ifcopeningelement");
|
||||
entities.insert("ifcspace");
|
||||
}
|
||||
}
|
||||
|
||||
Logger::SetOutput(&std::cout, &log_stream);
|
||||
Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR);
|
||||
|
||||
@@ -258,6 +283,15 @@ int main(int argc, char** argv) {
|
||||
// See: http://tracker.dev.opencascade.org/view.php?id=23679
|
||||
IGESControl_Controller::Init();
|
||||
serializer = new IgesSerializer(output_filename);
|
||||
} else if (output_extension == ".svg") {
|
||||
settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true);
|
||||
serializer = new SvgSerializer(output_filename);
|
||||
if (bounding_width && bounding_height) {
|
||||
((SvgSerializer*) serializer)->setBoundingRectangle(
|
||||
static_cast<double>(*bounding_width),
|
||||
static_cast<double>(*bounding_height)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unknown output filename extension");
|
||||
write_log();
|
||||
@@ -300,6 +334,8 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
serializer->setFile(context_iterator.getFile());
|
||||
|
||||
if (convert_back_units) {
|
||||
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<const float>(context_iterator.getUnitMagnitude()));
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Copyright 2015 IfcOpenShell and ROOT B.V. *
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
#include <gp_Pln.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <BRepBuilderAPI_GTransform.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepAlgo_Section.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <BRepAlgoAPI_Section.hxx>
|
||||
#include <ShapeAnalysis_FreeBounds.hxx>
|
||||
#include <TopTools_HSequenceOfShape.hxx>
|
||||
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <gp_Ax22d.hxx>
|
||||
|
||||
#include "../ifcparse/IfcGlobalId.h"
|
||||
|
||||
#include "SvgSerializer.h"
|
||||
|
||||
const double PI2 = M_PI * 2.;
|
||||
|
||||
bool SvgSerializer::ready() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SvgSerializer::write(path_object& p, const TopoDS_Wire& wire) {
|
||||
/* ShapeFix_Wire fix;
|
||||
Handle(ShapeExtend_WireData) data = new ShapeExtend_WireData;
|
||||
for (TopExp_Explorer edges(result, TopAbs_EDGE); edges.More(); edges.Next()) {
|
||||
data->Add(edges.Current());
|
||||
}
|
||||
fix.Load(data);
|
||||
fix.FixReorder();
|
||||
fix.FixConnected();
|
||||
const TopoDS_Wire fixed_wire = fix.Wire(); */
|
||||
|
||||
bool first = true;
|
||||
util::string_buffer path;
|
||||
path.add(" <path style=\"stroke:black; fill:none;\" d=\"");
|
||||
for (TopExp_Explorer edges(wire, TopAbs_EDGE); edges.More(); edges.Next()) {
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(edges.Current());
|
||||
|
||||
double u1, u2;
|
||||
Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, u1, u2);
|
||||
|
||||
const bool reversed = edge.Orientation() == TopAbs_REVERSED;
|
||||
|
||||
gp_Pnt p1, p2;
|
||||
curve->D0(u1, p1);
|
||||
curve->D0(u2, p2);
|
||||
|
||||
if (reversed) {
|
||||
std::swap(p1, p2);
|
||||
}
|
||||
|
||||
if (first) {
|
||||
path.add("M");
|
||||
addXCoordinate(path.add(p1.X()));
|
||||
path.add(",");
|
||||
addYCoordinate(path.add(p1.Y()));
|
||||
|
||||
if (p1.X() < xmin) xmin = p1.X();
|
||||
if (p1.X() > xmax) xmax = p1.X();
|
||||
if (p1.Y() < ymin) ymin = p1.Y();
|
||||
if (p1.Y() > ymax) ymax = p1.Y();
|
||||
}
|
||||
|
||||
if (p2.X() < xmin) xmin = p2.X();
|
||||
if (p2.X() > xmax) xmax = p2.X();
|
||||
if (p2.Y() < ymin) ymin = p2.Y();
|
||||
if (p2.Y() > ymax) ymax = p2.Y();
|
||||
|
||||
Handle(Standard_Type) ty = curve->DynamicType();
|
||||
|
||||
if (ty == STANDARD_TYPE(Geom_Circle) || ty == STANDARD_TYPE(Geom_Ellipse)) {
|
||||
Handle(Geom_Conic) conic = Handle(Geom_Conic)::DownCast(curve);
|
||||
const bool mirrored = conic->Position().Axis().Direction().Z() < 0;
|
||||
|
||||
double r1, r2;
|
||||
bool larger_arc_segment = (fmod(u2 - u1 + PI2, PI2) > M_PI);
|
||||
bool positive_direction = (u2 > u1);
|
||||
|
||||
if (mirrored != reversed) {
|
||||
// In case the local coordinate system is mirrored
|
||||
// the direction is reversed.
|
||||
positive_direction = !positive_direction;
|
||||
}
|
||||
|
||||
if (ty == STANDARD_TYPE(Geom_Circle)) {
|
||||
Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast(curve);
|
||||
r1 = r2 = circle->Radius();
|
||||
} else {
|
||||
Handle(Geom_Ellipse) ellipse = Handle(Geom_Ellipse)::DownCast(curve);
|
||||
r1 = ellipse->MajorRadius();
|
||||
r2 = ellipse->MinorRadius();
|
||||
}
|
||||
|
||||
// Calculate the angle between 2d vecs to have signed result
|
||||
const gp_Dir& d = conic->Position().XDirection();
|
||||
const gp_Dir2d d2(d.X(), d.Y());
|
||||
const double ang = d2.Angle(gp::DX2d());
|
||||
|
||||
// Write radii
|
||||
path.add(" A");
|
||||
addSizeComponent(path.add(r1));
|
||||
path.add(",");
|
||||
addSizeComponent(path.add(r2));
|
||||
|
||||
// Write X-axis rotation
|
||||
{ std::stringstream ss; ss << " " << ang << " ";
|
||||
path.add(ss.str()); }
|
||||
|
||||
// Write large-arc-flag and sweep-flag
|
||||
path.add(std::string(1, '0'+static_cast<int>(larger_arc_segment)));
|
||||
path.add(",");
|
||||
path.add(std::string(1, '0'+static_cast<int>(positive_direction)));
|
||||
|
||||
path.add(" ");
|
||||
|
||||
// Write arc end point
|
||||
xcoords.push_back(path.add(p2.X()));
|
||||
path.add(",");
|
||||
ycoords.push_back(path.add(p2.Y()));
|
||||
} else {
|
||||
// Either a Geom_Line or something unimplemented,
|
||||
// drawn as a straight line segment.
|
||||
path.add(" L");
|
||||
xcoords.push_back(path.add(p2.X()));
|
||||
path.add(",");
|
||||
ycoords.push_back(path.add(p2.Y()));
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
path.add("\"/>\n");
|
||||
p.second.push_back(path);
|
||||
}
|
||||
|
||||
SvgSerializer::path_object& SvgSerializer::start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id) {
|
||||
SvgSerializer::path_object& p = paths.insert(std::make_pair(storey, path_object()))->second;
|
||||
p.first = id;
|
||||
return p;
|
||||
}
|
||||
|
||||
void SvgSerializer::write(const IfcGeom::BRepElement<double>* o) {
|
||||
IfcSchema::IfcBuildingStorey* storey = 0;
|
||||
IfcSchema::IfcObjectDefinition* obdef = static_cast<IfcSchema::IfcObjectDefinition*>(file->entityById(o->id()));
|
||||
|
||||
#ifdef USE_IFC2x3
|
||||
typedef IfcSchema::IfcRelDecomposes decomposition_element;
|
||||
#else
|
||||
typedef IfcSchema::IfcRelAggregates decomposition_element;
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
// Iterate over the decomposing element to find the parent IfcBuildingStorey
|
||||
decomposition_element::list::ptr decomposes = obdef->Decomposes();
|
||||
if (!decomposes->size()) {
|
||||
if (obdef->is(IfcSchema::Type::IfcElement)) {
|
||||
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr containment = ((IfcSchema::IfcElement*)obdef)->ContainedInStructure();
|
||||
if (!containment->size()) {
|
||||
break;
|
||||
}
|
||||
for (IfcSchema::IfcRelContainedInSpatialStructure::list::it it = containment->begin(); it != containment->end(); ++it) {
|
||||
IfcSchema::IfcRelContainedInSpatialStructure* container = *it;
|
||||
if (container->RelatingStructure() != obdef) {
|
||||
obdef = container->RelatingStructure();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (decomposition_element::list::it it = decomposes->begin(); it != decomposes->end(); ++it) {
|
||||
decomposition_element* decompose = *it;
|
||||
if (decompose->RelatingObject() != obdef) {
|
||||
obdef = decompose->RelatingObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obdef->is(IfcSchema::Type::IfcBuildingStorey)) {
|
||||
storey = static_cast<IfcSchema::IfcBuildingStorey*>(obdef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!storey) return;
|
||||
|
||||
path_object& p = start_path(storey, o->unique_id());
|
||||
|
||||
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->geometry().begin(); it != o->geometry().end(); ++ it) {
|
||||
gp_GTrsf gtrsf = it->Placement();
|
||||
|
||||
gp_Trsf o_trsf;
|
||||
const std::vector<double>& matrix = o->transformation().matrix().data();
|
||||
o_trsf.SetValues(
|
||||
matrix[0], matrix[3], matrix[6], matrix[ 9],
|
||||
matrix[1], matrix[4], matrix[7], matrix[10],
|
||||
matrix[2], matrix[5], matrix[8], matrix[11]
|
||||
#if OCC_VERSION_HEX < 0x60800
|
||||
, Precision::Angular(), Precision::Confusion()
|
||||
#endif
|
||||
);
|
||||
gtrsf.PreMultiply(o_trsf);
|
||||
const TopoDS_Shape& s = it->Shape();
|
||||
|
||||
bool trsf_valid = false;
|
||||
gp_Trsf trsf;
|
||||
try {
|
||||
trsf = gtrsf.Trsf();
|
||||
trsf_valid = true;
|
||||
} catch (...) {}
|
||||
|
||||
const TopoDS_Shape moved_shape = trsf_valid
|
||||
? BRepBuilderAPI_Transform(s, trsf, true).Shape()
|
||||
: BRepBuilderAPI_GTransform(s, gtrsf, true).Shape();
|
||||
|
||||
const double inf = std::numeric_limits<double>::infinity();
|
||||
double zmin = inf;
|
||||
double zmax = -inf;
|
||||
{TopExp_Explorer exp(moved_shape, TopAbs_VERTEX);
|
||||
for (; exp.More(); exp.Next()) {
|
||||
const TopoDS_Vertex& vertex = TopoDS::Vertex(exp.Current());
|
||||
gp_Pnt pnt = BRep_Tool::Pnt(vertex);
|
||||
if (pnt.Z() < zmin) { zmin = pnt.Z(); }
|
||||
if (pnt.Z() > zmax) { zmax = pnt.Z(); }
|
||||
}}
|
||||
|
||||
if (section_height) {
|
||||
if (zmin > section_height || zmax < section_height) continue;
|
||||
} else {
|
||||
if (zmin == inf || (zmax - zmin) < 1.) continue;
|
||||
}
|
||||
|
||||
const double cut_z = section_height.get_value_or(zmin + 1.);
|
||||
|
||||
// Create a horizontal cross section 1 meter above the bottom point of the shape
|
||||
TopoDS_Shape result = BRepAlgoAPI_Section(moved_shape, gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ()));
|
||||
|
||||
Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape();
|
||||
Handle(TopTools_HSequenceOfShape) wires = new TopTools_HSequenceOfShape();
|
||||
{TopExp_Explorer exp(result, TopAbs_EDGE);
|
||||
for (; exp.More(); exp.Next()) {
|
||||
edges->Append(exp.Current());
|
||||
}}
|
||||
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, 1e-5, false, wires);
|
||||
|
||||
gp_Pnt prev;
|
||||
|
||||
for (int i = 1; i <= wires->Length(); ++i) {
|
||||
const TopoDS_Wire& wire = TopoDS::Wire(wires->Value(i));
|
||||
write(p, wire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SvgSerializer::setBoundingRectangle(double width, double height) {
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->rescale = true;
|
||||
}
|
||||
|
||||
void SvgSerializer::finalize() {
|
||||
|
||||
if (rescale) {
|
||||
// Scale the resulting image to a bounding rectangle specified by command line arguments
|
||||
const double dx = xmax - xmin;
|
||||
const double dy = ymax - ymin;
|
||||
|
||||
double sc = 1.;
|
||||
|
||||
if (dx / width > dy / height) {
|
||||
sc = width / dx;
|
||||
} else {
|
||||
sc = height / dy;
|
||||
}
|
||||
|
||||
const double cx = xmin * sc;
|
||||
const double cy = ymin * sc;
|
||||
|
||||
{std::vector< SHARED_PTR<util::string_buffer::float_item> >::const_iterator it;
|
||||
for (it = xcoords.begin(); it != xcoords.end(); ++it) {
|
||||
double& v = (*it)->value();
|
||||
v = v * sc - cx;
|
||||
}
|
||||
for (it = ycoords.begin(); it != ycoords.end(); ++it) {
|
||||
double& v = (*it)->value();
|
||||
v = v * sc - cy;
|
||||
}
|
||||
for (it = radii.begin(); it != radii.end(); ++it) {
|
||||
(*it)->value() *= sc;
|
||||
}}
|
||||
}
|
||||
|
||||
std::multimap<IfcSchema::IfcBuildingStorey*, path_object>::const_iterator it;
|
||||
|
||||
IfcSchema::IfcBuildingStorey* previous = 0;
|
||||
bool first = true;
|
||||
for (it = paths.begin(); it != paths.end(); ++it) {
|
||||
if (it->first != previous || first) {
|
||||
if (!first) {
|
||||
svg_file << " </g>\n";
|
||||
}
|
||||
std::ostringstream oss;
|
||||
svg_file << " <g id=\"storey-" << IfcParse::IfcGlobalId(it->first->GlobalId()).formatted() << "\">\n";
|
||||
}
|
||||
svg_file << " <g id=\"" << it->second.first << "\">\n";
|
||||
std::vector<util::string_buffer>::const_iterator jt;
|
||||
for (jt = it->second.second.begin(); jt != it->second.second.end(); ++jt) {
|
||||
svg_file << jt->str();
|
||||
}
|
||||
svg_file << " </g>\n";
|
||||
previous = it->first;
|
||||
first = false;
|
||||
}
|
||||
|
||||
svg_file << " </g>\n";
|
||||
svg_file << "</svg>\n";
|
||||
}
|
||||
|
||||
void SvgSerializer::writeHeader() {
|
||||
svg_file << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Copyright 2015 IfcOpenShell and ROOT B.V. *
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef SVGSERIALIZER_H
|
||||
#define SVGSERIALIZER_H
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
#include "../ifcgeom/IfcGeomIterator.h"
|
||||
|
||||
#include "../ifcconvert/GeometrySerializer.h"
|
||||
#include "../ifcconvert/util.h"
|
||||
|
||||
class SvgSerializer : public GeometrySerializer {
|
||||
public:
|
||||
typedef std::pair<std::string, std::vector<util::string_buffer> > path_object;
|
||||
protected:
|
||||
const char* getSymbolForUnitMagnitude(float mag);
|
||||
std::ofstream svg_file;
|
||||
double xmin, ymin, xmax, ymax, width, height;
|
||||
boost::optional<double> section_height;
|
||||
bool rescale;
|
||||
std::multimap<IfcSchema::IfcBuildingStorey*, path_object> paths;
|
||||
std::vector< SHARED_PTR<util::string_buffer::float_item> > xcoords;
|
||||
std::vector< SHARED_PTR<util::string_buffer::float_item> > ycoords;
|
||||
std::vector< SHARED_PTR<util::string_buffer::float_item> > radii;
|
||||
IfcParse::IfcFile* file;
|
||||
public:
|
||||
explicit SvgSerializer(const std::string& out_filename)
|
||||
: GeometrySerializer()
|
||||
, svg_file(out_filename.c_str())
|
||||
, xmin(+std::numeric_limits<double>::infinity())
|
||||
, xmax(-std::numeric_limits<double>::infinity())
|
||||
, ymin(+std::numeric_limits<double>::infinity())
|
||||
, ymax(-std::numeric_limits<double>::infinity())
|
||||
, rescale(false)
|
||||
, file(0)
|
||||
{}
|
||||
virtual void addXCoordinate(const SHARED_PTR<util::string_buffer::float_item>& fi) { xcoords.push_back(fi); }
|
||||
virtual void addYCoordinate(const SHARED_PTR<util::string_buffer::float_item>& fi) { ycoords.push_back(fi); }
|
||||
virtual void addSizeComponent(const SHARED_PTR<util::string_buffer::float_item>& fi) { radii.push_back(fi); }
|
||||
virtual ~SvgSerializer() {}
|
||||
virtual void writeHeader();
|
||||
virtual void writeMaterial(const IfcGeom::SurfaceStyle& style) {}
|
||||
virtual bool ready();
|
||||
virtual void write(const IfcGeom::TriangulationElement<double>* o) {}
|
||||
virtual void write(const IfcGeom::BRepElement<double>* o);
|
||||
virtual void write(path_object& p, const TopoDS_Wire& wire);
|
||||
virtual path_object& start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id);
|
||||
virtual bool isTesselated() const { return false; }
|
||||
virtual void finalize();
|
||||
virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) {}
|
||||
virtual void setFile(IfcParse::IfcFile* f) { file = f; }
|
||||
virtual void setBoundingRectangle(double width, double height);
|
||||
virtual void setSectionHeight(double h) { section_height = h; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
#include "../ifcconvert/util.h"
|
||||
|
||||
using namespace util;
|
||||
|
||||
SHARED_PTR<string_buffer::string_item> string_buffer::add(const std::string& s) {
|
||||
SHARED_PTR<string_item> i = SHARED_PTR<string_item>(new string_item(s));
|
||||
items.push_back(i);
|
||||
return i;
|
||||
}
|
||||
SHARED_PTR<string_buffer::float_item> string_buffer::add(const double& d) {
|
||||
SHARED_PTR<float_item> i = SHARED_PTR<float_item>(new float_item(d));
|
||||
items.push_back(i);
|
||||
return i;
|
||||
}
|
||||
std::string string_buffer::str() const {
|
||||
std::stringstream ss;
|
||||
for (std::vector< SHARED_PTR<item> >::const_iterator it = items.begin(); it != items.end(); ++it) {
|
||||
ss << (**it).str();
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCCONVERT_UTIL_H
|
||||
#define IFCCONVERT_UTIL_H
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "../ifcparse/SharedPointer.h"
|
||||
|
||||
namespace util {
|
||||
class string_buffer {
|
||||
public:
|
||||
class item {
|
||||
public:
|
||||
virtual std::string str() const = 0;
|
||||
};
|
||||
class string_item : public item {
|
||||
std::string s;
|
||||
public:
|
||||
string_item(const std::string& s) : s(s) {}
|
||||
void assign(const std::string& s) { this->s = s; }
|
||||
const std::string& value() const { return s; }
|
||||
std::string& value() { return s; }
|
||||
std::string str() const { return s; }
|
||||
};
|
||||
class float_item : public item {
|
||||
double d;
|
||||
public:
|
||||
float_item(const double& d) : d(d) {}
|
||||
void assign(const double& d) { this->d = d; }
|
||||
const double& value() const { return d; }
|
||||
double& value() { return d; }
|
||||
std::string str() const { std::stringstream ss; ss << d; return ss.str(); }
|
||||
};
|
||||
private:
|
||||
std::vector< SHARED_PTR<item> > items;
|
||||
void clear();
|
||||
void assign(const std::vector< SHARED_PTR<item> >& other);
|
||||
public:
|
||||
SHARED_PTR<string_item> add(const std::string& s);
|
||||
SHARED_PTR<float_item> add(const double& d);
|
||||
std::string str() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -54,18 +54,19 @@ namespace IfcGeom {
|
||||
class BRep : public Representation {
|
||||
private:
|
||||
unsigned int id;
|
||||
const IfcGeom::IfcRepresentationShapeItems shapes;
|
||||
const IfcGeom::IfcRepresentationShapeItems _shapes;
|
||||
BRep(const BRep& other);
|
||||
BRep& operator=(const BRep& other);
|
||||
public:
|
||||
BRep(const ElementSettings& settings, unsigned int id, const IfcGeom::IfcRepresentationShapeItems& shapes)
|
||||
: Representation(settings)
|
||||
, id(id)
|
||||
, shapes(shapes)
|
||||
, _shapes(shapes)
|
||||
{}
|
||||
virtual ~BRep() {}
|
||||
IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return shapes.begin(); }
|
||||
IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes.end(); }
|
||||
IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return _shapes.begin(); }
|
||||
IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return _shapes.end(); }
|
||||
const IfcGeom::IfcRepresentationShapeItems& shapes() const { return _shapes; }
|
||||
const unsigned int& getId() const { return id; }
|
||||
};
|
||||
|
||||
|
||||
@@ -179,6 +179,14 @@
|
||||
RelativePath="..\src\ifcconvert\OpenCascadeBasedSerializer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ifcconvert\SvgSerializer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ifcconvert\util.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ifcconvert\WavefrontObjSerializer.cpp"
|
||||
>
|
||||
@@ -217,6 +225,14 @@
|
||||
RelativePath="..\src\ifcconvert\Serializer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ifcconvert\SvgSerializer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ifcconvert\util.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ifcconvert\WavefrontObjSerializer.h"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user