From dab3382b29803956b3cb6561f18346a85f44ce8d Mon Sep 17 00:00:00 2001 From: Jean Niklas L'orange Date: Thu, 20 Sep 2018 15:58:24 +0200 Subject: [PATCH] Implement support for custom default materials The support for custom default materials is implemented as a JSON file passed via the command line. The default material specification will override the defaults, except the toplevel default value. --- src/ifcconvert/IfcConvert.cpp | 14 +++++++-- src/ifcgeom/IfcGeomRenderStyles.cpp | 49 +++++++++++++++++++++++++++++ src/ifcgeom/IfcGeomRenderStyles.h | 3 +- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index cd9fba7f756..f1a4beb457f 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -34,6 +34,7 @@ #include "../ifcconvert/SvgSerializer.h" #include "../ifcgeom/IfcGeomIterator.h" +#include "../ifcgeom/IfcGeomRenderStyles.h" #include #include @@ -178,7 +179,8 @@ int main(int argc, char** argv) inclusion_traverse_filter include_traverse_filter; exclusion_filter exclude_filter; exclusion_traverse_filter exclude_traverse_filter; - std::string filter_filename; + std::string filter_filename; + std::string default_material_filename; po::options_description geom_options("Geometry options"); geom_options.add_options() @@ -259,7 +261,11 @@ int main(int argc, char** argv) "Specifies a filter file that describes the used filtering criteria. Supported formats " "are '--include=arg GlobalId ...' and 'include arg GlobalId ...'. Spaces and tabs can be used as delimiters." "Multiple filters of same type with different values can be inserted on their own lines. " - "See --include, --include+, --exclude, and --exclude+ for more details."); + "See --include, --include+, --exclude, and --exclude+ for more details.") + ("default-material-file", po::value(&default_material_filename), + "Specifies a material file that describes the material object types will have" + "if an object does not have any specified material in the IFC file."); + std::string bounds, offset_str; #ifdef HAVE_ICU @@ -491,6 +497,10 @@ int main(int argc, char** argv) } } + if (!default_material_filename.empty()) { + IfcGeom::set_default_style(default_material_filename); + } + /// @todo Clean up this filter code further. std::vector used_filters; if (include_filter.type != geom_filter::UNUSED) { used_filters.push_back(include_filter); } diff --git a/src/ifcgeom/IfcGeomRenderStyles.cpp b/src/ifcgeom/IfcGeomRenderStyles.cpp index 39c0d4ef37c..04875679f57 100644 --- a/src/ifcgeom/IfcGeomRenderStyles.cpp +++ b/src/ifcgeom/IfcGeomRenderStyles.cpp @@ -17,10 +17,16 @@ * * ********************************************************************************/ +#include +#include +#include + #include #include "IfcGeom.h" +namespace pt = boost::property_tree; + bool process_colour(IfcSchema::IfcColourRgb* colour, double* rgb) { if (colour != 0) { rgb[0] = colour->Red(); @@ -170,6 +176,49 @@ void InitDefaultMaterials() { default_materials_initialized = true; } +void IfcGeom::set_default_style(const std::string& json_file) { + if (default_materials_initialized) { + default_materials.clear(); + } + + pt::ptree root; + pt::read_json(json_file, root); + + for (pt::ptree::value_type &material_pair : root) { + std::string name = material_pair.first; + default_materials.insert(std::make_pair(name, IfcGeom::SurfaceStyle(name))); + + pt::ptree material = material_pair.second; + boost::optional diffuse = material.get_child_optional("diffuse"); + if (diffuse) { + double rgb[3]; + int i = 0; + for (pt::ptree::value_type &colour : diffuse.get()) { + rgb[i] = colour.second.get_value(); + i++; + } + default_materials[name].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2])); + } + boost::optional specular = material.get_child_optional("specular"); + if (specular) { + double rgb[3]; + int i = 0; + for (pt::ptree::value_type &colour : specular.get()) { + rgb[i] = colour.second.get_value(); + i++; + } + default_materials[name].Specular().reset(IfcGeom::SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2])); + } + boost::optional specular_roughness = material.get_optional("specular-roughness"); + if (specular_roughness) { + default_materials[name].Specularity().reset(1.0 / specular_roughness.get()); + } + default_materials[name].Transparency() = material.get_optional("transparency"); + } + + default_materials_initialized = true; +} + const IfcGeom::SurfaceStyle* IfcGeom::get_default_style(const std::string& s) { if (!default_materials_initialized) InitDefaultMaterials(); std::map::const_iterator it = default_materials.find(s); diff --git a/src/ifcgeom/IfcGeomRenderStyles.h b/src/ifcgeom/IfcGeomRenderStyles.h index 39a67136dd4..03c34e27027 100644 --- a/src/ifcgeom/IfcGeomRenderStyles.h +++ b/src/ifcgeom/IfcGeomRenderStyles.h @@ -96,7 +96,8 @@ namespace IfcGeom { boost::optional& Specularity() { return specularity; } }; - IFC_GEOM_API const SurfaceStyle* get_default_style(const std::string& ifc_type); + IFC_GEOM_API const SurfaceStyle* get_default_style(const std::string& ifc_type); + IFC_GEOM_API void set_default_style(const std::string& json_file); } #endif