From 1d1fd49608fc6e0d78d35928be3f10c55f9a4eaa Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Mon, 13 May 2013 06:40:30 +0000 Subject: [PATCH] Added missing files --- src/ifcgeom/IfcGeomRenderStyles.cpp | 170 ++++++++++++++++++ src/ifcgeom/IfcGeomRenderStyles.h | 134 ++++++++++++++ ...apeList.h => IfcRepresentationShapeItem.h} | 26 ++- 3 files changed, 327 insertions(+), 3 deletions(-) create mode 100644 src/ifcgeom/IfcGeomRenderStyles.cpp create mode 100644 src/ifcgeom/IfcGeomRenderStyles.h rename src/ifcgeom/{IfcShapeList.h => IfcRepresentationShapeItem.h} (60%) diff --git a/src/ifcgeom/IfcGeomRenderStyles.cpp b/src/ifcgeom/IfcGeomRenderStyles.cpp new file mode 100644 index 0000000000..657af73e33 --- /dev/null +++ b/src/ifcgeom/IfcGeomRenderStyles.cpp @@ -0,0 +1,170 @@ +/******************************************************************************** + * * + * 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 "IfcGeomRenderStyles.h" + +namespace IfcGeom { + namespace Cache { + std::map Style; + void PurgeStyleCache() { + Style.clear(); + } + } +} + +bool process_colour(Ifc2x3::IfcColourRgb* colour, std::array& rgb) { + if (colour != 0) { + rgb[0] = colour->Red(); + rgb[1] = colour->Green(); + rgb[2] = colour->Blue(); + } + return colour != 0; +} + +bool process_colour(IfcUtil::IfcArgumentSelect* factor, std::array& rgb) { + if (factor != 0) { + const double f = *factor->wrappedValue(); + rgb[0] = rgb[1] = rgb[2] = f; + } + return factor != 0; +} + +bool process_colour(Ifc2x3::IfcColourOrFactor colour_or_factor, std::array& rgb) { + if (colour_or_factor == 0) { + return false; + } else if (colour_or_factor->is(Ifc2x3::Type::IfcColourRgb)) { + return process_colour(static_cast(colour_or_factor), rgb); + } else if (colour_or_factor->is(Ifc2x3::Type::IfcNormalisedRatioMeasure)) { + return process_colour(static_cast(colour_or_factor), rgb); + } else { + return false; + } +} + +const IfcGeom::SurfaceStyle* IfcGeom::get_style(Ifc2x3::IfcRepresentationItem* item) { + std::pair shading_styles = get_surface_style(item); + if (shading_styles.second == 0) { + return 0; + } + int surface_style_id = shading_styles.first->entity->id(); + std::map::const_iterator it = Cache::Style.find(surface_style_id); + if (it != Cache::Style.end()) { + return &(it->second); + } + SurfaceStyle surface_style; + if (shading_styles.first->hasName()) { + surface_style = SurfaceStyle(surface_style_id, shading_styles.first->Name()); + } else { + surface_style = SurfaceStyle(surface_style_id); + } + std::array rgb; + if (process_colour(shading_styles.second->SurfaceColour(), rgb)) { + surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2])); + } + if (shading_styles.second->is(Ifc2x3::Type::IfcSurfaceStyleRendering)) { + Ifc2x3::IfcSurfaceStyleRendering* rendering_style = static_cast(shading_styles.second); + if (rendering_style->hasDiffuseColour() && process_colour(rendering_style->DiffuseColour(), rgb)) { + SurfaceStyle::ColorComponent diffuse = surface_style.Diffuse().get_value_or(SurfaceStyle::ColorComponent(1,1,1)); + surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(diffuse.R() * rgb[0], diffuse.G() * rgb[1], diffuse.B() * rgb[2])); + } + if (rendering_style->hasDiffuseTransmissionColour()) { + // Not supported + } + if (rendering_style->hasReflectionColour()) { + // Not supported + } + if (rendering_style->hasSpecularColour() && process_colour(rendering_style->SpecularColour(), rgb)) { + surface_style.Specular().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2])); + } + if (rendering_style->hasSpecularHighlight()) { + IfcUtil::IfcArgumentSelect* highlight = static_cast(rendering_style->SpecularHighlight()); + if (highlight->is(Ifc2x3::Type::IfcSpecularRoughness)) { + double roughness = *highlight->wrappedValue(); + if (roughness >= 1e-9) { + surface_style.Specularity().reset(1.0 / roughness); + } + } else if (highlight->is(Ifc2x3::Type::IfcSpecularRoughness)) { + surface_style.Specularity().reset(*highlight->wrappedValue()); + } + } + if (rendering_style->hasTransmissionColour()) { + // Not supported + } + if (rendering_style->hasTransparency()) { + const double d = rendering_style->Transparency(); + surface_style.Transparency().reset(d); + } + } + return &(Cache::Style[surface_style_id] = surface_style); +} + +static std::map default_materials; +static IfcGeom::SurfaceStyle default_material; +static bool default_materials_initialized = false; + +void InitDefaultMaterials() { + default_materials.insert(std::make_pair("IfcSite", IfcGeom::SurfaceStyle("IfcSite"))); + default_materials["IfcSite" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.65)); + + default_materials.insert(std::make_pair("IfcSlab", IfcGeom::SurfaceStyle("IfcSlab"))); + default_materials["IfcSlab" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.4 , 0.4, 0.4 )); + + default_materials.insert(std::make_pair("IfcWallStandardCase", IfcGeom::SurfaceStyle("IfcWallStandardCase"))); + default_materials["IfcWallStandardCase"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9 , 0.9, 0.9 )); + + default_materials.insert(std::make_pair("IfcWall", IfcGeom::SurfaceStyle("IfcWall"))); + default_materials["IfcWall" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9 , 0.9, 0.9 )); + + default_materials.insert(std::make_pair("IfcWindow", IfcGeom::SurfaceStyle("IfcWindow"))); + default_materials["IfcWindow" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.75)); + default_materials["IfcWindow" ].Transparency().reset(0.3); + + default_materials.insert(std::make_pair("IfcDoor", IfcGeom::SurfaceStyle("IfcDoor"))); + default_materials["IfcDoor" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.55, 0.3, 0.15)); + + default_materials.insert(std::make_pair("IfcBeam", IfcGeom::SurfaceStyle("IfcBeam"))); + default_materials["IfcBeam" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.7, 0.7 )); + + default_materials.insert(std::make_pair("IfcRailing", IfcGeom::SurfaceStyle("IfcRailing"))); + default_materials["IfcRailing" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6 )); + + default_materials.insert(std::make_pair("IfcMember", IfcGeom::SurfaceStyle("IfcMember"))); + default_materials["IfcMember" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6 )); + + default_materials.insert(std::make_pair("IfcPlate", IfcGeom::SurfaceStyle("IfcPlate"))); + default_materials["IfcPlate" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.8 , 0.8, 0.8 )); + + default_material = IfcGeom::SurfaceStyle("DefaultMaterial"); + default_material.Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.7, 0.7, 0.7)); + + 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); + if (it == default_materials.end()) return &default_material; + else { + const IfcGeom::SurfaceStyle& surface_style = it->second; + return &surface_style; + } +} diff --git a/src/ifcgeom/IfcGeomRenderStyles.h b/src/ifcgeom/IfcGeomRenderStyles.h new file mode 100644 index 0000000000..77897ef220 --- /dev/null +++ b/src/ifcgeom/IfcGeomRenderStyles.h @@ -0,0 +1,134 @@ +/******************************************************************************** + * * + * 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 IFCGEOMRENDERSTYLES_H +#define IFCGEOMRENDERSTYLES_H + +#include + +#include "../ifcparse/Ifc2x3.h" + +namespace IfcGeom { + class SurfaceStyle { + public: + class ColorComponent { + private: + std::array data; + public: + ColorComponent(double r, double g, double b) { + data[0] = r; data[1] = g; data[2] = b; + } + const double& R() const { return data[0]; } + const double& G() const { return data[1]; } + const double& B() const { return data[2]; } + double& R() { return data[0]; } + double& G() { return data[1]; } + double& B() { return data[2]; } + }; + private: + boost::optional name; + boost::optional id; + boost::optional diffuse, specular; + boost::optional transparency; + boost::optional specularity; + public: + SurfaceStyle() {} + SurfaceStyle(int id) : id(id) {} + SurfaceStyle(const std::string& name) : name(name) {} + SurfaceStyle(int id, const std::string& name) : id(id), name(name) {} + + // Not used at this point. In fact, equality testing in the current + // architecture can just as easily be accomplished by comparing the + // pointer addresses of the styles, as they are always referenced + // from out of a global map of some sort. + bool operator==(const SurfaceStyle& other) { + if (name && other.name) { + return *name == *other.name; + } else if (id && other.id) { + return *id == *other.id; + } else { + return false; + } + } + + const std::string Name() const { + if (name && id) { + std::stringstream sstr; + sstr << (*id) << "_" << (*name); + return sstr.str(); + } else if (name) { + return *name; + } else if (id) { + std::stringstream sstr; + sstr << "IfcSurfaceStyleShading_" << (*id); + return sstr.str(); + } else { + return "IfcSurfaceStyleShading"; + } + } + + const boost::optional& Diffuse() const { return diffuse; } + const boost::optional& Specular() const { return specular; } + const boost::optional& Transparency() const { return transparency; } + const boost::optional& Specularity() const { return specularity; } + boost::optional& Diffuse() { return diffuse; } + boost::optional& Specular() { return specular; } + boost::optional& Transparency() { return transparency; } + boost::optional& Specularity() { return specularity; } + }; + + template std::pair get_surface_style(Ifc2x3::IfcRepresentationItem* representation_item) { + Ifc2x3::IfcStyledItem::list styled_items = representation_item->StyledByItem(); + for (Ifc2x3::IfcStyledItem::it jt = styled_items->begin(); jt != styled_items->end(); ++jt) { + Ifc2x3::IfcPresentationStyleAssignment::list style_assignments = (*jt)->Styles(); + for (Ifc2x3::IfcPresentationStyleAssignment::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) { + IfcAbstractSelect::list styles = (*kt)->Styles(); + for (IfcAbstractSelect::it lt = styles->begin(); lt != styles->end(); ++lt) { + IfcAbstractSelect::ptr style = *lt; + if (style->is(Ifc2x3::Type::IfcSurfaceStyle)) { + Ifc2x3::IfcSurfaceStyle* surface_style = (Ifc2x3::IfcSurfaceStyle*) style; + if (surface_style->Side() != Ifc2x3::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) { + IfcAbstractSelect::list styles_elements = surface_style->Styles(); + for (IfcAbstractSelect::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) { + if ((*mt)->is(T::Class())) { + return std::make_pair(surface_style, (T*) *mt); + } + } + } + } + } + } + + // StyledByItem is a SET [0:1] OF IfcStyledItem, so we + // break after encountering the first IfcStyledItem + break; + } + + return std::make_pair(0,0); + } + + const SurfaceStyle* get_style(Ifc2x3::IfcRepresentationItem* representation_item); + const SurfaceStyle* get_default_style(const std::string& ifc_type); + + namespace Cache { + void PurgeStyleCache(); + } +} + +#endif \ No newline at end of file diff --git a/src/ifcgeom/IfcShapeList.h b/src/ifcgeom/IfcRepresentationShapeItem.h similarity index 60% rename from src/ifcgeom/IfcShapeList.h rename to src/ifcgeom/IfcRepresentationShapeItem.h index b49e5a6f3b..db0a37a0fc 100644 --- a/src/ifcgeom/IfcShapeList.h +++ b/src/ifcgeom/IfcRepresentationShapeItem.h @@ -23,8 +23,28 @@ #include #include -namespace IfcGeom { - typedef std::pair LocationShape; - typedef std::vector ShapeList; +#include "../ifcgeom/IfcGeomRenderStyles.h" + +namespace IfcGeom { + class IfcRepresentationShapeItem { + private: + gp_GTrsf placement; + TopoDS_Shape shape; + const SurfaceStyle* style; + public: + IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style) + : placement(placement), shape(shape), style(style) {} + IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape) + : placement(placement), shape(shape) {} + IfcRepresentationShapeItem(const TopoDS_Shape& shape, const SurfaceStyle* style) + : shape(shape), style(style) {} + IfcRepresentationShapeItem(const TopoDS_Shape& shape) : shape(shape) {} + void move(const gp_GTrsf& trsf) { placement.Multiply(trsf); } + const TopoDS_Shape& Shape() const { return shape; } + const gp_GTrsf& Placement() const { return placement; } + bool hasStyle() const { return style != 0; } + const SurfaceStyle& Style() const { return *style; } + }; + typedef std::vector IfcRepresentationShapeItems; } #endif