diff --git a/src/serializers/GeometrySerializer.h b/src/serializers/GeometrySerializer.h index 3e04c8c4f8..cd5017c10a 100644 --- a/src/serializers/GeometrySerializer.h +++ b/src/serializers/GeometrySerializer.h @@ -27,7 +27,7 @@ class SerializerSettings : public IfcGeom::IteratorSettings { public: - enum Setting + enum Setting : uint64_t { /// Use entity names instead of unique IDs for naming elements. /// Applicable for OBJ, DAE, and SVG output. @@ -64,6 +64,42 @@ public: enum { DEFAULT_PRECISION = 15 }; }; +class stream_or_filename { +private: + std::shared_ptr ofs_; + std::shared_ptr oss_; + boost::optional filename_; + +public: + std::ostream& stream; + + stream_or_filename(const std::string& fn) + : ofs_(new std::ofstream(IfcUtil::path::from_utf8(fn).c_str())) + , stream(*ofs_) + {} + + stream_or_filename() + : oss_(new std::ostringstream) + , stream(*oss_) + {} + + std::string get_value() const { + return oss_->str(); + } + + boost::optional filename() const { + return filename_; + } + + bool is_ready() { + if (ofs_) { + return ofs_->is_open(); + } else { + return true; + } + } +}; + class GeometrySerializer : public Serializer { public: GeometrySerializer(const SerializerSettings& settings) : settings_(settings) {} diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index c674e82c9d..b866bd38bd 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -1949,30 +1949,30 @@ void SvgSerializer::finalize() { for (it = paths.begin(); it != paths.end(); ++it) { if (!previous || it->first != *previous) { if (previous) { - svg_file << " \n"; + svg_file.stream << " \n"; } std::ostringstream oss; if (it->first.first) { - svg_file << " first.first) << " " << writeMetadata(drawing_metadata[it->first]) << ">\n"; + svg_file.stream << " first.first) << " " << writeMetadata(drawing_metadata[it->first]) << ">\n"; } else { auto n = it->first.second; IfcUtil::escape_xml(n); - svg_file << " first]) << ">\n"; + svg_file.stream << " first]) << ">\n"; } } - svg_file << " second.first << ">\n"; + svg_file.stream << " 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.stream << jt->str(); } - svg_file << " \n"; + svg_file.stream << " \n"; previous = it->first; } if (previous) { - svg_file << " \n"; + svg_file.stream << " \n"; } - svg_file << "" << std::endl; + svg_file.stream << "" << std::endl; } void SvgSerializer::writeHeader() { @@ -1981,18 +1981,18 @@ void SvgSerializer::writeHeader() { } void SvgSerializer::doWriteHeader() { - svg_file << "first << "mm\"" " height=\"" << size_->second << "mm\"" << " viewBox=\"0 0 " << size_->first << " " << size_->second << "\""; } - svg_file << ">\n" + svg_file.stream << ">\n" " \n" " \n" " \n" @@ -2027,7 +2027,7 @@ void SvgSerializer::doWriteHeader() { // (pt) (px) (in) (mm) // approx 12 / 0.75 / 96 * 25.4 - svg_file << + svg_file.stream << " text {\n" " font-size: 2;\n" // (reduced to two). " }\n" @@ -2036,7 +2036,7 @@ void SvgSerializer::doWriteHeader() { " }\n"; } - svg_file << + svg_file.stream << " ]]>\n" " \n"; } diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index 978be7d371..f57e6d38a3 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -137,7 +137,7 @@ public: SH_NONE, SH_FULL, SH_LEFT }; protected: - std::ofstream svg_file; + stream_or_filename svg_file; double xmin, ymin, xmax, ymax; boost::optional> section_data_; boost::optional> deferred_section_data_; @@ -182,9 +182,9 @@ protected: void draw_hlr(const gp_Pln& pln, const drawing_key& drawing_name); public: - SvgSerializer(const std::string& out_filename, const SerializerSettings& settings) + SvgSerializer(const stream_or_filename& out_filename, const SerializerSettings& settings) : GeometrySerializer(settings) - , svg_file(IfcUtil::path::from_utf8(out_filename).c_str()) + , svg_file(out_filename) , xmin(+std::numeric_limits::infinity()) , ymin(+std::numeric_limits::infinity()) , xmax(-std::numeric_limits::infinity()) diff --git a/src/serializers/WavefrontObjSerializer.cpp b/src/serializers/WavefrontObjSerializer.cpp index ef5b26b571..8c9399f5ac 100644 --- a/src/serializers/WavefrontObjSerializer.cpp +++ b/src/serializers/WavefrontObjSerializer.cpp @@ -27,35 +27,36 @@ #include #include -WaveFrontOBJSerializer::WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename, const SerializerSettings& settings) +WaveFrontOBJSerializer::WaveFrontOBJSerializer(const stream_or_filename& obj_filename, const stream_or_filename& mtl_filename, const SerializerSettings& settings) : GeometrySerializer(settings) - , mtl_filename(mtl_filename) - , obj_stream(IfcUtil::path::from_utf8(obj_filename).c_str()) - , mtl_stream(IfcUtil::path::from_utf8(mtl_filename).c_str()) + , obj_stream(obj_filename) + , mtl_stream(mtl_filename) , vcount_total(1) { - obj_stream << std::setprecision(settings.precision); - mtl_stream << std::setprecision(settings.precision); + obj_stream.stream << std::setprecision(settings.precision); + mtl_stream.stream << std::setprecision(settings.precision); } bool WaveFrontOBJSerializer::ready() { - return obj_stream.is_open() && mtl_stream.is_open(); + return obj_stream.is_ready() && mtl_stream.is_ready(); } void WaveFrontOBJSerializer::writeHeader() { - obj_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n"; + obj_stream.stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n"; #ifdef WIN32 const char dir_separator = '\\'; #else const char dir_separator = '/'; #endif - std::string mtl_basename = mtl_filename; - std::string::size_type slash = mtl_basename.find_last_of(dir_separator); - if (slash != std::string::npos) { - mtl_basename = mtl_basename.substr(slash+1); + if (mtl_stream.filename()) { + std::string mtl_basename = *mtl_stream.filename(); + std::string::size_type slash = mtl_basename.find_last_of(dir_separator); + if (slash != std::string::npos) { + mtl_basename = mtl_basename.substr(slash + 1); + } + obj_stream.stream << "mtllib " << mtl_basename << "\n"; } - obj_stream << "mtllib " << mtl_basename << "\n"; - mtl_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n"; + mtl_stream.stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n"; } void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style) @@ -63,34 +64,34 @@ void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style) std::string material_name = (settings().get(SerializerSettings::USE_MATERIAL_NAMES) ? style.original_name() : style.name()); IfcUtil::sanitate_material_name(material_name); - mtl_stream << "newmtl " << material_name << "\n"; + mtl_stream.stream << "newmtl " << material_name << "\n"; if (style.hasDiffuse()) { const double* diffuse = style.diffuse(); - mtl_stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n"; + mtl_stream.stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n"; } if (style.hasSpecular()) { const double* specular = style.specular(); - mtl_stream << "Ks " << specular[0] << " " << specular[1] << " " << specular[2] << "\n"; + mtl_stream.stream << "Ks " << specular[0] << " " << specular[1] << " " << specular[2] << "\n"; } if (style.hasSpecularity()) { - mtl_stream << "Ns " << style.specularity() << "\n"; + mtl_stream.stream << "Ns " << style.specularity() << "\n"; } if (style.hasTransparency()) { const double transparency = 1.0 - style.transparency(); if (transparency < 1) { - mtl_stream << "d " << transparency << "\n"; + mtl_stream.stream << "d " << transparency << "\n"; } } } void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) { - obj_stream << "g " << object_id(o) << "\n"; - obj_stream << "s 1" << "\n"; + obj_stream.stream << "g " << object_id(o) << "\n"; + obj_stream.stream << "s 1" << "\n"; const bool isyup = settings().get(SerializerSettings::USE_Y_UP); - const IfcGeom::Representation::Triangulation& mesh = o->geometry(); + const IfcGeom::Representation::Triangulation& mesh = o->geometry(); const int vcount = (int)mesh.verts().size() / 3; for ( std::vector::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) { @@ -99,9 +100,9 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) const double z = *(it++); if (isyup) { - obj_stream << "v " << x << " " << z << " " << -y << "\n"; + obj_stream.stream << "v " << x << " " << z << " " << -y << "\n"; } else { - obj_stream << "v " << x << " " << y << " " << z << "\n"; + obj_stream.stream << "v " << x << " " << y << " " << z << "\n"; } } @@ -109,13 +110,13 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) const double x = *(it++); const double y = *(it++); const double z = *(it++); - obj_stream << "vn " << x << " " << y << " " << z << "\n"; + obj_stream.stream << "vn " << x << " " << y << " " << z << "\n"; } for (std::vector::const_iterator it = mesh.uvs().begin(); it != mesh.uvs().end();) { const double u = *it++; const double v = *it++; - obj_stream << "vt " << u << " " << v << "\n"; + obj_stream.stream << "vt " << u << " " << v << "\n"; } int previous_material_id = -2; @@ -131,7 +132,7 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) std::string material_name = (settings().get(SerializerSettings::USE_MATERIAL_NAMES) ? material.original_name() : material.name()); IfcUtil::sanitate_material_name(material_name); - obj_stream << "usemtl " << material_name << "\n"; + obj_stream.stream << "usemtl " << material_name << "\n"; if (materials.find(material_name) == materials.end()) { writeMaterial(material); materials.insert(material_name); @@ -144,15 +145,15 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) const int v3 = *(it++)+vcount_total; if (has_normals && has_uvs) { - obj_stream << "f " << v1 << "/" << v1 << "/" << v1 << " " + obj_stream.stream << "f " << v1 << "/" << v1 << "/" << v1 << " " << v2 << "/" << v2 << "/" << v2 << " " << v3 << "/" << v3 << "/" << v3 << "\n"; } else if (has_normals) { - obj_stream << "f " << v1 << "//" << v1 << " " + obj_stream.stream << "f " << v1 << "//" << v1 << " " << v2 << "//" << v2 << " " << v3 << "//" << v3 << "\n"; } else { - obj_stream << "f " << v1 << " " << v2 << " " << v3 << "\n"; + obj_stream.stream << "f " << v1 << " " << v2 << " " << v3 << "\n"; } } @@ -175,7 +176,7 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) std::string material_name = (settings().get(SerializerSettings::USE_MATERIAL_NAMES) ? material.original_name() : material.name()); IfcUtil::sanitate_material_name(material_name); - obj_stream << "usemtl " << material_name << "\n"; + obj_stream.stream << "usemtl " << material_name << "\n"; if (materials.find(material_name) == materials.end()) { writeMaterial(material); materials.insert(material_name); @@ -186,7 +187,7 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o) const int v1 = i1 + vcount_total; const int v2 = i2 + vcount_total; - obj_stream << "l " << v1 << " " << v2 << "\n"; + obj_stream.stream << "l " << v1 << " " << v2 << "\n"; } vcount_total += vcount; diff --git a/src/serializers/WavefrontObjSerializer.h b/src/serializers/WavefrontObjSerializer.h index 00244abf95..94b02242dd 100644 --- a/src/serializers/WavefrontObjSerializer.h +++ b/src/serializers/WavefrontObjSerializer.h @@ -29,13 +29,12 @@ // http://people.sc.fsu.edu/~jburkardt/txt/obj_format.txt class WaveFrontOBJSerializer : public GeometrySerializer { private: - const std::string mtl_filename; - std::ofstream obj_stream; - std::ofstream mtl_stream; + stream_or_filename obj_stream; + stream_or_filename mtl_stream; unsigned int vcount_total; std::set materials; public: - WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename, const SerializerSettings& settings); + WaveFrontOBJSerializer(const stream_or_filename& obj_filename, const stream_or_filename& mtl_filename, const SerializerSettings& settings); virtual ~WaveFrontOBJSerializer() {} bool ready(); void writeHeader();