Program Listing for File mapping.h

↰ Return to documentation for file (src/ifcgeom/mapping/mapping.h)

#ifndef MAPPING_H
#define MAPPING_H

#include "../abstract_mapping.h"
#include "../../ifcparse/macros.h"
#include "../../ifcparse/file.h"
#include "../../ifcparse/logger.h"

#include <mutex>
#include <cstdint>
#include <unordered_set>

#include INCLUDE_SCHEMA(../../ifcparse/schemas, IfcSchema)
#include INCLUDE_SCHEMA_DEFINITIONS(../../ifcparse/schemas, IfcSchema)

namespace ifcopenshell {

namespace geom {

    class POSTFIX_SCHEMA(mapping) : public abstract_mapping {
    private:
        ifcopenshell::file* file_;
        double length_unit_, angle_unit_;
        std::string length_unit_name_;

        std::map<uint32_t, ifcopenshell::geom::taxonomy::ptr> cache_;
      std::mutex cache_guard_; // provides mutually exclusive access to cache_

        const ifcopenshell::declaration* placement_rel_to_type_;
        const express::base placement_rel_to_instance_;

        Eigen::Matrix4d offset_and_rotation_ = Eigen::Matrix4d::Identity();

        void initialize_units_();
        void addRepresentationsFromContextIds(std::vector<IfcSchema::IfcRepresentation>&);
        void addRepresentationsFromPriorities(std::vector<IfcSchema::IfcRepresentation>&);
        void addRepresentationsFromDefaultContexts(std::vector<IfcSchema::IfcRepresentation>&);
        void ensureRepresentationContextCache_();

        // Set of instances to mark failures that are intended, such as representations not
        // resulting in any items due to dimensionality filters.
        std::set<express::base> failed_on_purpose_;
        std::set<IfcSchema::IfcRepresentationMap> not_reusable_maps_;
        std::unordered_set<uint32_t> representation_context_cache_;
        std::vector<uint32_t> representation_context_priority_cache_;
        std::set<int> representation_context_cache_ids_;
        std::vector<std::string> representation_context_cache_priorities_;
        settings::OutputDimensionalityTypes representation_context_cache_dimensionality_ = settings::SURFACES_AND_SOLIDS;
        bool representation_context_cache_has_context_ids_ = false;
        bool representation_context_cache_has_context_priorities_ = false;
        bool representation_context_cache_valid_ = false;
        std::mutex representation_context_cache_guard_;

        template <typename T>
        void process_mapping(bool& matched, taxonomy::ptr& item, const express::base& inst) {
            if (!item && inst.as<T>()) {
                matched = true;
                try {
                    item = map_impl(inst.as<T>());
                    if (item != nullptr) {
                        if (!item->instance) {
                            item->instance = inst;
                        }
                        try {
                            if (inst.as<IfcSchema::IfcRepresentationItem>() && !inst.as<IfcSchema::IfcStyledItem>() &&
                                /* @todo */
                                (item->kind() == taxonomy::SOLID || item->kind() == taxonomy::SHELL || item->kind() == taxonomy::COLLECTION || item->kind() == taxonomy::EXTRUSION || item->kind() == taxonomy::LOFT || item->kind() == taxonomy::BOOLEAN_RESULT || item->kind() == taxonomy::REVOLVE || item->kind() == taxonomy::SWEEP_ALONG_CURVE || item->kind() == taxonomy::FACE)
                                ) {
                                auto style = find_style(inst.as<IfcSchema::IfcRepresentationItem>());
                                if (style) {
                                    auto mstyle = map(style);
                                    if (mstyle) {
                                        taxonomy::cast<taxonomy::geom_item>(item)->surface_style = taxonomy::cast<taxonomy::style>(mstyle);
                                    }
                                }
                            }
                        } catch (const std::exception& e) {
                            logger_.message(ifcopenshell::logger::LOG_ERROR, "GEO", 325, std::string(e.what()) + "\nFailed to convert:", inst);
                        }
                    } else if (failed_on_purpose_.find(inst) == failed_on_purpose_.end()) {
                        logger_.message(ifcopenshell::logger::LOG_ERROR, "GEO", 326, "Failed to convert:", inst);
                    }
                } catch (const std::exception& e) {
                    logger_.message(ifcopenshell::logger::LOG_ERROR, "GEO", 327, std::string(e.what()) + "\nFailed to convert:", inst);
                }
            }
        }
        IfcSchema::IfcStyledItem find_style(const IfcSchema::IfcRepresentationItem&);
    public:
        POSTFIX_SCHEMA(mapping)(ifcopenshell::file* file, ifcopenshell::geom::settings& settings, ifcopenshell::logger& logger = ifcopenshell::logger::root()) : abstract_mapping(settings, logger), file_(file), placement_rel_to_type_(nullptr) {
            initialize_units_();
        }
        virtual ifcopenshell::geom::taxonomy::ptr map(const express::base&);
        virtual void get_representations(std::vector<geometry_conversion_task>& tasks, std::vector<filter_function>& filters);
        virtual std::map<std::string, express::base> get_layers(const express::base&);
        virtual void initialize_settings();
        virtual double get_length_unit() const { return length_unit_; }
        virtual const std::string& get_length_unit_name() const { return length_unit_name_; }
        virtual std::vector<express::base> find_openings(const express::base&);
        virtual express::base representation_of(const express::base& product);

        virtual const express::base get_product_type(const express::base& product_);
        virtual const express::base get_single_material_association(const express::base& product);
        IfcSchema::IfcRepresentation representation_mapped_to(const IfcSchema::IfcRepresentation& representation);
        std::vector<IfcSchema::IfcProduct> products_represented_by(const IfcSchema::IfcRepresentation& representation, IfcSchema::IfcRepresentationMap& rmap, bool only_direct = false);
        bool reuse_ok_(const std::vector<IfcSchema::IfcProduct>& products);
        express::base get_decomposing_entity(const express::base& product, bool include_openings);

        bool get_layerset_information(const express::base&, layerset_information&, int&);
        bool get_wall_neighbours(const express::base&, std::vector<endpoint_connection>&);
        IfcSchema::IfcRepresentation find_representation(const IfcSchema::IfcProduct&, const std::string&);

#include "bind_convert_decl.i"
    };

    template <typename U>
    struct element_type {
        typedef taxonomy::item type;
    };
    template <>
    struct element_type<taxonomy::boolean_result> {
        typedef taxonomy::geom_item type;
    };
    template <>
    struct element_type<taxonomy::collection> {
        typedef taxonomy::geom_item type;
    };
    template <>
    struct element_type<taxonomy::shell> {
        typedef taxonomy::face type;
    };
    template <>
    struct element_type<taxonomy::loop> {
        typedef taxonomy::edge type;
    };
    template <>
    struct element_type<taxonomy::solid> {
        typedef taxonomy::shell type;
    };

    template <typename U = taxonomy::collection, typename T>
    typename U::ptr map_to_collection(POSTFIX_SCHEMA(mapping)* m, const T& ts) {
        auto c = taxonomy::make<U>();
        if (ts.size()) {
            for (auto& t : ts) {
                if (auto r = m->map(t)) {
                    c->children.push_back(taxonomy::cast<typename element_type<U>::type>(r));
                }
            }
        }
        if (c->children.empty()) {
#ifdef TAXONOMY_USE_NAKED_PTR
            delete c;
#endif
            return nullptr;
        }
        return c;
    }

}

}

#endif