Files
IfcOpenShell/src/ifcgeom/SurfaceStyle.cpp
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

136 lines
6.1 KiB
C++
Raw Normal View History

2023-03-21 20:15:01 +01:00
#include "../ifcgeom/IfcGeomRenderStyles.h"
2017-12-20 16:38:55 +01:00
2018-10-30 14:32:28 +01:00
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
2017-12-20 16:38:55 +01:00
#include <map>
2020-12-20 14:38:54 +01:00
#include <mutex>
2017-12-20 16:38:55 +01:00
2018-10-30 14:32:28 +01:00
namespace pt = boost::property_tree;
2024-06-10 20:11:24 +02:00
static std::map<std::string, ifcopenshell::geometry::taxonomy::style::ptr> default_materials;
static ifcopenshell::geometry::taxonomy::style::ptr default_material;
2017-12-20 16:38:55 +01:00
static bool default_materials_initialized = false;
void InitDefaultMaterials() {
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcSite", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcSite")));
default_materials["IfcSite"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.75, 0.8, 0.65);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcSlab", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcSlab")));
default_materials["IfcSlab"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.4, 0.4, 0.4);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcWallStandardCase", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcWallStandardCase")));
default_materials["IfcWallStandardCase"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.9, 0.9, 0.9);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcWall", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcWall")));
default_materials["IfcWall"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.9, 0.9, 0.9);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcWindow", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcWindow")));
default_materials["IfcWindow"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.75, 0.8, 0.75);
default_materials["IfcWindow"]->transparency = 0.3;
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcDoor", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcDoor")));
default_materials["IfcDoor"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.55, 0.3, 0.15);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcBeam", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcBeam")));
default_materials["IfcBeam"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.75, 0.7, 0.7);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcRailing", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcRailing")));
default_materials["IfcRailing"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.65, 0.6, 0.6);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcMember", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcMember")));
default_materials["IfcMember"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.65, 0.6, 0.6);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcPlate", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcPlate")));
default_materials["IfcPlate"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.8, 0.8, 0.8);
2017-12-20 16:38:55 +01:00
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair("IfcSpace", std::make_shared<ifcopenshell::geometry::taxonomy::style>("IfcSpace")));
default_materials["IfcSpace"]->diffuse = ifcopenshell::geometry::taxonomy::colour(0.65, 0.75, 0.8);
default_materials["IfcSpace"]->transparency = 0.8;
2024-06-10 20:11:24 +02:00
default_material = std::make_shared<ifcopenshell::geometry::taxonomy::style>("DefaultMaterial");
default_material->diffuse = ifcopenshell::geometry::taxonomy::colour(0.7, 0.7, 0.7);
2017-12-20 16:38:55 +01:00
default_materials_initialized = true;
}
2023-03-21 20:15:01 +01:00
ifcopenshell::geometry::taxonomy::colour read_colour_component(const boost::optional<pt::ptree&> list) {
2018-10-30 14:32:28 +01:00
if (!list) {
2023-03-21 20:15:01 +01:00
return ifcopenshell::geometry::taxonomy::colour();
2018-10-30 14:32:28 +01:00
}
double rgb[3];
int i = 0;
for (pt::ptree::value_type &colour : list.get()) {
if (3 <= i) {
throw std::runtime_error("rgb array over 3 elements large");
}
rgb[i] = colour.second.get_value<double>();
i++;
}
if (i != 3) {
throw std::runtime_error("rgb array less than 3 elements large (was " + std::to_string(i) + ")");
}
2023-03-21 20:15:01 +01:00
return ifcopenshell::geometry::taxonomy::colour(rgb[0], rgb[1], rgb[2]);
2018-10-30 14:32:28 +01:00
}
void IfcGeom::set_default_style_file(const std::string& json_file) {
if (!default_materials_initialized) InitDefaultMaterials();
default_materials.clear();
2019-03-08 11:40:16 +01:00
// @todo this will probably need to be updated for UTF-8 paths on Windows
2018-10-30 14:32:28 +01:00
pt::ptree root;
pt::read_json(json_file, root);
for (pt::ptree::value_type &material_pair : root) {
std::string name = material_pair.first;
2024-06-10 20:11:24 +02:00
default_materials.insert(std::make_pair(name, std::make_shared<ifcopenshell::geometry::taxonomy::style>(name)));
2018-10-30 14:32:28 +01:00
pt::ptree material = material_pair.second;
boost::optional<pt::ptree&> diffuse = material.get_child_optional("diffuse");
2024-06-10 20:11:24 +02:00
default_materials[name]->diffuse = read_colour_component(diffuse);
2018-10-30 14:32:28 +01:00
2024-08-20 11:44:20 -03:00
// @todo Is it necessary to get the surface too?
// boost::optional<pt::ptree&> surface = material.get_child_optional("surface");
// default_materials[name]->surface = read_colour_component(surface);
2018-10-30 14:32:28 +01:00
boost::optional<pt::ptree&> specular = material.get_child_optional("specular");
2024-06-10 20:11:24 +02:00
default_materials[name]->specular = read_colour_component(specular);
2018-10-30 14:32:28 +01:00
if (material.get_child_optional("specular-roughness")) {
2024-06-10 20:11:24 +02:00
default_materials[name]->specularity = 1.0 / material.get<double>("specular-roughness");
2018-10-30 14:32:28 +01:00
}
if (material.get_child_optional("transparency")) {
2024-06-10 20:11:24 +02:00
default_materials[name]->transparency = material.get<double>("transparency");
2018-10-30 14:32:28 +01:00
}
}
// Is "*" present? If yes, remove it and make it the default style.
2021-10-08 15:38:46 +02:00
auto it = default_materials.find("*");
2018-10-30 14:32:28 +01:00
if (it != default_materials.end()) {
2021-10-08 15:38:46 +02:00
default_material = it->second;
2018-10-30 14:32:28 +01:00
default_materials.erase(it);
}
}
2024-06-10 20:11:24 +02:00
const ifcopenshell::geometry::taxonomy::style::ptr& IfcGeom::get_default_style(const std::string& s) {
2020-12-20 14:38:54 +01:00
static std::mutex m;
std::lock_guard<std::mutex> lk(m);
2017-12-20 16:38:55 +01:00
if (!default_materials_initialized) InitDefaultMaterials();
2021-10-08 15:38:46 +02:00
auto it = default_materials.find(s);
2017-12-20 16:38:55 +01:00
if (it == default_materials.end()) {
2021-10-08 15:38:46 +02:00
default_materials.insert(std::make_pair(s, default_material));
2017-12-20 16:38:55 +01:00
it = default_materials.find(s);
}
2021-10-08 15:38:46 +02:00
return it->second;
2017-12-20 16:38:55 +01:00
}
2024-06-10 20:11:24 +02:00
ifcopenshell::geometry::taxonomy::style::ptr& IfcGeom::update_default_style(const std::string& s) {
if (!default_materials_initialized) InitDefaultMaterials();
2021-10-08 15:38:46 +02:00
auto it = default_materials.find(s);
if (it == default_materials.end()) {
throw std::runtime_error("No style registered for " + s);
}
2023-03-21 20:15:01 +01:00
return it->second;
}