Files

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

693 lines
30 KiB
C++
Raw Permalink Normal View History

2023-03-21 20:15:01 +01:00
#ifndef CONVERSIONSETTINGS_H
#define CONVERSIONSETTINGS_H
2017-12-20 16:38:55 +01:00
2023-03-21 20:15:01 +01:00
#include <array>
2023-03-30 14:28:25 +02:00
#include <limits>
2023-03-30 14:29:06 +02:00
#include <string>
2023-11-15 10:32:20 +01:00
#include <iostream>
#include <string>
#include <map>
#include <tuple>
#include <type_traits>
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/optional/optional_io.hpp>
2023-03-30 14:28:25 +02:00
2023-03-21 20:15:01 +01:00
#include "ifc_geom_api.h"
2017-12-22 13:51:11 +01:00
2023-11-15 10:32:20 +01:00
#ifndef SWIG
namespace po = boost::program_options;
namespace std {
2025-09-26 14:24:49 +02:00
IFC_GEOM_API istream& operator>>(istream& in, set<int>& ints);
IFC_GEOM_API istream& operator>>(istream& in, set<string>& ints);
IFC_GEOM_API istream& operator>>(istream& in, vector<double>& vs);
2023-11-15 10:32:20 +01:00
}
#endif
2023-03-21 20:15:01 +01:00
namespace ifcopenshell {
namespace geometry {
2023-11-15 10:32:20 +01:00
inline namespace settings {
2022-07-18 13:51:45 +02:00
2023-11-15 10:32:20 +01:00
#ifndef SWIG
template <typename T, typename U = int>
struct HasDefault : std::false_type { };
2023-03-21 20:15:01 +01:00
2023-11-15 10:32:20 +01:00
template <typename T>
struct HasDefault<T, decltype((void)T::defaultvalue, 0)> : std::true_type { };
#endif
2025-04-29 10:52:27 +02:00
template <typename Derived, typename T, bool Internal=false>
2023-11-15 10:32:20 +01:00
struct SettingBase {
typedef T base_type;
// boost program options does not seem to handle optional<vector> types, so in case
// of vector settings we need to strip away the optional and detect argument presence
// with !vector::empty()
// tfk: we no longer do this because negative values can not be passed like this as boost confuses them with options
// std::conditional_t<std::is_same_v<T, std::vector<double>>, T, boost::optional<T>> value;
boost::optional<T> value;
2023-11-15 10:32:20 +01:00
SettingBase() {}
void defineOption(po::options_description& desc) {
auto apply_default = [](auto x) {
if constexpr (HasDefault<Derived>()) {
return x->default_value(Derived::defaultvalue);
} else {
return x;
}
};
2025-04-29 10:52:27 +02:00
if constexpr (Internal) {
// do nothing, this is an internal setting and not supposed to be set from the command line
} else if constexpr (std::is_same_v<T, bool>) {
2023-11-15 10:32:20 +01:00
// @todo bool_switch doesn't work with optional unfortunately...
value.emplace();
desc.add_options()(Derived::name, apply_default(po::bool_switch(&*value)), Derived::description);
} else if constexpr (std::is_same_v<T, std::vector<double>>) {
// these options have to be supplied manually in IfcConvert.cpp
// desc.add_options()(Derived::name, apply_default(po::value(&value)->multitoken()), Derived::description);
2023-11-15 10:32:20 +01:00
} else {
desc.add_options()(Derived::name, apply_default(po::value(&value)), Derived::description);
}
}
T get() const {
if constexpr (false && std::is_same_v<T, std::vector<double>>) {
return value;
} else {
if (value) {
return value.get();
}
if constexpr (HasDefault<Derived>()) {
return Derived::defaultvalue;
2025-10-03 14:10:07 +03:00
} else {
throw std::runtime_error("Setting not set");
}
2023-11-15 10:32:20 +01:00
}
}
bool has() const {
if constexpr (false && std::is_same_v<T, std::vector<double>>) {
return !value.empty();
} else {
// @todo this is not reliable, better use vmap[...].defaulted()
return !!value;
}
2023-11-15 10:32:20 +01:00
}
};
// These are the old geometry settings values from the kernel
struct MesherLinearDeflection : public SettingBase<MesherLinearDeflection, double> {
static constexpr const char* const name = "mesher-linear-deflection";
static constexpr const char* const description = "Specifies the linear deflection of the mesher. Controls the detail of curved surfaces in triangulated output formats.";
static constexpr double defaultvalue = 0.001;
};
struct MesherAngularDeflection : public SettingBase<MesherAngularDeflection, double> {
static constexpr const char* const name = "mesher-angular-deflection";
static constexpr const char* const description = "Sets the angular tolerance of the mesher in radians 0.5 by default if not specified.";
static constexpr double defaultvalue = 0.5;
};
struct ReorientShells : public SettingBase<ReorientShells, bool> {
static constexpr const char* const name = "reorient-shells";
static constexpr const char* const description = "Specifies whether to orient the faces of IfcConnectedFaceSets. "
"This is a potentially time consuming operation, but guarantees a "
"consistent orientation of surface normals, even if the faces are not "
"properly oriented in the IFC file.";
static constexpr bool defaultvalue = false;
};
2025-04-29 10:52:27 +02:00
struct LengthUnit : public SettingBase<LengthUnit, double, true> {
2023-11-15 10:32:20 +01:00
static constexpr const char* const name = "length-unit";
static constexpr const char* const description = "";
static constexpr double defaultvalue = 1.0;
};
2025-04-29 10:52:27 +02:00
struct PlaneUnit : public SettingBase<PlaneUnit, double, true> {
2023-11-15 10:32:20 +01:00
static constexpr const char* const name = "angle-unit";
static constexpr const char* const description = "";
static constexpr double defaultvalue = 1.0;
};
2025-04-29 10:52:27 +02:00
struct Precision : public SettingBase<Precision, double, true> {
2023-11-15 10:32:20 +01:00
static constexpr const char* const name = "precision";
static constexpr const char* const description = "";
static constexpr double defaultvalue = 0.00001;
};
struct LayersetFirst : public SettingBase<LayersetFirst, bool> {
static constexpr const char* const name = "layerset-first";
static constexpr const char* const description = "Assigns the first layer material of the layerset "
"to the complete product.";
static constexpr bool defaultvalue = false;
};
struct DisableBooleanResult : public SettingBase<DisableBooleanResult, bool> {
static constexpr const char* const name = "disable-boolean-result";
static constexpr const char* const description = "Specifies whether to disable the boolean operation within representations "
"such as clippings by means of IfcBooleanResult and subtypes";
static constexpr bool defaultvalue = false;
};
struct NoWireIntersectionCheck : public SettingBase<NoWireIntersectionCheck, bool> {
static constexpr const char* const name = "no-wire-intersection-check";
static constexpr const char* const description = "Skip wire intersection check.";
static constexpr bool defaultvalue = false;
};
struct NoWireIntersectionTolerance : public SettingBase<NoWireIntersectionTolerance, double> {
static constexpr const char* const name = "no-wire-intersection-tolerance";
static constexpr const char* const description = "Set wire intersection tolerance to 0.";
static constexpr bool defaultvalue = false;
};
struct PrecisionFactor : public SettingBase<PrecisionFactor, double> {
static constexpr const char* const name = "precision-factor";
static constexpr const char* const description = "Option to increase linear tolerance for more permissive edge curves and fewer artifacts after "
"boolean operations at the expense of geometric detail "
"due to vertex collapsing and wire intersection fuzziness.";
static constexpr double defaultvalue = 1.0;
};
2024-12-10 21:17:37 +01:00
struct DebugBooleanOperations : public SettingBase<DebugBooleanOperations, bool> {
static constexpr const char* const name = "debug";
static constexpr const char* const description = "write boolean operands to file in current directory for debugging purposes";
2023-11-15 10:32:20 +01:00
static constexpr bool defaultvalue = false;
};
2024-12-10 21:17:37 +01:00
struct BooleanAttempt2d : public SettingBase<BooleanAttempt2d, bool> {
2023-11-15 10:32:20 +01:00
static constexpr const char* const name = "boolean-attempt-2d";
static constexpr const char* const description = "Do not attempt to process boolean subtractions in 2D.";
static constexpr bool defaultvalue = true;
};
// These are the old IteratorSettings
struct WeldVertices : public SettingBase<WeldVertices, bool> {
static constexpr const char* const name = "weld-vertices";
static constexpr const char* const description = "Specifies whether vertices are welded, meaning that the coordinates "
"vector will only contain unique xyz-triplets. This results in a "
"manifold mesh which is useful for modelling applications, but might "
"result in unwanted shading artefacts in rendering applications.";
static constexpr bool defaultvalue = true;
};
struct UseWorldCoords : public SettingBase<UseWorldCoords, bool> {
static constexpr const char* const name = "use-world-coords";
static constexpr const char* const description = "Specifies whether to apply the local placements of building elements "
"directly to the coordinates of the representation mesh rather than "
"to represent the local placement in the 4x3 matrix, which will in that "
"case be the identity matrix.";
static constexpr bool defaultvalue = false;
2023-03-21 20:15:01 +01:00
};
2023-11-15 10:32:20 +01:00
2024-10-07 20:47:01 +02:00
struct UnifyShapes : public SettingBase<UnifyShapes, bool> {
static constexpr const char* const name = "unify-shapes";
static constexpr const char* const description = "Unify adjacent co-planar and co-linear subshapes (topological entities "
"sharing the same geometric domain) before triangulation or further processing";
static constexpr bool defaultvalue = false;
};
struct UseMaterialNames : public SettingBase<UseMaterialNames, bool> {
static constexpr const char* const name = "use-material-names";
static constexpr const char* const description = "Use material names instead of unique IDs for naming materials upon serialization. "
"Applicable for OBJ and DAE output.";
static constexpr bool defaultvalue = false;
};
2023-11-15 10:32:20 +01:00
struct ConvertBackUnits : public SettingBase<ConvertBackUnits, bool> {
static constexpr const char* const name = "convert-back-units";
static constexpr const char* const description = "Specifies whether to convert back geometrical output back to the "
"unit of measure in which it is defined in the IFC file. Default is "
"to use meters.";
static constexpr bool defaultvalue = false;
};
struct ContextIds : public SettingBase<ContextIds, std::set<int>> {
static constexpr const char* const name = "context-ids";
static constexpr const char* const description = "List of comma separated context ids to process - e.g. '15,29' (no quotes needed).";
2023-11-15 10:32:20 +01:00
};
struct ContextTypes : public SettingBase<ContextTypes, std::set<std::string>> {
static constexpr const char* const name = "context-types";
static constexpr const char* const description = "Currently option has no effect.";
};
struct ContextIdentifiers : public SettingBase<ContextIdentifiers, std::set<std::string>> {
static constexpr const char* const name = "context-identifiers";
static constexpr const char* const description = "Currently option has no effect.";
};
enum OutputDimensionalityTypes {
CURVES,
SURFACES_AND_SOLIDS,
CURVES_SURFACES_AND_SOLIDS
};
2025-09-26 14:24:49 +02:00
IFC_GEOM_API std::istream& operator>>(std::istream& in, OutputDimensionalityTypes& ioo);
struct OutputDimensionality : public SettingBase<OutputDimensionality, OutputDimensionalityTypes> {
static constexpr const char* const name = "dimensionality";
2025-07-11 17:48:57 +05:00
static constexpr const char* const description =
"Specifies whether to include curves and/or surfaces and solids in the output result. "
"Defaults to only surfaces and solids (SURFACES_AND_SOLIDS). "
"Other possible values are CURVES, CURVES_SURFACES_AND_SOLIDS.";
2024-04-18 21:36:45 +02:00
static constexpr OutputDimensionalityTypes defaultvalue = SURFACES_AND_SOLIDS;
};
2023-11-15 10:32:20 +01:00
enum IteratorOutputOptions {
TRIANGULATED,
NATIVE,
SERIALIZED
};
2025-09-26 14:24:49 +02:00
IFC_GEOM_API std::istream& operator>>(std::istream& in, IteratorOutputOptions& ioo);
2023-11-15 10:32:20 +01:00
struct IteratorOutput : public SettingBase<IteratorOutput, IteratorOutputOptions> {
static constexpr const char* const name = "iterator-output";
static constexpr const char* const description = "";
static constexpr IteratorOutputOptions defaultvalue = TRIANGULATED;
};
struct DisableOpeningSubtractions : public SettingBase<DisableOpeningSubtractions, bool> {
static constexpr const char* const name = "disable-opening-subtractions";
static constexpr const char* const description = "Specifies whether to disable the boolean subtraction of "
"IfcOpeningElement Representations from their RelatingElements.";
static constexpr bool defaultvalue = false;
};
struct ApplyDefaultMaterials : public SettingBase<ApplyDefaultMaterials, bool> {
static constexpr const char* const name = "apply-default-materials";
static constexpr const char* const description = "";
static constexpr bool defaultvalue = true;
};
struct DontEmitNormals : public SettingBase<DontEmitNormals, bool> {
static constexpr const char* const name = "no-normals";
static constexpr const char* const description = "Disables computation of normals.Saves time and file size and is useful "
"in instances where you're going to recompute normals for the exported "
"model in other modelling application in any case.";
static constexpr bool defaultvalue = false;
};
struct GenerateUvs : public SettingBase<GenerateUvs, bool> {
static constexpr const char* const name = "generate-uvs";
static constexpr const char* const description = "Generates UVs (texture coordinates) by using simple box projection. Requires normals. "
"Not guaranteed to work properly if used with --weld-vertices.";
static constexpr bool defaultvalue = false;
};
struct ApplyLayerSets : public SettingBase<ApplyLayerSets, bool> {
static constexpr const char* const name = "enable-layerset-slicing";
static constexpr const char* const description = "Specifies whether to enable the slicing of products according "
"to their associated IfcMaterialLayerSet.";
static constexpr bool defaultvalue = false;
};
struct UseElementHierarchy : public SettingBase<UseElementHierarchy, bool> {
static constexpr const char* const name = "element-hierarchy";
static constexpr const char* const description = "Assign the elements using their e.g IfcBuildingStorey parent."
"Applicable to DAE output.";
static constexpr bool defaultvalue = false;
};
struct ValidateQuantities : public SettingBase<ValidateQuantities, bool> {
static constexpr const char* const name = "validate";
static constexpr const char* const description = "Checks whether geometrical output conforms to the included explicit quantities.";
static constexpr bool defaultvalue = false;
};
struct EdgeArrows : public SettingBase<EdgeArrows, bool> {
static constexpr const char* const name = "edge-arrows";
static constexpr const char* const description = "Adds arrow heads to edge segments to signify edge direction";
static constexpr bool defaultvalue = false;
};
struct SiteLocalPlacement : public SettingBase<SiteLocalPlacement, bool> {
static constexpr const char* const name = "site-local-placement";
static constexpr const char* const description = "Place elements locally in the IfcSite coordinate system, instead of placing "
"them in the IFC global coords. Applicable for OBJ, DAE, and STP output.";
static constexpr bool defaultvalue = false;
};
struct BuildingLocalPlacement : public SettingBase<BuildingLocalPlacement, bool> {
static constexpr const char* const name = "building-local-placement";
static constexpr const char* const description = "Similar to --site-local-placement, but placing elements in locally in the parent IfcBuilding coord system";
static constexpr bool defaultvalue = false;
};
struct NoParallelMapping : public SettingBase<NoParallelMapping, bool> {
static constexpr const char* const name = "no-parallel-mapping";
static constexpr const char* const description = "Perform mapping upfront (single-threaded) as opposed to in parallel. May decrease performance, but also decrease output size (in the future)";
static constexpr bool defaultvalue = false;
};
struct PermissiveShapeReuse : public SettingBase<PermissiveShapeReuse, bool> {
static constexpr const char* const name = "permissive-shape-reuse";
static constexpr const char* const description = "Traverse geometry-level transformations and apply to product-level placement in order to increase reuse of geometries";
static constexpr bool defaultvalue = false;
};
2023-11-15 10:32:20 +01:00
struct ForceSpaceTransparency : public SettingBase<ForceSpaceTransparency, double> {
static constexpr const char* const name = "force-space-transparency";
static constexpr const char* const description = "Overrides transparency of spaces in geometry output.";
};
struct CircleSegments : public SettingBase<CircleSegments, int> {
static constexpr const char* const name = "circle-segments";
static constexpr const char* const description = "Number of segments to approximate full circles in CGAL kernel.";
static constexpr int defaultvalue = 16;
};
struct CgalSmoothAngleDegrees : public SettingBase<CgalSmoothAngleDegrees, double> {
static constexpr const char* const name = "cgal-smooth-angle-degrees";
static constexpr const char* const description = "Angle in degrees under which adjacent facets will have averaged vertex normals in CGAL output. NB irrespective of original IFC geometry types. Defaults to -1 to disable smoothing.";
2025-08-21 14:06:54 +02:00
static constexpr double defaultvalue = -1.;
};
struct KeepBoundingBoxes : public SettingBase<KeepBoundingBoxes, bool> {
static constexpr const char* const name = "keep-bounding-boxes";
static constexpr const char* const description =
"Default is to removes IfcBoundingBox from model prior to converting geometry."
"Setting this option disables that behaviour";
static constexpr bool defaultvalue = false;
};
struct SurfaceColour : public SettingBase<SurfaceColour, bool> {
static constexpr const char* const name = "surface-colour";
static constexpr const char* const description =
"Prioritizes the surface color instead of using diffuse.";
static constexpr bool defaultvalue = false;
};
2025-03-14 07:31:50 -07:00
struct ComputeCurvature : public SettingBase<ComputeCurvature, bool> {
static constexpr const char* const name = "compute-curvature";
static constexpr const char* const description = "Specifies whether function_item_evaluator.evaluate() computes curvature.";
static constexpr bool defaultvalue = false;
};
2025-01-02 11:10:56 -08:00
enum FunctionStepMethod {
MAXSTEPSIZE,
MINSTEPS };
2025-09-26 14:24:49 +02:00
IFC_GEOM_API std::istream& operator>>(std::istream& in, FunctionStepMethod& ioo);
2025-01-02 11:10:56 -08:00
struct FunctionStepType : public SettingBase<FunctionStepType, FunctionStepMethod> {
static constexpr const char* const name = "function-step-type";
static constexpr const char* const description = "Indicates the method used for defining step size when evaluating function-based curves. Provides interpretation of function-step-param";
static constexpr FunctionStepMethod defaultvalue = MAXSTEPSIZE;
};
2025-01-02 11:10:56 -08:00
struct FunctionStepParam : public SettingBase<FunctionStepParam, double> {
static constexpr const char* const name = "function-step-param";
static constexpr const char* const description = "Indicates the parameter value for defining step size when evaluating function-based curves.";
static constexpr double defaultvalue = 0.5; // ceiling of this value is used when FunctionStepMethod is MinSteps
};
struct ModelOffset : public SettingBase<ModelOffset, std::vector<double>> {
static constexpr const char* const name = "model-offset";
static constexpr const char* const description = "Applies an arbitrary offset of form x,y,z to all placements.";
};
struct ModelRotation : public SettingBase<ModelRotation, std::vector<double>> {
static constexpr const char* const name = "model-rotation";
static constexpr const char* const description = "Applies an arbitrary quaternion rotation of form x,y,z,w to all placements.";
};
enum TriangulationMethod {
TRIANGLE_MESH,
POLYHEDRON_WITHOUT_HOLES,
POLYHEDRON_WITH_HOLES
};
2025-09-26 14:24:49 +02:00
IFC_GEOM_API std::istream& operator>>(std::istream& in, TriangulationMethod& ioo);
struct TriangulationType : public SettingBase<TriangulationType, TriangulationMethod> {
static constexpr const char* const name = "triangulation-type";
static constexpr const char* const description = "Type of planar facet to be emitted";
static constexpr TriangulationMethod defaultvalue = TRIANGLE_MESH;
};
struct CgalEmitOriginalEdges : public SettingBase<CgalEmitOriginalEdges, bool> {
static constexpr const char* const name = "cgal-original-edges";
static constexpr const char* const description = "Try to emit original edge face boundary edges instead of recomputed ones based on face normal. Falls back to triangulated data in case of boolean operands and faces with holes.";
static constexpr bool defaultvalue = false;
};
struct OcctNoCleanTriangulation : public SettingBase<OcctNoCleanTriangulation, bool, true> {
static constexpr const char* const name = "no-clean-triangulation";
static constexpr const char* const description = "Don't clean triangulations, might cause memory leaks";
static constexpr bool defaultvalue = false;
};
struct CacheShapes : public SettingBase<CacheShapes, bool> {
static constexpr const char* const name = "cache-shapes";
static constexpr const char* const description = "Experimental as not all topology hash functions fully implemented";
static constexpr bool defaultvalue = false;
};
struct MakeVolume : public SettingBase<MakeVolume, bool> {
static constexpr const char* const name = "make-volume";
static constexpr const char* const description = "Try to isolate and fix a valid volume from non-manifold elements prior to opening subtraction";
static constexpr bool defaultvalue = false;
};
struct DeferProcessingFirstElement : public SettingBase<DeferProcessingFirstElement, bool, true> {
static constexpr const char* const name = "defer-processing-first-element";
static constexpr const char* const description = "Don't process first element in Iterator::initialize call()";
static constexpr bool defaultvalue = false;
};
struct MaxOffset : public SettingBase<MaxOffset, double> {
static constexpr const char* const name = "max-offset";
static constexpr const char* const description = "Maximum translation offset to be observed after which median offset in model gets removed and logged. Requires --no-parallel-mapping.";
};
struct MaxOffsetDeviation : public SettingBase<MaxOffsetDeviation, double> {
static constexpr const char* const name = "max-offset-deviation";
static constexpr const char* const description = "To retain field of view, completely remove elements outside of the median offset. Requires --no-parallel-mapping.";
};
struct ApplyOffset : public SettingBase<ApplyOffset, std::vector<double>> {
static constexpr const char* const name = "apply-offset";
static constexpr const char* const description = "Slight variation of --model-offset where large offsets are applied by negating existing large offsets to retain maximum precision. Requires --no-parallel-mapping.";
};
2023-11-15 10:32:20 +01:00
}
2025-03-19 11:42:43 +01:00
namespace impl {
template <typename T>
struct readable_name {
static constexpr const char* name = "Unknown Type";
};
template <>
struct readable_name<bool> {
static constexpr const char* name = "bool";
};
template <>
struct readable_name<int> {
static constexpr const char* name = "int";
};
template <>
struct readable_name<double> {
static constexpr const char* name = "double";
};
template <>
struct readable_name<std::string> {
static constexpr const char* name = "std::string";
};
template <>
struct readable_name<std::set<int>> {
static constexpr const char* name = "std::set<int>";
};
template <>
struct readable_name<std::set<std::string>> {
static constexpr const char* name = "std::set<std::string>";
};
template <>
struct readable_name<std::vector<double>> {
static constexpr const char* name = "std::vector<double>";
};
template <>
struct readable_name<IteratorOutputOptions> {
static constexpr const char* name = "IteratorOutputOptions";
};
template <>
struct readable_name<FunctionStepMethod> {
static constexpr const char* name = "FunctionStepMethod";
};
template <>
struct readable_name<OutputDimensionalityTypes> {
static constexpr const char* name = "OutputDimensionalityTypes";
};
template <>
struct readable_name<TriangulationMethod> {
static constexpr const char* name = "TriangulationMethod";
};
}
2023-11-15 10:32:20 +01:00
template <typename settings_t>
2025-09-26 14:24:49 +02:00
class SettingsContainer {
2023-11-15 10:32:20 +01:00
public:
2025-01-02 11:10:56 -08:00
typedef boost::variant<bool, int, double, std::string, std::set<int>, std::set<std::string>, std::vector<double>, IteratorOutputOptions, FunctionStepMethod, OutputDimensionalityTypes, TriangulationMethod> value_variant_t;
2023-11-15 10:32:20 +01:00
private:
settings_t settings;
template <std::size_t Index>
void define_options_(po::options_description& desc) {
std::get<Index>(settings).defineOption(desc);
if constexpr (Index + 1 < std::tuple_size_v<settings_t>) {
define_options_<Index + 1>(desc);
}
}
template <std::size_t Index>
value_variant_t get_option_(const std::string& name) const {
if (std::tuple_element_t<Index, settings_t>::name == name) {
return std::get<Index>(settings).get();
}
if constexpr (Index + 1 < std::tuple_size_v<settings_t>) {
return get_option_<Index + 1>(name);
} else {
throw std::runtime_error("Setting not available");
}
}
2025-03-19 11:42:43 +01:00
template <std::size_t Index>
std::string get_type_(const std::string& name) const {
if (std::tuple_element_t<Index, settings_t>::name == name) {
return impl::readable_name<typename std::tuple_element_t<Index, settings_t>::base_type>::name;
}
if constexpr (Index + 1 < std::tuple_size_v<settings_t>) {
return get_type_<Index + 1>(name);
} else {
throw std::runtime_error("Setting not available");
}
}
2023-11-15 10:32:20 +01:00
template <std::size_t Index>
void set_option_(const std::string& name, const value_variant_t& val) {
if (std::tuple_element_t<Index, settings_t>::name == name) {
2024-04-21 10:19:17 +02:00
if constexpr (std::is_enum_v<typename std::tuple_element_t<Index, settings_t>::base_type>) {
2025-03-19 11:42:43 +01:00
if (auto* val_ptr = boost::get<int>(&val)) {
auto val_as_enum = (typename std::tuple_element_t<Index, settings_t>::base_type) *val_ptr;
2024-04-21 10:19:17 +02:00
std::get<Index>(settings).value = val_as_enum;
return;
}
}
2025-03-19 11:42:43 +01:00
try {
std::get<Index>(settings).value = boost::get<typename std::tuple_element_t<Index, settings_t>::base_type>(val);
} catch (const boost::bad_get&) {
std::string ty = impl::readable_name<typename std::tuple_element_t<Index, settings_t>::base_type>::name;
throw std::runtime_error("Expected a value of type <" + ty + "> for setting '" + name + "'");
}
2023-11-15 10:32:20 +01:00
} else if constexpr (Index + 1 < std::tuple_size_v<settings_t>) {
set_option_<Index + 1>(name, val);
} else {
throw std::runtime_error("Setting not available");
}
}
template <std::size_t Index>
void get_setting_names_(std::vector<std::string>& vec) const {
vec.push_back(std::tuple_element_t<Index, settings_t>::name);
if constexpr (Index + 1 < std::tuple_size_v<settings_t>) {
return get_setting_names_<Index + 1>(vec);
}
}
public:
typedef settings_t settings_tuple;
void define_options(po::options_description& desc) {
define_options_<0>(desc);
}
template <typename T>
const T& get() const {
return std::get<T>(settings);
}
template <typename T>
T& get() {
return std::get<T>(settings);
}
template <typename T>
void set(T& v) {
std::get<T>(settings) = v;
}
value_variant_t get(const std::string& name) const {
return get_option_<0>(name);
}
void set(const std::string& name, value_variant_t val) {
set_option_<0>(name, val);
}
2025-03-19 11:42:43 +01:00
std::string get_type(const std::string& name) {
return get_type_<0>(name);
}
2023-11-15 10:32:20 +01:00
std::vector<std::string> setting_names() const {
std::vector<std::string> r;
get_setting_names_<0>(r);
return r;
}
2017-12-22 13:51:11 +01:00
};
2023-11-15 10:32:20 +01:00
2025-09-26 14:24:49 +02:00
class Settings : public SettingsContainer<
std::tuple<MesherLinearDeflection, MesherAngularDeflection, ReorientShells, LengthUnit, PlaneUnit, Precision, OutputDimensionality, LayersetFirst, DisableBooleanResult, NoWireIntersectionCheck, NoWireIntersectionTolerance, PrecisionFactor, DebugBooleanOperations, BooleanAttempt2d, SurfaceColour, WeldVertices, UseWorldCoords, UnifyShapes, UseMaterialNames, ConvertBackUnits, ContextIds, ContextTypes, ContextIdentifiers, IteratorOutput, DisableOpeningSubtractions, ApplyDefaultMaterials, DontEmitNormals, GenerateUvs, ApplyLayerSets, UseElementHierarchy, ValidateQuantities, EdgeArrows, BuildingLocalPlacement, SiteLocalPlacement, ForceSpaceTransparency, CircleSegments, CgalSmoothAngleDegrees, KeepBoundingBoxes, ComputeCurvature, FunctionStepType, FunctionStepParam, NoParallelMapping, PermissiveShapeReuse, ModelOffset, ModelRotation, TriangulationType, CgalEmitOriginalEdges, OcctNoCleanTriangulation, CacheShapes, DeferProcessingFirstElement, MaxOffset, MaxOffsetDeviation, ApplyOffset, MakeVolume>
2023-11-15 10:32:20 +01:00
>
{};
}
2023-03-21 20:15:01 +01:00
}
2023-03-21 20:15:01 +01:00
// @todo find a place
namespace IfcGeom {
2025-10-03 14:00:20 +00:00
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4275)
#endif
2025-09-26 14:24:49 +02:00
class IFC_GEOM_API geometry_exception : public std::runtime_error {
2022-06-14 15:02:54 +02:00
protected:
std::string message;
public:
geometry_exception(const std::string& m)
2025-09-26 14:24:49 +02:00
: std::runtime_error(m)
{}
2025-10-03 14:00:20 +00:00
~geometry_exception() override;
2022-06-14 15:02:54 +02:00
};
class IFC_GEOM_API too_many_faces_exception : public geometry_exception {
public:
too_many_faces_exception()
: geometry_exception("Too many faces for operation") {}
2025-10-03 14:00:20 +00:00
~too_many_faces_exception() override;
2022-06-14 15:02:54 +02:00
};
2017-12-20 16:38:55 +01:00
}
2025-10-03 14:00:20 +00:00
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
2023-03-21 20:15:01 +01:00
#endif