Merge branch 'v0.6.0' into v0.7.0

# Conflicts:
#	cmake/CMakeLists.txt
#	src/ifcconvert/IfcConvert.cpp
#	src/ifcgeom/IfcGeomRepresentation.h
#	src/ifcgeom/IfcRepresentationShapeItem.h
#	src/ifcgeom/kernels/opencascade/IfcGeomFunctions.cpp
#	src/ifcgeom/schema_agnostic/IfcGeomRepresentation.cpp
#	src/ifcgeom/schema_agnostic/Kernel.cpp
#	src/ifcgeom/schema_agnostic/Kernel.h
#	src/ifcgeomserver/IfcGeomServer.cpp
#	src/serializers/schema_dependent/XmlSerializer.cpp
This commit is contained in:
Thomas Krijnen
2019-04-26 15:07:50 +02:00
51 changed files with 10815 additions and 7568 deletions
+130 -94
View File
@@ -27,42 +27,46 @@
bl_info = {
"name": "IfcBlender",
"description": "Import files in the "\
"description": "Import files in the "
"Industry Foundation Classes (.ifc) file format",
"author": "Thomas Krijnen, IfcOpenShell",
"blender": (2, 73, 0),
"blender": (2, 80, 0),
"location": "File > Import",
"tracker_url": "https://sourceforge.net/p/ifcopenshell/"\
"tracker_url": "https://sourceforge.net/p/ifcopenshell/"
"_list/tickets?source=navbar",
"category": "Import-Export"}
if "bpy" in locals():
import imp
import importlib
if "ifcopenshell" in locals():
imp.reload(ifcopenshell)
importlib.reload(ifcopenshell)
import bpy
import mathutils
from bpy.props import StringProperty, IntProperty, BoolProperty
from bpy_extras.io_utils import ImportHelper
major,minor = bpy.app.version[0:2]
major, minor = bpy.app.version[0:2]
transpose_matrices = minor >= 62
bpy.types.Object.ifc_id = IntProperty(name="IFC Entity ID",
bpy.types.Object.ifc_id = IntProperty(
name="IFC Entity ID",
description="The STEP entity instance name")
bpy.types.Object.ifc_guid = StringProperty(name="IFC Entity GUID",
bpy.types.Object.ifc_guid = StringProperty(
name="IFC Entity GUID",
description="The IFC Globally Unique Identifier")
bpy.types.Object.ifc_name = StringProperty(name="IFC Entity Name",
bpy.types.Object.ifc_name = StringProperty(
name="IFC Entity Name",
description="The optional name attribute")
bpy.types.Object.ifc_type = StringProperty(name="IFC Entity Type",
bpy.types.Object.ifc_type = StringProperty(
name="IFC Entity Type",
description="The STEP Datatype keyword")
def import_ifc(filename, use_names, process_relations, blender_booleans):
from . import ifcopenshell
from .ifcopenshell import geom as ifcopenshell_geom
print("Reading %s..."%bpy.path.basename(filename))
print(f"Reading {bpy.path.basename(filename)}...")
settings = ifcopenshell_geom.settings()
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS, blender_booleans)
iterator = ifcopenshell_geom.iterator(settings, filename)
@@ -76,9 +80,14 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
openings = []
old_progress = -1
print("Creating geometry...")
collection = bpy.data.collections.new(f"{bpy.path.basename(filename)}")
bpy.context.scene.collection.children.link(collection)
if process_relations:
rel_collection = bpy.data.collections.new("Relations")
collection.children.link(rel_collection)
while True:
ob = iterator.get()
f = ob.geometry.faces
v = ob.geometry.verts
mats = ob.geometry.materials
@@ -86,54 +95,75 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
m = ob.transformation.matrix.data
t = ob.type[0:21]
nm = ob.name if len(ob.name) and use_names else ob.guid
verts = [[v[i], v[i + 1], v[i + 2]] \
for i in range(0, len(v), 3)]
faces = [[f[i], f[i + 1], f[i + 2]] \
for i in range(0, len(f), 3)]
# MESH CREATION
# Depending on version, geometry.id will be either int or str
me = bpy.data.meshes.new('mesh-%r' % ob.geometry.id)
me.from_pydata(verts, [], faces)
me.validate()
def add_material(mname, props):
if mname in bpy.data.materials:
mat = bpy.data.materials[mname]
mat.use_fake_user = True
else:
mat = bpy.data.materials.new(mname)
for k,v in props.items():
setattr(mat, k, v)
me.materials.append(mat)
needs_default = -1 in matids
if needs_default: add_material(t, {})
for mat in mats:
props = {}
if mat.has_diffuse: props['diffuse_color'] = mat.diffuse
if mat.has_specular: props['specular_color'] = mat.specular
if mat.has_transparency and mat.transparency > 0:
props['alpha'] = 1.0 - mat.transparency
props['use_transparency'] = True
if mat.has_specularity: props['specular_hardness'] = mat.specularity
add_material(mat.name, props)
mesh_name = 'mesh-%r' % ob.geometry.id
if mesh_name in bpy.data.meshes:
me = bpy.data.meshes[mesh_name]
else:
verts = [[v[i], v[i + 1], v[i + 2]]
for i in range(0, len(v), 3)]
faces = [[f[i], f[i + 1], f[i + 2]]
for i in range(0, len(f), 3)]
me = bpy.data.meshes.new(mesh_name)
me.from_pydata(verts, [], faces)
me.validate()
# MATERIAL CREATION
def add_material(mname, props):
if mname in bpy.data.materials:
mat = bpy.data.materials[mname]
mat.use_fake_user = True
else:
mat = bpy.data.materials.new(mname)
for k, v in props.items():
if k == 'transparency':
mat.blend_method = 'HASHED'
mat.use_screen_refraction = True
mat.refraction_depth = 0.1
mat.use_nodes = True
mat.node_tree.nodes["Principled BSDF"].inputs[15].default_value = v
else:
setattr(mat, k, v)
me.materials.append(mat)
needs_default = -1 in matids
if needs_default:
add_material(t, {})
for mat in mats:
props = {}
if mat.has_diffuse:
props['diffuse_color'] = mat.diffuse
if mat.has_specular:
props['specular_color'] = mat.specular
if mat.has_transparency and mat.transparency > 0:
props['transparency'] = mat.transparency
if mat.has_specularity:
props['specular_intensity'] = mat.specularity
add_material(mat.name, props)
faces = me.polygons if hasattr(me, 'polygons') else me.faces
if len(faces) == len(matids):
for face, matid in zip(faces, matids):
face.material_index = matid + (1 if needs_default else 0)
# OBJECT CREATION
bob = bpy.data.objects.new(nm, me)
mat = mathutils.Matrix(([m[0], m[1], m[2], 0],
[m[3], m[4], m[5], 0],
[m[6], m[7], m[8], 0],
[m[9], m[10], m[11], 1]))
if transpose_matrices: mat.transpose()
[m[3], m[4], m[5], 0],
[m[6], m[7], m[8], 0],
[m[9], m[10], m[11], 1]))
if transpose_matrices:
mat.transpose()
if process_relations:
id_to_matrix[ob.id] = mat
else:
bob.matrix_world = mat
bpy.context.scene.objects.link(bob)
collection.objects.link(bob)
bpy.context.scene.objects.active = bob
bpy.context.view_layer.objects.active = bob
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.normals_make_consistent()
bpy.ops.object.mode_set(mode='OBJECT')
@@ -143,23 +173,19 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
if ob.type == 'IfcSpace' or ob.type == 'IfcOpeningElement':
if not (ob.type == 'IfcOpeningElement' and blender_booleans):
bob.hide = bob.hide_render = True
bob.draw_type = 'WIRE'
if ob.id not in id_to_object: id_to_object[ob.id] = []
bob.hide_viewport = bob.hide_render = True
bob.display_type = 'WIRE'
if ob.id not in id_to_object:
id_to_object[ob.id] = []
id_to_object[ob.id].append(bob)
if ob.parent_id > 0:
id_to_parent[ob.id] = ob.parent_id
if blender_booleans and ob.type == 'IfcOpeningElement':
openings.append(ob.id)
faces = me.polygons if hasattr(me, 'polygons') else me.faces
if len(faces) == len(matids):
for face, matid in zip(faces, matids):
face.material_index = matid + (1 if needs_default else 0)
progress = iterator.progress() // 2
if progress > old_progress:
print("\r[" + "#" * progress + " " * (50 - progress) + "]", end="")
@@ -170,13 +196,13 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
print("\rDone creating geometry" + " " * 30)
id_to_parent_temp = dict(id_to_parent)
if process_relations:
print("Processing relations...")
while len(id_to_parent_temp) and process_relations:
id, parent_id = id_to_parent_temp.popitem()
if parent_id in id_to_object:
bob = id_to_object[parent_id][0]
else:
@@ -188,16 +214,17 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
nm = parent_ob.name if len(parent_ob.name) and use_names \
else parent_ob.guid
bob = bpy.data.objects.new(nm, None)
mat = mathutils.Matrix((
[m[0], m[1], m[2], 0],
[m[3], m[4], m[5], 0],
[m[6], m[7], m[8], 0],
[m[9], m[10], m[11], 1]))
if transpose_matrices: mat.transpose()
if transpose_matrices:
mat.transpose()
id_to_matrix[parent_ob.id] = mat
bpy.context.scene.objects.link(bob)
rel_collection.objects.link(bob)
bob.ifc_id = parent_ob.id
bob.ifc_name, bob.ifc_type, bob.ifc_guid = \
@@ -220,13 +247,13 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
parent_matrix = id_to_matrix.get(parent_id, None)
for ob in id_to_object[id]:
if parent_matrix:
ob.matrix_local = parent_matrix.inverted() * matrix
ob.matrix_local = parent_matrix.inverted() @ matrix
else:
ob.matrix_world = matrix
if process_relations:
print("Done processing relations")
for opening_id in openings:
parent_id = id_to_parent[opening_id]
if parent_id in id_to_object:
@@ -235,8 +262,8 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
mod = parent_ob.modifiers.new("opening", "BOOLEAN")
mod.operation = "DIFFERENCE"
mod.object = opening_ob
txt = bpy.data.texts.new("%s.log"%bpy.path.basename(filename))
txt = bpy.data.texts.new(f"{bpy.path.basename(filename)}.log")
txt.from_string(iterator.getLog())
return True
@@ -247,42 +274,51 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
bl_label = "Import .ifc file"
filename_ext = ".ifc"
filter_glob = StringProperty(default="*.ifc", options={'HIDDEN'})
filter_glob: StringProperty(default="*.ifc", options={'HIDDEN'})
use_names = BoolProperty(name="Use entity names",
description="Use entity names rather than GlobalIds for objects",
default=True)
process_relations = BoolProperty(name="Process relations",
description="Convert containment and aggregation" \
" relations to parenting" \
" (warning: may be slow on large files)",
default=False)
blender_booleans = BoolProperty(name="Use Blender booleans",
description="Use Blender boolean modifiers for opening" \
" elements",
default=False)
use_names: BoolProperty(name="Use entity names",
description="Use entity names rather than "
"GlobalIds for objects",
default=True)
process_relations: BoolProperty(name="Process relations",
description="Convert containment and "
"aggregation relations to parenting"
" (warning: may be slow on large files)",
default=False)
blender_booleans: BoolProperty(name="Use Blender booleans",
description="Use Blender boolean modifiers "
"for opening elements",
default=False)
def execute(self, context):
if not import_ifc(self.filepath, self.use_names, self.process_relations, self.blender_booleans):
if not import_ifc(self.filepath, self.use_names,
self.process_relations, self.blender_booleans):
self.report({'ERROR'},
'Unable to parse .ifc file or no geometrical entities found'
)
'Unable to parse .ifc file or no geometrical entities found'
)
return {'FINISHED'}
def menu_func_import(self, context):
self.layout.operator(ImportIFC.bl_idname,
text="Industry Foundation Classes (.ifc)")
text="Industry Foundation Classes (.ifc)")
classes = (
ImportIFC,
)
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_import.append(menu_func_import)
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_import.remove(menu_func_import)
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
if __name__ == "__main__":
+263 -187
View File
@@ -37,6 +37,8 @@
#include "../ifcgeom/schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom/schema_agnostic/IfcGeomRenderStyles.h"
#include "../ifcparse/utils.h"
#include <Standard_Version.hxx>
#if OCC_VERSION_HEX < 0x60900
@@ -55,6 +57,23 @@
#include <vld.h>
#endif
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
// C++11 header:
#include <random>
#endif
#if defined(_MSC_VER) && defined(_UNICODE)
typedef std::wstring path_t;
static std::wostream& cout_ = std::wcout;
static std::wostream& cerr_ = std::wcerr;
#else
typedef std::string path_t;
static std::ostream& cout_ = std::cout;
static std::ostream& cerr_ = std::cerr;
#endif
const std::string DEFAULT_EXTENSION = "obj";
const std::string TEMP_FILE_EXTENSION = ".tmp";
@@ -62,12 +81,12 @@ namespace po = boost::program_options;
void print_version()
{
std::cout << "IfcOpenShell IfcConvert " << IFCOPENSHELL_VERSION << " (OCC " << OCC_VERSION_STRING_EXT << ")\n";
cout_ << "IfcOpenShell IfcConvert " << IFCOPENSHELL_VERSION << " (OCC " << OCC_VERSION_STRING_EXT << ")\n";
}
void print_usage(bool suggest_help = true)
{
std::cout << "Usage: IfcConvert [options] <input.ifc> [<output>]\n"
cout_ << "Usage: IfcConvert [options] <input.ifc> [<output>]\n"
<< "\n"
<< "Converts (the geometry in) an IFC file into one of the following formats:\n"
<< " .obj WaveFront OBJ (a .mtl file is also created)\n"
@@ -80,48 +99,46 @@ void print_usage(bool suggest_help = true)
<< " .svg SVG Scalable Vector Graphics (2D floor plan)\n"
<< " .ifc IFC-SPF Industry Foundation Classes\n"
<< "\n"
<< "If no output filename given, <input>." + DEFAULT_EXTENSION + " will be used as the output file.\n";
<< "If no output filename given, <input>." << IfcUtil::path::from_utf8(DEFAULT_EXTENSION) << " will be used as the output file.\n";
if (suggest_help) {
std::cout << "\nRun 'IfcConvert --help' for more information.";
cout_ << "\nRun 'IfcConvert --help' for more information.";
}
std::cout << std::endl;
cout_ << std::endl;
}
/// @todo Add help for single option
void print_options(const po::options_description& options)
{
std::cout << "\n" << options;
std::cout << std::endl;
#if defined(_MSC_VER) && defined(_UNICODE)
// See issue https://svn.boost.org/trac10/ticket/10952
std::ostringstream temp;
temp << options;
cout_ << "\n" << temp.str().c_str();
#else
cout_ << "\n" << options;
#endif
cout_ << std::endl;
}
std::string change_extension(const std::string& fn, const std::string& ext) {
std::string::size_type dot = fn.find_last_of('.');
if (dot != std::string::npos) {
return fn.substr(0,dot+1) + ext;
template <typename T>
T change_extension(const T& fn, const T& ext) {
typename T::size_type dot = fn.find_last_of('.');
if (dot != T::npos) {
return fn.substr(0, dot) + ext;
} else {
return fn + "." + ext;
return fn + ext;
}
}
bool file_exists(const std::string& filename)
{
/// @todo Windows Unicode support
std::ifstream file(filename.c_str());
bool file_exists(const std::string& filename) {
std::ifstream file(IfcUtil::path::from_utf8(filename).c_str());
return file.good();
}
bool rename_file(const std::string& old_filename, const std::string& new_filename)
{
// Whether or not rename() replaces an existing file is implementation-specific,
// so remove() possible existing file always.
/// @todo Windows Unicode support
std::remove(new_filename.c_str());
return std::rename(old_filename.c_str(), new_filename.c_str()) == 0;
}
static std::stringstream log_stream;
static std::basic_stringstream<path_t::value_type> log_stream;
void write_log(bool);
void fix_quantities(IfcParse::IfcFile&, bool, bool, bool);
std::string format_duration(time_t start, time_t end);
/// @todo make the filters non-global
IfcGeom::entity_filter entity_filter; // Entity filter is used always by default.
@@ -152,9 +169,28 @@ std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>&, co
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap);
int main(int argc, char** argv)
{
#if defined(_MSC_VER) && defined(_UNICODE)
int wmain(int argc, wchar_t** argv) {
typedef po::wcommand_line_parser command_line_parser;
typedef wchar_t char_t;
_setmode(_fileno(stdout), _O_U16TEXT);
_setmode(_fileno(stderr), _O_U16TEXT);
#else
int main(int argc, char** argv) {
typedef po::command_line_parser command_line_parser;
typedef char char_t;
#endif
double deflection_tolerance;
inclusion_filter include_filter;
inclusion_traverse_filter include_traverse_filter;
exclusion_filter exclude_filter;
exclusion_traverse_filter exclude_traverse_filter;
path_t filter_filename;
path_t default_material_filename;
std::string log_format;
po::options_description generic_options("Command line options");
generic_options.add_options()
("help,h", "display usage information")
@@ -171,8 +207,8 @@ int main(int argc, char** argv)
#ifdef USE_MMAP
("mmap", "use memory-mapped file for input")
#endif
("input-file", po::value<std::string>(), "input IFC file")
("output-file", po::value<std::string>(), "output geometry file");
("input-file", new po::typed_value<path_t, char_t>(0), "input IFC file")
("output-file", new po::typed_value<path_t, char_t>(0), "output geometry file");
double deflection_tolerance;
@@ -252,7 +288,7 @@ int main(int argc, char** argv)
("exclude+", po::value<exclusion_traverse_filter>(&exclude_traverse_filter)->multitoken(),
"Same as --exclude but applies filtering also to the decomposition and/or containment "
"of the filtered entity. See --include+ for more details.")
("filter-file", po::value<std::string>(&filter_filename),
("filter-file", new po::typed_value<path_t, char_t>(&filter_filename),
"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. "
@@ -266,7 +302,7 @@ int main(int argc, char** argv)
("generate-uvs",
"Generates UVs (texture coordinates) by using simple box projection. Requires normals. "
"Not guaranteed to work properly if used with --weld-vertices.")
("default-material-file", po::value<std::string>(&default_material_filename),
("default-material-file", new po::typed_value<path_t, char_t>(&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.")
("validate", "Checks whether geometrical output conforms to the included explicit quantities.");
@@ -329,21 +365,21 @@ int main(int argc, char** argv)
po::variables_map vmap;
try {
po::store(po::command_line_parser(argc, argv).
po::store(command_line_parser(argc, argv).
options(cmdline_options).positional(positional_options).run(), vmap);
} catch (const po::unknown_option& e) {
std::cerr << "[Error] Unknown option '" << e.get_option_name() << "'\n\n";
cerr_ << "[Error] Unknown option '" << e.get_option_name().c_str() << "'\n\n";
print_usage();
return EXIT_FAILURE;
} catch (const po::error_with_option_name& e) {
std::cerr << "[Error] Invalid usage of '" << e.get_option_name() << "': " << e.what() << "\n\n";
cerr_ << "[Error] Invalid usage of '" << e.get_option_name().c_str() << "': " << e.what() << "\n\n";
return EXIT_FAILURE;
} catch (const std::exception& e) {
std::cerr << "[Error] " << e.what() << "\n\n";
cerr_ << "[Error] " << e.what() << "\n\n";
print_usage();
return EXIT_FAILURE;
} catch (...) {
std::cerr << "[Error] Unknown error parsing command line options\n\n";
cerr_ << "[Error] Unknown error parsing command line options\n\n";
print_usage();
return EXIT_FAILURE;
}
@@ -378,11 +414,11 @@ int main(int argc, char** argv)
const bool generate_uvs = vmap.count("generate-uvs") != 0;
const bool validate = vmap.count("validate") != 0;
if (!quiet || vmap.count("version")) {
if (!quiet || vmap.count("version")) {
print_version();
}
if (vmap.count("version")) {
if (vmap.count("version")) {
return EXIT_SUCCESS;
} else if (vmap.count("help")) {
print_usage(false);
@@ -393,70 +429,7 @@ int main(int argc, char** argv)
print_usage();
return EXIT_FAILURE;
}
#ifdef HAVE_ICU
if (!unicode_mode.empty()) {
if (unicode_mode == "utf8") {
IfcParse::IfcCharacterDecoder::mode = IfcParse::IfcCharacterDecoder::UTF8;
} else if (unicode_mode == "escape") {
IfcParse::IfcCharacterDecoder::mode = IfcParse::IfcCharacterDecoder::JSON;
} else {
std::cerr << "[Error] Invalid value for --unicode" << std::endl;
print_options(serializer_options);
return 1;
}
}
#endif
boost::optional<double> bounding_width;
boost::optional<double> bounding_height;
if (vmap.count("bounds") == 1) {
int w, h;
if (sscanf(bounds.c_str(), "%ux%u", &w, &h) == 2 && w > 0 && h > 0) {
bounding_width = w;
bounding_height = h;
} else {
std::cerr << "[Error] Invalid use of --bounds" << std::endl;
print_options(serializer_options);
return EXIT_FAILURE;
}
}
const std::string input_filename = vmap["input-file"].as<std::string>();
if (!file_exists(input_filename)) {
std::cerr << "[Error] Input file '" << input_filename << "' does not exist" << std::endl;
return EXIT_FAILURE;
}
// If no output filename is specified a Wavefront OBJ file will be output
// to maintain backwards compatibility with the obsolete IfcObj executable.
const std::string output_filename = vmap.count("output-file") == 1
? vmap["output-file"].as<std::string>()
: change_extension(input_filename, DEFAULT_EXTENSION);
if (output_filename.size() < 5) {
std::cerr << "[Error] Invalid or unsupported output file '" << output_filename << "' given" << std::endl;
print_usage();
return EXIT_FAILURE;
}
if (file_exists(output_filename) && !vmap.count("yes")) {
std::string answer;
std::cout << "A file '" << output_filename << "' already exists. Overwrite the existing file?" << std::endl;
std::cin >> answer;
if (!boost::iequals(answer, "yes") && !boost::iequals(answer, "y")) {
return EXIT_SUCCESS;
}
}
std::string output_temp_filename = output_filename + TEMP_FILE_EXTENSION;
std::string output_extension = output_filename.substr(output_filename.size()-4);
boost::to_lower(output_extension);
Logger::SetOutput(&std::cout, &log_stream);
Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR);
if (vmap.count("log-format") == 1) {
boost::to_lower(log_format);
if (log_format == "plain") {
@@ -469,20 +442,116 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
}
if (!filter_filename.empty()) {
size_t num_filters = read_filters_from_file(IfcUtil::path::to_utf8(filter_filename), include_filter, include_traverse_filter, exclude_filter, exclude_traverse_filter);
if (num_filters) {
Logger::Notice(boost::lexical_cast<std::string>(num_filters) + " filters read from specifified file.");
} else {
std::cerr << "[Error] No filters read from specifified file.\n";
return EXIT_FAILURE;
}
}
#ifdef HAVE_ICU
if (!unicode_mode.empty()) {
if (unicode_mode == "utf8") {
IfcParse::IfcCharacterDecoder::mode = IfcParse::IfcCharacterDecoder::UTF8;
} else if (unicode_mode == "escape") {
IfcParse::IfcCharacterDecoder::mode = IfcParse::IfcCharacterDecoder::JSON;
} else {
cerr_ << "[Error] Invalid value for --unicode" << std::endl;
print_options(serializer_options);
return 1;
}
}
#endif
if (!default_material_filename.empty()) {
try {
IfcGeom::set_default_style_file(IfcUtil::path::to_utf8(default_material_filename));
} catch (const std::exception& e) {
std::cerr << "[Error] Could not read default material file:" << std::endl;
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
}
boost::optional<double> bounding_width;
boost::optional<double> bounding_height;
if (vmap.count("bounds") == 1) {
int w, h;
if (sscanf(bounds.c_str(), "%ux%u", &w, &h) == 2 && w > 0 && h > 0) {
bounding_width = w;
bounding_height = h;
} else {
cerr_ << "[Error] Invalid use of --bounds" << std::endl;
print_options(serializer_options);
return EXIT_FAILURE;
}
}
const path_t input_filename = vmap["input-file"].as<path_t>();
if (!file_exists(IfcUtil::path::to_utf8(input_filename))) {
cerr_ << "[Error] Input file '" << input_filename << "' does not exist" << std::endl;
return EXIT_FAILURE;
}
// If no output filename is specified a Wavefront OBJ file will be output
// to maintain backwards compatibility with the obsolete IfcObj executable.
const path_t output_filename = vmap.count("output-file") == 1
? vmap["output-file"].as<path_t>()
: change_extension(input_filename, IfcUtil::path::from_utf8(DEFAULT_EXTENSION));
if (output_filename.size() < 5) {
cerr_ << "[Error] Invalid or unsupported output file '" << output_filename << "' given" << std::endl;
print_usage();
return EXIT_FAILURE;
}
if (file_exists(IfcUtil::path::to_utf8(output_filename)) && !vmap.count("yes")) {
std::string answer;
cout_ << "A file '" << output_filename << "' already exists. Overwrite the existing file?" << std::endl;
std::cin >> answer;
if (!boost::iequals(answer, "yes") && !boost::iequals(answer, "y")) {
return EXIT_SUCCESS;
}
}
Logger::SetOutput(&cout_, &log_stream);
Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR);
path_t output_temp_filename = output_filename + IfcUtil::path::from_utf8(TEMP_FILE_EXTENSION);
path_t output_extension = output_filename.substr(output_filename.size()-4);
boost::to_lower(output_extension);
IfcParse::IfcFile* ifc_file = 0;
const path_t OBJ = IfcUtil::path::from_utf8(".obj"),
MTL = IfcUtil::path::from_utf8(".mtl"),
DAE = IfcUtil::path::from_utf8(".dae"),
STP = IfcUtil::path::from_utf8(".stp"),
IGS = IfcUtil::path::from_utf8(".igs"),
SVG = IfcUtil::path::from_utf8(".svg"),
XML = IfcUtil::path::from_utf8(".xml"),
IFC = IfcUtil::path::from_utf8(".ifc");
// @todo clean up serializer selection
// @todo detect program options that conflict with the chosen serializer
if (output_extension == ".xml") {
if (output_extension == XML) {
int exit_code = EXIT_FAILURE;
try {
if (init_input_file(input_filename, ifc_file, no_progress || quiet, mmap)) {
XmlSerializer s(ifc_file, output_temp_filename);
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
time_t start, end;
time(&start);
XmlSerializer s(ifc_file, IfcUtil::path::to_utf8(output_temp_filename));
Logger::Status("Writing XML output...");
s.finalize();
Logger::Status("Done!");
rename_file(output_temp_filename, output_filename);
time(&end);
Logger::Status("Done! Conversion took " + format_duration(start, end));
IfcUtil::path::rename_file(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(output_filename));
exit_code = EXIT_SUCCESS;
}
} catch (const std::exception& e) {
@@ -490,10 +559,12 @@ int main(int argc, char** argv)
}
write_log(!quiet);
return exit_code;
} else if (output_extension == ".ifc") {
} else if (output_extension == IFC) {
int exit_code = EXIT_FAILURE;
try {
if (init_input_file(input_filename, ifc_file, no_progress || quiet, mmap)) {
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
time_t start, end;
time(&start);
std::ofstream fs(output_filename.c_str());
if (fs.is_open()) {
if (vmap.count("calculate-quantities")) {
@@ -504,6 +575,8 @@ int main(int argc, char** argv)
} else {
Logger::Error("Unable to open output file for writing");
}
time(&end);
Logger::Status("Done! Writing IFC took " + format_duration(start, end));
}
} catch (const std::exception& e) {
Logger::Error(e);
@@ -512,27 +585,6 @@ int main(int argc, char** argv)
return exit_code;
}
if (!filter_filename.empty()) {
size_t num_filters = read_filters_from_file(filter_filename, include_filter, include_traverse_filter, exclude_filter, exclude_traverse_filter);
if (num_filters) {
Logger::Notice(boost::lexical_cast<std::string>(num_filters) + " filters read from '" + filter_filename + "'.");
} else {
std::cerr << "[Error] No filters read from '" + filter_filename + "'.\n";
return EXIT_FAILURE;
}
}
if (!default_material_filename.empty()) {
try {
IfcGeom::set_default_style_file(default_material_filename);
} catch (const std::exception& e) {
std::cerr << "[Error] Could not read default material file " << default_material_filename << ":" << std::endl;
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
}
/// @todo Clean up this filter code further.
std::vector<geom_filter> used_filters;
if (include_filter.type != geom_filter::UNUSED) { used_filters.push_back(include_filter); }
@@ -540,16 +592,30 @@ int main(int argc, char** argv)
if (exclude_filter.type != geom_filter::UNUSED) { used_filters.push_back(exclude_filter); }
if (exclude_traverse_filter.type != geom_filter::UNUSED) { used_filters.push_back(exclude_traverse_filter); }
std::vector<IfcGeom::filter_t> filter_funcs = setup_filters(used_filters, output_extension);
std::vector<IfcGeom::filter_t> filter_funcs = setup_filters(used_filters, IfcUtil::path::to_utf8(output_extension));
if (filter_funcs.empty()) {
std::cerr << "[Error] Failed to set up geometry filters\n";
cerr_ << "[Error] Failed to set up geometry filters\n";
return EXIT_FAILURE;
}
if (!entity_filter.entity_names.empty()) { entity_filter.update_description(); Logger::Notice(entity_filter.description); }
if (!layer_filter.values.empty()) { layer_filter.update_description(); Logger::Notice(layer_filter.description); }
if (!attribute_filter.attribute_name.empty()) { attribute_filter.update_description(); Logger::Notice(layer_filter.description); }
#ifdef _MSC_VER
if (output_extension == DAE || output_extension == STP || output_extension == IGS) {
// These serializers do not support opening unicode paths on Windows. Therefore
// a random temp file is generated using only ASCII characters instead.
std::random_device rng;
std::uniform_int_distribution<int> index_dist(L'A', L'Z');
output_temp_filename = L".ifcopenshell.";
for (int i = 0; i < 8; ++i) {
output_temp_filename.push_back(static_cast<wchar_t>(index_dist(rng)));
}
output_temp_filename += L".tmp";
}
#endif
SerializerSettings settings;
/// @todo Make APPLY_DEFAULT_MATERIALS configurable? Quickly tested setting this to false and using obj exporter caused the program to crash and burn.
settings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, true);
@@ -579,29 +645,29 @@ int main(int argc, char** argv)
settings.precision = precision;
boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */
if (output_extension == ".obj") {
if (output_extension == OBJ) {
// Do not use temp file for MTL as it's such a small file.
const std::string mtl_filename = change_extension(output_filename, "mtl");
const path_t mtl_filename = change_extension(output_filename, MTL);
if (!use_world_coords) {
Logger::Notice("Using world coords when writing WaveFront OBJ files");
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
}
serializer = boost::make_shared<WaveFrontOBJSerializer>(output_temp_filename, mtl_filename, settings);
serializer = boost::make_shared<WaveFrontOBJSerializer>(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(mtl_filename), settings);
#ifdef WITH_OPENCOLLADA
} else if (output_extension == ".dae") {
serializer = boost::make_shared<ColladaSerializer>(output_temp_filename, settings);
} else if (output_extension == DAE) {
serializer = boost::make_shared<ColladaSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
#endif
} else if (output_extension == ".stp") {
serializer = boost::make_shared<StepSerializer>(output_temp_filename, settings);
} else if (output_extension == ".igs") {
} else if (output_extension == STP) {
serializer = boost::make_shared<StepSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
} else if (output_extension == IGS) {
#if OCC_VERSION_HEX < 0x60900
// According to https://tracker.dev.opencascade.org/view.php?id=25689 something has been fixed in 6.9.0
IGESControl_Controller::Init(); // work around Open Cascade bug
#endif
serializer = boost::make_shared<IgesSerializer>(output_temp_filename, settings);
} else if (output_extension == ".svg") {
serializer = boost::make_shared<IgesSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
} else if (output_extension == SVG) {
settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true);
serializer = boost::make_shared<SvgSerializer>(output_temp_filename, settings);
serializer = boost::make_shared<SvgSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
if (vmap.count("section-height") != 0) {
Logger::Notice("Overriding section height");
static_cast<SvgSerializer*>(serializer.get())->setSectionHeight(section_height);
@@ -610,18 +676,18 @@ int main(int argc, char** argv)
static_cast<SvgSerializer*>(serializer.get())->setBoundingRectangle(bounding_width.get(), bounding_height.get());
}
} else {
std::cerr << "[Error] Unknown output filename extension '" + output_extension + "'\n";
cerr_ << "[Error] Unknown output filename extension '" << output_extension << "'\n";
write_log(!quiet);
print_usage();
return EXIT_FAILURE;
}
if (use_element_hierarchy && output_extension != ".dae") {
std::cerr << "[Error] --use-element-hierarchy can be used only with .dae output.\n";
if (use_element_hierarchy && output_extension != DAE) {
cerr_ << "[Error] --use-element-hierarchy can be used only with .dae output.\n";
/// @todo Lots of duplicate error-and-exit code.
write_log(!quiet);
print_usage();
std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
return EXIT_FAILURE;
}
@@ -641,7 +707,7 @@ int main(int argc, char** argv)
}
if (!serializer->ready()) {
std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
write_log(!quiet);
return EXIT_FAILURE;
}
@@ -649,9 +715,9 @@ int main(int argc, char** argv)
time_t start,end;
time(&start);
if (!init_input_file(input_filename, ifc_file, no_progress || quiet, mmap)) {
if (!init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
write_log(!quiet);
std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename)); /**< @todo Windows Unicode support */
return EXIT_FAILURE;
}
@@ -660,7 +726,7 @@ int main(int argc, char** argv)
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
/// and for a case we found no entities that satisfy our filtering criteria.
Logger::Notice("No geometrical elements found or none succesfully converted");
std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
write_log(!quiet);
return EXIT_FAILURE;
}
@@ -695,8 +761,8 @@ int main(int argc, char** argv)
offset[2] = -center.Z();
} else {
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
std::cerr << "[Error] Invalid use of --model-offset\n";
std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */
cerr_ << "[Error] Invalid use of --model-offset\n";
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
print_options(serializer_options);
return EXIT_FAILURE;
}
@@ -774,10 +840,10 @@ int main(int argc, char** argv)
// Renaming might fail (e.g. maybe the existing file was open in a viewer application)
// Do not remove the temp file as user can salvage the conversion result from it.
bool successful = rename_file(output_temp_filename, output_filename);
bool successful = IfcUtil::path::rename_file(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(output_filename));
if (!successful) {
Logger::Error("Unable to write output file '" + output_filename + "', see '" +
output_temp_filename + "' for the conversion result.");
cerr_ << "Unable to write output file '" << output_filename << "', see '" <<
output_temp_filename << "' for the conversion result.";
}
if (validate && Logger::MaxSeverity() >= Logger::LOG_ERROR) {
@@ -789,45 +855,52 @@ int main(int argc, char** argv)
time(&end);
if (!quiet) {
int seconds = (int)difftime(end, start);
std::stringstream msg;
int minutes = seconds / 60;
seconds = seconds % 60;
msg << "\nConversion took";
if (minutes > 0) {
msg << " " << minutes << " minute";
if (minutes > 1) {
msg << "s";
}
}
msg << " " << seconds << " second";
if (seconds > 1) {
msg << "s";
}
Logger::Status(msg.str());
}
if (!quiet) {
Logger::Status("\nConversion took " + format_duration(start, end));
}
return successful ? EXIT_SUCCESS : EXIT_FAILURE;
}
std::string format_duration(time_t start, time_t end)
{
int seconds = (int)difftime(end, start);
std::stringstream ss;
int minutes = seconds / 60;
seconds = seconds % 60;
if (minutes > 0) {
ss << minutes << " minute";
if (minutes == 0 || minutes > 1) {
ss << "s";
}
ss << " ";
}
ss << seconds << " second";
if (seconds == 0 || seconds > 1) {
ss << "s";
}
return ss.str();
}
void write_log(bool header) {
std::string log = log_stream.str();
path_t log = log_stream.str();
if (!log.empty()) {
if (header) {
std::cout << "\nLog:\n";
}
std::cout << log << std::endl;
if (header) {
cout_ << "\nLog:\n";
}
cout_ << log << std::endl;
}
}
#include <boost/algorithm/string/predicate.hpp>
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap) {
time_t start, end;
// Prevent IfcFile::Init() prints by setting output to null temporarily
if (no_progress) { Logger::SetOutput(NULL, &log_stream); }
time(&start);
#ifdef USE_MMAP
ifc_file = new IfcParse::IfcFile(filename, mmap);
#else
@@ -844,8 +917,10 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file,
Logger::Error("Unable to parse input file '" + filename + "'");
return false;
}
time(&end);
if (no_progress) { Logger::SetOutput(&std::cout, &log_stream); }
if (no_progress) { Logger::SetOutput(&cout_, &log_stream); }
else { Logger::Status("Parsing input file took " + format_duration(start, end)); }
return true;
@@ -857,7 +932,7 @@ bool append_filter(const std::string& type, const std::vector<std::string>& valu
parse_filter(temp, values);
// Merge values only if type and arg match.
if ((filter.type != geom_filter::UNUSED && filter.type != temp.type) || (!filter.arg.empty() && filter.arg != temp.arg)) {
std::cerr << "[Error] Multiple '" << type << "' filters specified with different criteria\n";
cerr_ << "[Error] Multiple '" << type.c_str() << "' filters specified with different criteria\n";
return false;
}
filter.type = temp.type;
@@ -873,9 +948,10 @@ size_t read_filters_from_file(
exclusion_filter& exclude_filter,
exclusion_traverse_filter& exclude_traverse_filter)
{
std::ifstream filter_file(filename.c_str());
std::ifstream filter_file(IfcUtil::path::from_utf8(filename).c_str());
if (!filter_file.is_open()) {
std::cerr << "[Error] Unable to open filter file '" + filename + "' or the file does not exist.\n";
cerr_ << "[Error] Unable to open filter file '" << IfcUtil::path::from_utf8(filename) << "' or the file does not exist.\n";
return 0;
}
@@ -910,11 +986,11 @@ size_t read_filters_from_file(
else if (type == "exclude") { if (append_filter("exclude", values, exclude_filter)) { ++num_filters; } }
else if (type == "exclude+") { if (append_filter("exclude+", values, exclude_traverse_filter)) { ++num_filters; } }
else {
std::cerr << "[Error] Invalid filtering type at line " + boost::lexical_cast<std::string>(line_number) + "\n";
cerr_ << "[Error] Invalid filtering type at line " << boost::lexical_cast<path_t>(line_number) << "\n";
return 0;
}
} catch(...) {
std::cerr << "[Error] Unable to parse filter at line " + boost::lexical_cast<std::string>(line_number) + ".\n";
cerr_ << "[Error] Unable to parse filter at line " << boost::lexical_cast<path_t>(line_number) << ".\n";
return 0;
}
}
+2
View File
@@ -122,6 +122,7 @@ actions = {
'select_type' : "lambda t: SelectType(t)",
'binary_type' : "lambda t: BinaryType(t)",
'subtype_declaration' : "lambda t: SubTypeExpression(t)",
'supertype_constraint' : "lambda t: SuperTypeExpression(t)",
'derive_clause' : "lambda t: AttributeList('derive', t)",
'derived_attr' : "lambda t: DerivedAttribute(t)",
'inverse_clause' : "lambda t: AttributeList('inverse', t)",
@@ -178,6 +179,7 @@ cache_file = sys.argv[1] + ".cache.dat"
if os.path.exists(cache_file):
with open(cache_file, "rb") as f:
mapping = pickle.load(f)
schema = mapping.schema
else:
from pyparsing import *
from nodes import *
+23 -6
View File
@@ -23,6 +23,8 @@ import nodes
import codegen
import templates
from collections import defaultdict
class SchemaClass(codegen.Base):
def __init__(self, mapping):
@@ -109,7 +111,8 @@ __attribute__((optnone))
try:
declared_type = get_declared_type(type, emitted)
except UnmetDependenciesException:
print("Unmet", repr(name))
# @todo?
# print("Unmet", repr(name))
return False
statements.append(' %(schema_name)s_%(name)s_type = new type_declaration("%(name)s", %%(index_in_schema_%(name)s)d, %(declared_type)s);' % locals())
@@ -124,7 +127,8 @@ __attribute__((optnone))
def write_entity(schema_name, name, type):
if len(type.supertypes) == 0 or set(map(lambda s: s.lower(), type.supertypes)) < emitted:
supertype = '0' if len(type.supertypes) == 0 else '%s_%s_type' % (schema_name, type.supertypes[0])
statements.append(' %(schema_name)s_%(name)s_type = new entity("%(name)s", %%(index_in_schema_%(name)s)d, %(supertype)s);' % locals())
is_abstract = "true" if type.abstract else "false"
statements.append(' %(schema_name)s_%(name)s_type = new entity("%(name)s", %(is_abstract)s, %%(index_in_schema_%(name)s)d, %(supertype)s);' % locals())
else: return False
def write_select(schema_name, name, type):
@@ -166,11 +170,11 @@ __attribute__((optnone))
attribute_names = list(map(operator.attrgetter('name'), mapping.arguments(type)))
statements.append(' {')
statements.append(' std::vector<const entity::attribute*> attributes; attributes.reserve(%d);' % len(type.attributes))
statements.append(' std::vector<const attribute*> attributes; attributes.reserve(%d);' % len(type.attributes))
for attr in type.attributes:
attr_name, optional = attr.name, str(attr.optional).lower()
decl_type = get_declared_type(attr.type)
statements.append(' attributes.push_back(new entity::attribute("%(attr_name)s", %(decl_type)s, %(optional)s));' % locals())
statements.append(' attributes.push_back(new attribute("%(attr_name)s", %(decl_type)s, %(optional)s));' % locals())
statements.append(' std::vector<bool> derived; derived.reserve(%d);' % len(attribute_names))
statements.append(' ' + " ".join(map(lambda b: 'derived.push_back(%s);' % str(b in derived).lower(), attribute_names)))
statements.append(' %(schema_name)s_%(name)s_type->set_attributes(attributes, derived);' % locals())
@@ -179,7 +183,7 @@ __attribute__((optnone))
for name, type in mapping.schema.entities.items():
if type.inverse:
statements.append(' {')
statements.append(' std::vector<const entity::inverse_attribute*> attributes; attributes.reserve(%d);' % len(type.inverse.elements))
statements.append(' std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);' % len(type.inverse.elements))
for attr in type.inverse.elements:
if attr.bounds:
make_bound = lambda b: -1 if b == '?' else int(b)
@@ -189,9 +193,22 @@ __attribute__((optnone))
attr_name, aggr_type, entity_ref = attr.name, attr.type, attr.entity
if aggr_type is None: aggr_type = 'unspecified'
attribute_entity, attribute_entity_index = find_inverse_name_and_index(entity_ref, attr.attribute)
statements.append(' attributes.push_back(new entity::inverse_attribute("%(attr_name)s", entity::inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(schema_name)s_%(entity_ref)s_type, %(schema_name)s_%(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));' % locals())
statements.append(' attributes.push_back(new inverse_attribute("%(attr_name)s", inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(schema_name)s_%(entity_ref)s_type, %(schema_name)s_%(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));' % locals())
statements.append(' %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);' % locals())
statements.append(' }')
subtypes = defaultdict(list)
for name, type in mapping.schema.entities.items():
for ty in type.supertypes:
subtypes[ty].append(name)
for name, tys in subtypes.items():
statements.append(' {')
statements.append(' std::vector<const entity*> defs; defs.reserve(%d);' % len(tys))
statements.append((' ' + "".join(map(lambda t: ("defs.push_back(%%(schema_name)s_%s_type);" % t), tys))) % locals())
statements.append(' %(schema_name)s_%(name)s_type->set_subtypes(defs);' % locals())
statements.append(' }')
statements.append('')
statements.append(' std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);' % locals())
+6 -1
View File
@@ -126,6 +126,7 @@ private:
std::map<int, int> vertex_mapping_;
std::map<std::pair<int, int>, TopoDS_Edge> edges_;
double eps_;
bool non_manifold_;
template <typename Fn>
void loop_(IfcSchema::IfcCartesianPoint::list::ptr& ps, const Fn& callback) {
@@ -153,6 +154,9 @@ private:
~faceset_helper();
bool non_manifold() const { return non_manifold_; }
bool& non_manifold() { return non_manifold_; }
bool edge(const IfcSchema::IfcCartesianPoint* a, const IfcSchema::IfcCartesianPoint* b, TopoDS_Edge& e) {
int A = vertex_mapping_[a->data().id()];
int B = vertex_mapping_[b->data().id()];
@@ -194,6 +198,7 @@ private:
if (kernel_->wire_intersections(wire, results)) {
Logger::Warning("Self-intersections with " + boost::lexical_cast<std::string>(results.Extent()) + " cycles detected", loop);
kernel_->select_largest(results, wire);
non_manifold_ = true;
}
return true;
@@ -295,7 +300,7 @@ public:
void remove_collinear_points_from_loop(TColgp_SequenceOfPnt& polygon, bool closed, double tol=-1.);
bool wire_to_sequence_of_point(const TopoDS_Wire&, TColgp_SequenceOfPnt&);
void sequence_of_point_to_wire(const TColgp_SequenceOfPnt&, TopoDS_Wire&, bool closed);
bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&);
bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&, double eps=-1.);
bool flatten_wire(TopoDS_Wire&);
bool triangulate_wire(const TopoDS_Wire&, TopTools_ListOfShape&);
bool wire_intersections(const TopoDS_Wire & wire, TopTools_ListOfShape & wires);
@@ -95,6 +95,8 @@
#include <TopTools_DataMapOfShapeInteger.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <BRepLib_FindSurface.hxx>
#ifdef USE_IFC4
#include <Geom_BSplineSurface.hxx>
#include <TColgp_Array2OfPnt.hxx>
@@ -212,8 +214,6 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
for (; exp.More(); exp.Next(), count++) {
if (count < 2) {
edges[count] = TopoDS::Edge(exp.Current());
} else {
break;
}
}
@@ -258,22 +258,19 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
// @todo is this still relevant considering the code above
mf = new BRepBuilderAPI_MakeFace(pln, wire, true);
} else {
mf = new BRepBuilderAPI_MakeFace(wire);
BRepLib_FindSurface fs(wire, getValue(GV_PRECISION), true, true);
if (fs.Found()) {
mf = new BRepBuilderAPI_MakeFace(fs.Surface(), wire);
ShapeFix_ShapeTolerance ftol;
ftol.SetTolerance(wire, fs.ToleranceReached(), TopAbs_WIRE);
}
}
} else {
/// @todo check necessity of false here
mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false);
}
mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false);
}
/* BRepBuilderAPI_FaceError er = mf->Error();
if (er == BRepBuilderAPI_NotPlanar) {
ShapeFix_ShapeTolerance FTol;
FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
delete mf;
mf = new BRepBuilderAPI_MakeFace(wire);
} */
if (mf->IsDone()) {
if (mf && mf->IsDone()) {
TopoDS_Face outer_face_bound = mf->Face();
// In case of (non-planar) face surface, p-curves need to be computed.
@@ -315,11 +312,12 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
success = true;
}
} else {
const bool non_planar = mf->Error() == BRepBuilderAPI_NotPlanar;
// if mf == nullptr, it means we failed to find a surface earlier using BRepLib_FindSurface
const bool non_planar = mf == nullptr || mf->Error() == BRepBuilderAPI_NotPlanar;
delete mf;
if (non_planar && bounds->size() == 1 && face_surface.IsNull()) {
Logger::Message(Logger::LOG_ERROR, "Triangulating face boundary", bound);
Logger::Message(Logger::LOG_WARNING, "Triangulating face boundary", bound);
// When creating a solid, flatting the boundary only postpones the issue to
// creating a topological manifold out of the individual faces.
@@ -101,12 +101,15 @@
#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Solid.hxx>
#include <ShapeFix_Shell.hxx>
#include <ShapeAnalysis_Curve.hxx>
#include <ShapeAnalysis_Wire.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include <ShapeAnalysis_ShapeTolerance.hxx>
#include <ShapeUpgrade_UnifySameDomain.hxx>
#include <BRepFilletAPI_MakeFillet2d.hxx>
#include <TopLoc_Location.hxx>
@@ -139,6 +142,7 @@
#include <GCPnts_AbscissaPoint.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <GeomAPI_ExtremaCurveCurve.hxx>
@@ -313,6 +317,124 @@ namespace {
return M;
}
class points_on_planar_face_generator {
private:
const TopoDS_Face& f_;
Handle(Geom_Surface) plane_;
BRepTopAdaptor_FClass2d cls_;
double u0, u1, v0, v1;
int i, j;
static const int N = 10;
public:
points_on_planar_face_generator(const TopoDS_Face& f)
: f_(f)
, plane_(BRep_Tool::Surface(f_))
, cls_(f_, BRep_Tool::Tolerance(f_))
, i(0), j(0)
{
BRepTools::UVBounds(f_, u0, u1, v0, v1);
}
void reset() {
i = j = 0;
}
bool operator()(gp_Pnt& p) {
while (j < N) {
double u = u0 + (u1 - u0) * i / N;
double v = v0 + (v1 - v0) * j / N;
i++;
if (i == N) {
i = 0;
j++;
}
// Specifically does not consider ON
if (cls_.Perform(gp_Pnt2d(u, v)) == TopAbs_IN) {
plane_->D0(u, v, p);
return true;
}
}
return false;
}
};
double min_face_face_distance(const TopoDS_Shape& a, double max_search) {
/*
NB: This is currently only implemented for planar surfaces.
*/
double M = std::numeric_limits<double>::infinity();
TopTools_IndexedMapOfShape faces;
TopExp::MapShapes(a, TopAbs_FACE, faces);
IfcGeom::impl::tree<int> tree;
// Add edges to tree
for (int i = 1; i <= faces.Extent(); ++i) {
if (BRep_Tool::Surface(TopoDS::Face(faces(i)))->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
tree.add(i, faces(i));
}
}
for (int j = 1; j <= faces.Extent(); ++j) {
const TopoDS_Face& f = TopoDS::Face(faces(j));
const Handle(Geom_Surface)& fs = BRep_Tool::Surface(f);
if (fs->DynamicType() != STANDARD_TYPE(Geom_Plane)) {
continue;
}
points_on_planar_face_generator pgen(f);
Bnd_Box b;
BRepBndLib::AddClose(f, b);
b.Enlarge(max_search);
std::vector<int> edge_idxs = tree.select_box(b, false);
std::vector<int>::const_iterator it = edge_idxs.begin();
for (; it != edge_idxs.end(); ++it) {
if (*it == j) {
continue;
}
const TopoDS_Face& g = TopoDS::Face(faces(*it));
const Handle(Geom_Surface)& gs = BRep_Tool::Surface(g);
auto p0 = Handle(Geom_Plane)::DownCast(fs);
auto p1 = Handle(Geom_Plane)::DownCast(gs);
if (p0->Position().IsCoplanar(p1->Position(), max_search, asin(max_search))) {
pgen.reset();
BRepTopAdaptor_FClass2d cls(g, BRep_Tool::Tolerance(g));
gp_Pnt test;
while (pgen(test)) {
gp_Vec d = test.XYZ() - p1->Position().Location().XYZ();
double u = d.Dot(p1->Position().XDirection());
double v = d.Dot(p1->Position().YDirection());
if (cls.Perform(gp_Pnt2d(u, v)) == TopAbs_IN) {
gp_Pnt test2;
p1->D0(u, v, test2);
double w = gp_Vec(p1->Position().Direction().XYZ()).Dot(test2.XYZ() - test.XYZ());
if (w < M) {
M = w;
}
}
}
}
}
}
return M;
}
void bounding_box_overlap(double p, const TopoDS_Shape& a, const TopTools_ListOfShape& b, TopTools_ListOfShape& c) {
Bnd_Box A;
BRepBndLib::Add(a, A);
@@ -335,6 +457,17 @@ namespace {
}
}
}
#ifdef UNIFY_OPERANDS
TopoDS_Shape unify(const TopoDS_Shape& s) {
ShapeUpgrade_UnifySameDomain usd(s);
usd.SetLinearTolerance(Precision::Confusion() * 10.);
usd.SetAngularTolerance(Precision::Angular() * 10.);
usd.Build();
return usd.Shape();
}
#endif
}
namespace {
@@ -375,32 +508,71 @@ bool IfcGeom::Kernel::create_solid_from_faces(const TopTools_ListOfShape& face_l
return false;
}
TopTools_ListIteratorOfListOfShape face_iterator;
TopTools_ListIteratorOfListOfShape face_iterator;
BRepOffsetAPI_Sewing builder;
builder.SetTolerance(getValue(GV_PRECISION));
builder.SetMaxTolerance(getValue(GV_PRECISION));
builder.SetMinTolerance(getValue(GV_PRECISION));
bool has_shared_edges = false;
TopTools_MapOfShape edge_set;
// In case there are wire interesections or failures in non-planar wire triangulations
// the idea is to let occt do an exhaustive search of edge partners. But we have not
// found a case where this actually improves boolean ops later on.
// if (!faceset_helper_ || !faceset_helper_->non_manifold()) {
for (face_iterator.Initialize(face_list); face_iterator.More(); face_iterator.Next()) {
builder.Add(face_iterator.Value());
// As soon as is detected one of the edges is shared, the assumption is made no
// additional sewing is necessary.
if (!has_shared_edges) {
TopExp_Explorer exp(face_iterator.Value(), TopAbs_EDGE);
for (; exp.More(); exp.Next()) {
if (edge_set.Contains(exp.Current())) {
has_shared_edges = true;
break;
}
edge_set.Add(exp.Current());
}
}
}
BRepOffsetAPI_Sewing sewing_builder;
sewing_builder.SetTolerance(getValue(GV_PRECISION));
sewing_builder.SetMaxTolerance(getValue(GV_PRECISION));
sewing_builder.SetMinTolerance(getValue(GV_PRECISION));
BRep_Builder builder;
TopoDS_Shell shell;
builder.MakeShell(shell);
for (face_iterator.Initialize(face_list); face_iterator.More(); face_iterator.Next()) {
if (has_shared_edges) {
builder.Add(shell, face_iterator.Value());
} else {
sewing_builder.Add(face_iterator.Value());
}
}
try {
builder.Perform();
shape = builder.SewedShape();
if (has_shared_edges) {
ShapeFix_Shell fix;
fix.FixFaceOrientation(shell);
shape = fix.Shape();
} else {
sewing_builder.Perform();
shape = sewing_builder.SewedShape();
}
BRepCheck_Analyzer ana(shape);
valid_shell = ana.IsValid();
{
BRepCheck_Analyzer ana(shape);
if (!ana.IsValid()) {
ShapeFix_Shape sfs(shape);
sfs.Perform();
shape = sfs.Shape();
}
if (!valid_shell) {
ShapeFix_Shape sfs(shape);
sfs.Perform();
shape = sfs.Shape();
BRepCheck_Analyzer reana(shape);
valid_shell = reana.IsValid();
}
BRepCheck_Analyzer ana(shape);
valid_shell = ana.IsValid() != 0 && count_occt(shape, TopAbs_SHELL) > 0;
valid_shell &= count_occt(shape, TopAbs_SHELL) > 0;
} catch (const Standard_Failure& e) {
if (e.GetMessageString() && strlen(e.GetMessageString())) {
Logger::Error(e.GetMessageString());
@@ -2276,12 +2448,15 @@ bool IfcGeom::Kernel::is_identity_transform(const IfcUtil::IfcBaseClass* l) {
}
}
bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp_Pln& plane) {
bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp_Pln& plane, double eps) {
// Newell's Method is used for the normal calculation
// as a simple edge cross product can give opposite results
// for a concave face boundary.
// Reference: Graphics Gems III p. 231
const double eps_ = eps < 1. ? getValue(GV_PRECISION) : eps;
const double eps2 = eps_ * eps_;
double x = 0, y = 0, z = 0;
gp_Pnt current, previous, first;
gp_XYZ center;
@@ -2321,8 +2496,18 @@ bool IfcGeom::Kernel::approximate_plane_through_wire(const TopoDS_Wire& wire, gp
if (n < 3) {
return false;
}
plane = gp_Pln(center / n, gp_Dir(x, y, z));
exp.Init(wire);
for (; exp.More(); exp.Next()) {
const TopoDS_Vertex& v = exp.CurrentVertex();
current = BRep_Tool::Pnt(v);
if (plane.SquareDistance(current) > eps2) {
return false;
}
}
return true;
}
@@ -2355,12 +2540,16 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS
// alternatively we use the regular OCCT incremental mesher on a new face
// created from the UV coordinates of the original wire. Pray to our gods
// that the vertex coordinates are unaffected by the meshing algorithm and
// map them back to 3d coordinates when iterating over the mesh triangles.
// map them back to 3d coordinates when iterating over the mesh triangles.
// In addition, to maintain a manifold shell, we need to make sure that
// every edge from the input wire is used exactly once in the list of
// resulting faces. And that other internal edges are used twice.
typedef std::pair<double, double> uv_node;
gp_Pln pln;
if (!approximate_plane_through_wire(wire, pln)) {
if (!approximate_plane_through_wire(wire, pln, std::numeric_limits<double>::infinity())) {
return false;
}
@@ -2370,15 +2559,35 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS
BRepTools_WireExplorer exp(wire);
BRepBuilderAPI_MakePolygon mp;
std::map<uv_node, gp_Pnt> mapping;
std::map<uv_node, TopoDS_Vertex> mapping;
std::map<std::pair<uv_node, uv_node>, TopoDS_Edge> existing_edges, new_edges;
// Add UV coordinates to a newly created polygon
for (; exp.More(); exp.Next()) {
gp_Pnt p = BRep_Tool::Pnt(exp.CurrentVertex());
// Project onto plane
const TopoDS_Vertex& V = exp.CurrentVertex();
gp_Pnt p = BRep_Tool::Pnt(V);
double u = (p.XYZ() - pnt).Dot(udir);
double v = (p.XYZ() - pnt).Dot(vdir);
mp.Add(gp_Pnt(u, v, 0));
mapping.insert(std::make_pair(std::make_pair(u, v), p));
mp.Add(gp_Pnt(u, v, 0.));
mapping.insert(std::make_pair(std::make_pair(u, v), V));
// Store existing edges in a map so that triangles can
// actually reference the preexisting edges.
const TopoDS_Edge& e = exp.Current();
TopoDS_Vertex V0, V1;
TopExp::Vertices(e, V0, V1, true);
gp_Pnt p0 = BRep_Tool::Pnt(V0);
gp_Pnt p1 = BRep_Tool::Pnt(V1);
double u0 = (p0.XYZ() - pnt).Dot(udir);
double v0 = (p0.XYZ() - pnt).Dot(vdir);
double u1 = (p1.XYZ() - pnt).Dot(udir);
double v1 = (p1.XYZ() - pnt).Dot(vdir);
uv_node uv0 = std::make_pair(u0, v0);
uv_node uv1 = std::make_pair(u1, v1);
existing_edges.insert(std::make_pair(std::make_pair(uv0, uv1), e));
existing_edges.insert(std::make_pair(std::make_pair(uv1, uv0), TopoDS::Edge(e.Reversed())));
}
// Not closed by default
@@ -2391,7 +2600,7 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS
int n123[3];
TopLoc_Location loc;
Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face, loc);
if (!tri.IsNull()) {
const TColgp_Array1OfPnt& nodes = tri->Nodes();
@@ -2402,20 +2611,49 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS
else triangles(i).Get(n123[0], n123[1], n123[2]);
// Create polygons from the mesh vertices
BRepBuilderAPI_MakePolygon mp2;
BRepBuilderAPI_MakeWire mp2;
for (int j = 0; j < 3; ++j) {
const gp_Pnt& uv = nodes.Value(n123[j]);
uv_node key = std::make_pair(uv.X(), uv.Y());
uv_node uvnodes[2];
TopoDS_Vertex vs[2];
if (mapping.find(key) == mapping.end()) {
Logger::Error("Internal error: unable to unproject uv-mesh");
return false;
for (int k = 0; k < 2; ++k) {
const gp_Pnt& uv = nodes.Value(n123[(j + k) % 3]);
uvnodes[k] = std::make_pair(uv.X(), uv.Y());
auto it = mapping.find(uvnodes[k]);
if (it == mapping.end()) {
Logger::Error("Internal error: unable to unproject uv-mesh");
return false;
}
vs[k] = it->second;
}
const gp_Pnt& p = mapping.find(key)->second;
mp2.Add(p);
auto it = existing_edges.find(std::make_pair(uvnodes[0], uvnodes[1]));
if (it != existing_edges.end()) {
// This is a boundary edge, reuse existing edge from wire
mp2.Add(it->second);
} else {
auto jt = new_edges.find(std::make_pair(uvnodes[0], uvnodes[1]));
if (jt != new_edges.end()) {
// We have already added the reverse as part of another
// triangle, reuse this edge.
mp2.Add(TopoDS::Edge(jt->second));
} else {
// This is a new internal edge. Register the reverse
// for reuse later. We need to be sure to reuse vertices
// for the edge construction because otherwise the wire
// builder will use geometrical proximity for vertex
// connections in which case the edge will be copied
// and no longer partner with other edges from the shell.
TopoDS_Edge ne = BRepBuilderAPI_MakeEdge(vs[0], vs[1]);
mp2.Add(ne);
// Store the reverse to be picked up later.
new_edges.insert(std::make_pair(std::make_pair(uvnodes[1], uvnodes[0]), TopoDS::Edge(ne.Reversed())));
}
}
}
mp2.Close();
BRepBuilderAPI_MakeFace mf(mp2.Wire());
if (mf.IsDone()) {
@@ -2428,6 +2666,42 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS
}
}
faces.Append(triangle_face);
} else {
Logger::Error("Internal error: missing face");
return false;
}
}
}
TopTools_IndexedDataMapOfShapeListOfShape mape, mapn;
TopExp::MapShapesAndAncestors(wire, TopAbs_EDGE, TopAbs_WIRE, mape);
TopTools_ListIteratorOfListOfShape it(faces);
for (; it.More(); it.Next()) {
TopExp::MapShapesAndAncestors(it.Value(), TopAbs_EDGE, TopAbs_WIRE, mapn);
}
// Validation
for (int i = 1; i <= mape.Extent(); ++i) {
TopTools_ListOfShape val;
if (!mapn.FindFromKey(mape.FindKey(i), val)) {
// All existing edges need to exist in the new faces
Logger::Error("Internal error, missing edge from triangulation");
if (faceset_helper_ != nullptr) {
faceset_helper_->non_manifold() = true;
}
}
}
for (int i = 1; i <= mapn.Extent(); ++i) {
const TopoDS_Shape& v = mapn.FindKey(i);
int n = mapn.FindFromIndex(i).Extent();
// Existing edges are boundaries with use 1
// New edges are internal with use 2
if (n != (mape.Contains(v) ? 1 : 2)) {
Logger::Error("Internal error, non-manifold result from triangulation");
if (faceset_helper_ != nullptr) {
faceset_helper_->non_manifold() = true;
}
}
}
@@ -2876,7 +3150,23 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopoDS_Shap
return succesful;
}
#else
bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_ListOfShape& b_, BOPAlgo_Operation op, TopoDS_Shape& result, double fuzziness) {
bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a_, const TopTools_ListOfShape& b__, BOPAlgo_Operation op, TopoDS_Shape& result, double fuzziness) {
#ifdef UNIFY_OPERANDS
TopoDS_Shape a = unify(a_);
TopTools_ListOfShape b_;
{
TopTools_ListIteratorOfListOfShape it(b__);
for (; it.More(); it.Next()) {
b_.Append(unify(it.Value()));
}
}
#else
const TopoDS_Shape& a = a_;
const TopTools_ListOfShape& b_ = b__;
#endif
bool success = false;
BRepAlgoAPI_BooleanOperation* builder;
TopTools_ListOfShape B, b;
@@ -2954,14 +3244,25 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li
// when there are edges or vertex-edge distances close to the used fuzziness, the
// output is not trusted and the operation is attempted with a higher fuzziness.
double min_lengh_result = (std::min)(min_edge_length(r), min_vertex_edge_distance(r, getValue(GV_PRECISION), fuzziness * 10.));
success = min_lengh_result <= min_length_orig || min_lengh_result > fuzziness * 10.;
int reason = 0;
double v;
if ((v = min_edge_length(r)) < fuzziness * 10.) {
reason = 0;
success = false;
} else if ((v = min_vertex_edge_distance(r, getValue(GV_PRECISION), fuzziness * 10.)) < fuzziness * 10.) {
reason = 1;
success = false;
} else if ((v = min_face_face_distance(r, fuzziness * 10.)) < fuzziness * 10.) {
reason = 2;
success = false;
}
if (success) {
result = r;
} else {
static const char* const reason_strings[] = { "edge length", "vertex-edge", "face-face" };
std::stringstream str;
str << "Boolean operation result failing interference check, with fuzziness " << fuzziness << " min length " << min_lengh_result << " originally " << min_length_orig;
str << "Boolean operation result failing " << reason_strings[reason] << " interference check, with fuzziness " << fuzziness << " with length " << v;
Logger::Notice(str.str());
}
} else {
@@ -2975,16 +3276,21 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li
#if OCC_VERSION_HEX >= 0x70000
builder->DumpErrors(str);
#else
str << "Error code :" << builder->ErrorStatus();
str << "Error code: " << builder->ErrorStatus();
#endif
Logger::Notice(str.str());
std::string str_str = str.str();
if (str_str.size()) {
Logger::Notice(str_str);
}
}
delete builder;
if (!success) {
const double new_fuzziness = fuzziness * 10.;
if (new_fuzziness + 1e-15 <= getValue(GV_PRECISION) * 1000. && new_fuzziness < min_length_orig) {
if (new_fuzziness - 1e-15 <= getValue(GV_PRECISION) * 10000. && new_fuzziness < min_length_orig) {
return boolean_operation(a, b, op, result, new_fuzziness);
}
} else {
Logger::Notice("No longer attempting boolean operation with higher fuzziness");
}
}
return success;
}
@@ -3024,6 +3330,7 @@ IfcGeom::Kernel::faceset_helper::~faceset_helper() {
IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema::IfcConnectedFaceSet* l)
: kernel_(kernel)
, non_manifold_(false)
{
kernel->faceset_helper_ = this;
@@ -3048,6 +3355,9 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema:
}
}
// Use the bbox diagonal to influence local epsilon
// double bdiff = std::sqrt(box.SquareExtent());
// Find the minimal bounding box edge
double bmin[3], bmax[3];
box.Get(bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2]);
@@ -3060,6 +3370,12 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema:
}
eps_ = kernel->getValue(GV_PRECISION) * 10. * (std::min)(1.0, bdiff);
if (eps_ < Precision::Confusion()) {
// occt uses some hard coded precision values, don't go smaller than that.
// @todo, can be reset though with BRepLib::Precision(double)
eps_ = Precision::Confusion();
}
std::map<std::pair<int, int>, int> edge_use;
@@ -163,15 +163,38 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcVector* l, gp_Vec& v) {
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement3D* l, gp_Trsf& trsf) {
IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf)
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection;
IfcGeom::Kernel::convert(l->Location(),o);
bool hasRef = l->hasRefDirection();
if ( l->hasAxis() ) IfcGeom::Kernel::convert(l->Axis(),axis);
if ( hasRef ) IfcGeom::Kernel::convert(l->RefDirection(),refDirection);
gp_Ax3 ax3;
if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection);
else ax3 = gp_Ax3(o,axis);
IN_CACHE(IfcAxis2Placement3D, l, gp_Trsf, trsf)
gp_Pnt o;
gp_Dir axis(0, 0, 1);
gp_Dir refDirection;
IfcGeom::Kernel::convert(l->Location(), o);
const bool hasAxis = l->hasAxis();
const bool hasRef = l->hasRefDirection();
if (hasAxis != hasRef) {
Logger::Warning("Axis and RefDirection should be specified together", l);
}
if (hasAxis) {
IfcGeom::Kernel::convert(l->Axis(), axis);
}
if (hasRef) {
IfcGeom::Kernel::convert(l->RefDirection(), refDirection);
} else {
if (!axis.IsParallel(gp::DX(), 1.e-5)) {
refDirection = gp::DX();
} else {
refDirection = gp::DZ();
}
gp_Vec Xvec = axis.Dot(refDirection) * axis;
gp_Vec Xaxis = refDirection.XYZ() - Xvec.XYZ();
refDirection = Xaxis;
}
gp_Ax3 ax3(o, axis, refDirection);
if (!axis_equal(ax3, (gp_Ax3) gp::XOY(), getValue(GV_PRECISION))) {
trsf.SetTransformation(ax3, gp::XOY());
@@ -482,8 +482,46 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape
TopoDS_Wire boundary_wire;
IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand();
IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand();
bool is_halfspace = operand2->declaration().is(IfcSchema::IfcHalfSpaceSolid::Class());
bool is_unbounded_halfspace = is_halfspace && !operand2->declaration().is(IfcSchema::IfcPolygonalBoundedHalfSpace::Class());
bool has_halfspace_operand = false;
BOPAlgo_Operation occ_op;
const IfcSchema::IfcBooleanOperator::Value op = l->Operator();
if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) {
occ_op = BOPAlgo_CUT;
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) {
occ_op = BOPAlgo_COMMON;
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) {
occ_op = BOPAlgo_FUSE;
} else {
return false;
}
std::vector<IfcSchema::IfcBooleanOperand*> second_operands;
second_operands.push_back(operand2);
if (occ_op == BOPAlgo_CUT) {
bool process_as_list = true;
while (true) {
auto res1 = operand1->as<IfcSchema::IfcBooleanResult>();
if (res1) {
if (res1->Operator() == op) {
operand1 = res1->FirstOperand();
second_operands.push_back(res1->SecondOperand());
} else {
process_as_list = false;
break;
}
} else {
break;
}
}
if (!process_as_list) {
operand1 = l->FirstOperand();
second_operands = { operand2 };
}
}
if ( shape_type(operand1) == ST_SHAPELIST ) {
if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) {
@@ -501,49 +539,60 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape
}
const double first_operand_volume = shape_volume(s1);
if ( first_operand_volume <= ALMOST_ZERO )
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand());
bool shape2_processed = false;
if ( shape_type(operand2) == ST_SHAPELIST ) {
shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true);
} else if ( shape_type(operand2) == ST_SHAPE ) {
shape2_processed = convert_shape(operand2,s2);
if (shape2_processed && !is_halfspace) {
TopoDS_Solid temp_solid;
s2 = ensure_fit_for_subtraction(s2, temp_solid);
}
} else {
Logger::Message(Logger::LOG_ERROR, "Invalid representation item for boolean operation", operand2);
if (first_operand_volume <= ALMOST_ZERO) {
Logger::Message(Logger::LOG_WARNING, "Empty solid for:", l->FirstOperand());
}
if (!shape2_processed) {
shape = s1;
Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l);
return true;
}
TopTools_ListOfShape second_operand_shapes;
if (!is_halfspace) {
const double second_operand_volume = shape_volume(s2);
if ( second_operand_volume <= ALMOST_ZERO )
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2);
}
for (auto& operand2 : second_operands) {
bool shape2_processed = false;
if (is_unbounded_halfspace) {
TopoDS_Shape temp;
double d;
if (fit_halfspace(s1, s2, temp, d)) {
if (d < getValue(GV_PRECISION)) {
Logger::Message(Logger::LOG_WARNING, "Subtraction yields unchanged volume:", l);
shape = s1;
return true;
bool is_halfspace = operand2->declaration().is(IfcSchema::IfcHalfSpaceSolid::Class());
bool is_unbounded_halfspace = is_halfspace && !operand2->declaration().is(IfcSchema::IfcPolygonalBoundedHalfSpace::Class());
has_halfspace_operand |= is_halfspace;
{
if (shape_type(operand2) == ST_SHAPELIST) {
shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true);
} else if (shape_type(operand2) == ST_SHAPE) {
shape2_processed = convert_shape(operand2, s2);
if (shape2_processed) {
TopoDS_Solid temp_solid;
s2 = ensure_fit_for_subtraction(s2, temp_solid);
}
} else {
s2 = temp;
Logger::Message(Logger::LOG_ERROR, "Invalid representation item for boolean operation", operand2);
}
}
}
const IfcSchema::IfcBooleanOperator::Value op = l->Operator();
if (is_unbounded_halfspace) {
TopoDS_Shape temp;
double d;
if (fit_halfspace(s1, s2, temp, d)) {
if (d < getValue(GV_PRECISION)) {
Logger::Message(Logger::LOG_WARNING, "Halfspace subtraction yields unchanged volume:", l);
continue;
} else {
s2 = temp;
}
}
}
if (!shape2_processed) {
Logger::Message(Logger::LOG_ERROR, "Failed to convert SecondOperand:", operand2);
continue;
}
if (operand2->declaration().is(IfcSchema::IfcHalfSpaceSolid::Class())) {
const double second_operand_volume = shape_volume(s2);
if (second_operand_volume <= ALMOST_ZERO) {
Logger::Message(Logger::LOG_WARNING, "Empty solid for:", operand2);
}
}
second_operand_shapes.Append(s2);
}
/*
// TK: A little debugging trick to output both operands for visual inspection
@@ -555,24 +604,13 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape
builder.Add(compound, s2);
shape = compound;
return true;
*/
BOPAlgo_Operation occ_op;
if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) {
occ_op = BOPAlgo_CUT;
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) {
occ_op = BOPAlgo_COMMON;
} else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) {
occ_op = BOPAlgo_FUSE;
} else {
return false;
}
*/
#if OCC_VERSION_HEX < 0x60900
bool valid_result = boolean_operation(s1, s2, occ_op, shape);
#else
const double fuzz = is_halfspace ? getValue(GV_PRECISION) * 10. : -1.;
bool valid_result = boolean_operation(s1, s2, occ_op, shape, fuzz);
const double fuzz = has_halfspace_operand ? getValue(GV_PRECISION) * 10. : -1.;
bool valid_result = boolean_operation(s1, second_operand_shapes, occ_op, shape, fuzz);
#endif
if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) {
@@ -893,7 +931,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcRectangularTrimmedSurface* l,
}
bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l, TopoDS_Shape& shape) {
gp_Trsf directrix, position;
gp_Trsf directrix;
TopoDS_Shape face;
TopoDS_Wire wire, section;
@@ -972,7 +1010,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcSurfaceCurveSweptAreaSolid* l,
if (has_position) {
// IfcSweptAreaSolid.Position (trsf) is an IfcAxis2Placement3D
// and therefore has a unit scale factor
shape.Move(position);
shape.Move(trsf);
}
return true;
@@ -1121,9 +1159,9 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_
// IfcElementarySurface.Position has unit scale factor
#if OCC_VERSION_HEX < 0x60502
face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius())).Face().Moved(trsf);
face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius() * getValue(GV_LENGTH_UNIT))).Face().Moved(trsf);
#else
face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius()), getValue(GV_PRECISION)).Face().Moved(trsf);
face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius() * getValue(GV_LENGTH_UNIT)), getValue(GV_PRECISION)).Face().Moved(trsf);
#endif
return true;
}
@@ -875,45 +875,53 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcIndexedPolyCurve* l, TopoDS_Wi
BRepBuilderAPI_MakeWire w;
IfcEntityList::ptr segments = l->Segments();
for (IfcEntityList::it it = segments->begin(); it != segments->end(); ++it) {
IfcUtil::IfcBaseClass* segment = *it;
if (segment->declaration().is(IfcSchema::IfcLineIndex::Class())) {
IfcSchema::IfcLineIndex* line = (IfcSchema::IfcLineIndex*) segment;
std::vector<int> indices = *line;
gp_Pnt previous;
for (std::vector<int>::const_iterator jt = indices.begin(); jt != indices.end(); ++jt) {
if (*jt < 1 || *jt > max_index) {
throw IfcParse::IfcException("IfcIndexedPolyCurve index out of bounds for index " + boost::lexical_cast<std::string>(*jt));
if(l->hasSegments()) {
IfcEntityList::ptr segments = l->Segments();
for (IfcEntityList::it it = segments->begin(); it != segments->end(); ++it) {
IfcUtil::IfcBaseClass* segment = *it;
if (segment->declaration().is(IfcSchema::IfcLineIndex::Class())) {
IfcSchema::IfcLineIndex* line = (IfcSchema::IfcLineIndex*) segment;
std::vector<int> indices = *line;
gp_Pnt previous;
for (std::vector<int>::const_iterator jt = indices.begin(); jt != indices.end(); ++jt) {
if (*jt < 1 || *jt > max_index) {
throw IfcParse::IfcException("IfcIndexedPolyCurve index out of bounds for index " + boost::lexical_cast<std::string>(*jt));
}
const gp_Pnt& current = points[*jt - 1];
if (jt != indices.begin()) {
w.Add(BRepBuilderAPI_MakeEdge(previous, current));
}
previous = current;
}
const gp_Pnt& current = points[*jt - 1];
if (jt != indices.begin()) {
w.Add(BRepBuilderAPI_MakeEdge(previous, current));
} else if (segment->declaration().is(IfcSchema::IfcArcIndex::Class())) {
IfcSchema::IfcArcIndex* arc = (IfcSchema::IfcArcIndex*) segment;
std::vector<int> indices = *arc;
if (indices.size() != 3) {
throw IfcParse::IfcException("Invalid IfcArcIndex encountered");
}
previous = current;
}
} else if (segment->declaration().is(IfcSchema::IfcArcIndex::Class())) {
IfcSchema::IfcArcIndex* arc = (IfcSchema::IfcArcIndex*) segment;
std::vector<int> indices = *arc;
if (indices.size() != 3) {
throw IfcParse::IfcException("Invalid IfcArcIndex encountered");
}
for (int i = 0; i < 3; ++i) {
const int& idx = indices[i];
if (idx < 1 || idx > max_index) {
throw IfcParse::IfcException("IfcIndexedPolyCurve index out of bounds for index " + boost::lexical_cast<std::string>(idx));
for (int i = 0; i < 3; ++i) {
const int& idx = indices[i];
if (idx < 1 || idx > max_index) {
throw IfcParse::IfcException("IfcIndexedPolyCurve index out of bounds for index " + boost::lexical_cast<std::string>(idx));
}
}
const gp_Pnt& a = points[indices[0] - 1];
const gp_Pnt& b = points[indices[1] - 1];
const gp_Pnt& c = points[indices[2] - 1];
Handle(Geom_Circle) circ = GC_MakeCircle(a, b, c).Value();
w.Add(BRepBuilderAPI_MakeEdge(circ, a, c));
} else {
throw IfcParse::IfcException("Unexpected IfcIndexedPolyCurve segment of type " + segment->declaration().name());
}
const gp_Pnt& a = points[indices[0] - 1];
const gp_Pnt& b = points[indices[1] - 1];
const gp_Pnt& c = points[indices[2] - 1];
Handle(Geom_Circle) circ = GC_MakeCircle(a, b, c).Value();
w.Add(BRepBuilderAPI_MakeEdge(circ, a, c));
} else {
throw IfcParse::IfcException("Unexpected IfcIndexedPolyCurve segment of type " + segment->declaration().name());
}
}
} else if (points.begin() < points.end()) {
std::vector<gp_Pnt>::const_iterator previous = points.begin();
for (std::vector<gp_Pnt>::const_iterator current = previous+1; current < points.end(); ++current){
w.Add(BRepBuilderAPI_MakeEdge(*previous, *current));
previous = current;
}
}
result = w.Wire();
return true;
}
@@ -85,7 +85,7 @@ namespace IfcGeom {
const ConversionResultPlacement* Placement() const { return placement; }
bool hasStyle() const { return style != 0; }
const SurfaceStyle& Style() const { return *style; }
void setStyle(const SurfaceStyle* style) { this->style = style; }
void setStyle(const SurfaceStyle* newStyle) { style = newStyle; }
int ItemId() const { return id; }
};
+13 -10
View File
@@ -40,14 +40,17 @@ namespace IfcGeom {
/// http://www.boost.org/doc/libs/1_62_0/doc/html/function/tutorial.html
typedef boost::function<bool(IfcUtil::IfcBaseEntity*)> filter_t;
struct filter {
filter() : include(false), traverse(false) {}
filter(bool incl, bool trav) : include(incl), traverse(trav) {}
struct filter
{
filter() : include(false), traverse(false), traverse_openings(false) {}
filter(bool incl, bool trav, bool trav_openings = false) : include(incl), traverse(trav), traverse_openings(trav_openings) {}
/// Should the product be included (true) or excluded (false).
bool include;
/// If traversal requested, traverse to the parents to see if they satisfy the criteria. E.g. we might be looking for
/// children of a storey named "Level 20", or children of entities that have no representation, e.g. IfcCurtainWall.
bool traverse;
/// Include opening relationships as part of traversal.
bool traverse_openings;
/// Optional description for the filtering criteria of this filter.
std::string description;
@@ -59,9 +62,10 @@ namespace IfcGeom {
return is_match == include;
}
static bool traverse_match(IfcUtil::IfcBaseEntity* prod, const filter_t& pred) {
IfcUtil::IfcBaseEntity* parent, *current = prod;
while ((parent = IfcGeom::Kernel::get_decomposing_entity(current)) != nullptr) {
bool traverse_match(IfcUtil::IfcBaseEntity* prod, const filter_t& pred) const
{
IfcUtil::IfcBaseEntity* parent, *current = prod;
while ((parent = IfcGeom::Kernel::get_decomposing_entity(current, traverse_openings)) != nullptr) {
if (pred(parent)) {
return true;
}
@@ -139,8 +143,7 @@ namespace IfcGeom {
}
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
// @note bind1st() and mem_fun() deprecated in C++11, use bind() and mem_fn() when migrating to C++11.
return filter::match(prod, std::bind1st(std::mem_fun(&attribute_filter::match), this));
return filter::match(prod, std::bind(&attribute_filter::match, this, std::placeholders::_1));
}
void update_description() {
@@ -172,7 +175,7 @@ namespace IfcGeom {
}
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
return filter::match(prod, std::bind1st(std::mem_fun(&layer_filter::match), this));
return filter::match(prod, std::bind(&layer_filter::match, this, std::placeholders::_1));
}
struct wildcards_match {
@@ -215,7 +218,7 @@ namespace IfcGeom {
}
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
return filter::match(prod, std::bind1st(std::mem_fun(&entity_filter::match), this));
return filter::match(prod, std::bind(&entity_filter::match, this, std::placeholders::_1));
}
void update_description() {
@@ -86,7 +86,7 @@ TopoDS_Shape apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t) {
}
}
IfcGeom::ConversionResultShape* IfcGeom::Representation::BRep::as_compound() const {
IfcGeom::ConversionResultShape* IfcGeom::Representation::BRep::as_compound(bool force_meters) const {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
@@ -98,7 +98,7 @@ IfcGeom::ConversionResultShape* IfcGeom::Representation::BRep::as_compound() con
trsf = ((OpenCascadePlacement*)it->Placement())->trsf();
}
if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
if (!force_meters && settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
trsf.PreMultiply(scale);
@@ -60,7 +60,7 @@ namespace IfcGeom {
IfcGeom::ConversionResults::const_iterator end() const { return shapes_.end(); }
const IfcGeom::ConversionResults& shapes() const { return shapes_; }
const std::string& id() const { return id_; }
ConversionResultShape* as_compound() const;
ConversionResultShape* as_compound(bool force_meters = false) const;
bool calculate_volume(double&) const;
bool calculate_surface_area(double&) const;
+6 -23
View File
@@ -91,11 +91,11 @@ IfcGeom::Kernel* IfcGeom::impl::KernelFactoryImplementation::construct(const std
#define CREATE_GET_DECOMPOSING_ENTITY(IfcSchema) \
\
IfcSchema::IfcObjectDefinition* get_decomposing_entity_impl(IfcSchema::IfcProduct* product) { \
IfcSchema::IfcObjectDefinition* get_decomposing_entity_impl(IfcSchema::IfcProduct* product, bool include_openings) {\
IfcSchema::IfcObjectDefinition* parent = 0; \
\
/* In case of an opening element, parent to the RelatingBuildingElement */ \
if (product->declaration().is(IfcSchema::IfcOpeningElement::Class())) { \
if (include_openings && product->declaration().is(IfcSchema::IfcOpeningElement::Class())) { \
IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product; \
IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); \
if (voids->size()) { \
@@ -106,7 +106,7 @@ IfcSchema::IfcObjectDefinition* get_decomposing_entity_impl(IfcSchema::IfcProduc
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; \
IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids(); \
/* In case of a RelatedBuildingElement parent to the opening element */ \
if (fills->size()) { \
if (fills->size() && include_openings) { \
for (IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++it) { \
IfcSchema::IfcRelFillsElement* fill = *it; \
IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement(); \
@@ -158,26 +158,17 @@ namespace {
CREATE_GET_DECOMPOSING_ENTITY(Ifc4);
}
IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBaseEntity* inst) {
IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBaseEntity* inst, bool include_openings) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc2x3::IfcProduct>());
return get_decomposing_entity_impl(inst->as<Ifc2x3::IfcProduct>(), include_openings);
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4::IfcProduct>());
return get_decomposing_entity_impl(inst->as<Ifc4::IfcProduct>(), include_openings);
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}
namespace {
// LayerAssignments renamed from plural to singular, LayerAssignment, so work around that
IfcEntityList::ptr getLayerAssignments(Ifc2x3::IfcRepresentationItem* item) {
return item->LayerAssignments()->generalize();
}
IfcEntityList::ptr getLayerAssignments(Ifc4::IfcRepresentationItem* item) {
return item->LayerAssignment()->generalize();
}
template <typename Schema>
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers_impl(typename Schema::IfcProduct* prod) {
std::map<std::string, IfcUtil::IfcBaseEntity*> layers;
@@ -190,14 +181,6 @@ namespace {
layers[(*jt)->Name()] = *jt;
}
}
typename Schema::IfcRepresentationItem::list::ptr items = r->template as<typename Schema::IfcRepresentationItem>();
for (typename Schema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = getLayerAssignments(*it)->template as<typename Schema::IfcPresentationLayerAssignment>();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
layers[(*jt)->Name()] = *jt;
}
}
}
return layers;
}
+1 -1
View File
@@ -78,7 +78,7 @@ namespace IfcGeom {
static int surface_genus(const ConversionResultShape*);
static bool is_manifold(const ConversionResultShape*);
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*);
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*, bool include_openings=true);
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers(IfcUtil::IfcBaseEntity*);
static IfcEntityList::ptr find_openings(IfcUtil::IfcBaseEntity* product);
};
@@ -72,6 +72,7 @@ void IfcGeom::set_default_style_file(const std::string& json_file) {
if (!default_materials_initialized) InitDefaultMaterials();
default_materials.clear();
// @todo this will probably need to be updated for UTF-8 paths on Windows
pt::ptree root;
pt::read_json(json_file, root);
+91 -14
View File
@@ -49,6 +49,8 @@
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#include <BRepBndLib.hxx>
#include <Bnd_Box.hxx>
#include <Geom_Plane.hxx>
#include <memory>
@@ -89,6 +91,21 @@ std::string format_json(const std::string& s) {
return "\"" + s + "\"";
}
template <>
std::string format_json(const double& d) {
std::stringstream ss;
ss << std::setprecision(std::numeric_limits<double>::digits10) << d;
return ss.str();
}
template <>
std::string format_json(const gp_Dir& d) {
std::stringstream ss;
ss << std::setprecision(std::numeric_limits<double>::digits10)
<< "[" << d.X() << "," << d.Y() << "," << d.Z() << "]";
return ss.str();
}
static std::streambuf *stdout_orig, *stdout_redir;
template <typename T>
@@ -106,6 +123,20 @@ void swrite(std::ostream& s, std::string t) {
while (len++ % 4) s.put(0);
}
template <typename T, typename U>
void swrite_array(std::ostream& s, const std::vector<U>& us) {
if (std::is_same<T, U>::value) {
swrite(s, std::string((char*)us.data(), us.size() * sizeof(U)));
} else {
std::vector<T> ts;
ts.reserve(us.size());
for (auto& u : us) {
ts.push_back((T)u);
}
swrite_array<T, T>(s, ts);
}
}
class Command {
protected:
virtual void read_content(std::istream& s) = 0;
@@ -256,7 +287,7 @@ public:
class Entity : public Command {
private:
const IfcGeom::TriangulationElement<float, double>* geom;
const IfcGeom::TriangulationElement<double, double>* geom;
bool append_line_data;
EntityExtension* eext_;
protected:
@@ -281,8 +312,9 @@ protected:
const int integer_representation_id = atoi(representation_id.c_str());
swrite<int32_t>(s, (int32_t)integer_representation_id);
swrite(s, std::string((char*)geom->geometry().verts().data(), geom->geometry().verts().size() * sizeof(float)));
swrite(s, std::string((char*)geom->geometry().normals().data(), geom->geometry().normals().size() * sizeof(float)));
swrite_array<double>(s, geom->geometry().verts());
swrite_array<float>(s, geom->geometry().normals());
{
std::vector<int32_t> indices;
const std::vector<int>& faces = geom->geometry().faces();
@@ -290,7 +322,7 @@ protected:
for (std::vector<int>::const_iterator it = faces.begin(); it != faces.end(); ++it) {
indices.push_back(*it);
}
swrite(s, std::string((char*) indices.data(), indices.size() * sizeof(int32_t)));
swrite_array<int32_t>(s, indices);
if (append_line_data) {
std::vector<int32_t> lines;
@@ -309,7 +341,7 @@ protected:
lines.push_back(i2);
}
swrite(s, std::string((char*) lines.data(), lines.size() * sizeof(int32_t)));
swrite_array<int32_t>(s, lines);
}
}
{ std::vector<float> diffuse_color_array;
@@ -342,7 +374,7 @@ protected:
}
}
public:
Entity(const IfcGeom::TriangulationElement<float, double>* geom, EntityExtension* eext = 0) : Command(ENTITY), geom(geom), append_line_data(false), eext_(eext) {};
Entity(const IfcGeom::TriangulationElement<double, double>* geom, EntityExtension* eext = 0) : Command(ENTITY), geom(geom), append_line_data(false), eext_(eext) {};
};
class Next : public Command {
@@ -401,12 +433,16 @@ static const std::string SURFACE_AREA_ALONG_X = "SURFACE_AREA_ALONG_X";
static const std::string SURFACE_AREA_ALONG_Y = "SURFACE_AREA_ALONG_Y";
static const std::string SURFACE_AREA_ALONG_Z = "SURFACE_AREA_ALONG_Z";
static const std::string WALKABLE_SURFACE_AREA = "WALKABLE_SURFACE_AREA";
static const std::string LARGEST_FACE_AREA = "LARGEST_FACE_AREA";
static const std::string LARGEST_FACE_DIRECTION = "LARGEST_FACE_DIRECTION";
static const std::string BOUNDING_BOX_SIZE_ALONG_ = "BOUNDING_BOX_SIZE_ALONG_";
static const std::array<std::string, 3> XYZ = { "X", "Y", "Z" };
class QuantityWriter_v0 : public EntityExtension {
private:
const IfcGeom::NativeElement<float, double>* elem_;
const IfcGeom::NativeElement<double, double>* elem_;
public:
QuantityWriter_v0(const IfcGeom::NativeElement<float, double>* elem) :
QuantityWriter_v0(const IfcGeom::NativeElement<double, double>* elem) :
elem_(elem)
{
put_json(TOTAL_SURFACE_AREA, 0.);
@@ -419,12 +455,12 @@ public:
class QuantityWriter_v1 : public EntityExtension {
private:
const IfcGeom::NativeElement<float, double>* elem_;
const IfcGeom::NativeElement<double, double>* elem_;
public:
QuantityWriter_v1(const IfcGeom::NativeElement<float, double>* elem) :
QuantityWriter_v1(const IfcGeom::NativeElement<double, double>* elem) :
elem_(elem)
{
double a, b, c;
double a, b, c, largest_face_area = 0.;
if (elem_->geometry().calculate_surface_area(a)) {
put_json(TOTAL_SURFACE_AREA, a);
@@ -439,6 +475,47 @@ public:
put_json(SURFACE_AREA_ALONG_Y, b);
put_json(SURFACE_AREA_ALONG_Z, c);
}
boost::optional<gp_Dir> largest_face_dir;
{
TopoDS_Compound compound = elem_->geometry().as_compound(true);
TopExp_Explorer exp(compound, TopAbs_FACE);
for (; exp.More(); exp.Next()) {
GProp_GProps prop;
BRepGProp::SurfaceProperties(exp.Current(), prop);
const double area = prop.Mass();
if (area > largest_face_area) {
largest_face_area = area;
Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(exp.Current()));
if (surf->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
largest_face_dir = Handle(Geom_Plane)::DownCast(surf)->Axis().Direction();
if (exp.Current().Orientation() == TopAbs_REVERSED) {
largest_face_dir->Reverse();
}
}
}
}
Bnd_Box box;
double xyz[6];
BRepBndLib::AddClose(compound, box);
if (!box.IsVoid()) {
box.Get(xyz[0], xyz[1], xyz[2], xyz[3], xyz[4], xyz[5]);
for (int i = 0; i < 3; ++i) {
const double bsz = xyz[i + 3] - xyz[i];
put_json(BOUNDING_BOX_SIZE_ALONG_ + XYZ[i], bsz);
}
}
}
if (largest_face_dir) {
put_json(LARGEST_FACE_DIRECTION, *largest_face_dir);
put_json(LARGEST_FACE_AREA, largest_face_area);
}
}
};
@@ -462,7 +539,7 @@ int main () {
double deflection = 1.e-3;
bool has_more = false;
IfcGeom::Iterator<float, double>* iterator = 0;
IfcGeom::Iterator<double, double>* iterator = 0;
IfcParse::IfcFile* file = 0;
std::vector< std::pair<uint32_t, uint32_t> > setting_pairs;
@@ -497,7 +574,7 @@ int main () {
settings.set_deflection_tolerance(deflection);
file = new IfcParse::IfcFile(data, (int)len);
iterator = new IfcGeom::Iterator<float, double>(settings, file);
iterator = new IfcGeom::Iterator<double, double>(settings, file);
has_more = iterator->initialize();
More(has_more).write(std::cout);
@@ -509,7 +586,7 @@ int main () {
exit_code = 1;
break;
}
const IfcGeom::TriangulationElement<float, double>* geom = static_cast<const IfcGeom::TriangulationElement<float, double>*>(iterator->get());
const IfcGeom::TriangulationElement<double, double>* geom = static_cast<const IfcGeom::TriangulationElement<double, double>*>(iterator->get());
std::unique_ptr<EntityExtension> eext;
if (emit_quantities) {
eext.reset(new QuantityWriter_v1(iterator->get_native()));
+13 -6
View File
@@ -16,25 +16,32 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
################################################################################
foreach(max_year RANGE 2014 2030)
set(max_sdk "$ENV{ADSK_3DSMAX_SDK_${max_year}}")
if (NOT "${max_sdk}" STREQUAL "")
INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCLUDE_DIRS} ${ICU_INCLUDE_DIR}
${Boost_INCLUDE_DIRS} ${THREEDS_MAX_SDK_HOME}/include
${Boost_INCLUDE_DIRS} ${max_sdk}/include
)
# All recent versions of 3ds Max (2014 and newer) are 64-bit only so assume lib/x64 directory
LINK_DIRECTORIES(${LINK_DIRECTORIES} ${IfcOpenShell_BINARY_DIR} ${OCC_LIBRARY_DIR} ${OPENCOLLADA_LIBRARY_DIR}
${ICU_LIBRARY_DIR} ${Boost_LIBRARY_DIRS} ${THREEDS_MAX_SDK_HOME}/lib/x64/Release
${ICU_LIBRARY_DIR} ${Boost_LIBRARY_DIRS} ${max_sdk}/lib/x64/Release
)
ADD_LIBRARY(IfcMax SHARED IfcMax.h IfcMax.cpp)
ADD_LIBRARY(IfcMax_${max_year} SHARED IfcMax.h IfcMax.cpp)
# TODO: find the minimal subset of 3dsmax libraries to reference
TARGET_LINK_LIBRARIES(IfcMax ${IFCOPENSHELL_LIBRARIES} Comctl32.lib zlibdll.lib bmm.lib core.lib CustDlg.lib edmodel.lib expr.lib
TARGET_LINK_LIBRARIES(IfcMax_${max_year} ${IFCOPENSHELL_LIBRARIES} Comctl32.lib zlibdll.lib bmm.lib core.lib CustDlg.lib edmodel.lib expr.lib
flt.lib geom.lib gfx.lib gup.lib imageViewers.lib ManipSys.lib maxnet.lib Maxscrpt.lib
maxutil.lib MenuMan.lib menus.lib mesh.lib MNMath.lib Paramblk2.lib particle.lib Poly.lib RenderUtil.lib
tessint.lib viewfile.lib ${OPENCASCADE_LIBRARIES}
)
SET_TARGET_PROPERTIES(IfcMax PROPERTIES SUFFIX ".dli")
SET_TARGET_PROPERTIES(IfcMax_${max_year} PROPERTIES SUFFIX ".dli")
INSTALL(TARGETS IfcMax RUNTIME DESTINATION ${BINDIR})
INSTALL(TARGETS IfcMax_${max_year} RUNTIME DESTINATION ${BINDIR})
endif()
endforeach()
+6 -2
View File
@@ -24,7 +24,10 @@
#include <istdplug.h>
#include "IfcMax.h"
#include "../ifcgeom/IfcGeomIterator.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h"
#include "../ifcgeom/IfcGeomElement.h"
static const int NUM_MATERIAL_SLOTS = 24;
@@ -226,7 +229,8 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
const char* fn_mb = name;
#endif
IfcGeom::Iterator<float> iterator(settings, fn_mb);
IfcParse::IfcFile file(fn_mb);
IfcGeom::Iterator<float> iterator(settings, &file);
delete fn_mb;
if (!iterator.initialize()) return false;
@@ -0,0 +1,103 @@
from __future__ import print_function
import ifcopenshell
named_type = ifcopenshell.ifcopenshell_wrapper.named_type
aggregation_type = ifcopenshell.ifcopenshell_wrapper.aggregation_type
simple_type = ifcopenshell.ifcopenshell_wrapper.simple_type
type_declaration = ifcopenshell.ifcopenshell_wrapper.type_declaration
enumeration_type = ifcopenshell.ifcopenshell_wrapper.enumeration_type
entity_type = ifcopenshell.ifcopenshell_wrapper.entity
select_type = ifcopenshell.ifcopenshell_wrapper.select_type
attribute = ifcopenshell.ifcopenshell_wrapper.attribute
class ValidationError(Exception): pass
simple_type_python_mapping = {
"string": str,
"integer": int,
"real": float,
"number": float,
"boolean": bool,
"logical": bool, # still not implemented in IfcOpenShell
"binary": str # maps to a str of "0" and "1"
}
def assert_valid_inverse(attr, val):
b1, b2 = attr.bound1(), attr.bound2()
invalid = len(val) < b1 or (b2 != -1 and len(val) > b2)
if invalid:
raise ValidationError("%r not valid for %s" % (val, attr))
return True
def assert_valid(attr, val):
if isinstance(attr, attribute):
attr_type = attr.type_of_attribute()
else:
attr_type = attr
type_wrappers = (named_type,)
if not isinstance(val, ifcopenshell.entity_instance):
# If val is not an entity instance we need to
# flatten the type declaration to something that
# maps to the python types
type_wrappers += (type_declaration,)
while isinstance(attr_type, type_wrappers):
attr_type = attr_type.declared_type()
if isinstance(attr_type, simple_type):
invalid = type(val) != simple_type_python_mapping[attr_type.declared_type()]
elif isinstance(attr_type, (entity_type, type_declaration)):
invalid = not isinstance(val, ifcopenshell.entity_instance) or not val.is_a(attr_type.name())
elif isinstance(attr_type, select_type):
invalid = not any(try_valid(x, val) for x in attr_type.select_list())
elif isinstance(attr_type, enumeration_type):
invalid = val not in attr_type.enumeration_items()
elif isinstance(attr_type, aggregation_type):
b1, b2 = attr_type.bound1(), attr_type.bound2()
ty = attr_type.type_of_element()
invalid = len(val) < b1 or (b2 != -1 and len(val) > b2) or not all(assert_valid(ty, v) for v in val)
else:
raise NotImplementedError("Not impl %s %s" % (type(attr_type), attr_type))
if invalid:
raise ValidationError("%r not valid for %s" % (val, attr))
return True
def try_valid(attr, val):
try:
return assert_valid(attr, val)
except ValidationError as e:
return False
def validate(f):
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(f.schema)
for inst in f:
entity = schema.declaration_by_name(inst.is_a())
for attr, val, is_derived in zip(entity.all_attributes(), inst, entity.derived()):
if val is None and not (is_derived or attr.optional()):
raise Exception("Attribute %s.%s not optional" % (entity, attr))
if val is not None:
attr_type = attr.type_of_attribute()
try:
assert_valid(attr, val)
except ValidationError as e:
print("In", inst)
print(e)
print()
for attr in entity.all_inverse_attributes():
val = getattr(inst, attr.name())
assert_valid_inverse(attr, val)
if __name__ == "__main__":
import sys
for fn in sys.argv[1:]:
print("Validating", fn)
validate(ifcopenshell.open(fn))
-4
View File
@@ -52,10 +52,6 @@ namespace IfcUtil {
IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type);
IFC_PARSE_API bool valid_binary_string(const std::string& s);
/// Replaces spaces and potentially other problem causing characters with underscores.
IFC_PARSE_API void sanitate_material_name(std::string &str);
IFC_PARSE_API void escape_xml(std::string &str);
IFC_PARSE_API void unescape_xml(std::string &str);
}
class IFC_PARSE_API Argument {
File diff suppressed because it is too large Load Diff
+5184 -4033
View File
File diff suppressed because it is too large Load Diff
+133 -29
View File
@@ -356,10 +356,13 @@ extern entity* IFC4_IfcIShapeProfileDef_type;
extern entity* IFC4_IfcImageTexture_type;
extern entity* IFC4_IfcIndexedColourMap_type;
extern entity* IFC4_IfcIndexedPolyCurve_type;
extern entity* IFC4_IfcIndexedPolygonalFace_type;
extern entity* IFC4_IfcIndexedPolygonalFaceWithVoids_type;
extern entity* IFC4_IfcIndexedTextureMap_type;
extern entity* IFC4_IfcIndexedTriangleTextureMap_type;
extern entity* IFC4_IfcInterceptor_type;
extern entity* IFC4_IfcInterceptorType_type;
extern entity* IFC4_IfcIntersectionCurve_type;
extern entity* IFC4_IfcInventory_type;
extern entity* IFC4_IfcIrregularTimeSeries_type;
extern entity* IFC4_IfcIrregularTimeSeriesValue_type;
@@ -469,6 +472,7 @@ extern entity* IFC4_IfcPointOnCurve_type;
extern entity* IFC4_IfcPointOnSurface_type;
extern entity* IFC4_IfcPolyLoop_type;
extern entity* IFC4_IfcPolygonalBoundedHalfSpace_type;
extern entity* IFC4_IfcPolygonalFaceSet_type;
extern entity* IFC4_IfcPolyline_type;
extern entity* IFC4_IfcPort_type;
extern entity* IFC4_IfcPostalAddress_type;
@@ -619,6 +623,7 @@ extern entity* IFC4_IfcSIUnit_type;
extern entity* IFC4_IfcSanitaryTerminal_type;
extern entity* IFC4_IfcSanitaryTerminalType_type;
extern entity* IFC4_IfcSchedulingTime_type;
extern entity* IFC4_IfcSeamCurve_type;
extern entity* IFC4_IfcSectionProperties_type;
extern entity* IFC4_IfcSectionReinforcementProperties_type;
extern entity* IFC4_IfcSectionedSpine_type;
@@ -652,6 +657,7 @@ extern entity* IFC4_IfcSpatialStructureElementType_type;
extern entity* IFC4_IfcSpatialZone_type;
extern entity* IFC4_IfcSpatialZoneType_type;
extern entity* IFC4_IfcSphere_type;
extern entity* IFC4_IfcSphericalSurface_type;
extern entity* IFC4_IfcStackTerminal_type;
extern entity* IFC4_IfcStackTerminalType_type;
extern entity* IFC4_IfcStair_type;
@@ -702,6 +708,7 @@ extern entity* IFC4_IfcSubContractResource_type;
extern entity* IFC4_IfcSubContractResourceType_type;
extern entity* IFC4_IfcSubedge_type;
extern entity* IFC4_IfcSurface_type;
extern entity* IFC4_IfcSurfaceCurve_type;
extern entity* IFC4_IfcSurfaceCurveSweptAreaSolid_type;
extern entity* IFC4_IfcSurfaceFeature_type;
extern entity* IFC4_IfcSurfaceOfLinearExtrusion_type;
@@ -756,6 +763,7 @@ extern entity* IFC4_IfcTimeSeries_type;
extern entity* IFC4_IfcTimeSeriesValue_type;
extern entity* IFC4_IfcTopologicalRepresentationItem_type;
extern entity* IFC4_IfcTopologyRepresentation_type;
extern entity* IFC4_IfcToroidalSurface_type;
extern entity* IFC4_IfcTransformer_type;
extern entity* IFC4_IfcTransformerType_type;
extern entity* IFC4_IfcTransportElement_type;
@@ -912,7 +920,6 @@ extern type_declaration* IFC4_IfcSoundPressureMeasure_type;
extern type_declaration* IFC4_IfcSpecificHeatCapacityMeasure_type;
extern type_declaration* IFC4_IfcSpecularExponent_type;
extern type_declaration* IFC4_IfcSpecularRoughness_type;
extern type_declaration* IFC4_IfcStrippedOptional_type;
extern type_declaration* IFC4_IfcTemperatureGradientMeasure_type;
extern type_declaration* IFC4_IfcTemperatureRateOfChangeMeasure_type;
extern type_declaration* IFC4_IfcText_type;
@@ -1307,8 +1314,8 @@ Ifc4::IfcBuildingElementPartTypeEnum::Value Ifc4::IfcBuildingElementPartTypeEnum
}
const char* Ifc4::IfcBuildingElementProxyTypeEnum::ToString(Value v) {
if ( v < 0 || v >= 6 ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { "COMPLEX", "ELEMENT", "PARTIAL", "PROVISIONFORVOID", "USERDEFINED", "NOTDEFINED" };
if ( v < 0 || v >= 7 ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { "COMPLEX", "ELEMENT", "PARTIAL", "PROVISIONFORVOID", "PROVISIONFORSPACE", "USERDEFINED", "NOTDEFINED" };
return names[v];
}
@@ -1317,6 +1324,7 @@ Ifc4::IfcBuildingElementProxyTypeEnum::Value Ifc4::IfcBuildingElementProxyTypeEn
if (s == "ELEMENT") return ::Ifc4::IfcBuildingElementProxyTypeEnum::IfcBuildingElementProxyType_ELEMENT;
if (s == "PARTIAL") return ::Ifc4::IfcBuildingElementProxyTypeEnum::IfcBuildingElementProxyType_PARTIAL;
if (s == "PROVISIONFORVOID") return ::Ifc4::IfcBuildingElementProxyTypeEnum::IfcBuildingElementProxyType_PROVISIONFORVOID;
if (s == "PROVISIONFORSPACE") return ::Ifc4::IfcBuildingElementProxyTypeEnum::IfcBuildingElementProxyType_PROVISIONFORSPACE;
if (s == "USERDEFINED") return ::Ifc4::IfcBuildingElementProxyTypeEnum::IfcBuildingElementProxyType_USERDEFINED;
if (s == "NOTDEFINED") return ::Ifc4::IfcBuildingElementProxyTypeEnum::IfcBuildingElementProxyType_NOTDEFINED;
throw IfcException("Unable to find find keyword in schema");
@@ -2447,7 +2455,7 @@ Ifc4::IfcEventTypeEnum::Value Ifc4::IfcEventTypeEnum::FromString(const std::stri
const char* Ifc4::IfcExternalSpatialElementTypeEnum::ToString(Value v) {
if ( v < 0 || v >= 6 ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { "EXTERNAL", "EXTERNAL_EARTH", "EXTERNAL_WATER", "EXTERNAL_FIRE", "USERDEFINED", "NOTDEFIEND" };
const char* names[] = { "EXTERNAL", "EXTERNAL_EARTH", "EXTERNAL_WATER", "EXTERNAL_FIRE", "USERDEFINED", "NOTDEFINED" };
return names[v];
}
@@ -2457,7 +2465,7 @@ Ifc4::IfcExternalSpatialElementTypeEnum::Value Ifc4::IfcExternalSpatialElementTy
if (s == "EXTERNAL_WATER") return ::Ifc4::IfcExternalSpatialElementTypeEnum::IfcExternalSpatialElementType_EXTERNAL_WATER;
if (s == "EXTERNAL_FIRE") return ::Ifc4::IfcExternalSpatialElementTypeEnum::IfcExternalSpatialElementType_EXTERNAL_FIRE;
if (s == "USERDEFINED") return ::Ifc4::IfcExternalSpatialElementTypeEnum::IfcExternalSpatialElementType_USERDEFINED;
if (s == "NOTDEFIEND") return ::Ifc4::IfcExternalSpatialElementTypeEnum::IfcExternalSpatialElementType_NOTDEFIEND;
if (s == "NOTDEFINED") return ::Ifc4::IfcExternalSpatialElementTypeEnum::IfcExternalSpatialElementType_NOTDEFINED;
throw IfcException("Unable to find find keyword in schema");
}
@@ -3254,6 +3262,19 @@ Ifc4::IfcPlateTypeEnum::Value Ifc4::IfcPlateTypeEnum::FromString(const std::stri
throw IfcException("Unable to find find keyword in schema");
}
const char* Ifc4::IfcPreferredSurfaceCurveRepresentation::ToString(Value v) {
if ( v < 0 || v >= 3 ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { "CURVE3D", "PCURVE_S1", "PCURVE_S2" };
return names[v];
}
Ifc4::IfcPreferredSurfaceCurveRepresentation::Value Ifc4::IfcPreferredSurfaceCurveRepresentation::FromString(const std::string& s) {
if (s == "CURVE3D") return ::Ifc4::IfcPreferredSurfaceCurveRepresentation::IfcPreferredSurfaceCurveRepresentation_CURVE3D;
if (s == "PCURVE_S1") return ::Ifc4::IfcPreferredSurfaceCurveRepresentation::IfcPreferredSurfaceCurveRepresentation_PCURVE_S1;
if (s == "PCURVE_S2") return ::Ifc4::IfcPreferredSurfaceCurveRepresentation::IfcPreferredSurfaceCurveRepresentation_PCURVE_S2;
throw IfcException("Unable to find find keyword in schema");
}
const char* Ifc4::IfcProcedureTypeEnum::ToString(Value v) {
if ( v < 0 || v >= 9 ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { "ADVICE_CAUTION", "ADVICE_NOTE", "ADVICE_WARNING", "CALIBRATION", "DIAGNOSTIC", "SHUTDOWN", "STARTUP", "USERDEFINED", "NOTDEFINED" };
@@ -3706,12 +3727,13 @@ Ifc4::IfcSectionTypeEnum::Value Ifc4::IfcSectionTypeEnum::FromString(const std::
}
const char* Ifc4::IfcSensorTypeEnum::ToString(Value v) {
if ( v < 0 || v >= 25 ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { "CO2SENSOR", "CONDUCTANCESENSOR", "CONTACTSENSOR", "FIRESENSOR", "FLOWSENSOR", "FROSTSENSOR", "GASSENSOR", "HEATSENSOR", "HUMIDITYSENSOR", "IDENTIFIERSENSOR", "IONCONCENTRATIONSENSOR", "LEVELSENSOR", "LIGHTSENSOR", "MOISTURESENSOR", "MOVEMENTSENSOR", "PHSENSOR", "PRESSURESENSOR", "RADIATIONSENSOR", "RADIOACTIVITYSENSOR", "SMOKESENSOR", "SOUNDSENSOR", "TEMPERATURESENSOR", "WINDSENSOR", "USERDEFINED", "NOTDEFINED" };
if ( v < 0 || v >= 26 ) throw IfcException("Unable to find find keyword in schema");
const char* names[] = { "COSENSOR", "CO2SENSOR", "CONDUCTANCESENSOR", "CONTACTSENSOR", "FIRESENSOR", "FLOWSENSOR", "FROSTSENSOR", "GASSENSOR", "HEATSENSOR", "HUMIDITYSENSOR", "IDENTIFIERSENSOR", "IONCONCENTRATIONSENSOR", "LEVELSENSOR", "LIGHTSENSOR", "MOISTURESENSOR", "MOVEMENTSENSOR", "PHSENSOR", "PRESSURESENSOR", "RADIATIONSENSOR", "RADIOACTIVITYSENSOR", "SMOKESENSOR", "SOUNDSENSOR", "TEMPERATURESENSOR", "WINDSENSOR", "USERDEFINED", "NOTDEFINED" };
return names[v];
}
Ifc4::IfcSensorTypeEnum::Value Ifc4::IfcSensorTypeEnum::FromString(const std::string& s) {
if (s == "COSENSOR") return ::Ifc4::IfcSensorTypeEnum::IfcSensorType_COSENSOR;
if (s == "CO2SENSOR") return ::Ifc4::IfcSensorTypeEnum::IfcSensorType_CO2SENSOR;
if (s == "CONDUCTANCESENSOR") return ::Ifc4::IfcSensorTypeEnum::IfcSensorType_CONDUCTANCESENSOR;
if (s == "CONTACTSENSOR") return ::Ifc4::IfcSensorTypeEnum::IfcSensorType_CONTACTSENSOR;
@@ -5375,13 +5397,6 @@ Ifc4::IfcSpecularRoughness::IfcSpecularRoughness(IfcEntityInstanceData* e) { dat
Ifc4::IfcSpecularRoughness::IfcSpecularRoughness(double v) { data_ = new IfcEntityInstanceData(IFC4_IfcSpecularRoughness_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v); data_->setArgument(0, attr);} }
Ifc4::IfcSpecularRoughness::operator double() const { return *data_->getArgument(0); }
// Function implementations for IfcStrippedOptional
const IfcParse::type_declaration& Ifc4::IfcStrippedOptional::Class() { return *IFC4_IfcStrippedOptional_type; }
const IfcParse::type_declaration& Ifc4::IfcStrippedOptional::declaration() const { return *IFC4_IfcStrippedOptional_type; }
Ifc4::IfcStrippedOptional::IfcStrippedOptional(IfcEntityInstanceData* e) { data_ = e; }
Ifc4::IfcStrippedOptional::IfcStrippedOptional(bool v) { data_ = new IfcEntityInstanceData(IFC4_IfcStrippedOptional_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v); data_->setArgument(0, attr);} }
Ifc4::IfcStrippedOptional::operator bool() const { return *data_->getArgument(0); }
// Function implementations for IfcTemperatureGradientMeasure
const IfcParse::type_declaration& Ifc4::IfcTemperatureGradientMeasure::Class() { return *IFC4_IfcTemperatureGradientMeasure_type; }
const IfcParse::type_declaration& Ifc4::IfcTemperatureGradientMeasure::declaration() const { return *IFC4_IfcTemperatureGradientMeasure_type; }
@@ -9506,6 +9521,27 @@ const IfcParse::entity& Ifc4::IfcIndexedPolyCurve::Class() { return *IFC4_IfcInd
Ifc4::IfcIndexedPolyCurve::IfcIndexedPolyCurve(IfcEntityInstanceData* e) : IfcBoundedCurve((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcIndexedPolyCurve_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcIndexedPolyCurve::IfcIndexedPolyCurve(::Ifc4::IfcCartesianPointList* v1_Points, boost::optional< IfcEntityList::ptr > v2_Segments, boost::optional< bool > v3_SelfIntersect) : IfcBoundedCurve((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcIndexedPolyCurve_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Points));data_->setArgument(0,attr);} if (v2_Segments) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v2_Segments));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); } if (v3_SelfIntersect) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_SelfIntersect));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); } }
// Function implementations for IfcIndexedPolygonalFace
std::vector< int > /*[3:?]*/ Ifc4::IfcIndexedPolygonalFace::CoordIndex() const { return *data_->getArgument(0); }
void Ifc4::IfcIndexedPolygonalFace::setCoordIndex(std::vector< int > /*[3:?]*/ v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(0,attr);} }
::Ifc4::IfcPolygonalFaceSet::list::ptr Ifc4::IfcIndexedPolygonalFace::ToFaceSet() const { return data_->getInverse(IFC4_IfcPolygonalFaceSet_type, 2)->as<IfcPolygonalFaceSet>(); }
const IfcParse::entity& Ifc4::IfcIndexedPolygonalFace::declaration() const { return *IFC4_IfcIndexedPolygonalFace_type; }
const IfcParse::entity& Ifc4::IfcIndexedPolygonalFace::Class() { return *IFC4_IfcIndexedPolygonalFace_type; }
Ifc4::IfcIndexedPolygonalFace::IfcIndexedPolygonalFace(IfcEntityInstanceData* e) : IfcTessellatedItem((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcIndexedPolygonalFace_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcIndexedPolygonalFace::IfcIndexedPolygonalFace(std::vector< int > /*[3:?]*/ v1_CoordIndex) : IfcTessellatedItem((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcIndexedPolygonalFace_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_CoordIndex));data_->setArgument(0,attr);} }
// Function implementations for IfcIndexedPolygonalFaceWithVoids
std::vector< std::vector< int > > Ifc4::IfcIndexedPolygonalFaceWithVoids::InnerCoordIndices() const { return *data_->getArgument(1); }
void Ifc4::IfcIndexedPolygonalFaceWithVoids::setInnerCoordIndices(std::vector< std::vector< int > > v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(1,attr);} }
const IfcParse::entity& Ifc4::IfcIndexedPolygonalFaceWithVoids::declaration() const { return *IFC4_IfcIndexedPolygonalFaceWithVoids_type; }
const IfcParse::entity& Ifc4::IfcIndexedPolygonalFaceWithVoids::Class() { return *IFC4_IfcIndexedPolygonalFaceWithVoids_type; }
Ifc4::IfcIndexedPolygonalFaceWithVoids::IfcIndexedPolygonalFaceWithVoids(IfcEntityInstanceData* e) : IfcIndexedPolygonalFace((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcIndexedPolygonalFaceWithVoids_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcIndexedPolygonalFaceWithVoids::IfcIndexedPolygonalFaceWithVoids(std::vector< int > /*[3:?]*/ v1_CoordIndex, std::vector< std::vector< int > > v2_InnerCoordIndices) : IfcIndexedPolygonalFace((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcIndexedPolygonalFaceWithVoids_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_CoordIndex));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_InnerCoordIndices));data_->setArgument(1,attr);} }
// Function implementations for IfcIndexedTextureMap
::Ifc4::IfcTessellatedFaceSet* Ifc4::IfcIndexedTextureMap::MappedTo() const { return (::Ifc4::IfcTessellatedFaceSet*)((IfcUtil::IfcBaseClass*)(*data_->getArgument(1))); }
void Ifc4::IfcIndexedTextureMap::setMappedTo(::Ifc4::IfcTessellatedFaceSet* v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(1,attr);} }
@@ -9550,6 +9586,14 @@ const IfcParse::entity& Ifc4::IfcInterceptorType::Class() { return *IFC4_IfcInte
Ifc4::IfcInterceptorType::IfcInterceptorType(IfcEntityInstanceData* e) : IfcFlowTreatmentDeviceType((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcInterceptorType_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcInterceptorType::IfcInterceptorType(std::string v1_GlobalId, ::Ifc4::IfcOwnerHistory* v2_OwnerHistory, boost::optional< std::string > v3_Name, boost::optional< std::string > v4_Description, boost::optional< std::string > v5_ApplicableOccurrence, boost::optional< IfcTemplatedEntityList< ::Ifc4::IfcPropertySetDefinition >::ptr > v6_HasPropertySets, boost::optional< IfcTemplatedEntityList< ::Ifc4::IfcRepresentationMap >::ptr > v7_RepresentationMaps, boost::optional< std::string > v8_Tag, boost::optional< std::string > v9_ElementType, ::Ifc4::IfcInterceptorTypeEnum::Value v10_PredefinedType) : IfcFlowTreatmentDeviceType((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcInterceptorType_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_GlobalId));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_OwnerHistory));data_->setArgument(1,attr);} if (v3_Name) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_Name));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); } if (v4_Description) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v4_Description));data_->setArgument(3,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(3, attr); } if (v5_ApplicableOccurrence) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v5_ApplicableOccurrence));data_->setArgument(4,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(4, attr); } if (v6_HasPropertySets) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v6_HasPropertySets)->generalize());data_->setArgument(5,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(5, attr); } if (v7_RepresentationMaps) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v7_RepresentationMaps)->generalize());data_->setArgument(6,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(6, attr); } if (v8_Tag) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v8_Tag));data_->setArgument(7,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(7, attr); } if (v9_ElementType) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v9_ElementType));data_->setArgument(8,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(8, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(v10_PredefinedType,::Ifc4::IfcInterceptorTypeEnum::ToString(v10_PredefinedType))));data_->setArgument(9,attr);} }
// Function implementations for IfcIntersectionCurve
const IfcParse::entity& Ifc4::IfcIntersectionCurve::declaration() const { return *IFC4_IfcIntersectionCurve_type; }
const IfcParse::entity& Ifc4::IfcIntersectionCurve::Class() { return *IFC4_IfcIntersectionCurve_type; }
Ifc4::IfcIntersectionCurve::IfcIntersectionCurve(IfcEntityInstanceData* e) : IfcSurfaceCurve((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcIntersectionCurve_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcIntersectionCurve::IfcIntersectionCurve(::Ifc4::IfcCurve* v1_Curve3D, IfcTemplatedEntityList< ::Ifc4::IfcPcurve >::ptr v2_AssociatedGeometry, ::Ifc4::IfcPreferredSurfaceCurveRepresentation::Value v3_MasterRepresentation) : IfcSurfaceCurve((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcIntersectionCurve_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Curve3D));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_AssociatedGeometry)->generalize());data_->setArgument(1,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(v3_MasterRepresentation,::Ifc4::IfcPreferredSurfaceCurveRepresentation::ToString(v3_MasterRepresentation))));data_->setArgument(2,attr);} }
// Function implementations for IfcInventory
bool Ifc4::IfcInventory::hasPredefinedType() const { return !data_->getArgument(5)->isNull(); }
::Ifc4::IfcInventoryTypeEnum::Value Ifc4::IfcInventory::PredefinedType() const { return ::Ifc4::IfcInventoryTypeEnum::FromString(*data_->getArgument(5)); }
@@ -11039,6 +11083,22 @@ const IfcParse::entity& Ifc4::IfcPolygonalBoundedHalfSpace::Class() { return *IF
Ifc4::IfcPolygonalBoundedHalfSpace::IfcPolygonalBoundedHalfSpace(IfcEntityInstanceData* e) : IfcHalfSpaceSolid((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcPolygonalBoundedHalfSpace_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcPolygonalBoundedHalfSpace::IfcPolygonalBoundedHalfSpace(::Ifc4::IfcSurface* v1_BaseSurface, bool v2_AgreementFlag, ::Ifc4::IfcAxis2Placement3D* v3_Position, ::Ifc4::IfcBoundedCurve* v4_PolygonalBoundary) : IfcHalfSpaceSolid((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcPolygonalBoundedHalfSpace_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_BaseSurface));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_AgreementFlag));data_->setArgument(1,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v3_Position));data_->setArgument(2,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v4_PolygonalBoundary));data_->setArgument(3,attr);} }
// Function implementations for IfcPolygonalFaceSet
bool Ifc4::IfcPolygonalFaceSet::hasClosed() const { return !data_->getArgument(1)->isNull(); }
bool Ifc4::IfcPolygonalFaceSet::Closed() const { return *data_->getArgument(1); }
void Ifc4::IfcPolygonalFaceSet::setClosed(bool v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(1,attr);} }
IfcTemplatedEntityList< ::Ifc4::IfcIndexedPolygonalFace >::ptr Ifc4::IfcPolygonalFaceSet::Faces() const { IfcEntityList::ptr es = *data_->getArgument(2); return es->as< ::Ifc4::IfcIndexedPolygonalFace >(); }
void Ifc4::IfcPolygonalFaceSet::setFaces(IfcTemplatedEntityList< ::Ifc4::IfcIndexedPolygonalFace >::ptr v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize());data_->setArgument(2,attr);} }
bool Ifc4::IfcPolygonalFaceSet::hasPnIndex() const { return !data_->getArgument(3)->isNull(); }
std::vector< int > /*[1:?]*/ Ifc4::IfcPolygonalFaceSet::PnIndex() const { return *data_->getArgument(3); }
void Ifc4::IfcPolygonalFaceSet::setPnIndex(std::vector< int > /*[1:?]*/ v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(3,attr);} }
const IfcParse::entity& Ifc4::IfcPolygonalFaceSet::declaration() const { return *IFC4_IfcPolygonalFaceSet_type; }
const IfcParse::entity& Ifc4::IfcPolygonalFaceSet::Class() { return *IFC4_IfcPolygonalFaceSet_type; }
Ifc4::IfcPolygonalFaceSet::IfcPolygonalFaceSet(IfcEntityInstanceData* e) : IfcTessellatedFaceSet((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcPolygonalFaceSet_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcPolygonalFaceSet::IfcPolygonalFaceSet(::Ifc4::IfcCartesianPointList3D* v1_Coordinates, boost::optional< bool > v2_Closed, IfcTemplatedEntityList< ::Ifc4::IfcIndexedPolygonalFace >::ptr v3_Faces, boost::optional< std::vector< int > /*[1:?]*/ > v4_PnIndex) : IfcTessellatedFaceSet((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcPolygonalFaceSet_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Coordinates));data_->setArgument(0,attr);} if (v2_Closed) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v2_Closed));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v3_Faces)->generalize());data_->setArgument(2,attr);} if (v4_PnIndex) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v4_PnIndex));data_->setArgument(3,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(3, attr); } }
// Function implementations for IfcPolyline
IfcTemplatedEntityList< ::Ifc4::IfcCartesianPoint >::ptr Ifc4::IfcPolyline::Points() const { IfcEntityList::ptr es = *data_->getArgument(0); return es->as< ::Ifc4::IfcCartesianPoint >(); }
void Ifc4::IfcPolyline::setPoints(IfcTemplatedEntityList< ::Ifc4::IfcCartesianPoint >::ptr v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize());data_->setArgument(0,attr);} }
@@ -13060,6 +13120,14 @@ const IfcParse::entity& Ifc4::IfcSchedulingTime::Class() { return *IFC4_IfcSched
Ifc4::IfcSchedulingTime::IfcSchedulingTime(IfcEntityInstanceData* e) : IfcUtil::IfcBaseEntity() { if (!e) return; if (e->type() != IFC4_IfcSchedulingTime_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcSchedulingTime::IfcSchedulingTime(boost::optional< std::string > v1_Name, boost::optional< ::Ifc4::IfcDataOriginEnum::Value > v2_DataOrigin, boost::optional< std::string > v3_UserDefinedDataOrigin) : IfcUtil::IfcBaseEntity() {data_ = new IfcEntityInstanceData(IFC4_IfcSchedulingTime_type); if (v1_Name) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v1_Name));data_->setArgument(0,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(0, attr); } if (v2_DataOrigin) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(*v2_DataOrigin,::Ifc4::IfcDataOriginEnum::ToString(*v2_DataOrigin))));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); } if (v3_UserDefinedDataOrigin) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_UserDefinedDataOrigin));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); } }
// Function implementations for IfcSeamCurve
const IfcParse::entity& Ifc4::IfcSeamCurve::declaration() const { return *IFC4_IfcSeamCurve_type; }
const IfcParse::entity& Ifc4::IfcSeamCurve::Class() { return *IFC4_IfcSeamCurve_type; }
Ifc4::IfcSeamCurve::IfcSeamCurve(IfcEntityInstanceData* e) : IfcSurfaceCurve((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcSeamCurve_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcSeamCurve::IfcSeamCurve(::Ifc4::IfcCurve* v1_Curve3D, IfcTemplatedEntityList< ::Ifc4::IfcPcurve >::ptr v2_AssociatedGeometry, ::Ifc4::IfcPreferredSurfaceCurveRepresentation::Value v3_MasterRepresentation) : IfcSurfaceCurve((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcSeamCurve_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Curve3D));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_AssociatedGeometry)->generalize());data_->setArgument(1,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(v3_MasterRepresentation,::Ifc4::IfcPreferredSurfaceCurveRepresentation::ToString(v3_MasterRepresentation))));data_->setArgument(2,attr);} }
// Function implementations for IfcSectionProperties
::Ifc4::IfcSectionTypeEnum::Value Ifc4::IfcSectionProperties::SectionType() const { return ::Ifc4::IfcSectionTypeEnum::FromString(*data_->getArgument(0)); }
void Ifc4::IfcSectionProperties::setSectionType(::Ifc4::IfcSectionTypeEnum::Value v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,::Ifc4::IfcSectionTypeEnum::ToString(v)));data_->setArgument(0,attr);} }
@@ -13474,6 +13542,16 @@ const IfcParse::entity& Ifc4::IfcSphere::Class() { return *IFC4_IfcSphere_type;
Ifc4::IfcSphere::IfcSphere(IfcEntityInstanceData* e) : IfcCsgPrimitive3D((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcSphere_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcSphere::IfcSphere(::Ifc4::IfcAxis2Placement3D* v1_Position, double v2_Radius) : IfcCsgPrimitive3D((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcSphere_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Position));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_Radius));data_->setArgument(1,attr);} }
// Function implementations for IfcSphericalSurface
double Ifc4::IfcSphericalSurface::Radius() const { return *data_->getArgument(1); }
void Ifc4::IfcSphericalSurface::setRadius(double v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(1,attr);} }
const IfcParse::entity& Ifc4::IfcSphericalSurface::declaration() const { return *IFC4_IfcSphericalSurface_type; }
const IfcParse::entity& Ifc4::IfcSphericalSurface::Class() { return *IFC4_IfcSphericalSurface_type; }
Ifc4::IfcSphericalSurface::IfcSphericalSurface(IfcEntityInstanceData* e) : IfcElementarySurface((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcSphericalSurface_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcSphericalSurface::IfcSphericalSurface(::Ifc4::IfcAxis2Placement3D* v1_Position, double v2_Radius) : IfcElementarySurface((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcSphericalSurface_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Position));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_Radius));data_->setArgument(1,attr);} }
// Function implementations for IfcStackTerminal
bool Ifc4::IfcStackTerminal::hasPredefinedType() const { return !data_->getArgument(8)->isNull(); }
::Ifc4::IfcStackTerminalTypeEnum::Value Ifc4::IfcStackTerminal::PredefinedType() const { return ::Ifc4::IfcStackTerminalTypeEnum::FromString(*data_->getArgument(8)); }
@@ -14086,6 +14164,20 @@ const IfcParse::entity& Ifc4::IfcSurface::Class() { return *IFC4_IfcSurface_type
Ifc4::IfcSurface::IfcSurface(IfcEntityInstanceData* e) : IfcGeometricRepresentationItem((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcSurface_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcSurface::IfcSurface() : IfcGeometricRepresentationItem((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcSurface_type); }
// Function implementations for IfcSurfaceCurve
::Ifc4::IfcCurve* Ifc4::IfcSurfaceCurve::Curve3D() const { return (::Ifc4::IfcCurve*)((IfcUtil::IfcBaseClass*)(*data_->getArgument(0))); }
void Ifc4::IfcSurfaceCurve::setCurve3D(::Ifc4::IfcCurve* v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(0,attr);} }
IfcTemplatedEntityList< ::Ifc4::IfcPcurve >::ptr Ifc4::IfcSurfaceCurve::AssociatedGeometry() const { IfcEntityList::ptr es = *data_->getArgument(1); return es->as< ::Ifc4::IfcPcurve >(); }
void Ifc4::IfcSurfaceCurve::setAssociatedGeometry(IfcTemplatedEntityList< ::Ifc4::IfcPcurve >::ptr v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize());data_->setArgument(1,attr);} }
::Ifc4::IfcPreferredSurfaceCurveRepresentation::Value Ifc4::IfcSurfaceCurve::MasterRepresentation() const { return ::Ifc4::IfcPreferredSurfaceCurveRepresentation::FromString(*data_->getArgument(2)); }
void Ifc4::IfcSurfaceCurve::setMasterRepresentation(::Ifc4::IfcPreferredSurfaceCurveRepresentation::Value v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,::Ifc4::IfcPreferredSurfaceCurveRepresentation::ToString(v)));data_->setArgument(2,attr);} }
const IfcParse::entity& Ifc4::IfcSurfaceCurve::declaration() const { return *IFC4_IfcSurfaceCurve_type; }
const IfcParse::entity& Ifc4::IfcSurfaceCurve::Class() { return *IFC4_IfcSurfaceCurve_type; }
Ifc4::IfcSurfaceCurve::IfcSurfaceCurve(IfcEntityInstanceData* e) : IfcCurve((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcSurfaceCurve_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcSurfaceCurve::IfcSurfaceCurve(::Ifc4::IfcCurve* v1_Curve3D, IfcTemplatedEntityList< ::Ifc4::IfcPcurve >::ptr v2_AssociatedGeometry, ::Ifc4::IfcPreferredSurfaceCurveRepresentation::Value v3_MasterRepresentation) : IfcCurve((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcSurfaceCurve_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Curve3D));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_AssociatedGeometry)->generalize());data_->setArgument(1,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(v3_MasterRepresentation,::Ifc4::IfcPreferredSurfaceCurveRepresentation::ToString(v3_MasterRepresentation))));data_->setArgument(2,attr);} }
// Function implementations for IfcSurfaceCurveSweptAreaSolid
::Ifc4::IfcCurve* Ifc4::IfcSurfaceCurveSweptAreaSolid::Directrix() const { return (::Ifc4::IfcCurve*)((IfcUtil::IfcBaseClass*)(*data_->getArgument(2))); }
void Ifc4::IfcSurfaceCurveSweptAreaSolid::setDirectrix(::Ifc4::IfcCurve* v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(2,attr);} }
@@ -14681,25 +14773,19 @@ void Ifc4::IfcTendonType::setNominalDiameter(double v) { {IfcWrite::IfcWriteArgu
bool Ifc4::IfcTendonType::hasCrossSectionArea() const { return !data_->getArgument(11)->isNull(); }
double Ifc4::IfcTendonType::CrossSectionArea() const { return *data_->getArgument(11); }
void Ifc4::IfcTendonType::setCrossSectionArea(double v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(11,attr);} }
bool Ifc4::IfcTendonType::hasSheethDiameter() const { return !data_->getArgument(12)->isNull(); }
double Ifc4::IfcTendonType::SheethDiameter() const { return *data_->getArgument(12); }
void Ifc4::IfcTendonType::setSheethDiameter(double v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(12,attr);} }
bool Ifc4::IfcTendonType::hasSheathDiameter() const { return !data_->getArgument(12)->isNull(); }
double Ifc4::IfcTendonType::SheathDiameter() const { return *data_->getArgument(12); }
void Ifc4::IfcTendonType::setSheathDiameter(double v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(12,attr);} }
const IfcParse::entity& Ifc4::IfcTendonType::declaration() const { return *IFC4_IfcTendonType_type; }
const IfcParse::entity& Ifc4::IfcTendonType::Class() { return *IFC4_IfcTendonType_type; }
Ifc4::IfcTendonType::IfcTendonType(IfcEntityInstanceData* e) : IfcReinforcingElementType((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcTendonType_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcTendonType::IfcTendonType(std::string v1_GlobalId, ::Ifc4::IfcOwnerHistory* v2_OwnerHistory, boost::optional< std::string > v3_Name, boost::optional< std::string > v4_Description, boost::optional< std::string > v5_ApplicableOccurrence, boost::optional< IfcTemplatedEntityList< ::Ifc4::IfcPropertySetDefinition >::ptr > v6_HasPropertySets, boost::optional< IfcTemplatedEntityList< ::Ifc4::IfcRepresentationMap >::ptr > v7_RepresentationMaps, boost::optional< std::string > v8_Tag, boost::optional< std::string > v9_ElementType, ::Ifc4::IfcTendonTypeEnum::Value v10_PredefinedType, boost::optional< double > v11_NominalDiameter, boost::optional< double > v12_CrossSectionArea, boost::optional< double > v13_SheethDiameter) : IfcReinforcingElementType((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTendonType_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_GlobalId));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_OwnerHistory));data_->setArgument(1,attr);} if (v3_Name) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_Name));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); } if (v4_Description) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v4_Description));data_->setArgument(3,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(3, attr); } if (v5_ApplicableOccurrence) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v5_ApplicableOccurrence));data_->setArgument(4,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(4, attr); } if (v6_HasPropertySets) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v6_HasPropertySets)->generalize());data_->setArgument(5,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(5, attr); } if (v7_RepresentationMaps) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v7_RepresentationMaps)->generalize());data_->setArgument(6,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(6, attr); } if (v8_Tag) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v8_Tag));data_->setArgument(7,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(7, attr); } if (v9_ElementType) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v9_ElementType));data_->setArgument(8,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(8, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(v10_PredefinedType,::Ifc4::IfcTendonTypeEnum::ToString(v10_PredefinedType))));data_->setArgument(9,attr);} if (v11_NominalDiameter) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v11_NominalDiameter));data_->setArgument(10,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(10, attr); } if (v12_CrossSectionArea) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v12_CrossSectionArea));data_->setArgument(11,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(11, attr); } if (v13_SheethDiameter) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v13_SheethDiameter));data_->setArgument(12,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(12, attr); } }
Ifc4::IfcTendonType::IfcTendonType(std::string v1_GlobalId, ::Ifc4::IfcOwnerHistory* v2_OwnerHistory, boost::optional< std::string > v3_Name, boost::optional< std::string > v4_Description, boost::optional< std::string > v5_ApplicableOccurrence, boost::optional< IfcTemplatedEntityList< ::Ifc4::IfcPropertySetDefinition >::ptr > v6_HasPropertySets, boost::optional< IfcTemplatedEntityList< ::Ifc4::IfcRepresentationMap >::ptr > v7_RepresentationMaps, boost::optional< std::string > v8_Tag, boost::optional< std::string > v9_ElementType, ::Ifc4::IfcTendonTypeEnum::Value v10_PredefinedType, boost::optional< double > v11_NominalDiameter, boost::optional< double > v12_CrossSectionArea, boost::optional< double > v13_SheathDiameter) : IfcReinforcingElementType((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTendonType_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_GlobalId));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_OwnerHistory));data_->setArgument(1,attr);} if (v3_Name) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_Name));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); } if (v4_Description) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v4_Description));data_->setArgument(3,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(3, attr); } if (v5_ApplicableOccurrence) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v5_ApplicableOccurrence));data_->setArgument(4,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(4, attr); } if (v6_HasPropertySets) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v6_HasPropertySets)->generalize());data_->setArgument(5,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(5, attr); } if (v7_RepresentationMaps) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v7_RepresentationMaps)->generalize());data_->setArgument(6,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(6, attr); } if (v8_Tag) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v8_Tag));data_->setArgument(7,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(7, attr); } if (v9_ElementType) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v9_ElementType));data_->setArgument(8,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(8, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(v10_PredefinedType,::Ifc4::IfcTendonTypeEnum::ToString(v10_PredefinedType))));data_->setArgument(9,attr);} if (v11_NominalDiameter) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v11_NominalDiameter));data_->setArgument(10,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(10, attr); } if (v12_CrossSectionArea) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v12_CrossSectionArea));data_->setArgument(11,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(11, attr); } if (v13_SheathDiameter) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v13_SheathDiameter));data_->setArgument(12,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(12, attr); } }
// Function implementations for IfcTessellatedFaceSet
::Ifc4::IfcCartesianPointList3D* Ifc4::IfcTessellatedFaceSet::Coordinates() const { return (::Ifc4::IfcCartesianPointList3D*)((IfcUtil::IfcBaseClass*)(*data_->getArgument(0))); }
void Ifc4::IfcTessellatedFaceSet::setCoordinates(::Ifc4::IfcCartesianPointList3D* v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(0,attr);} }
bool Ifc4::IfcTessellatedFaceSet::hasNormals() const { return !data_->getArgument(1)->isNull(); }
std::vector< std::vector< double > > Ifc4::IfcTessellatedFaceSet::Normals() const { return *data_->getArgument(1); }
void Ifc4::IfcTessellatedFaceSet::setNormals(std::vector< std::vector< double > > v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(1,attr);} }
bool Ifc4::IfcTessellatedFaceSet::hasClosed() const { return !data_->getArgument(2)->isNull(); }
bool Ifc4::IfcTessellatedFaceSet::Closed() const { return *data_->getArgument(2); }
void Ifc4::IfcTessellatedFaceSet::setClosed(bool v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(2,attr);} }
::Ifc4::IfcIndexedColourMap::list::ptr Ifc4::IfcTessellatedFaceSet::HasColours() const { return data_->getInverse(IFC4_IfcIndexedColourMap_type, 0)->as<IfcIndexedColourMap>(); }
::Ifc4::IfcIndexedTextureMap::list::ptr Ifc4::IfcTessellatedFaceSet::HasTextures() const { return data_->getInverse(IFC4_IfcIndexedTextureMap_type, 1)->as<IfcIndexedTextureMap>(); }
@@ -14707,7 +14793,7 @@ void Ifc4::IfcTessellatedFaceSet::setClosed(bool v) { {IfcWrite::IfcWriteArgumen
const IfcParse::entity& Ifc4::IfcTessellatedFaceSet::declaration() const { return *IFC4_IfcTessellatedFaceSet_type; }
const IfcParse::entity& Ifc4::IfcTessellatedFaceSet::Class() { return *IFC4_IfcTessellatedFaceSet_type; }
Ifc4::IfcTessellatedFaceSet::IfcTessellatedFaceSet(IfcEntityInstanceData* e) : IfcTessellatedItem((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcTessellatedFaceSet_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcTessellatedFaceSet::IfcTessellatedFaceSet(::Ifc4::IfcCartesianPointList3D* v1_Coordinates, boost::optional< std::vector< std::vector< double > > > v2_Normals, boost::optional< bool > v3_Closed) : IfcTessellatedItem((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTessellatedFaceSet_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Coordinates));data_->setArgument(0,attr);} if (v2_Normals) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v2_Normals));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); } if (v3_Closed) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_Closed));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); } }
Ifc4::IfcTessellatedFaceSet::IfcTessellatedFaceSet(::Ifc4::IfcCartesianPointList3D* v1_Coordinates) : IfcTessellatedItem((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTessellatedFaceSet_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Coordinates));data_->setArgument(0,attr);} }
// Function implementations for IfcTessellatedItem
@@ -14946,6 +15032,18 @@ const IfcParse::entity& Ifc4::IfcTopologyRepresentation::Class() { return *IFC4_
Ifc4::IfcTopologyRepresentation::IfcTopologyRepresentation(IfcEntityInstanceData* e) : IfcShapeModel((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcTopologyRepresentation_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcTopologyRepresentation::IfcTopologyRepresentation(::Ifc4::IfcRepresentationContext* v1_ContextOfItems, boost::optional< std::string > v2_RepresentationIdentifier, boost::optional< std::string > v3_RepresentationType, IfcTemplatedEntityList< ::Ifc4::IfcRepresentationItem >::ptr v4_Items) : IfcShapeModel((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTopologyRepresentation_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_ContextOfItems));data_->setArgument(0,attr);} if (v2_RepresentationIdentifier) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v2_RepresentationIdentifier));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); } if (v3_RepresentationType) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_RepresentationType));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v4_Items)->generalize());data_->setArgument(3,attr);} }
// Function implementations for IfcToroidalSurface
double Ifc4::IfcToroidalSurface::MajorRadius() const { return *data_->getArgument(1); }
void Ifc4::IfcToroidalSurface::setMajorRadius(double v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(1,attr);} }
double Ifc4::IfcToroidalSurface::MinorRadius() const { return *data_->getArgument(2); }
void Ifc4::IfcToroidalSurface::setMinorRadius(double v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(2,attr);} }
const IfcParse::entity& Ifc4::IfcToroidalSurface::declaration() const { return *IFC4_IfcToroidalSurface_type; }
const IfcParse::entity& Ifc4::IfcToroidalSurface::Class() { return *IFC4_IfcToroidalSurface_type; }
Ifc4::IfcToroidalSurface::IfcToroidalSurface(IfcEntityInstanceData* e) : IfcElementarySurface((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcToroidalSurface_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcToroidalSurface::IfcToroidalSurface(::Ifc4::IfcAxis2Placement3D* v1_Position, double v2_MajorRadius, double v3_MinorRadius) : IfcElementarySurface((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcToroidalSurface_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Position));data_->setArgument(0,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v2_MajorRadius));data_->setArgument(1,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v3_MinorRadius));data_->setArgument(2,attr);} }
// Function implementations for IfcTransformer
bool Ifc4::IfcTransformer::hasPredefinedType() const { return !data_->getArgument(8)->isNull(); }
::Ifc4::IfcTransformerTypeEnum::Value Ifc4::IfcTransformer::PredefinedType() const { return ::Ifc4::IfcTransformerTypeEnum::FromString(*data_->getArgument(8)); }
@@ -15005,17 +15103,23 @@ Ifc4::IfcTrapeziumProfileDef::IfcTrapeziumProfileDef(IfcEntityInstanceData* e) :
Ifc4::IfcTrapeziumProfileDef::IfcTrapeziumProfileDef(::Ifc4::IfcProfileTypeEnum::Value v1_ProfileType, boost::optional< std::string > v2_ProfileName, ::Ifc4::IfcAxis2Placement2D* v3_Position, double v4_BottomXDim, double v5_TopXDim, double v6_YDim, double v7_TopXOffset) : IfcParameterizedProfileDef((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTrapeziumProfileDef_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(v1_ProfileType,::Ifc4::IfcProfileTypeEnum::ToString(v1_ProfileType))));data_->setArgument(0,attr);} if (v2_ProfileName) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v2_ProfileName));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v3_Position));data_->setArgument(2,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v4_BottomXDim));data_->setArgument(3,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v5_TopXDim));data_->setArgument(4,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v6_YDim));data_->setArgument(5,attr);}{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v7_TopXOffset));data_->setArgument(6,attr);} }
// Function implementations for IfcTriangulatedFaceSet
bool Ifc4::IfcTriangulatedFaceSet::hasNormals() const { return !data_->getArgument(1)->isNull(); }
std::vector< std::vector< double > > Ifc4::IfcTriangulatedFaceSet::Normals() const { return *data_->getArgument(1); }
void Ifc4::IfcTriangulatedFaceSet::setNormals(std::vector< std::vector< double > > v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(1,attr);} }
bool Ifc4::IfcTriangulatedFaceSet::hasClosed() const { return !data_->getArgument(2)->isNull(); }
bool Ifc4::IfcTriangulatedFaceSet::Closed() const { return *data_->getArgument(2); }
void Ifc4::IfcTriangulatedFaceSet::setClosed(bool v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(2,attr);} }
std::vector< std::vector< int > > Ifc4::IfcTriangulatedFaceSet::CoordIndex() const { return *data_->getArgument(3); }
void Ifc4::IfcTriangulatedFaceSet::setCoordIndex(std::vector< std::vector< int > > v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(3,attr);} }
bool Ifc4::IfcTriangulatedFaceSet::hasNormalIndex() const { return !data_->getArgument(4)->isNull(); }
std::vector< std::vector< int > > Ifc4::IfcTriangulatedFaceSet::NormalIndex() const { return *data_->getArgument(4); }
void Ifc4::IfcTriangulatedFaceSet::setNormalIndex(std::vector< std::vector< int > > v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(4,attr);} }
bool Ifc4::IfcTriangulatedFaceSet::hasPnIndex() const { return !data_->getArgument(4)->isNull(); }
std::vector< int > /*[1:?]*/ Ifc4::IfcTriangulatedFaceSet::PnIndex() const { return *data_->getArgument(4); }
void Ifc4::IfcTriangulatedFaceSet::setPnIndex(std::vector< int > /*[1:?]*/ v) { {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v);data_->setArgument(4,attr);} }
const IfcParse::entity& Ifc4::IfcTriangulatedFaceSet::declaration() const { return *IFC4_IfcTriangulatedFaceSet_type; }
const IfcParse::entity& Ifc4::IfcTriangulatedFaceSet::Class() { return *IFC4_IfcTriangulatedFaceSet_type; }
Ifc4::IfcTriangulatedFaceSet::IfcTriangulatedFaceSet(IfcEntityInstanceData* e) : IfcTessellatedFaceSet((IfcEntityInstanceData*)0) { if (!e) return; if (e->type() != IFC4_IfcTriangulatedFaceSet_type) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
Ifc4::IfcTriangulatedFaceSet::IfcTriangulatedFaceSet(::Ifc4::IfcCartesianPointList3D* v1_Coordinates, boost::optional< std::vector< std::vector< double > > > v2_Normals, boost::optional< bool > v3_Closed, std::vector< std::vector< int > > v4_CoordIndex, boost::optional< std::vector< std::vector< int > > > v5_NormalIndex) : IfcTessellatedFaceSet((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTriangulatedFaceSet_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Coordinates));data_->setArgument(0,attr);} if (v2_Normals) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v2_Normals));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); } if (v3_Closed) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_Closed));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v4_CoordIndex));data_->setArgument(3,attr);} if (v5_NormalIndex) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v5_NormalIndex));data_->setArgument(4,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(4, attr); } }
Ifc4::IfcTriangulatedFaceSet::IfcTriangulatedFaceSet(::Ifc4::IfcCartesianPointList3D* v1_Coordinates, boost::optional< std::vector< std::vector< double > > > v2_Normals, boost::optional< bool > v3_Closed, std::vector< std::vector< int > > v4_CoordIndex, boost::optional< std::vector< int > /*[1:?]*/ > v5_PnIndex) : IfcTessellatedFaceSet((IfcEntityInstanceData*)0) {data_ = new IfcEntityInstanceData(IFC4_IfcTriangulatedFaceSet_type); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v1_Coordinates));data_->setArgument(0,attr);} if (v2_Normals) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v2_Normals));data_->setArgument(1,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(1, attr); } if (v3_Closed) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v3_Closed));data_->setArgument(2,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(2, attr); }{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((v4_CoordIndex));data_->setArgument(3,attr);} if (v5_PnIndex) {{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((*v5_PnIndex));data_->setArgument(4,attr);} } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); data_->setArgument(4, attr); } }
// Function implementations for IfcTrimmedCurve
::Ifc4::IfcCurve* Ifc4::IfcTrimmedCurve::BasisCurve() const { return (::Ifc4::IfcCurve*)((IfcUtil::IfcBaseClass*)(*data_->getArgument(0))); }
+128 -32
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -40,6 +40,7 @@ public:
it end();
IfcUtil::IfcBaseClass* operator[] (int i);
unsigned int size() const;
void reserve(unsigned capacity);
bool contains(IfcUtil::IfcBaseClass*) const;
template <class U>
typename U::list::ptr as() {
+6
View File
@@ -41,6 +41,7 @@ public:
typedef boost::unordered_map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
typedef std::map<std::string, IfcUtil::IfcBaseClass*> entity_by_guid_t;
typedef std::map<unsigned int, std::vector<unsigned int> > entities_by_ref_t;
typedef std::map<unsigned int, IfcEntityList::ptr> ref_map_t;
typedef entity_by_id_t::const_iterator const_iterator;
class type_iterator : private entities_by_type_t::const_iterator {
@@ -86,6 +87,7 @@ private:
entities_by_type_t bytype;
entities_by_type_t bytype_excl;
entities_by_ref_t byref;
ref_map_t by_ref_cached_;
entity_by_guid_t byguid;
entity_entity_map_t entity_file_map;
@@ -181,6 +183,10 @@ public:
IfcEntityList::ptr getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index);
/// Marks entity as modified so that potential cache for it is invalidated.
/// @todo Currently the whole cache is invalidated. Implement more fine-grained invalidation.
void mark_entity_as_modified(int id);
unsigned int FreshId() { return ++MaxId; }
IfcUtil::IfcBaseClass* addEntity(IfcUtil::IfcBaseClass* entity);
+82 -29
View File
@@ -32,58 +32,101 @@
#include <iostream>
#include <algorithm>
using boost::property_tree::ptree;
namespace {
static const char* severity_strings[] = {"Notice", "Warning", "Error"};
template <typename T>
struct severity_strings {
static const std::array<std::basic_string<T>, 3> value;
};
void plain_text_message(std::ostream& os, const boost::optional<IfcUtil::IfcBaseClass*>& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance) {
os << "[" << severity_strings[type] << "] ";
template <>
const std::array<std::basic_string<char>, 3> severity_strings<char>::value = { "Notice", "Warning", "Error" };
template <>
const std::array<std::basic_string<wchar_t>, 3> severity_strings<wchar_t>::value = { L"Notice", L"Warning", L"Error" };
template <typename T>
void plain_text_message(T& os, const boost::optional<IfcUtil::IfcBaseClass*>& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance) {
os << "[" << severity_strings<typename T::char_type>::value[type] << "] ";
if (current_product) {
std::string global_id = *(**current_product).data().getArgument((**current_product).declaration().as_entity()->attribute_index("GlobalId"));
os << "{" << global_id << "} ";
std::string global_id = *((IfcUtil::IfcBaseEntity*)*current_product)->get("GlobalId");
os << "{" << global_id.c_str() << "} ";
}
os << message << std::endl;
os << message.c_str() << std::endl;
if (instance) {
std::string instance_string = instance->data().toString();
if (instance_string.size() > 259) {
instance_string = instance_string.substr(0, 256) + "...";
}
os << instance_string << std::endl;
os << instance_string.c_str() << std::endl;
}
}
void json_message(std::ostream& os, const boost::optional<IfcUtil::IfcBaseClass*>& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance) {
ptree pt;
pt.put("level", severity_strings[type]);
template <typename T>
std::basic_string<T> string_as(const std::string& s) {
std::basic_string<T> v;
v.assign(s.begin(), s.end());
return v;
}
template <typename T>
void json_message(T& os, const boost::optional<IfcUtil::IfcBaseClass*>& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance) {
boost::property_tree::basic_ptree<std::basic_string<typename T::char_type>, std::basic_string<typename T::char_type> > pt;
// @todo this is crazy
static const typename T::char_type level_string[] = { 'l', 'e', 'v', 'e', 'l', 0 };
static const typename T::char_type product_string[] = { 'p', 'r', 'o', 'd', 'u', 'c', 't', 0 };
static const typename T::char_type message_string[] = { 'm', 'e', 's', 's', 'a', 'g', 'e', 0 };
static const typename T::char_type instance_string[] = { 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 0 };
pt.put(level_string, severity_strings<typename T::char_type>::value[type]);
if (current_product) {
pt.put("product", (**current_product).data().toString());
pt.put(product_string, string_as<typename T::char_type>((**current_product).data().toString()));
}
pt.put("message", message);
pt.put(message_string, string_as<typename T::char_type>(message));
if (instance) {
pt.put("instance", instance->data().toString());
pt.put(instance_string, string_as<typename T::char_type>(instance->data().toString()));
}
boost::property_tree::write_json(os, pt, false);
}
}
void Logger::SetOutput(std::ostream* l1, std::ostream* l2) {
void Logger::SetProduct(boost::optional<IfcUtil::IfcBaseClass*> product) {
current_product = product;
}
void Logger::SetOutput(std::ostream* l1, std::ostream* l2) {
wlog1 = wlog2 = 0;
log1 = l1;
log2 = l2;
if ( ! log2 ) {
if (!log2) {
log2 = &log_stream;
}
}
void Logger::SetOutput(std::wostream* l1, std::wostream* l2) {
log1 = log2 = 0;
wlog1 = l1;
wlog2 = l2;
if (!wlog2) {
log2 = &log_stream;
}
}
void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance) {
if (type > max_severity) {
max_severity = type;
}
if (log2 && type >= verbosity) {
if ((log2 || wlog2) && type >= verbosity) {
if (format == FMT_PLAIN) {
plain_text_message(*log2, current_product, type, message, instance);
if (log2) {
plain_text_message(*log2, current_product, type, message, instance);
} else if (wlog2) {
plain_text_message(*wlog2, current_product, type, message, instance);
}
} else if (format == FMT_JSON) {
json_message(*log2, current_product, type, message, instance);
if (log2) {
json_message(*log2, current_product, type, message, instance);
} else if (wlog2) {
json_message(*wlog2, current_product, type, message, instance);
}
}
}
}
@@ -92,18 +135,26 @@ void Logger::Message(Logger::Severity type, const std::exception& exception, con
Message(type, std::string(exception.what()), instance);
}
template <typename T>
void status(T& log1, const std::string& message, bool new_line) {
log1 << message.c_str();
if (new_line) {
log1 << std::endl;
} else {
log1 << std::flush;
}
}
void Logger::Status(const std::string& message, bool new_line) {
if (log1) {
(*log1) << message;
if ( new_line ) (*log1) << std::endl;
else (*log1) << std::flush;
status(*log1, message, new_line);
} else if (wlog1) {
status(*wlog1, message, new_line);
}
}
void Logger::ProgressBar(int progress) {
if (log1) {
Status("\r[" + std::string(progress,'#') + std::string(50 - progress,' ') + "]", false);
}
Status("\r[" + std::string(progress,'#') + std::string(50 - progress,' ') + "]", false);
}
std::string Logger::GetLog() {
@@ -120,6 +171,8 @@ Logger::Format Logger::OutputFormat() { return format; }
std::ostream* Logger::log1 = 0;
std::ostream* Logger::log2 = 0;
std::wostream* Logger::wlog1 = 0;
std::wostream* Logger::wlog2 = 0;
std::stringstream Logger::log_stream;
Logger::Severity Logger::verbosity = Logger::LOG_NOTICE;
Logger::Severity Logger::max_severity = Logger::LOG_NOTICE;
+12 -4
View File
@@ -38,19 +38,27 @@ public:
typedef enum { LOG_NOTICE, LOG_WARNING, LOG_ERROR } Severity;
typedef enum { FMT_PLAIN, FMT_JSON } Format;
private:
// To both stream variants need to exist at runtime or should this be a
// template argument of Logger or controlled using preprocessor directives?
static std::ostream* log1;
static std::ostream* log2;
static std::wostream* wlog1;
static std::wostream* wlog2;
static std::stringstream log_stream;
static Severity verbosity;
static Format format;
static boost::optional<IfcUtil::IfcBaseClass*> current_product;
static Severity max_severity;
public:
static void SetProduct(boost::optional<IfcUtil::IfcBaseClass*> product);
static void SetProduct(boost::optional<IfcUtil::IfcBaseClass*> product) {
current_product = product;
}
/// Determines to what stream respectively progress and errors are logged
static void SetOutput(std::wostream* l1, std::wostream* l2);
/// Determines to what stream respectively progress and errors are logged
static void SetOutput(std::ostream* l1, std::ostream* l2);
+28 -18
View File
@@ -25,10 +25,6 @@
#include <ctime>
#include <boost/circular_buffer.hpp>
#ifdef _MSC_VER
#include <Windows.h>
#endif
#include <boost/algorithm/string.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
@@ -40,6 +36,7 @@
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcSIPrefix.h"
#include "../ifcparse/IfcSchema.h"
#include "../ifcparse/utils.h"
#ifdef USE_MMAP
#include <boost/filesystem/path.hpp>
@@ -117,9 +114,8 @@ IfcSpfStream::IfcSpfStream(const std::string& fn)
, eof(false)
{
#ifdef _MSC_VER
int fn_buffer_size = MultiByteToWideChar(CP_UTF8, 0, fn.c_str(), -1, 0, 0);
wchar_t* fn_wide = new wchar_t[fn_buffer_size];
MultiByteToWideChar(CP_UTF8, 0, fn.c_str(), -1, fn_wide, fn_buffer_size);
std::wstring fn_ws = IfcUtil::path::from_utf8(fn);
const wchar_t* fn_wide = fn_ws.c_str();
#ifdef USE_MMAP
if (mmap) {
@@ -131,7 +127,6 @@ IfcSpfStream::IfcSpfStream(const std::string& fn)
}
#endif
delete[] fn_wide;
#else
#ifdef USE_MMAP
@@ -1257,7 +1252,9 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
if (this->file) {
register_inverse_visitor visitor(*this->file, *this);
apply_individual_instance_visitor(copy).apply(visitor);
}
this->file->mark_entity_as_modified(id_);
}
attributes_[i] = copy;
}
@@ -1504,6 +1501,11 @@ IfcEntityList::ptr IfcFile::traverse(IfcUtil::IfcBaseClass* instance, int max_le
return IfcParse::traverse(instance, max_level);
}
void IfcFile::mark_entity_as_modified(int /*id*/)
{
by_ref_cached_.clear();
}
void IfcFile::addEntities(IfcEntityList::ptr es) {
for( IfcEntityList::it i = es->begin(); i != es->end(); ++ i ) {
addEntity(*i);
@@ -1868,17 +1870,25 @@ IfcEntityList::ptr IfcFile::instances_by_type(const std::string& t) {
IfcEntityList::ptr IfcFile::instances_by_reference(int t) {
entities_by_ref_t::const_iterator it = byref.find(t);
IfcEntityList::ptr return_value;
IfcEntityList::ptr ret;
if (it != byref.end()) {
const std::vector<unsigned>& ids = it->second;
for (std::vector<unsigned>::const_iterator jt = ids.begin(); jt != ids.end(); ++jt) {
if (!return_value) {
return_value.reset(new IfcEntityList);
}
return_value->push(instance_by_id(*jt));
}
ref_map_t::const_iterator cached_it = by_ref_cached_.find(t);
if (cached_it != by_ref_cached_.end()) {
ret = cached_it->second;
}
else {
if (it->second.size()) {
ret.reset(new IfcEntityList);
ret->reserve((unsigned)it->second.size());
const std::vector<unsigned>& ids = it->second;
for (std::vector<unsigned>::const_iterator jt = ids.begin(); jt != ids.end(); ++jt) {
ret->push(instance_by_id(*jt));
}
}
by_ref_cached_[t] = ret;
}
}
return return_value;
return ret;
}
IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
+49 -47
View File
@@ -195,53 +195,52 @@ namespace IfcParse {
virtual const enumeration_type* as_enumeration_type() const { return this; }
};
class entity : public declaration {
public:
class attribute {
protected:
std::string name_;
const parameter_type* type_of_attribute_;
bool optional_;
public:
attribute(const std::string& name, parameter_type* type_of_attribute, bool optional)
: name_(name)
, type_of_attribute_(type_of_attribute)
, optional_(optional) {}
const std::string& name() const { return name_; }
const parameter_type* type_of_attribute() const { return type_of_attribute_; }
bool optional() const { return optional_; }
};
class inverse_attribute {
public:
typedef enum { bag_type, set_type, unspecified_type } aggregate_type;
protected:
std::string name_;
aggregate_type type_of_aggregation_;
int bound1_, bound2_;
const entity* entity_reference_;
const attribute* attribute_reference_;
public:
inverse_attribute(const std::string& name, aggregate_type type_of_aggregation, int bound1, int bound2, const entity* entity_reference, const attribute* attribute_reference)
: name_(name)
, type_of_aggregation_(type_of_aggregation)
, bound1_(bound1)
, bound2_(bound2)
, entity_reference_(entity_reference)
, attribute_reference_(attribute_reference)
{}
const std::string& name() const { return name_; }
aggregate_type type_of_aggregation() const { return type_of_aggregation_; }
int bound1() const { return bound1_; }
int bound2() const { return bound2_; }
const entity* entity_reference() const { return entity_reference_; }
const attribute* attribute_reference() const { return attribute_reference_; }
};
class attribute {
protected:
std::string name_;
const parameter_type* type_of_attribute_;
bool optional_;
public:
attribute(const std::string& name, parameter_type* type_of_attribute, bool optional)
: name_(name)
, type_of_attribute_(type_of_attribute)
, optional_(optional) {}
const std::string& name() const { return name_; }
const parameter_type* type_of_attribute() const { return type_of_attribute_; }
bool optional() const { return optional_; }
};
class inverse_attribute {
public:
typedef enum { bag_type, set_type, unspecified_type } aggregate_type;
protected:
std::string name_;
aggregate_type type_of_aggregation_;
int bound1_, bound2_;
const entity* entity_reference_;
const attribute* attribute_reference_;
public:
inverse_attribute(const std::string& name, aggregate_type type_of_aggregation, int bound1, int bound2, const entity* entity_reference, const attribute* attribute_reference)
: name_(name)
, type_of_aggregation_(type_of_aggregation)
, bound1_(bound1)
, bound2_(bound2)
, entity_reference_(entity_reference)
, attribute_reference_(attribute_reference) {}
const std::string& name() const { return name_; }
aggregate_type type_of_aggregation() const { return type_of_aggregation_; }
int bound1() const { return bound1_; }
int bound2() const { return bound2_; }
const entity* entity_reference() const { return entity_reference_; }
const attribute* attribute_reference() const { return attribute_reference_; }
};
class entity : public declaration {
protected:
bool is_abstract_;
const entity* supertype_; /* NB: IFC explicitly allows only single inheritance */
std::vector<const entity*> subtypes_;
@@ -276,8 +275,9 @@ namespace IfcParse {
}
public:
entity(const std::string& name, int index_in_schema, entity* supertype)
entity(const std::string& name, bool is_abstract, int index_in_schema, entity* supertype)
: declaration(name, index_in_schema)
, is_abstract_(is_abstract)
, supertype_(supertype)
{}
@@ -293,6 +293,8 @@ namespace IfcParse {
else return false;
}
bool is_abstract() const { return is_abstract_; }
void set_subtypes(const std::vector<const entity*>& subtypes) {
subtypes_ = subtypes;
}
+85 -1
View File
@@ -17,8 +17,43 @@
* *
********************************************************************************/
#ifdef _MSC_VER
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef NOMSG
#define NOMSG NOMSG
#endif
#ifndef NODRAWTEXT
#define NODRAWTEXT NODRAWTEXT
#endif
#ifndef NOGDI
#define NOGDI NOGDI
#endif
#ifndef NOSERVICE
#define NOSERVICE NOSERVICE
#endif
#ifndef NOKERNEL
#define NOKERNEL NOKERNEL
#endif
#ifndef NOUSER
#define NOUSER NOUSER
#endif
#ifndef NOMCX
#define NOMCX NOMCX
#endif
#ifndef NOIME
#define NOIME NOIME
#endif
#include <Windows.h>
#endif
#include "../ifcparse/IfcBaseClass.h"
#include "../ifcparse/Argument.h"
#include "../ifcparse/utils.h"
#include "../ifcparse/IfcException.h"
#include "../ifcparse/IfcEntityList.h"
@@ -42,6 +77,7 @@ void IfcEntityList::push(const IfcEntityList::ptr& l) {
}
}
unsigned int IfcEntityList::size() const { return (unsigned int) ls.size(); }
void IfcEntityList::reserve(unsigned capacity) { ls.reserve((size_t)capacity); }
IfcEntityList::it IfcEntityList::begin() { return ls.begin(); }
IfcEntityList::it IfcEntityList::end() { return ls.end(); }
IfcUtil::IfcBaseClass* IfcEntityList::operator[] (int i) {
@@ -239,4 +275,52 @@ IfcUtil::ArgumentType IfcUtil::from_parameter_type(const IfcParse::parameter_typ
}
return IfcUtil::Argument_UNKNOWN;
}
}
#ifdef _MSC_VER
std::string IfcUtil::path::to_utf8(const std::wstring& str) {
int buffer_size = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, 0, 0, 0, 0);
char* buffer = new char[buffer_size];
WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, buffer, buffer_size, 0, 0);
std::string str_utf8(buffer);
delete[] buffer;
return str_utf8;
}
std::wstring IfcUtil::path::from_utf8(const std::string& str) {
int buffer_size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, 0, 0);
wchar_t* buffer = new wchar_t[buffer_size];
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, buffer_size);
std::wstring str_wide(buffer);
delete[] buffer;
return str_wide;
}
IFC_PARSE_API bool IfcUtil::path::rename_file(const std::string& old_filename, const std::string& new_filename) {
std::wstring old_filename_w = from_utf8(old_filename);
std::wstring new_filename_w = from_utf8(new_filename);
delete_file(new_filename);
const bool success = !!MoveFileW(old_filename_w.c_str(), new_filename_w.c_str());
return success;
}
IFC_PARSE_API bool IfcUtil::path::delete_file(const std::string& filename) {
std::wstring filename_w = from_utf8(filename);
const bool success = !!DeleteFileW(filename_w.c_str());
return success;
}
#else
IFC_PARSE_API bool IfcUtil::path::rename_file(const std::string& old_filename, const std::string& new_filename) {
// Whether or not rename() replaces an existing file is implementation-specific,
// so remove() possible existing file always.
delete_file(new_filename);
return std::rename(old_filename.c_str(), new_filename.c_str()) == 0;
}
IFC_PARSE_API bool IfcUtil::path::delete_file(const std::string& filename) {
return std::remove(filename.c_str());
}
#endif
+4 -4
View File
@@ -47,7 +47,7 @@ protected:
node_type type_;
IfcUtil::IfcBaseClass* inst_;
int idx_;
const IfcParse::entity::inverse_attribute* inv_;
const IfcParse::inverse_attribute* inv_;
std::string tagname_;
std::string id_in_file_;
const IfcParse::parameter_type* aggregate_elem_type_;
@@ -92,7 +92,7 @@ public:
return n;
}
static stack_node inverse(IfcUtil::IfcBaseClass* inst, const IfcParse::entity::inverse_attribute* inv) {
static stack_node inverse(IfcUtil::IfcBaseClass* inst, const IfcParse::inverse_attribute* inv) {
stack_node n;
n.type_ = node_inverse;
n.inst_ = inst;
@@ -125,7 +125,7 @@ public:
IfcUtil::IfcBaseClass* inst() const { return inst_; }
int idx() const { return idx_; }
const IfcParse::entity::inverse_attribute* inv_attr() const { return inv_; }
const IfcParse::inverse_attribute* inv_attr() const { return inv_; }
const std::string& tagname() const { return tagname_; }
const std::string& id_in_file() const { return id_in_file_; }
const IfcParse::parameter_type* aggregate_elem_type() const { return aggregate_elem_type_; }
@@ -483,7 +483,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
auto idx = current->attribute_index(tagname);
if (idx == -1) {
auto inverses = current->all_inverse_attributes();
auto found = std::find_if(inverses.begin(), inverses.end(), [&tagname](const IfcParse::entity::inverse_attribute* attr) {
auto found = std::find_if(inverses.begin(), inverses.end(), [&tagname](const IfcParse::inverse_attribute* attr) {
return attr->name() == tagname;
});
if (found == inverses.end()) {
+59
View File
@@ -0,0 +1,59 @@
/********************************************************************************
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "../ifcparse/ifc_parse_api.h"
#include <string>
#ifndef IFCPARSE_UTILS_H
#define IFCPARSE_UTILS_H
namespace IfcUtil {
/// Replaces spaces and potentially other problem causing characters with underscores.
IFC_PARSE_API void sanitate_material_name(std::string &str);
IFC_PARSE_API void escape_xml(std::string &str);
IFC_PARSE_API void unescape_xml(std::string &str);
namespace path {
IFC_PARSE_API bool delete_file(const std::string& filename);
IFC_PARSE_API bool rename_file(const std::string& old_filename, const std::string& new_filename);
#ifdef _MSC_VER
/// Uses windows.h string conversion functions
IFC_PARSE_API std::string to_utf8(const std::wstring& str);
/// Uses windows.h string conversion functions
IFC_PARSE_API std::wstring from_utf8(const std::string& str);
#else
/// Identity operation
IFC_PARSE_API inline std::string to_utf8(const std::string& str) { return str; }
/// Identity operation
IFC_PARSE_API inline std::string from_utf8(const std::string& str) { return str; }
#endif
}
}
#endif
+11 -17
View File
@@ -78,23 +78,17 @@ IF(PYTHONINTERP_FOUND AND NOT "${PYTHON_EXECUTABLE}" STREQUAL "")
IF("${python_package_dir}" STREQUAL "")
MESSAGE(WARNING "Unable to locate Python site-package directory, unable to install the Python wrapper")
ELSE()
INSTALL(FILES
"${CMAKE_BINARY_DIR}/ifcwrap/ifcopenshell_wrapper.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/__init__.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/entity_instance.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/file.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/guid.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/main.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/template.py"
DESTINATION "${python_package_dir}/ifcopenshell")
INSTALL(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/geom/__init__.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/geom/app.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/geom/main.py"
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/geom/occ_utils.py"
DESTINATION "${python_package_dir}/ifcopenshell/geom")
INSTALL(TARGETS _ifcopenshell_wrapper DESTINATION "${python_package_dir}/ifcopenshell")
FILE(GLOB_RECURSE sourcefiles "${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/*.py")
FOREACH(file ${sourcefiles})
FILE(RELATIVE_PATH relative "${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/" "${file}")
GET_FILENAME_COMPONENT(dir "${relative}" DIRECTORY)
INSTALL(FILES "${file}"
DESTINATION "${python_package_dir}/ifcopenshell/${dir}")
ENDFOREACH()
INSTALL(FILES "${CMAKE_BINARY_DIR}/ifcwrap/ifcopenshell_wrapper.py"
DESTINATION "${python_package_dir}/ifcopenshell")
INSTALL(TARGETS _ifcopenshell_wrapper
DESTINATION "${python_package_dir}/ifcopenshell")
ENDIF()
ELSE()
MESSAGE(WARNING "No Python interpreter found, unable to install the Python wrapper")
+102 -10
View File
@@ -136,8 +136,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
}
{
const std::vector<const IfcParse::entity::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
std::vector<const IfcParse::entity::attribute*>::const_iterator it = attrs.begin();
const std::vector<const IfcParse::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
std::vector<const IfcParse::attribute*>::const_iterator it = attrs.begin();
for (; it != attrs.end(); ++it) {
if ((*it)->name() == name) {
return 1;
@@ -146,8 +146,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
}
{
const std::vector<const IfcParse::entity::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
std::vector<const IfcParse::entity::inverse_attribute*>::const_iterator it = attrs.begin();
const std::vector<const IfcParse::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
std::vector<const IfcParse::inverse_attribute*>::const_iterator it = attrs.begin();
for (; it != attrs.end(); ++it) {
if ((*it)->name() == name) {
return 2;
@@ -178,12 +178,12 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
return std::vector<std::string>(1, "wrappedValue");
}
const std::vector<const IfcParse::entity::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
const std::vector<const IfcParse::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
std::vector<std::string> attr_names;
attr_names.reserve(attrs.size());
std::vector<const IfcParse::entity::attribute*>::const_iterator it = attrs.begin();
std::vector<const IfcParse::attribute*>::const_iterator it = attrs.begin();
for (; it != attrs.end(); ++it) {
attr_names.push_back((*it)->name());
}
@@ -196,12 +196,12 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
return std::vector<std::string>(0);
}
const std::vector<const IfcParse::entity::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
const std::vector<const IfcParse::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
std::vector<std::string> attr_names;
attr_names.reserve(attrs.size());
std::vector<const IfcParse::entity::inverse_attribute*>::const_iterator it = attrs.begin();
std::vector<const IfcParse::inverse_attribute*>::const_iterator it = attrs.begin();
for (; it != attrs.end(); ++it) {
attr_names.push_back((*it)->name());
}
@@ -260,8 +260,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
}
IfcEntityList::ptr get_inverse(const std::string& a) {
const std::vector<const IfcParse::entity::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
std::vector<const IfcParse::entity::inverse_attribute*>::const_iterator it = attrs.begin();
const std::vector<const IfcParse::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
std::vector<const IfcParse::inverse_attribute*>::const_iterator it = attrs.begin();
for (; it != attrs.end(); ++it) {
if ((*it)->name() == a) {
return self->data().getInverse(
@@ -586,6 +586,98 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
}
%}
%extend IfcParse::named_type {
%pythoncode %{
def __repr__(self):
return repr(self.declared_type())
%}
}
%extend IfcParse::simple_type {
%pythoncode %{
def __repr__(self):
return "<%s>" % self.declared_type()
%}
}
%extend IfcParse::aggregation_type {
std::string type_of_aggregation_string() const {
static const char* const aggr_strings[] = {"array", "bag", "list", "set"};
return aggr_strings[(int) $self->type_of_aggregation()];
}
%pythoncode %{
def __repr__(self):
format_bound = lambda i: "?" if i == -1 else str(i)
return "<%s [%s:%s] of %r>" % (
self.type_of_aggregation_string(),
format_bound(self.bound1()),
format_bound(self.bound2()),
self.type_of_element()
)
%}
}
%extend IfcParse::type_declaration {
%pythoncode %{
def __repr__(self):
return "<type %s: %r>" % (self.name(), self.declared_type())
%}
}
%extend IfcParse::select_type {
%pythoncode %{
def __repr__(self):
return "<select %s: (%s)>" % (self.name(), " | ".join(map(repr, self.select_list())))
%}
}
%extend IfcParse::enumeration_type {
%pythoncode %{
def __repr__(self):
return "<enumeration %s: (%s)>" % (self.name(), ", ".join(self.enumeration_items()))
%}
}
%extend IfcParse::attribute {
%pythoncode %{
def __repr__(self):
return "<attribute %s%s: %s>" % (self.name(), "?" if self.optional() else "", self.type_of_attribute())
%}
}
%extend IfcParse::inverse_attribute {
std::string type_of_aggregation_string() const {
static const char* const aggr_strings[] = {"bag", "set", ""};
return aggr_strings[(int) $self->type_of_aggregation()];
}
%pythoncode %{
def __repr__(self):
format_bound = lambda i: "?" if i == -1 else str(i)
return "<inverse %s: %s [%s:%s] of %r for %r>" % (
self.name(),
self.type_of_aggregation_string(),
format_bound(self.bound1()),
format_bound(self.bound2()),
self.entity_reference(),
self.attribute_reference()
)
%}
}
%extend IfcParse::entity {
%pythoncode %{
def __repr__(self):
return "<entity %s>" % (self.name())
%}
}
%extend IfcParse::schema_definition {
%pythoncode %{
def __repr__(self):
return "<schema %s>" % (self.name())
%}
}
%{
static std::stringstream ifcopenshell_log_stream;
%}
+17 -1
View File
@@ -106,12 +106,28 @@
// Conversion functions to convert STL vectors into Python objects
%{
swig_type_info* declaration_type_to_swig(const IfcParse::declaration* t) {
if (t->as_entity()) {
return SWIGTYPE_p_IfcParse__entity;
} else if (t->as_type_declaration()) {
return SWIGTYPE_p_IfcParse__type_declaration;
} else if (t->as_select_type()) {
return SWIGTYPE_p_IfcParse__select_type;
} else if (t->as_enumeration_type()) {
return SWIGTYPE_p_IfcParse__enumeration_type;
}
}
PyObject* pythonize(const int& t) { return PyInt_FromLong(t); }
PyObject* pythonize(const unsigned int& t) { return PyInt_FromLong(t); }
PyObject* pythonize(const bool& t) { return PyBool_FromLong(t); }
PyObject* pythonize(const double& t) { return PyFloat_FromDouble(t); }
PyObject* pythonize(const std::string& t) { return PyUnicode_FromString(t.c_str()); }
PyObject* pythonize(const IfcUtil::IfcBaseClass* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcUtil__IfcBaseClass, 0); }
PyObject* pythonize(const IfcUtil::IfcBaseClass* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcUtil__IfcBaseClass, 0); }
PyObject* pythonize(const IfcParse::attribute* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__attribute, 0); }
PyObject* pythonize(const IfcParse::inverse_attribute* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__inverse_attribute, 0); }
PyObject* pythonize(const IfcParse::entity* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__entity, 0); }
PyObject* pythonize(const IfcParse::declaration* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), declaration_type_to_swig(t), 0); }
// NB: This cannot be temporary as a Python object is constructed from a pointer to the address of this object
PyObject* pythonize(const IfcGeom::Material& t) { return SWIG_NewPointerObj(SWIG_as_voidptr(&t), SWIGTYPE_p_IfcGeom__Material, 0); }
+27
View File
@@ -10,6 +10,25 @@
$result = SWIG_Python_str_FromChar(IfcUtil::ArgumentTypeToString($1));
}
%typemap(out) IfcParse::declaration* {
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1), declaration_type_to_swig($1), 0);
}
%typemap(out) IfcParse::parameter_type* {
if ($1->as_named_type()) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_named_type()), SWIGTYPE_p_IfcParse__named_type, 0);
} else if ($1->as_simple_type()) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_simple_type()), SWIGTYPE_p_IfcParse__simple_type, 0);
} else if ($1->as_aggregation_type()) {
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_aggregation_type()), SWIGTYPE_p_IfcParse__aggregation_type, 0);
}
}
%typemap(out) IfcParse::simple_type::data_type {
static const char* const data_type_strings[] = {"binary", "boolean", "integer", "logical", "number", "real", "string"};
$result = SWIG_Python_str_FromChar(data_type_strings[(int)$1]);
}
%typemap(out) std::pair<IfcUtil::ArgumentType, Argument*> {
// The SWIG %exception directive does not take care
// of our typemap. So the attribute conversion block
@@ -79,6 +98,9 @@
IfcEntityListList::ptr v = arg;
$result = pythonize(v);
break; }
case IfcUtil::Argument_EMPTY_AGGREGATE: {
$result = PyTuple_New(0);
break; }
case IfcUtil::Argument_UNKNOWN:
default:
SWIG_exception(SWIG_RuntimeError,"Unknown attribute type");
@@ -101,8 +123,13 @@
}
%enddef
CREATE_VECTOR_TYPEMAP_OUT(bool)
CREATE_VECTOR_TYPEMAP_OUT(int)
CREATE_VECTOR_TYPEMAP_OUT(unsigned int)
CREATE_VECTOR_TYPEMAP_OUT(double)
CREATE_VECTOR_TYPEMAP_OUT(std::string)
CREATE_VECTOR_TYPEMAP_OUT(IfcGeom::Material)
CREATE_VECTOR_TYPEMAP_OUT(IfcParse::attribute const *)
CREATE_VECTOR_TYPEMAP_OUT(IfcParse::inverse_attribute const *)
CREATE_VECTOR_TYPEMAP_OUT(IfcParse::entity const *)
CREATE_VECTOR_TYPEMAP_OUT(IfcParse::declaration const *)
+2
View File
@@ -34,6 +34,8 @@
#include <string>
#include <cmath>
#include "../ifcparse/utils.h"
static std::string& collada_id(std::string& s)
{
IfcUtil::sanitate_material_name(s);
+1 -1
View File
@@ -198,7 +198,7 @@ private:
ColladaExporter(const std::string& scene_name, const std::string& fn, ColladaSerializer *_serializer,
bool double_precision)
: filename(fn)
, stream(filename, double_precision)
, stream(COLLADASW::NativeString(filename.c_str(), COLLADASW::NativeString::ENCODING_UTF8), double_precision)
, scene(scene_name, stream, _serializer)
, materials(stream, _serializer)
, geometries(stream, _serializer)
@@ -17,6 +17,10 @@
* *
********************************************************************************/
#include "OpenCascadeBasedSerializer.h"
#include "../ifcparse/utils.h"
#include <string>
#include <fstream>
#include <cstdio>
@@ -24,13 +28,11 @@
#include <Standard_Version.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include "OpenCascadeBasedSerializer.h"
bool OpenCascadeBasedSerializer::ready() {
std::ofstream test_file(out_filename.c_str(), std::ios_base::binary);
std::ofstream test_file(IfcUtil::path::from_utf8(out_filename).c_str(), std::ios_base::binary);
bool succeeded = test_file.is_open();
test_file.close();
remove(out_filename.c_str());
IfcUtil::path::delete_file(out_filename);
return succeeded;
}
+3 -1
View File
@@ -25,6 +25,8 @@
#include "../serializers/GeometrySerializer.h"
#include "../serializers/util.h"
#include "../ifcparse/utils.h"
#include <sstream>
#include <string>
#include <limits>
@@ -46,7 +48,7 @@ protected:
public:
SvgSerializer(const std::string& out_filename, const SerializerSettings& settings)
: GeometrySerializer(settings)
, svg_file(out_filename.c_str())
, svg_file(IfcUtil::path::from_utf8(out_filename).c_str())
, xmin(+std::numeric_limits<double>::infinity())
, ymin(+std::numeric_limits<double>::infinity())
, xmax(-std::numeric_limits<double>::infinity())
@@ -22,9 +22,22 @@
#include "../ifcgeom/schema_agnostic/IfcGeomRenderStyles.h"
#include "../ifcparse/utils.h"
#include <boost/lexical_cast.hpp>
#include <iomanip>
WaveFrontOBJSerializer::WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename, const SerializerSettings& settings)
: GeometrySerializer(settings)
, mtl_filename(mtl_filename)
, obj_stream(IfcUtil::path::from_utf8(obj_filename).c_str())
, mtl_stream(IfcUtil::path::from_utf8(mtl_filename).c_str())
, vcount_total(1)
{
obj_stream << std::setprecision(settings.precision);
mtl_stream << std::setprecision(settings.precision);
}
bool WaveFrontOBJSerializer::ready() {
return obj_stream.is_open() && mtl_stream.is_open();
}
+1 -11
View File
@@ -35,17 +35,7 @@ private:
unsigned int vcount_total;
std::set<std::string> materials;
public:
WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename, const SerializerSettings& settings)
: GeometrySerializer(settings)
, mtl_filename(mtl_filename)
, obj_stream(obj_filename.c_str())
, mtl_stream(mtl_filename.c_str())
, vcount_total(1)
{
obj_stream << std::setprecision(settings.precision);
mtl_stream << std::setprecision(settings.precision);
}
WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename, const SerializerSettings& settings);
virtual ~WaveFrontOBJSerializer() {}
bool ready();
void writeHeader();
@@ -17,8 +17,6 @@
* *
********************************************************************************/
#include <map>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/version.hpp>
@@ -29,6 +27,7 @@
#include <algorithm>
#include "../../ifcparse/IfcSIPrefix.h"
#include "../../ifcparse/utils.h"
#include "../../ifcgeom/kernels/opencascade/IfcGeom.h"
using boost::property_tree::ptree;
@@ -36,7 +35,7 @@ using boost::property_tree::ptree;
#include "XmlSerializer.h"
namespace {
struct factory_t {
struct MAKE_TYPE_NAME(factory_t) {
XmlSerializer* operator()(IfcParse::IfcFile* file, const std::string& xml_filename) const {
MAKE_TYPE_NAME(XmlSerializer)* s = new MAKE_TYPE_NAME(XmlSerializer)(file, xml_filename);
s->setFile(file);
@@ -47,7 +46,7 @@ namespace {
void MAKE_INIT_FN(XmlSerializer)(XmlSerializerFactory::Factory* mapping) {
static const std::string schema_name = STRINGIFY(IfcSchema);
factory_t factory;
MAKE_TYPE_NAME(factory_t) factory;
mapping->bind(schema_name, factory);
}
@@ -549,5 +548,7 @@ void MAKE_TYPE_NAME(XmlSerializer)::finalize() {
#else
boost::property_tree::xml_writer_settings<char> settings('\t', 1);
#endif
boost::property_tree::write_xml(xml_filename, root, std::locale(), settings);
std::ofstream f(IfcUtil::path::from_utf8(xml_filename).c_str());
boost::property_tree::write_xml(f, root, settings);
}