diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 6637b5bc61..429920293e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -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}) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index c645788dd1..54eeb5f7ee 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -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(), "input IFC file") ("output-file", boost::program_options::value(), "output geometry file"); + std::string bounds; std::vector 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(&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 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 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(); // 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() - : 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(*bounding_width), + static_cast(*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(context_iterator.getUnitMagnitude())); } else { diff --git a/src/ifcconvert/SvgSerializer.cpp b/src/ifcconvert/SvgSerializer.cpp new file mode 100644 index 0000000000..e2e073788c --- /dev/null +++ b/src/ifcconvert/SvgSerializer.cpp @@ -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 . * + * * + ********************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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(" 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(larger_arc_segment))); + path.add(","); + path.add(std::string(1, '0'+static_cast(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* o) { + IfcSchema::IfcBuildingStorey* storey = 0; + IfcSchema::IfcObjectDefinition* obdef = static_cast(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(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& 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::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 >::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::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 << " \n"; + } + std::ostringstream oss; + svg_file << " first->GlobalId()).formatted() << "\">\n"; + } + svg_file << " second.first << "\">\n"; + std::vector::const_iterator jt; + for (jt = it->second.second.begin(); jt != it->second.second.end(); ++jt) { + svg_file << jt->str(); + } + svg_file << " \n"; + previous = it->first; + first = false; + } + + svg_file << " \n"; + svg_file << "\n"; +} + +void SvgSerializer::writeHeader() { + svg_file << "\n"; +} diff --git a/src/ifcconvert/SvgSerializer.h b/src/ifcconvert/SvgSerializer.h new file mode 100644 index 0000000000..04dbb34188 --- /dev/null +++ b/src/ifcconvert/SvgSerializer.h @@ -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 . * + * * + ********************************************************************************/ + +#ifndef SVGSERIALIZER_H +#define SVGSERIALIZER_H + +#include +#include +#include + +#include "../ifcgeom/IfcGeomIterator.h" + +#include "../ifcconvert/GeometrySerializer.h" +#include "../ifcconvert/util.h" + +class SvgSerializer : public GeometrySerializer { +public: + typedef std::pair > path_object; +protected: + const char* getSymbolForUnitMagnitude(float mag); + std::ofstream svg_file; + double xmin, ymin, xmax, ymax, width, height; + boost::optional section_height; + bool rescale; + std::multimap paths; + std::vector< SHARED_PTR > xcoords; + std::vector< SHARED_PTR > ycoords; + std::vector< SHARED_PTR > radii; + IfcParse::IfcFile* file; +public: + explicit SvgSerializer(const std::string& out_filename) + : GeometrySerializer() + , svg_file(out_filename.c_str()) + , xmin(+std::numeric_limits::infinity()) + , xmax(-std::numeric_limits::infinity()) + , ymin(+std::numeric_limits::infinity()) + , ymax(-std::numeric_limits::infinity()) + , rescale(false) + , file(0) + {} + virtual void addXCoordinate(const SHARED_PTR& fi) { xcoords.push_back(fi); } + virtual void addYCoordinate(const SHARED_PTR& fi) { ycoords.push_back(fi); } + virtual void addSizeComponent(const SHARED_PTR& 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* o) {} + virtual void write(const IfcGeom::BRepElement* 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 diff --git a/src/ifcconvert/util.cpp b/src/ifcconvert/util.cpp new file mode 100644 index 0000000000..3e6668f53b --- /dev/null +++ b/src/ifcconvert/util.cpp @@ -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 . * + * * + ********************************************************************************/ + +#include +#include + +#include "../ifcconvert/util.h" + +using namespace util; + +SHARED_PTR string_buffer::add(const std::string& s) { + SHARED_PTR i = SHARED_PTR(new string_item(s)); + items.push_back(i); + return i; +} +SHARED_PTR string_buffer::add(const double& d) { + SHARED_PTR i = SHARED_PTR(new float_item(d)); + items.push_back(i); + return i; +} +std::string string_buffer::str() const { + std::stringstream ss; + for (std::vector< SHARED_PTR >::const_iterator it = items.begin(); it != items.end(); ++it) { + ss << (**it).str(); + } + return ss.str(); +} diff --git a/src/ifcconvert/util.h b/src/ifcconvert/util.h new file mode 100644 index 0000000000..ee69f9f3b6 --- /dev/null +++ b/src/ifcconvert/util.h @@ -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 . * + * * + ********************************************************************************/ + +#ifndef IFCCONVERT_UTIL_H +#define IFCCONVERT_UTIL_H + +#include +#include + +#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 > items; + void clear(); + void assign(const std::vector< SHARED_PTR >& other); + public: + SHARED_PTR add(const std::string& s); + SHARED_PTR add(const double& d); + std::string str() const; + }; +} + +#endif diff --git a/src/ifcgeom/IfcGeomRepresentation.h b/src/ifcgeom/IfcGeomRepresentation.h index cde87e15e2..bd7abee278 100644 --- a/src/ifcgeom/IfcGeomRepresentation.h +++ b/src/ifcgeom/IfcGeomRepresentation.h @@ -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; } }; diff --git a/win/IfcConvert.vcproj b/win/IfcConvert.vcproj index 8506fd6c68..b7e27a2ca2 100644 --- a/win/IfcConvert.vcproj +++ b/win/IfcConvert.vcproj @@ -179,6 +179,14 @@ RelativePath="..\src\ifcconvert\OpenCascadeBasedSerializer.cpp" > + + + + @@ -217,6 +225,14 @@ RelativePath="..\src\ifcconvert\Serializer.h" > + + + +