mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b2e8219caa | |||
| eddf5488dc | |||
| 533fd59c14 | |||
| 55e3d2959f | |||
| 0714fbdab5 | |||
| 91d6d9f20f | |||
| 0bc187faaa | |||
| 69384e87aa | |||
| 8895368ae3 | |||
| 22ab3ad06a | |||
| 23450c7c39 | |||
| b11f5929bf | |||
| e2bb18476d | |||
| de756166e0 | |||
| 43e6d5f105 |
+165
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -29,10 +29,11 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// Redirect the output (both progress and log) to stdout
|
||||
Ifc::SetOutput(&std::cout,&std::cout);
|
||||
Logger::SetOutput(&std::cout,&std::cout);
|
||||
|
||||
// Parse the IFC file provided in argv[1]
|
||||
if ( ! Ifc::Init(argv[1]) ) {
|
||||
IfcParse::IfcFile file;
|
||||
if ( ! file.Init(argv[1]) ) {
|
||||
std::cout << "Unable to parse .ifc file" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
@@ -53,12 +54,7 @@ int main(int argc, char** argv) {
|
||||
// we need to cast them to IfcWindows. Since these properties
|
||||
// are optional we need to make sure the properties are
|
||||
// defined for the window in question before accessing them.
|
||||
//
|
||||
// Since we are accessing properties that represent a length
|
||||
// measure we can multiply the value by Ifc::LengthUnit, which
|
||||
// contains the ratio of the unit defined in the IfcUnitAssignment
|
||||
// to the standard SI Unit, the meter.
|
||||
IfcBuildingElement::list elements = Ifc::EntitiesByType<IfcBuildingElement>();
|
||||
IfcBuildingElement::list elements = file.EntitiesByType<IfcBuildingElement>();
|
||||
|
||||
std::cout << "Found " << elements->Size() << " elements in " << argv[1] << ":" << std::endl;
|
||||
|
||||
@@ -71,8 +67,8 @@ int main(int argc, char** argv) {
|
||||
const IfcWindow::ptr window = reinterpret_pointer_cast<IfcBuildingElement,IfcWindow>(element);
|
||||
|
||||
if ( window->hasOverallWidth() && window->hasOverallHeight() ) {
|
||||
const float area = window->OverallWidth()*window->OverallHeight() * (Ifc::LengthUnit*Ifc::LengthUnit);
|
||||
std::cout << "This window has an area of " << area << "m2" << std::endl;
|
||||
const double area = window->OverallWidth()*window->OverallHeight();
|
||||
std::cout << "The area of this window is " << area << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ bl_info = {
|
||||
"description": "Import files in the "\
|
||||
"Industry Foundation Classes (.ifc) file format",
|
||||
"author": "Thomas Krijnen, IfcOpenShell",
|
||||
"blender": (2, 5, 8),
|
||||
"api": 37702,
|
||||
"blender": (2, 6, 5),
|
||||
"api": 52851,
|
||||
"location": "File > Import",
|
||||
"warning": "",
|
||||
"wiki_url": "http://sourceforge.net/apps/"\
|
||||
@@ -39,14 +39,6 @@ bl_info = {
|
||||
"tracker_url": "http://sourceforge.net/tracker/?group_id=543113",
|
||||
"category": "Import-Export"}
|
||||
|
||||
import sys
|
||||
max_unicode = 0x110000-1 if sys.platform[0:5] == 'linux' else 0x10000-1
|
||||
wrong_unicode = max_unicode != sys.maxunicode
|
||||
if wrong_unicode:
|
||||
print("\nWarning: wrong unicode representation detected, switching to "\
|
||||
"compatibility layer for text transferral, may result in undefined "\
|
||||
"behaviour, please use offical release from http://blender.org\n")
|
||||
|
||||
if "bpy" in locals():
|
||||
import imp
|
||||
if "IfcImport" in locals():
|
||||
@@ -71,15 +63,9 @@ bpy.types.Object.ifc_type = StringProperty(name="IFC Entity Type",
|
||||
|
||||
|
||||
def import_ifc(filename, use_names, process_relations):
|
||||
global wrong_unicode
|
||||
from . import IfcImport
|
||||
print("Reading %s..."%bpy.path.basename(filename))
|
||||
if wrong_unicode:
|
||||
valid_file = IfcImport.InitUCS2(
|
||||
''.join(['\0']+['\0%s'%s for s in filename]+['\0\0'])
|
||||
)
|
||||
else:
|
||||
valid_file = IfcImport.Init(filename)
|
||||
valid_file = IfcImport.Init(filename)
|
||||
if not valid_file:
|
||||
IfcImport.CleanUp()
|
||||
return False
|
||||
@@ -91,19 +77,12 @@ def import_ifc(filename, use_names, process_relations):
|
||||
print("Creating geometry...")
|
||||
while True:
|
||||
ob = IfcImport.Get()
|
||||
|
||||
if wrong_unicode:
|
||||
ob_name = ''.join([chr(c) for c in ob.name_as_intvector()])
|
||||
ob_type = ''.join([chr(c) for c in ob.type_as_intvector()])
|
||||
ob_guid = ''.join([chr(c) for c in ob.guid_as_intvector()])
|
||||
else:
|
||||
ob_name, ob_type, ob_guid = ob.name, ob.type, ob.guid
|
||||
|
||||
|
||||
f = ob.mesh.faces
|
||||
v = ob.mesh.verts
|
||||
m = ob.matrix
|
||||
t = ob_type[0:21]
|
||||
nm = ob_name if len(ob_name) and use_names else ob_guid
|
||||
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)]
|
||||
@@ -138,9 +117,9 @@ def import_ifc(filename, use_names, process_relations):
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
bob.ifc_id, bob.ifc_guid, bob.ifc_name, bob.ifc_type = \
|
||||
ob.id, ob_guid, ob_name, ob_type
|
||||
ob.id, ob.guid, ob.name, ob.type
|
||||
|
||||
bob.hide = ob_type == 'IfcSpace' or ob_type == 'IfcOpeningElement'
|
||||
bob.hide = ob.type == 'IfcSpace' or ob.type == 'IfcOpeningElement'
|
||||
bob.hide_render = bob.hide
|
||||
|
||||
if ob.id not in id_to_object: id_to_object[ob.id] = []
|
||||
@@ -173,20 +152,9 @@ def import_ifc(filename, use_names, process_relations):
|
||||
if parent_ob.id == -1:
|
||||
bob = None
|
||||
else:
|
||||
if wrong_unicode:
|
||||
parent_ob_name = ''.join(
|
||||
[chr(c) for c in parent_ob.name_as_intvector()])
|
||||
parent_ob_type = ''.join(
|
||||
[chr(c) for c in parent_ob.type_as_intvector()])
|
||||
parent_ob_guid = ''.join(
|
||||
[chr(c) for c in parent_ob.guid_as_intvector()])
|
||||
else:
|
||||
parent_ob_name, parent_ob_type, parent_ob_guid = \
|
||||
parent_ob.name, parent_ob.type, parent_ob.guid
|
||||
|
||||
m = parent_ob.matrix
|
||||
nm = parent_ob_name if len(parent_ob_name) and use_names \
|
||||
else parent_ob_guid
|
||||
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((
|
||||
@@ -201,7 +169,7 @@ def import_ifc(filename, use_names, process_relations):
|
||||
|
||||
bob.ifc_id = parent_ob.id
|
||||
bob.ifc_name, bob.ifc_type, bob.ifc_guid = \
|
||||
parent_ob_name, parent_ob_type, parent_ob_guid
|
||||
parent_ob.name, parent_ob.type, parent_ob.guid
|
||||
|
||||
if parent_ob.parent_id > 0:
|
||||
id_to_parent[parent_id] = parent_ob.parent_id
|
||||
@@ -227,9 +195,8 @@ def import_ifc(filename, use_names, process_relations):
|
||||
if process_relations:
|
||||
print("Done processing relations")
|
||||
|
||||
if not wrong_unicode:
|
||||
txt = bpy.data.texts.new("%s.log"%bpy.path.basename(filename))
|
||||
txt.from_string(IfcImport.GetLog())
|
||||
txt = bpy.data.texts.new("%s.log"%bpy.path.basename(filename))
|
||||
txt.from_string(IfcImport.GetLog())
|
||||
|
||||
IfcImport.CleanUp()
|
||||
|
||||
@@ -253,13 +220,7 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
|
||||
default=False)
|
||||
|
||||
def execute(self, context):
|
||||
global wrong_unicode
|
||||
if wrong_unicode and sys.platform[0:5] != 'linux':
|
||||
self.report({'ERROR'},
|
||||
'Your version of Blender is incompatible with IfcBlender\n' \
|
||||
'Please use the offical release from http://blender.org instead'
|
||||
)
|
||||
elif not import_ifc(self.filepath, self.use_names, self.process_relations):
|
||||
if not import_ifc(self.filepath, self.use_names, self.process_relations):
|
||||
self.report({'ERROR'},
|
||||
'Unable to parse .ifc file or no geometrical entities found'
|
||||
)
|
||||
|
||||
@@ -122,11 +122,11 @@ class ArrayType:
|
||||
self.lower = l[1]
|
||||
def __str__(self):
|
||||
if self.type in entity_names:
|
||||
return "SHARED_PTR< IfcTemplatedEntityList<%s> >"%self.type
|
||||
return "SHARED_PTR< IfcTemplatedEntityList< %s > >"%self.type
|
||||
elif self.type in selections:
|
||||
return "SHARED_PTR< IfcTemplatedEntityList<IfcAbstractSelect> >"
|
||||
return "SHARED_PTR< IfcTemplatedEntityList< IfcAbstractSelect > >"
|
||||
else:
|
||||
return "std::vector<%(type)s> /*[%(lower)s:%(upper)s]*/"%self.__dict__
|
||||
return "std::vector< %(type)s > /*[%(lower)s:%(upper)s]*/"%self.__dict__
|
||||
def type_enum(self):
|
||||
if self.type in simple_types:
|
||||
t = simple_types[self.type].type_enum()
|
||||
@@ -167,7 +167,7 @@ class EnumType:
|
||||
elif generator_mode == 'SOURCE_TO':
|
||||
return '{ "%s" }'%'","'.join([v1 for v1,v2 in self.v])
|
||||
elif generator_mode == 'SOURCE_FROM':
|
||||
return "".join([' if(s=="%s"%s) return %s::%s;\n'%(v1.upper()," "*(self.maxlen-len(v1)),"%(name)s",v2) for v1,v2 in self.v])
|
||||
return "".join([' if(s=="%s"%s) return ::%s::%s::%s;\n'%(v1.upper()," "*(self.maxlen-len(v1)),schema_version,"%(name)s",v2) for v1,v2 in self.v])
|
||||
def __len__(self): return len(self.v)
|
||||
def type_enum(self):
|
||||
return "Argument_ENUMERATION"
|
||||
@@ -292,7 +292,7 @@ class InverseList:
|
||||
s = ""
|
||||
for i in self.l:
|
||||
if generator_mode == 'HEADER':
|
||||
s += "\n SHARED_PTR< IfcTemplatedEntityList<%s> > %s(); // INVERSE %s::%s"%(i.type.type,i.name,i.type.type,i.reference)
|
||||
s += "\n SHARED_PTR< IfcTemplatedEntityList< %s > > %s(); // INVERSE %s::%s"%(i.type.type,i.name,i.type.type,i.reference)
|
||||
elif generator_mode == 'SOURCE':
|
||||
s += "\n%s::list %s::%s() { RETURN_INVERSE(%s) }"%(i.type.type,"%(class_name)s",i.name,i.type.type)
|
||||
return s
|
||||
@@ -317,8 +317,8 @@ class Classdef:
|
||||
"\n static Type::Enum Class();"+
|
||||
"\n %(class_name)s (IfcAbstractEntityPtr e = IfcAbstractEntityPtr());"+
|
||||
"\n typedef %(class_name)s* ptr;"+
|
||||
"\n typedef SHARED_PTR< IfcTemplatedEntityList<%(class_name)s> > list;"+
|
||||
"\n typedef IfcTemplatedEntityList<%(class_name)s>::it it;")%self.__dict__
|
||||
"\n typedef SHARED_PTR< IfcTemplatedEntityList< %(class_name)s > > list;"+
|
||||
"\n typedef IfcTemplatedEntityList< %(class_name)s >::it it;")%self.__dict__
|
||||
)
|
||||
elif generator_mode == 'SOURCE':
|
||||
self.arguments.argstart = argument_start(self.class_name)
|
||||
|
||||
+36
-15
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -42,21 +42,39 @@
|
||||
|
||||
#include "../ifcgeom/IfcShapeList.h"
|
||||
|
||||
// Tolerances for various geometrical operations:
|
||||
// Specifies the deflection of the mesher
|
||||
#define DEFLECTION_TOLERANCE 0.001
|
||||
// Specifies the tolerance of the wire builder, most notably for trimmed curves
|
||||
#define WIRE_CREATION_TOLERANCE 0.0001
|
||||
// Specifies the minimal area of a face to be included in an IfcConnectedFaceset
|
||||
#define MINIMAL_FACE_AREA 0.000001
|
||||
// Specifies the treshold distance under which cartesian points are deemed equal
|
||||
#define POINT_EQUALITY_TOLERANCE 0.00001
|
||||
|
||||
// Specifies maximum number of faces for a shell to be sewed. Sewing shells
|
||||
// that consist of many faces is really detrimental for the performance.
|
||||
#define MAX_FACES_TO_SEW 1000
|
||||
|
||||
namespace IfcGeom {
|
||||
|
||||
// Tolerances and settings for various geometrical operations:
|
||||
enum GeomValue {
|
||||
// Specifies the deflection of the mesher
|
||||
// Default: 0.001m / 1mm
|
||||
GV_DEFLECTION_TOLERANCE,
|
||||
// Specifies the tolerance of the wire builder, most notably for trimmed curves
|
||||
// Defailt: 0.0001m / 0.1mm
|
||||
GV_WIRE_CREATION_TOLERANCE,
|
||||
// Specifies the minimal area of a face to be included in an IfcConnectedFaceset
|
||||
// Default: 0.000001m 0.01cm2
|
||||
GV_MINIMAL_FACE_AREA,
|
||||
// Specifies the treshold distance under which cartesian points are deemed equal
|
||||
// Default: 0.00001m / 0.01mm
|
||||
GV_POINT_EQUALITY_TOLERANCE,
|
||||
// Specifies maximum number of faces for a shell to be sewed. Sewing shells
|
||||
// that consist of many faces is really detrimental for the performance.
|
||||
// Default: 1000
|
||||
GV_MAX_FACES_TO_SEW,
|
||||
// By default singular faces have no explicitly defined orientation, to
|
||||
// force faces to be defined CounterClockWise, set this value greater than zero.
|
||||
GV_FORCE_CCW_FACE_ORIENTATION,
|
||||
// The length unit used the creation of TopoDS_Shapes, primarily affects the
|
||||
// interpretation of IfcCartesianPoints and IfcVector magnitudes
|
||||
// DefaultL 1.0
|
||||
GV_LENGTH_UNIT,
|
||||
// The plane angle unit used for the creation of TopoDS_Shapes, primarily affects
|
||||
// the interpretation of IfcParamaterValues of IfcTrimmedCurves
|
||||
// Default: -1.0 (= not set, fist try degrees, then radians)
|
||||
GV_PLANEANGLE_UNIT,
|
||||
};
|
||||
|
||||
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
|
||||
bool convert_shapes(const IfcUtil::IfcBaseClass* L, ShapeList& result);
|
||||
bool is_shape_collection(const IfcUtil::IfcBaseClass* L);
|
||||
@@ -76,6 +94,9 @@ namespace IfcGeom {
|
||||
bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
|
||||
double shape_volume(const TopoDS_Shape& s);
|
||||
double face_area(const TopoDS_Face& f);
|
||||
void SetValue(GeomValue var, double value);
|
||||
double GetValue(GeomValue var);
|
||||
|
||||
namespace Cache {
|
||||
void Purge();
|
||||
void PurgeShapeCache();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -78,7 +78,7 @@
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve) {
|
||||
const double r = l->Radius() * Ifc::LengthUnit;
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
if ( r <= 0.0f ) { return false; }
|
||||
gp_Trsf trsf;
|
||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||
@@ -94,8 +94,8 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
|
||||
double x = l->SemiAxis1() * Ifc::LengthUnit;
|
||||
double y = l->SemiAxis2() * Ifc::LengthUnit;
|
||||
double x = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
double y = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
if ( x == 0.0f || y == 0.0f || y > x ) { return false; }
|
||||
gp_Trsf trsf;
|
||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -74,6 +74,7 @@
|
||||
#include <ShapeFix_Solid.hxx>
|
||||
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <BRepGProp_Face.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
@@ -81,15 +82,15 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
|
||||
Ifc2x3::IfcFaceBound::list bounds = l->Bounds();
|
||||
Ifc2x3::IfcFaceBound::it it = bounds->begin();
|
||||
Ifc2x3::IfcLoop::ptr loop = (*it)->Bound();
|
||||
TopoDS_Wire wire;
|
||||
if ( ! IfcGeom::convert_wire(loop,wire) ) return false;
|
||||
BRepBuilderAPI_MakeFace mf (wire);
|
||||
TopoDS_Wire outer_wire;
|
||||
if ( ! IfcGeom::convert_wire(loop,outer_wire) ) return false;
|
||||
BRepBuilderAPI_MakeFace mf (outer_wire);
|
||||
BRepBuilderAPI_FaceError er = mf.Error();
|
||||
if ( er == BRepBuilderAPI_NotPlanar ) {
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire, 0.01, TopAbs_WIRE);
|
||||
FTol.SetTolerance(outer_wire, 0.01, TopAbs_WIRE);
|
||||
mf.~BRepBuilderAPI_MakeFace();
|
||||
new (&mf) BRepBuilderAPI_MakeFace(wire);
|
||||
new (&mf) BRepBuilderAPI_MakeFace(outer_wire);
|
||||
er = mf.Error();
|
||||
}
|
||||
if ( er != BRepBuilderAPI_FaceDone ) return false;
|
||||
@@ -116,6 +117,65 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( IfcGeom::GetValue(GV_FORCE_CCW_FACE_ORIENTATION)>0 ) {
|
||||
// Check the orientation of the face by comparing the
|
||||
// normal of the topological surface to the Newell's Method's
|
||||
// normal. 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
|
||||
BRepGProp_Face prop(face);
|
||||
gp_Vec normal_direction;
|
||||
gp_Pnt center;
|
||||
double u1,u2,v1,v2;
|
||||
prop.Bounds(u1,u2,v1,v2);
|
||||
prop.Normal((u1+u2)/2.0,(v1+v2)/2.0,center,normal_direction);
|
||||
gp_Dir face_normal1 = gp_Dir(normal_direction.XYZ());
|
||||
|
||||
double x = 0, y = 0, z = 0;
|
||||
gp_Pnt current, previous, first;
|
||||
int n = 0;
|
||||
// Iterate over the vertices of the outer wire (discarding
|
||||
// any potential holes)
|
||||
for ( TopExp_Explorer exp(outer_wire,TopAbs_VERTEX);; exp.Next()) {
|
||||
unsigned has_more = exp.More();
|
||||
if ( has_more ) {
|
||||
const TopoDS_Vertex& v = TopoDS::Vertex(exp.Current());
|
||||
current = BRep_Tool::Pnt(v);
|
||||
} else {
|
||||
current = first;
|
||||
}
|
||||
if ( n ) {
|
||||
const double& xn = previous.X();
|
||||
const double& yn = previous.Y();
|
||||
const double& zn = previous.Z();
|
||||
const double& xn1 = current.X();
|
||||
const double& yn1 = current.Y();
|
||||
const double& zn1 = current.Z();
|
||||
x += (yn-yn1)*(zn+zn1);
|
||||
y += (xn+xn1)*(zn-zn1);
|
||||
z += (xn-xn1)*(yn+yn1);
|
||||
} else {
|
||||
first = current;
|
||||
}
|
||||
if ( !has_more ) {
|
||||
break;
|
||||
}
|
||||
previous = current;
|
||||
++n;
|
||||
}
|
||||
|
||||
// If Newell's normal does not point in the same direction
|
||||
// as the topological face normal the face orientation is
|
||||
// reversed
|
||||
gp_Vec face_normal2(x,y,z);
|
||||
if ( face_normal1.Dot(face_normal2) < 0 ) {
|
||||
TopAbs_Orientation o = face.Orientation();
|
||||
face.Orientation(o == TopAbs_FORWARD ? TopAbs_REVERSED : TopAbs_FORWARD);
|
||||
}
|
||||
}
|
||||
|
||||
// It might be a good idea to globally discard faces
|
||||
// smaller than a certain treshold value. But for now
|
||||
// only when processing IfcConnectedFacesets the small
|
||||
@@ -145,11 +205,11 @@ bool IfcGeom::convert(const Ifc2x3::IfcArbitraryProfileDefWithVoids::ptr l, Topo
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double x = l->XDim() / 2.0f * Ifc::LengthUnit;
|
||||
const double y = l->YDim() / 2.0f * Ifc::LengthUnit;
|
||||
const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( x == 0.0f || y == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -159,18 +219,18 @@ bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face&
|
||||
return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double x = l->OverallWidth() / 2.0f * Ifc::LengthUnit;
|
||||
const double y = l->OverallDepth() / 2.0f * Ifc::LengthUnit;
|
||||
const double d1 = l->WebThickness() / 2.0f * Ifc::LengthUnit;
|
||||
const double d2 = l->FlangeThickness() * Ifc::LengthUnit;
|
||||
const double x = l->OverallWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double y = l->OverallDepth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
bool doFillet = l->hasFilletRadius();
|
||||
double f;
|
||||
if ( doFillet ) {
|
||||
f = l->FilletRadius() * Ifc::LengthUnit;
|
||||
f = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
|
||||
if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -183,19 +243,19 @@ bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double x = l->Depth() / 2.0f * Ifc::LengthUnit;
|
||||
const double y = l->Width() / 2.0f * Ifc::LengthUnit;
|
||||
const double d1 = l->WallThickness() * Ifc::LengthUnit;
|
||||
const double d2 = l->Girth() * Ifc::LengthUnit;
|
||||
const double x = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double y = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d2 = l->Girth() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
bool doFillet = l->hasInternalFilletRadius();
|
||||
double f1,f2;
|
||||
if ( doFillet ) {
|
||||
f1 = l->InternalFilletRadius() * Ifc::LengthUnit;
|
||||
f1 = l->InternalFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
f2 = f1 + d1;
|
||||
}
|
||||
|
||||
if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -208,21 +268,21 @@ bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double y = l->Depth() / 2.0f * Ifc::LengthUnit;
|
||||
const double x = l->Width() / 2.0f * Ifc::LengthUnit;
|
||||
const double d = l->Thickness() * Ifc::LengthUnit;
|
||||
const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double x = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d = l->Thickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
bool doEdgeFillet = l->hasEdgeRadius();
|
||||
bool doFillet = l->hasFilletRadius();
|
||||
double f1 = 0.0f;
|
||||
double f2 = 0.0f;
|
||||
if (doFillet) {
|
||||
f1 = l->FilletRadius() * Ifc::LengthUnit;
|
||||
f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if ( doEdgeFillet) {
|
||||
f2 = l->EdgeRadius() * Ifc::LengthUnit;
|
||||
f2 = l->EdgeRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
}
|
||||
if ( x == 0.0f || y == 0.0f || d == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -235,9 +295,9 @@ bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double r = l->Radius() * Ifc::LengthUnit;
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
if ( r == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -252,11 +312,11 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& fac
|
||||
return IfcGeom::convert_wire_to_face(w,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double r = l->Radius() * Ifc::LengthUnit;
|
||||
const double t = l->WallThickness() * Ifc::LengthUnit;
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double t = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
if ( r == 0.0f || t == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -23,6 +23,8 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
@@ -88,9 +90,9 @@
|
||||
|
||||
bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
|
||||
BRepOffsetAPI_Sewing builder;
|
||||
builder.SetTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
builder.SetMaxTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
builder.SetMinTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
TopExp_Explorer exp(compound,TopAbs_FACE);
|
||||
if ( ! exp.More() ) return false;
|
||||
for ( ; exp.More(); exp.Next() ) {
|
||||
@@ -101,7 +103,7 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Sh
|
||||
shape = builder.SewedShape();
|
||||
try {
|
||||
ShapeFix_Solid sf_solid;
|
||||
sf_solid.LimitTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
sf_solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
shape = sf_solid.SolidFromShell(TopoDS::Shell(shape));
|
||||
} catch(...) {}
|
||||
return true;
|
||||
@@ -161,7 +163,7 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
||||
TopoDS_Shape entity_shape;
|
||||
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
||||
Ifc::LogMessage("Warning","Applying non uniform transformation to:",entity->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to:",entity->entity);
|
||||
entity_shape = BRepBuilderAPI_GTransform(entity_shape_unlocated,entity_shape_gtrsf,true).Shape();
|
||||
} else {
|
||||
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
||||
@@ -173,17 +175,17 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
const TopoDS_Shape& opening_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(*(it4->second),opening_shape_solid);
|
||||
const gp_GTrsf& opening_shape_gtrsf = *(it4->first);
|
||||
if ( opening_shape_gtrsf.Form() == gp_Other ) {
|
||||
Ifc::LogMessage("Warning","Applying non uniform transformation to opening of:",entity->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to opening of:",entity->entity);
|
||||
}
|
||||
const TopoDS_Shape& opening_shape = opening_shape_gtrsf.Form() == gp_Other
|
||||
? BRepBuilderAPI_GTransform(opening_shape_unlocated,opening_shape_gtrsf,true).Shape()
|
||||
: opening_shape_unlocated.Moved(opening_shape_gtrsf.Trsf());
|
||||
|
||||
double opening_volume, original_shape_volume;
|
||||
if ( Ifc::Verbosity > 1 ) {
|
||||
if ( Logger::Verbosity() >= Logger::LOG_WARNING ) {
|
||||
opening_volume = shape_volume(opening_shape);
|
||||
if ( opening_volume <= ALMOST_ZERO )
|
||||
Ifc::LogMessage("Warning","Empty opening for:",entity->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Empty opening for:",entity->entity);
|
||||
original_shape_volume = shape_volume(entity_shape);
|
||||
}
|
||||
|
||||
@@ -196,17 +198,17 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
bool is_valid = analyser.IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
entity_shape = brep_cut;
|
||||
if ( Ifc::Verbosity > 1 ) {
|
||||
if ( Logger::Verbosity() >= Logger::LOG_WARNING ) {
|
||||
const double volume_after_subtraction = shape_volume(entity_shape);
|
||||
|
||||
if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) )
|
||||
Ifc::LogMessage("Warning","Subtraction yields unchanged volume:",entity->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",entity->entity);
|
||||
}
|
||||
} else {
|
||||
Ifc::LogMessage("Error","Invalid result from subtraction:",entity->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Invalid result from subtraction:",entity->entity);
|
||||
}
|
||||
} else {
|
||||
Ifc::LogMessage("Error","Failed to process subtraction:",entity->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",entity->entity);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -272,7 +274,7 @@ bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const
|
||||
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
||||
TopoDS_Shape entity_shape;
|
||||
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
||||
Ifc::LogMessage("Warning","Applying non uniform transformation to:",entity->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to:",entity->entity);
|
||||
entity_shape = BRepBuilderAPI_GTransform(entity_shape_unlocated,entity_shape_gtrsf,true).Shape();
|
||||
} else {
|
||||
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
||||
@@ -293,7 +295,7 @@ bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const
|
||||
// Apparently processing the boolean operation failed or resulted in an invalid result
|
||||
// in which case the original shape without the subtractions is returned instead
|
||||
// we try convert the openings in the original way, one by one.
|
||||
Ifc::LogMessage("Warning","Subtracting combined openings compound failed:",entity->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Subtracting combined openings compound failed:",entity->entity);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -369,8 +371,8 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) {
|
||||
edge_points.push_back(P2);
|
||||
}
|
||||
if ( edge_points.size() != 2 ) continue;
|
||||
if ( edge_points[0].IsEqual(P1,POINT_EQUALITY_TOLERANCE)) neighbors.push_back(edge_points[1]);
|
||||
else if ( edge_points[1].IsEqual(P1,POINT_EQUALITY_TOLERANCE)) neighbors.push_back(edge_points[0]);
|
||||
if ( edge_points[0].IsEqual(P1,GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[1]);
|
||||
else if ( edge_points[1].IsEqual(P1, GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[0]);
|
||||
}
|
||||
// There should be two of these
|
||||
if ( neighbors.size() != 2 ) return false;
|
||||
@@ -379,10 +381,10 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) {
|
||||
for ( TopExp_Explorer exp2(wire,TopAbs_VERTEX); exp2.More(); exp2.Next() ) {
|
||||
TopoDS_Vertex V2 = TopoDS::Vertex(exp2.Current());
|
||||
gp_Pnt P2 = BRep_Tool::Pnt(V2);
|
||||
if ( P1.IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) continue;
|
||||
if ( P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) continue;
|
||||
bool found = false;
|
||||
for( std::vector<gp_Pnt>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++ it ) {
|
||||
if ( (*it).IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) { found = true; break; }
|
||||
if ( (*it).IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) { found = true; break; }
|
||||
}
|
||||
if ( ! found ) non_neighbors.push_back(P2);
|
||||
}
|
||||
@@ -421,4 +423,70 @@ gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) {
|
||||
} else {
|
||||
return pln.Location().Translated(-pln.Axis().Direction());
|
||||
}
|
||||
}
|
||||
|
||||
static double deflection_tolerance = 0.001;
|
||||
static double wire_creation_tolerance = 0.0001;
|
||||
static double minimal_face_area = 0.000001;
|
||||
static double point_equality_tolerance = 0.00001;
|
||||
static double max_faces_to_sew = -1.0;
|
||||
static double ifc_length_unit = 1.0;
|
||||
static double ifc_planeangle_unit = -1.0;
|
||||
static double force_ccw_face_orientation = -1.0;
|
||||
|
||||
void IfcGeom::SetValue(GeomValue var, double value) {
|
||||
switch (var) {
|
||||
case GV_DEFLECTION_TOLERANCE:
|
||||
deflection_tolerance = value;
|
||||
break;
|
||||
case GV_WIRE_CREATION_TOLERANCE:
|
||||
wire_creation_tolerance = value;
|
||||
break;
|
||||
case GV_MINIMAL_FACE_AREA:
|
||||
minimal_face_area = value;
|
||||
break;
|
||||
case GV_POINT_EQUALITY_TOLERANCE:
|
||||
point_equality_tolerance = value;
|
||||
break;
|
||||
case GV_MAX_FACES_TO_SEW:
|
||||
max_faces_to_sew = value;
|
||||
break;
|
||||
case GV_LENGTH_UNIT:
|
||||
ifc_length_unit = value;
|
||||
break;
|
||||
case GV_PLANEANGLE_UNIT:
|
||||
ifc_planeangle_unit = value;
|
||||
break;
|
||||
case GV_FORCE_CCW_FACE_ORIENTATION:
|
||||
force_ccw_face_orientation = value;
|
||||
break;
|
||||
default:
|
||||
assert(!"never reach here");
|
||||
}
|
||||
}
|
||||
|
||||
double IfcGeom::GetValue(GeomValue var) {
|
||||
switch (var) {
|
||||
case GV_DEFLECTION_TOLERANCE:
|
||||
return deflection_tolerance;
|
||||
case GV_WIRE_CREATION_TOLERANCE:
|
||||
return wire_creation_tolerance;
|
||||
case GV_MINIMAL_FACE_AREA:
|
||||
return minimal_face_area;
|
||||
case GV_POINT_EQUALITY_TOLERANCE:
|
||||
return point_equality_tolerance;
|
||||
case GV_MAX_FACES_TO_SEW:
|
||||
return max_faces_to_sew;
|
||||
case GV_LENGTH_UNIT:
|
||||
return ifc_length_unit;
|
||||
break;
|
||||
case GV_PLANEANGLE_UNIT:
|
||||
return ifc_planeangle_unit;
|
||||
break;
|
||||
case GV_FORCE_CCW_FACE_ORIENTATION:
|
||||
return force_ccw_face_orientation;
|
||||
break;
|
||||
}
|
||||
assert(!"never reach here");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -91,9 +91,9 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianPoint::ptr l, gp_Pnt& point) {
|
||||
IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point)
|
||||
std::vector<double> xyz = l->Coordinates();
|
||||
point = gp_Pnt(
|
||||
xyz.size() ? (xyz[0]*Ifc::LengthUnit) : 0.0f,
|
||||
xyz.size() > 1 ? (xyz[1]*Ifc::LengthUnit) : 0.0f,
|
||||
xyz.size() > 2 ? (xyz[2]*Ifc::LengthUnit) : 0.0f
|
||||
xyz.size() ? (xyz[0]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||
xyz.size() > 1 ? (xyz[1]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||
xyz.size() > 2 ? (xyz[2]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f
|
||||
);
|
||||
CACHE(IfcCartesianPoint,l,point)
|
||||
return true;
|
||||
@@ -113,7 +113,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcVector::ptr l, gp_Vec& v) {
|
||||
IN_CACHE(IfcVector,l,gp_Vec,v)
|
||||
gp_Dir d;
|
||||
IfcGeom::convert(l->Orientation(),d);
|
||||
v = l->Magnitude() * Ifc::LengthUnit * d;
|
||||
v = l->Magnitude() * IfcGeom::GetValue(GV_LENGTH_UNIT) * d;
|
||||
CACHE(IfcVector,l,v)
|
||||
return true;
|
||||
}
|
||||
|
||||
+114
-19
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -51,9 +51,9 @@ bool convert_back_units = false;
|
||||
bool use_faster_booleans = false;
|
||||
|
||||
int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
|
||||
const float X = convert_back_units ? (float) (p.X() / Ifc::LengthUnit) : (float)p.X();
|
||||
const float Y = convert_back_units ? (float) (p.Y() / Ifc::LengthUnit) : (float)p.Y();
|
||||
const float Z = convert_back_units ? (float) (p.Z() / Ifc::LengthUnit) : (float)p.Z();
|
||||
const float X = convert_back_units ? (float) (p.X() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.X();
|
||||
const float Y = convert_back_units ? (float) (p.Y() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Y();
|
||||
const float Z = convert_back_units ? (float) (p.Z() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Z();
|
||||
int i = (int) verts.size() / 3;
|
||||
if ( weld_vertices ) {
|
||||
const VertKey key = VertKey(X,std::pair<float,float>(Y,Z));
|
||||
@@ -71,6 +71,8 @@ int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
|
||||
bool use_world_coords = false;
|
||||
bool use_brep_data = false;
|
||||
|
||||
static IfcParse::IfcFile* ifc_file = 0;
|
||||
|
||||
IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
id = i;
|
||||
|
||||
@@ -102,10 +104,10 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
|
||||
// Triangulate the shape
|
||||
try {
|
||||
//BRepTools::Clean(s);
|
||||
BRepMesh::Mesh(s,DEFLECTION_TOLERANCE);
|
||||
// BRepTools::Clean(s);
|
||||
BRepMesh::Mesh(s, IfcGeom::GetValue(IfcGeom::GV_DEFLECTION_TOLERANCE));
|
||||
} catch(...) {
|
||||
Ifc::LogMessage("Error","Failed to triangulate mesh:",Ifc::EntityById(i)->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to triangulate mesh:",ifc_file->EntityById(i)->entity);
|
||||
continue;
|
||||
}
|
||||
TopExp_Explorer exp;
|
||||
@@ -401,7 +403,7 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes);
|
||||
}
|
||||
} catch(...) {
|
||||
Ifc::LogMessage("Error","Error processing openings for:",ifc_product->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",ifc_product->entity);
|
||||
}
|
||||
if ( use_world_coords ) {
|
||||
for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
@@ -452,7 +454,8 @@ bool IfcGeomObjects::Next() {
|
||||
}
|
||||
std::vector<IfcGeomObjects::IfcObject*> returned_objects;
|
||||
bool IfcGeomObjects::CleanUp() {
|
||||
Ifc::Dispose();
|
||||
// TODO: Correctly implement destructor for IfcFile
|
||||
delete ifc_file;
|
||||
IfcGeom::Cache::Purge();
|
||||
for ( std::vector<IfcGeomObjects::IfcObject*>::const_iterator it = returned_objects.begin();
|
||||
it != returned_objects.end();
|
||||
@@ -465,7 +468,7 @@ bool IfcGeomObjects::CleanUp() {
|
||||
const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
||||
IfcObject* ifc_object = 0;
|
||||
try {
|
||||
const IfcEntity& ifc_entity = Ifc::EntityById(id);
|
||||
const IfcParse::IfcEntity& ifc_entity = ifc_file->EntityById(id);
|
||||
if ( ifc_entity->is(Ifc2x3::Type::IfcProduct) ) {
|
||||
Ifc2x3::IfcProduct::ptr ifc_product = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,Ifc2x3::IfcProduct>(ifc_entity);
|
||||
int parent_id = -1;
|
||||
@@ -488,11 +491,93 @@ const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
||||
const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
|
||||
return current_geom_obj;
|
||||
}
|
||||
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v ) {
|
||||
if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_EXA ) return (double) 1e18;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PETA ) return (double) 1e15;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_TERA ) return (double) 1e12;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_GIGA ) return (double) 1e9;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MEGA ) return (double) 1e6;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_KILO ) return (double) 1e3;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_HECTO ) return (double) 1e2;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECA ) return (double) 1;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECI ) return (double) 1e-1;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_CENTI ) return (double) 1e-2;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MILLI ) return (double) 1e-3;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MICRO ) return (double) 1e-6;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_NANO ) return (double) 1e-9;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PICO ) return (double) 1e-12;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_FEMTO ) return (double) 1e-15;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_ATTO ) return (double) 1e-18;
|
||||
else return 1.0f;
|
||||
}
|
||||
|
||||
void IfcGeomObjects::InitUnits() {
|
||||
// Set default units, set length to meters, angles to undefined
|
||||
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,1.0);
|
||||
IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,-1.0);
|
||||
|
||||
Ifc2x3::IfcUnitAssignment::list unit_assignments = ifc_file->EntitiesByType<Ifc2x3::IfcUnitAssignment>();
|
||||
IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list();
|
||||
if ( unit_assignments->Size() ) {
|
||||
Ifc2x3::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin();
|
||||
units = unit_assignment->Units();
|
||||
}
|
||||
if ( ! units ) {
|
||||
// No units eh... Since tolerances and deflection are specified internally in meters
|
||||
// we will try to find another indication of the model size.
|
||||
Ifc2x3::IfcExtrudedAreaSolid::list extrusions = ifc_file->EntitiesByType<Ifc2x3::IfcExtrudedAreaSolid>();
|
||||
if ( ! extrusions->Size() ) return;
|
||||
double max_height = -1.0f;
|
||||
for ( Ifc2x3::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) {
|
||||
const double depth = (*it)->Depth();
|
||||
if ( depth > max_height ) max_height = depth;
|
||||
}
|
||||
if ( max_height > 100.0f ) IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,0.001);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) {
|
||||
const IfcUtil::IfcAbstractSelect::ptr base = *it;
|
||||
Ifc2x3::IfcSIUnit::ptr unit = Ifc2x3::IfcSIUnit::ptr();
|
||||
double value = 1.0f;
|
||||
if ( base->is(Ifc2x3::Type::IfcConversionBasedUnit) ) {
|
||||
const Ifc2x3::IfcConversionBasedUnit::ptr u = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcConversionBasedUnit>(base);
|
||||
const Ifc2x3::IfcMeasureWithUnit::ptr u2 = u->ConversionFactor();
|
||||
Ifc2x3::IfcUnit u3 = u2->UnitComponent();
|
||||
if ( u3->is(Ifc2x3::Type::IfcSIUnit) ) {
|
||||
unit = (Ifc2x3::IfcSIUnit*) u3;
|
||||
}
|
||||
Ifc2x3::IfcValue v = u2->ValueComponent();
|
||||
IfcUtil::IfcArgumentSelect* v2 = (IfcUtil::IfcArgumentSelect*) v;
|
||||
const double f = *v2->wrappedValue();
|
||||
value *= f;
|
||||
} else if ( base->is(Ifc2x3::Type::IfcSIUnit) ) {
|
||||
unit = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcSIUnit>(base);
|
||||
}
|
||||
if ( unit ) {
|
||||
if ( unit->hasPrefix() ) {
|
||||
value *= UnitPrefixToValue(unit->Prefix());
|
||||
}
|
||||
Ifc2x3::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
|
||||
if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
|
||||
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,value);
|
||||
} else if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
|
||||
IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( IfcException ex ) {
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeomObjects::Init(const std::string fn) {
|
||||
return IfcGeomObjects::Init(fn, 0, 0);
|
||||
}
|
||||
bool _Init() {
|
||||
shapereps = Ifc::EntitiesByType<Ifc2x3::IfcShapeRepresentation>();
|
||||
IfcGeomObjects::InitUnits();
|
||||
|
||||
shapereps = ifc_file->EntitiesByType<Ifc2x3::IfcShapeRepresentation>();
|
||||
if ( ! shapereps ) return false;
|
||||
|
||||
outer = shapereps->begin();
|
||||
@@ -506,18 +591,21 @@ bool _Init() {
|
||||
return true;
|
||||
}
|
||||
bool IfcGeomObjects::Init(const std::string fn, std::ostream* log1, std::ostream* log2) {
|
||||
Ifc::SetOutput(log1,log2);
|
||||
if ( !Ifc::Init(fn) ) return false;
|
||||
Logger::SetOutput(log1,log2);
|
||||
ifc_file = new IfcParse::IfcFile();
|
||||
if ( !ifc_file->Init(fn) ) return false;
|
||||
return _Init();
|
||||
}
|
||||
bool IfcGeomObjects::Init(std::istream& f, int len, std::ostream* log1, std::ostream* log2) {
|
||||
Ifc::SetOutput(log1,log2);
|
||||
if ( !Ifc::Init(f, len) ) return false;
|
||||
Logger::SetOutput(log1,log2);
|
||||
ifc_file = new IfcParse::IfcFile();
|
||||
if ( !ifc_file->Init(f, len) ) return false;
|
||||
return _Init();
|
||||
}
|
||||
bool IfcGeomObjects::Init(void* data, int len) {
|
||||
Ifc::SetOutput(0,0);
|
||||
if ( !Ifc::Init(data, len) ) return false;
|
||||
Logger::SetOutput(0,0);
|
||||
ifc_file = new IfcParse::IfcFile();
|
||||
if ( !ifc_file->Init(data, len) ) return false;
|
||||
return _Init();
|
||||
}
|
||||
void IfcGeomObjects::Settings(int setting, bool value) {
|
||||
@@ -538,7 +626,10 @@ void IfcGeomObjects::Settings(int setting, bool value) {
|
||||
use_faster_booleans = value;
|
||||
break;
|
||||
case SEW_SHELLS:
|
||||
Ifc::SewShells = value;
|
||||
IfcGeom::SetValue(IfcGeom::GV_MAX_FACES_TO_SEW,value ? 1000 : -1);
|
||||
break;
|
||||
case IfcGeomObjects::FORCE_CCW_FACE_ORIENTATION:
|
||||
IfcGeom::SetValue(IfcGeom::GV_FORCE_CCW_FACE_ORIENTATION,value ? 1 : -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -546,5 +637,9 @@ int IfcGeomObjects::Progress() {
|
||||
return 100 * done / total;
|
||||
}
|
||||
std::string IfcGeomObjects::GetLog() {
|
||||
return Ifc::GetLog();
|
||||
return Logger::GetLog();
|
||||
}
|
||||
|
||||
IfcParse::IfcFile* IfcGeomObjects::GetFile() {
|
||||
return ifc_file;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -94,6 +94,9 @@ namespace IfcGeomObjects {
|
||||
// Specifies whether to compose IfcOpeningElements into a single compound
|
||||
// in order to speed up the processing of opening subtractions.
|
||||
const int FASTER_BOOLEANS = 6;
|
||||
// By default singular faces have no explicitly defined orientation, to
|
||||
// force faces to be defined CounterClockWise set this to true.
|
||||
const int FORCE_CCW_FACE_ORIENTATION = 7;
|
||||
|
||||
// End of settings enumeration.
|
||||
|
||||
@@ -143,6 +146,7 @@ namespace IfcGeomObjects {
|
||||
IfcGeomObject(int my_id, int p_id, const std::string& n, const std::string& t, const std::string& g, const gp_Trsf& trsf, IfcMesh* m);
|
||||
};
|
||||
|
||||
void InitUnits();
|
||||
bool Init(const std::string fn);
|
||||
bool Init(void* data, int len);
|
||||
bool Init(const std::string fn, std::ostream* log1= 0, std::ostream* log2= 0);
|
||||
@@ -154,7 +158,7 @@ namespace IfcGeomObjects {
|
||||
int Progress();
|
||||
const IfcObject* GetObject(int id);
|
||||
std::string GetLog();
|
||||
|
||||
IfcParse::IfcFile* GetFile();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -81,7 +81,7 @@
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& shape) {
|
||||
TopoDS_Face face;
|
||||
if ( ! IfcGeom::convert_face(l->SweptArea(),face) ) return false;
|
||||
const double height = l->Depth() * Ifc::LengthUnit;
|
||||
const double height = l->Depth() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(l->Position(),trsf);
|
||||
|
||||
@@ -158,11 +158,11 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
||||
|
||||
const double first_operand_volume = shape_volume(s1);
|
||||
if ( first_operand_volume <= ALMOST_ZERO )
|
||||
Ifc::LogMessage("Warning","Empty solid for:",l->FirstOperand()->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand()->entity);
|
||||
|
||||
if ( !IfcGeom::convert_shape(l->SecondOperand(),s2) ) {
|
||||
shape = s1;
|
||||
Ifc::LogMessage("Error","Failed to convert SecondOperand of:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
||||
if ( ! is_halfspace ) {
|
||||
const double second_operand_volume = shape_volume(s2);
|
||||
if ( second_operand_volume <= ALMOST_ZERO )
|
||||
Ifc::LogMessage("Warning","Empty solid for:",operand2->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2->entity);
|
||||
}
|
||||
|
||||
bool valid_cut = false;
|
||||
@@ -211,7 +211,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
Ifc::LogMessage("Warning","Slightly nudged the SecondOperand of:",l->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Slightly nudged the SecondOperand of:",l->entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,9 +281,9 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
||||
if ( valid_cut ) {
|
||||
const double volume_after_subtraction = shape_volume(shape);
|
||||
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
|
||||
Ifc::LogMessage("Warning","Subtraction yields unchanged volume:",l->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",l->entity);
|
||||
} else {
|
||||
Ifc::LogMessage("Error","Failed to process subtraction:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",l->entity);
|
||||
shape = s1;
|
||||
}
|
||||
|
||||
@@ -294,18 +294,18 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
||||
Ifc2x3::IfcFace::list faces = l->CfsFaces();
|
||||
bool facesAdded = false;
|
||||
const unsigned int num_faces = faces->Size();
|
||||
if ( Ifc::SewShells && num_faces < MAX_FACES_TO_SEW ) {
|
||||
if ( num_faces < GetValue(GV_MAX_FACES_TO_SEW) ) {
|
||||
BRepOffsetAPI_Sewing builder;
|
||||
builder.SetTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
builder.SetMaxTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
builder.SetMinTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
|
||||
TopoDS_Face face;
|
||||
if ( IfcGeom::convert_face(*it,face) && face_area(face) > MINIMAL_FACE_AREA ) {
|
||||
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
|
||||
builder.Add(face);
|
||||
facesAdded = true;
|
||||
} else {
|
||||
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
|
||||
}
|
||||
}
|
||||
if ( ! facesAdded ) return false;
|
||||
@@ -313,7 +313,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
||||
shape = builder.SewedShape();
|
||||
try {
|
||||
ShapeFix_Solid solid;
|
||||
solid.LimitTolerance(POINT_EQUALITY_TOLERANCE);
|
||||
solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
shape = solid.SolidFromShell(TopoDS::Shell(shape));
|
||||
} catch(...) {}
|
||||
} else {
|
||||
@@ -322,11 +322,11 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
||||
builder.MakeCompound(compound);
|
||||
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
|
||||
TopoDS_Face face;
|
||||
if ( IfcGeom::convert_face(*it,face) && face_area(face) > MINIMAL_FACE_AREA ) {
|
||||
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
|
||||
builder.Add(compound,face);
|
||||
facesAdded = true;
|
||||
} else {
|
||||
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
|
||||
Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
|
||||
}
|
||||
}
|
||||
if ( ! facesAdded ) return false;
|
||||
|
||||
+115
-62
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -83,27 +83,60 @@
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) {
|
||||
if ( ! Ifc::hasPlaneAngleUnit ) {
|
||||
Ifc::LogMessage("Warning","Creating a composite curve without unit information:",l->entity);
|
||||
Ifc::hasPlaneAngleUnit = true;
|
||||
if ( IfcGeom::GetValue(GV_PLANEANGLE_UNIT)<0 ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity);
|
||||
|
||||
// Temporarily pretend we do have unit information
|
||||
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,1.0);
|
||||
|
||||
bool succes_radians = false;
|
||||
bool succes_degrees = false;
|
||||
bool use_radians = false;
|
||||
bool use_degrees = false;
|
||||
|
||||
// First try radians
|
||||
Ifc::PlaneAngleUnit = 1.0f;
|
||||
bool succes_radians = IfcGeom::convert(l,wire);
|
||||
bool succes_degrees;
|
||||
if ( succes_radians ) {
|
||||
Ifc::LogMessage("Notice","Used radians to create composite curve");
|
||||
} else {
|
||||
// Now try degrees
|
||||
Ifc::PlaneAngleUnit = 0.0174532925199433f;
|
||||
succes_degrees = IfcGeom::convert(l,wire);
|
||||
if ( succes_degrees ) {
|
||||
Ifc::LogMessage("Notice","Used degrees to create composite curve");
|
||||
TopoDS_Wire wire_radians, wire_degrees;
|
||||
try {
|
||||
succes_radians = IfcGeom::convert(l,wire_radians);
|
||||
} catch (...) {}
|
||||
|
||||
// Now try degrees
|
||||
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,0.0174532925199433);
|
||||
try {
|
||||
succes_degrees = IfcGeom::convert(l,wire_degrees);
|
||||
} catch (...) {}
|
||||
|
||||
// Restore to unknown unit state
|
||||
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,-1.0);
|
||||
|
||||
if ( succes_degrees && ! succes_radians ) {
|
||||
use_degrees = true;
|
||||
} else if ( succes_radians && ! succes_degrees ) {
|
||||
use_radians = true;
|
||||
} else if ( succes_radians && succes_degrees ) {
|
||||
if ( wire_degrees.Closed() && ! wire_radians.Closed() ) {
|
||||
use_degrees = true;
|
||||
} else if ( wire_radians.Closed() && ! wire_degrees.Closed() ) {
|
||||
use_radians = true;
|
||||
} else {
|
||||
// No heuristic left to prefer the one over the other,
|
||||
// apparently both variants are equally succesful.
|
||||
// The curve might be composed of only straight segments.
|
||||
// Let's go with the wire created using radians as that
|
||||
// at least is a SI unit.
|
||||
use_radians = true;
|
||||
}
|
||||
// Restore to radians
|
||||
Ifc::PlaneAngleUnit = 1.0f;
|
||||
}
|
||||
Ifc::hasPlaneAngleUnit = false;
|
||||
return succes_radians || succes_degrees;
|
||||
|
||||
if ( use_radians ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Used radians to create composite curve");
|
||||
wire = wire_radians;
|
||||
} else if ( use_degrees ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Used degrees to create composite curve");
|
||||
wire = wire_degrees;
|
||||
}
|
||||
|
||||
return use_radians || use_degrees;
|
||||
}
|
||||
Ifc2x3::IfcCompositeCurveSegment::list segments = l->Segments();
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
@@ -112,12 +145,12 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
||||
const Ifc2x3::IfcCurve::ptr curve = (*it)->ParentCurve();
|
||||
TopoDS_Wire wire2;
|
||||
if ( ! IfcGeom::convert_wire(curve,wire2) ) {
|
||||
Ifc::LogMessage("Error","Failed to convert curve:",curve->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert curve:",curve->entity);
|
||||
continue;
|
||||
}
|
||||
if ( ! (*it)->SameSense() ) wire2.Reverse();
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire2, WIRE_CREATION_TOLERANCE, TopAbs_WIRE);
|
||||
FTol.SetTolerance(wire2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_WIRE);
|
||||
/*if ( it != segments->begin() ) {
|
||||
TopExp_Explorer exp (wire2,TopAbs_VERTEX);
|
||||
const TopoDS_Vertex& first_vertex = TopoDS::Vertex(exp.Current());
|
||||
@@ -131,7 +164,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
||||
w.Add(wire2);
|
||||
//last_vertex = w.Vertex();
|
||||
if ( w.Error() != BRepBuilderAPI_WireDone ) {
|
||||
Ifc::LogMessage("Error","Failed to join curve segments:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to join curve segments:",l->entity);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -141,7 +174,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
Ifc2x3::IfcCurve::ptr basis_curve = l->BasisCurve();
|
||||
bool isConic = basis_curve->is(Ifc2x3::Type::IfcConic);
|
||||
double parameterFactor = isConic ? Ifc::PlaneAngleUnit : Ifc::LengthUnit;
|
||||
double parameterFactor = isConic ? IfcGeom::GetValue(GV_PLANEANGLE_UNIT) : IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
Handle(Geom_Curve) curve;
|
||||
if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false;
|
||||
bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
|
||||
@@ -149,53 +182,73 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
IfcUtil::IfcAbstractSelect::list trims2 = l->Trim2();
|
||||
bool trimmed1 = false;
|
||||
bool trimmed2 = false;
|
||||
bool sense_agreement = l->SenseAgreement();
|
||||
double flt1;
|
||||
gp_Pnt pnt1;
|
||||
unsigned sense_agreement = l->SenseAgreement() ? 0 : 1;
|
||||
double flts[2];
|
||||
gp_Pnt pnts[2];
|
||||
bool has_flts[2] = {false,false};
|
||||
bool has_pnts[2] = {false,false};
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = trims1->begin(); it != trims1->end(); it ++ ) {
|
||||
const IfcUtil::IfcAbstractSelect::ptr i = *it;
|
||||
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) && trim_cartesian ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnt1 );
|
||||
trimmed1 = true;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) && !trim_cartesian ) {
|
||||
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[sense_agreement] );
|
||||
has_pnts[sense_agreement] = true;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) {
|
||||
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
flt1 = value * parameterFactor;
|
||||
trimmed1 = true;
|
||||
flts[sense_agreement] = value * parameterFactor;
|
||||
has_flts[sense_agreement] = true;
|
||||
}
|
||||
}
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = trims2->begin(); it != trims2->end(); it ++ ) {
|
||||
const IfcUtil::IfcAbstractSelect::ptr i = *it;
|
||||
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) && trim_cartesian && trimmed1 ) {
|
||||
gp_Pnt pnt2;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnt2 );
|
||||
BRepBuilderAPI_MakeEdge e (curve,sense_agreement ? pnt1 : pnt2,sense_agreement ? pnt2 : pnt1);
|
||||
if ( ! e.IsDone() ) {
|
||||
BRepBuilderAPI_EdgeError err = e.Error();
|
||||
if ( err == BRepBuilderAPI_PointProjectionFailed ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(sense_agreement ? pnt1 : pnt2,sense_agreement ? pnt2 : pnt1));
|
||||
Ifc::LogMessage("Warning","Point projection failed for:",l->entity);
|
||||
}
|
||||
} else {
|
||||
w.Add(e.Edge());
|
||||
}
|
||||
trimmed2 = true;
|
||||
break;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) && !trim_cartesian && trimmed1 ) {
|
||||
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[1-sense_agreement] );
|
||||
has_pnts[1-sense_agreement] = true;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) {
|
||||
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
double flt2 = value * parameterFactor;
|
||||
if ( isConic && ALMOST_THE_SAME(fmod(flt2-flt1,(double)(M_PI*2.0)),0.0f) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(curve));
|
||||
} else {
|
||||
BRepBuilderAPI_MakeEdge e (curve,sense_agreement ? flt1 : flt2,sense_agreement ? flt2 : flt1);
|
||||
w.Add(e.Edge());
|
||||
}
|
||||
trimmed2 = true;
|
||||
break;
|
||||
flts[1-sense_agreement] = value * parameterFactor;
|
||||
has_flts[1-sense_agreement] = true;
|
||||
}
|
||||
}
|
||||
if ( trimmed2 ) wire = w.Wire();
|
||||
return trimmed2;
|
||||
trim_cartesian &= has_pnts[0] && has_pnts[1];
|
||||
bool trim_cartesian_failed = !trim_cartesian;
|
||||
if ( trim_cartesian ) {
|
||||
if ( pnts[0].Distance(pnts[1]) < GetValue(GV_WIRE_CREATION_TOLERANCE) ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Skipping segment with length below tolerance level:",l->entity);
|
||||
return false;
|
||||
}
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(pnts[0]);
|
||||
TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(pnts[1]);
|
||||
FTol.SetTolerance(v1, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX);
|
||||
FTol.SetTolerance(v2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_VERTEX);
|
||||
BRepBuilderAPI_MakeEdge e (curve,v1,v2);
|
||||
if ( ! e.IsDone() ) {
|
||||
BRepBuilderAPI_EdgeError err = e.Error();
|
||||
if ( err == BRepBuilderAPI_PointProjectionFailed ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Point projection failed for:",l->entity);
|
||||
trim_cartesian_failed = true;
|
||||
}
|
||||
} else {
|
||||
w.Add(e.Edge());
|
||||
}
|
||||
}
|
||||
if ( (!trim_cartesian || trim_cartesian_failed) && (has_flts[0] && has_flts[1]) ) {
|
||||
if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(curve));
|
||||
} else {
|
||||
BRepBuilderAPI_MakeEdge e (curve,flts[0],flts[1]);
|
||||
w.Add(e.Edge());
|
||||
}
|
||||
} else if ( trim_cartesian_failed && (has_pnts[0] && has_pnts[1]) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(pnts[0],pnts[1]));
|
||||
}
|
||||
if ( w.IsDone() ) {
|
||||
wire = w.Wire();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcPolyline::ptr l, TopoDS_Wire& result) {
|
||||
Ifc2x3::IfcCartesianPoint::list points = l->Points();
|
||||
@@ -204,7 +257,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolyline::ptr l, TopoDS_Wire& result) {
|
||||
gp_Pnt P1;gp_Pnt P2;
|
||||
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
IfcGeom::convert(*it,P2);
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) )
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) )
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
||||
P1 = P2;
|
||||
}
|
||||
@@ -220,13 +273,13 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolyLoop::ptr l, TopoDS_Wire& result) {
|
||||
int count = 0;
|
||||
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
IfcGeom::convert(*it,P2);
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) ) {
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
||||
count ++;
|
||||
} else if ( ! count ) F = P2;
|
||||
P1 = P2;
|
||||
}
|
||||
if ( !P1.IsEqual(F,POINT_EQUALITY_TOLERANCE) ) {
|
||||
if ( !P1.IsEqual(F,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,F));
|
||||
count ++;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -33,7 +33,7 @@ using namespace IfcUtil;
|
||||
|
||||
bool IfcGeom::convert_shapes(const IfcBaseClass* l, ShapeList& r) {
|
||||
#include "IfcRegisterConvertShapes.h"
|
||||
Ifc::LogMessage("Error","No operation defined for:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
bool IfcGeom::is_shape_collection(const IfcBaseClass* l) {
|
||||
@@ -45,21 +45,21 @@ const TopoDS_Shape* IfcGeom::convert_shape(const IfcBaseClass* l, TopoDS_Shape&
|
||||
std::map<int,TopoDS_Shape>::const_iterator it = Cache::Shape.find(id);
|
||||
if ( it != Cache::Shape.end() ) { r = it->second; return &(it->second); }
|
||||
#include "IfcRegisterConvertShape.h"
|
||||
Ifc::LogMessage("Error","No operation defined for:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return 0;
|
||||
}
|
||||
bool IfcGeom::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) {
|
||||
#include "IfcRegisterConvertWire.h"
|
||||
Ifc::LogMessage("Error","No operation defined for:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
bool IfcGeom::convert_face(const IfcBaseClass* l, TopoDS_Face& r) {
|
||||
#include "IfcRegisterConvertFace.h"
|
||||
Ifc::LogMessage("Error","No operation defined for:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
bool IfcGeom::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) {
|
||||
#include "IfcRegisterConvertCurve.h"
|
||||
Ifc::LogMessage("Error","No operation defined for:",l->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
using namespace Ifc2x3;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define CURVE(T) \
|
||||
if ( l->is(T::Class()) ) return convert((T*)l,r);
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define FACE(T) \
|
||||
if ( l->is(T::Class()) ) return convert((T*)l,r);
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define SHAPE(T) \
|
||||
if ( l->is(T::Class()) ) { \
|
||||
try { \
|
||||
@@ -7,8 +7,8 @@
|
||||
return &(Cache::Shape[id]); \
|
||||
} \
|
||||
} catch(...) { } \
|
||||
Ifc::LogMessage("Error","Failed to convert:",l->entity); \
|
||||
return false; \
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \
|
||||
return 0; \
|
||||
}
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define SHAPES(T) \
|
||||
if ( l->is(T::Class()) ) { \
|
||||
try { \
|
||||
return IfcGeom::convert((T*)l,r); \
|
||||
} catch (...) { } \
|
||||
Ifc::LogMessage("Error","Failed to convert:",l->entity); \
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \
|
||||
return false; \
|
||||
}
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define WIRE(T) \
|
||||
if ( l->is(T::Class()) ) return convert((T*)l,r);
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define CLASS(T,V) \
|
||||
std::map<int,V> T;
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef SHAPES
|
||||
#ifndef SHAPES
|
||||
#define SHAPES(T)
|
||||
#endif
|
||||
#ifndef SHAPE
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define CLASS(T,V) bool convert(const T::ptr L, V& r);
|
||||
#define SHAPES(T) CLASS(T,ShapeList)
|
||||
#define SHAPE(T) CLASS(T,TopoDS_Shape)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define SHAPES(T) \
|
||||
if ( l->is(T::Class()) ) return true;
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define CLASS(T,V) \
|
||||
T.clear();
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifdef SHAPES
|
||||
#ifdef SHAPES
|
||||
#undef SHAPES
|
||||
#endif
|
||||
#ifdef SHAPE
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class org_ifcopenshell_IfcOpenShellModel */
|
||||
|
||||
|
||||
+31
-12
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -17,9 +17,9 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Max.h"
|
||||
#include "stdmat.h"
|
||||
#include "istdplug.h"
|
||||
#include <Max.h>
|
||||
#include <stdmat.h>
|
||||
#include <istdplug.h>
|
||||
|
||||
#include "../ifcmax/IfcMax.h"
|
||||
#include "../ifcmax/MaxMaterials.h"
|
||||
@@ -103,13 +103,21 @@ DWORD WINAPI fn(LPVOID arg) { return 0; }
|
||||
|
||||
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) {
|
||||
|
||||
itfc->ProgressStart("Importing file...", TRUE, fn, NULL);
|
||||
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,false);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,true);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
|
||||
|
||||
if ( ! IfcGeomObjects::Init((char*)name,0,0) ) return false;
|
||||
#ifdef _UNICODE
|
||||
int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0);
|
||||
char* fn_mb = new char[fn_buffer_size];
|
||||
WideCharToMultiByte(CP_UTF8, 0, name, -1, fn_mb, fn_buffer_size, 0, 0);
|
||||
#else
|
||||
const char* fn_mb = name;
|
||||
#endif
|
||||
|
||||
if ( ! IfcGeomObjects::Init(fn_mb,0,0) ) return false;
|
||||
|
||||
itfc->ProgressStart(_T("Importing file..."), TRUE, fn, NULL);
|
||||
|
||||
//std::map<int, TriObject*> dict;
|
||||
MtlBaseLib* mats = itfc->GetSceneMtls();
|
||||
@@ -117,14 +125,25 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
|
||||
|
||||
do{
|
||||
|
||||
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
|
||||
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
|
||||
|
||||
#if MAX_RELEASE > 14000
|
||||
TSTR o_type = TSTR::FromCStr(o->type.c_str());
|
||||
TSTR o_guid = TSTR::FromCStr(o->guid.c_str());
|
||||
#elif defined(_UNICODE)
|
||||
TSTR o_type = WStr(o->type.c_str());
|
||||
TSTR o_guid = WStr(o->guid.c_str());
|
||||
#else
|
||||
TSTR o_type = CStr(o->type.c_str());
|
||||
TSTR o_guid = CStr(o->guid.c_str());
|
||||
#endif
|
||||
|
||||
Mtl *m;
|
||||
const int matIndex = mats->FindMtlByName(MSTR(o->type.c_str()));
|
||||
const int matIndex = mats->FindMtlByName(o_type);
|
||||
if ( matIndex == -1 ) {
|
||||
StdMat2* stdm = GetMaterial(o->type);
|
||||
m = stdm;
|
||||
m->SetName(o->type.c_str());
|
||||
m->SetName(o_type);
|
||||
mats->Add(m);
|
||||
itfc->PutMtlToMtlEditor(m,slot++);
|
||||
} else {
|
||||
@@ -169,13 +188,13 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
|
||||
|
||||
ImpNode* node = impitfc->CreateNode();
|
||||
node->Reference(tri);
|
||||
node->SetName(o->guid.c_str());
|
||||
node->SetName(o_guid);
|
||||
node->GetINode()->SetMtl(m);
|
||||
node->SetTransform(0,Matrix3 ( Point3(o->matrix[0],o->matrix[1],o->matrix[2]),Point3(o->matrix[3],o->matrix[4],o->matrix[5]),
|
||||
Point3(o->matrix[6],o->matrix[7],o->matrix[8]),Point3(o->matrix[9],o->matrix[10],o->matrix[11]) ));
|
||||
impitfc->AddNodeToScene(node);
|
||||
|
||||
itfc->ProgressUpdate(IfcGeomObjects::Progress(),true,"");
|
||||
itfc->ProgressUpdate(IfcGeomObjects::Progress(),true,_T(""));
|
||||
|
||||
} while ( IfcGeomObjects::Next() );
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -70,7 +70,7 @@ int main ( int argc, char** argv ) {
|
||||
std::cout << "Creating geometry..." << std::endl;
|
||||
|
||||
// The functions IfcGeomObjects::Get() and IfcGeomObjects::Next() wrap an iterator of all geometrical entities in the Ifc file.
|
||||
// IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcObjects.h for definition)
|
||||
// IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcGeomObjects.h for definition)
|
||||
// IfcGeomObjects::Next() is used to poll whether more geometrical entities are available
|
||||
int vcount_total = 1;
|
||||
do {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../IfcObj/Materials.h"
|
||||
#include "../IfcObj/Materials.h"
|
||||
|
||||
void InitMaterials() {
|
||||
materials["IFCSITE"] = ObjMaterial("IFCSITE",0.7f,0.8f,0.5f);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
+1443
-1443
File diff suppressed because it is too large
Load Diff
+1556
-1556
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
@@ -87,20 +87,35 @@ void IfcCharacterDecoder::addChar(std::stringstream& s,const UChar32& ch) {
|
||||
s.put(substitution_character);
|
||||
#endif
|
||||
}
|
||||
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::File* f) {
|
||||
file = f;
|
||||
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::IfcSpfStream* f) {
|
||||
file = f;
|
||||
#ifdef HAVE_ICU
|
||||
if ( ! destination && mode == UTF8 ) {
|
||||
destination = ucnv_open("utf-8", &status);
|
||||
} else if ( ! destination && mode == LATIN ) {
|
||||
destination = ucnv_open("iso-8859-1", &status);
|
||||
}
|
||||
if (destination) ucnv_close(destination);
|
||||
if (compatibility_converter) ucnv_close(compatibility_converter);
|
||||
destination = 0;
|
||||
compatibility_converter = 0;
|
||||
|
||||
if (mode == DEFAULT) {
|
||||
destination = ucnv_open(0, &status);
|
||||
} else if (mode == UTF8) {
|
||||
destination = ucnv_open("utf-8", &status);
|
||||
} else if (mode == LATIN) {
|
||||
destination = ucnv_open("iso-8859-1", &status);
|
||||
}
|
||||
if (compatibility_charset.empty()) {
|
||||
compatibility_charset = ucnv_getDefaultName();
|
||||
}
|
||||
compatibility_converter = ucnv_open(compatibility_charset.c_str(), &status);
|
||||
#endif
|
||||
}
|
||||
IfcCharacterDecoder::~IfcCharacterDecoder() {
|
||||
#ifdef HAVE_ICU
|
||||
if ( destination ) ucnv_close(destination);
|
||||
if ( converter ) ucnv_close(converter);
|
||||
if ( destination ) ucnv_close(destination);
|
||||
if ( converter ) ucnv_close(converter);
|
||||
if ( compatibility_converter ) ucnv_close(compatibility_converter);
|
||||
destination = 0;
|
||||
converter = 0;
|
||||
compatibility_converter = 0;
|
||||
#endif
|
||||
}
|
||||
IfcCharacterDecoder::operator std::string() {
|
||||
@@ -111,6 +126,9 @@ IfcCharacterDecoder::operator std::string() {
|
||||
int codepage = 1;
|
||||
unsigned int hex = 0;
|
||||
unsigned int hex_count = 0;
|
||||
#ifdef HAVE_ICU
|
||||
unsigned int old_hex = 0; // for compatibility_mode
|
||||
#endif
|
||||
while ( current_char = file->Peek() ) {
|
||||
if ( EXPECTS_CHARACTER(parse_state) ) {
|
||||
#ifdef HAVE_ICU
|
||||
@@ -164,7 +182,24 @@ IfcCharacterDecoder::operator std::string() {
|
||||
if ( (hex_count == 2 && !(parse_state & EXTENDED2)) ||
|
||||
(hex_count == 4 && !(parse_state & EXTENDED4)) ||
|
||||
(hex_count == 8) ) {
|
||||
addChar(s,(UChar32) hex);
|
||||
#ifdef HAVE_ICU
|
||||
if (compatibility_mode) {
|
||||
if (old_hex == 0) {
|
||||
old_hex = hex;
|
||||
} else {
|
||||
char characters[3] = { old_hex, hex };
|
||||
const char* char_array = &characters[0];
|
||||
UChar32 ch = ucnv_getNextUChar(compatibility_converter,&char_array,char_array+2,&status);
|
||||
addChar(s,ch);
|
||||
old_hex = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
addChar(s,(UChar32) hex);
|
||||
#ifdef HAVE_ICU
|
||||
}
|
||||
#endif
|
||||
if ( hex_count == 2 ) parse_state = 0;
|
||||
else CLEAR_HEX(parse_state);
|
||||
hex = hex_count = 0;
|
||||
@@ -177,8 +212,8 @@ IfcCharacterDecoder::operator std::string() {
|
||||
throw IfcException("Invalid character encountered");
|
||||
} else {
|
||||
parse_state = hex = hex_count = 0;
|
||||
// NOTE: this is in fact wrong, this ought to be the representation of the character.
|
||||
// In UTF-8 this is the same, but we should not rely on that.
|
||||
// NOTE: this is in fact wrong, this ought to be the representation of the character.
|
||||
// In UTF-8 this is the same, but we should not rely on that.
|
||||
s.put(current_char);
|
||||
}
|
||||
file->Inc();
|
||||
@@ -246,9 +281,18 @@ void IfcCharacterDecoder::dryRun() {
|
||||
#ifdef HAVE_ICU
|
||||
UConverter* IfcCharacterDecoder::destination = 0;
|
||||
UConverter* IfcCharacterDecoder::converter = 0;
|
||||
UConverter* IfcCharacterDecoder::compatibility_converter = 0;
|
||||
int IfcCharacterDecoder::previous_codepage = -1;
|
||||
UErrorCode IfcCharacterDecoder::status = U_ZERO_ERROR;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ICU
|
||||
IfcCharacterDecoder::ConversionMode IfcCharacterDecoder::mode = IfcCharacterDecoder::JSON;
|
||||
|
||||
// Many BIM software (eg. Revit, ArchiCAD, ...) has wrong behavior
|
||||
bool IfcCharacterDecoder::compatibility_mode = false;
|
||||
std::string IfcCharacterDecoder::compatibility_charset = "";
|
||||
|
||||
#else
|
||||
char IfcCharacterDecoder::substitution_character = '_';
|
||||
#endif
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Implementation of character decoding as described in ISO 10303-21 table 2 and *
|
||||
* table 4 *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
* *
|
||||
* Implementation of character decoding as described in ISO 10303-21 table 2 and *
|
||||
* table 4 *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCCHARACTERDECODER_H
|
||||
#define IFCCHARACTERDECODER_H
|
||||
|
||||
@@ -42,22 +42,30 @@ namespace IfcParse {
|
||||
|
||||
class IfcCharacterDecoder {
|
||||
private:
|
||||
IfcParse::File* file;
|
||||
IfcParse::IfcSpfStream* file;
|
||||
#ifdef HAVE_ICU
|
||||
static UConverter* destination;
|
||||
static UConverter* converter;
|
||||
static UConverter* compatibility_converter;
|
||||
static int previous_codepage;
|
||||
static UErrorCode status;
|
||||
#endif
|
||||
void addChar(std::stringstream& s,const UChar32& ch);
|
||||
public:
|
||||
#ifdef HAVE_ICU
|
||||
enum ConversionMode {UTF8,LATIN,JSON,PYTHON};
|
||||
enum ConversionMode {DEFAULT,UTF8,LATIN,JSON,PYTHON};
|
||||
static ConversionMode mode;
|
||||
|
||||
// Many BIM software (eg. Revit, ArchiCAD, ...) has wrong behavior to encode characters.
|
||||
// It just translate to extended string in system default code page, not unicode.
|
||||
// If you want to process these strings, set true.
|
||||
static bool compatibility_mode;
|
||||
static std::string compatibility_charset;
|
||||
|
||||
#else
|
||||
static char substitution_character;
|
||||
#endif
|
||||
IfcCharacterDecoder(IfcParse::File* file);
|
||||
IfcCharacterDecoder(IfcParse::IfcSpfStream* file);
|
||||
~IfcCharacterDecoder();
|
||||
void dryRun();
|
||||
operator std::string();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -34,21 +34,21 @@
|
||||
// loads a file on disk into multiple chunks, has been disabled.
|
||||
// It proved to be an inefficient way of working with large files,
|
||||
// as often these did not facilitate to be parsed in a sequential
|
||||
// manner efficiently, to enable the paging functionality uncomment
|
||||
// manner efficiently. To enable the paging functionality uncomment
|
||||
// the following statement.
|
||||
//const int BUF_SIZE = (128 * 1024 * 1024);
|
||||
// #define BUF_SIZE (8 * 1024 * 1024)
|
||||
|
||||
namespace IfcParse {
|
||||
/// The File class represents a ISO 10303-21 IFC-SPF file in memory.
|
||||
/// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory.
|
||||
/// The file is interpreted as a sequence of tokens which are lazily
|
||||
/// interpreted only when requested. If the size of the file is
|
||||
/// larger than BUF_SIZE, the file is split into seperate pages, of
|
||||
/// which only one is simultaneously kept in memory, for files
|
||||
/// that define their entities not in a sequential nature, this is
|
||||
/// detrimental for the performance of the parser.
|
||||
class File {
|
||||
class IfcSpfStream {
|
||||
private:
|
||||
std::ifstream stream;
|
||||
FILE* stream;
|
||||
char* buffer;
|
||||
unsigned int ptr;
|
||||
unsigned int len;
|
||||
@@ -61,9 +61,9 @@ namespace IfcParse {
|
||||
bool valid;
|
||||
bool eof;
|
||||
unsigned int size;
|
||||
File(const std::string& fn);
|
||||
File(std::istream& f, int len);
|
||||
File(void* data, int len);
|
||||
IfcSpfStream(const std::string& fn);
|
||||
IfcSpfStream(std::istream& f, int len);
|
||||
IfcSpfStream(void* data, int len);
|
||||
/// Returns the character at the cursor
|
||||
char Peek();
|
||||
/// Returns the character at specified offset
|
||||
|
||||
+152
-237
@@ -22,6 +22,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
@@ -33,17 +37,25 @@ using namespace IfcParse;
|
||||
//
|
||||
// Opens the file, gets the filesize and reads a chunk in memory
|
||||
//
|
||||
File::File(const std::string& fn) {
|
||||
IfcSpfStream::IfcSpfStream(const std::string& fn) {
|
||||
eof = false;
|
||||
stream.open(fn.c_str(),std::ios_base::binary);
|
||||
if ( ! stream.good() ) {
|
||||
#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);
|
||||
stream = _wfopen(fn_wide, L"rb");
|
||||
delete[] fn_wide;
|
||||
#else
|
||||
stream = fopen(fn.c_str(), "rb");
|
||||
#endif
|
||||
if (stream == NULL) {
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
valid = true;
|
||||
stream.seekg(0,std::ios_base::end);
|
||||
size = (unsigned int) stream.tellg();
|
||||
stream.seekg(0,std::ios_base::beg);
|
||||
fseek(stream, 0, SEEK_END);
|
||||
size = (unsigned int) ftell(stream);;
|
||||
rewind(stream);
|
||||
#ifdef BUF_SIZE
|
||||
offset = 0;
|
||||
paging = size > BUF_SIZE;
|
||||
@@ -56,7 +68,7 @@ File::File(const std::string& fn) {
|
||||
ReadBuffer(false);
|
||||
}
|
||||
|
||||
File::File(std::istream& f, int l) {
|
||||
IfcSpfStream::IfcSpfStream(std::istream& f, int l) {
|
||||
eof = false;
|
||||
size = l;
|
||||
#ifdef BUF_SIZE
|
||||
@@ -70,7 +82,7 @@ File::File(std::istream& f, int l) {
|
||||
len = l;
|
||||
}
|
||||
|
||||
File::File(void* data, int l) {
|
||||
IfcSpfStream::IfcSpfStream(void* data, int l) {
|
||||
eof = false;
|
||||
size = l;
|
||||
#ifdef BUF_SIZE
|
||||
@@ -83,37 +95,43 @@ File::File(void* data, int l) {
|
||||
len = l;
|
||||
}
|
||||
|
||||
void File::Close() {
|
||||
stream.close();
|
||||
void IfcSpfStream::Close() {
|
||||
#ifdef BUF_SIZE
|
||||
if ( paging ) fclose(stream);
|
||||
#endif
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
//
|
||||
// Reads a chunk of BUF_SIZE in memory and increments cursor if requested
|
||||
//
|
||||
void File::ReadBuffer(bool inc) {
|
||||
void IfcSpfStream::ReadBuffer(bool inc) {
|
||||
#ifdef BUF_SIZE
|
||||
if ( inc ) {
|
||||
offset += len;
|
||||
stream.seekg(offset,std::ios_base::beg);
|
||||
fseek(stream, offset, SEEK_SET);
|
||||
}
|
||||
#endif
|
||||
eof = stream.eof();
|
||||
eof = feof(stream) != 0;
|
||||
if ( eof ) return;
|
||||
#ifdef BUF_SIZE
|
||||
stream.read(buffer,size < BUF_SIZE ? size : BUF_SIZE);
|
||||
len = (unsigned int) fread(buffer, 1, size < BUF_SIZE ? size : BUF_SIZE, stream);
|
||||
#else
|
||||
stream.read(buffer,size);
|
||||
len = (unsigned int) fread(buffer, 1, size, stream);
|
||||
#endif
|
||||
len = (unsigned int) stream.gcount();
|
||||
eof = len == 0;
|
||||
ptr = 0;
|
||||
#ifdef BUF_SIZE
|
||||
if (!paging) fclose(stream);
|
||||
#else
|
||||
fclose(stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Seeks an arbitrary position in the file
|
||||
//
|
||||
void File::Seek(unsigned int o) {
|
||||
void IfcSpfStream::Seek(unsigned int o) {
|
||||
#ifdef BUF_SIZE
|
||||
if ( !paging ) {
|
||||
#endif
|
||||
@@ -125,8 +143,8 @@ void File::Seek(unsigned int o) {
|
||||
ptr = o - offset;
|
||||
} else {
|
||||
offset = o;
|
||||
stream.clear();
|
||||
stream.seekg(o,std::ios_base::beg);
|
||||
clearerr(stream);
|
||||
fseek(stream, o, SEEK_SET);
|
||||
ReadBuffer(false);
|
||||
}
|
||||
#endif
|
||||
@@ -135,14 +153,14 @@ void File::Seek(unsigned int o) {
|
||||
//
|
||||
// Returns the character at the cursor
|
||||
//
|
||||
char File::Peek() {
|
||||
char IfcSpfStream::Peek() {
|
||||
return buffer[ptr];
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the character at specified offset
|
||||
//
|
||||
char File::Read(unsigned int o) {
|
||||
char IfcSpfStream::Read(unsigned int o) {
|
||||
#ifdef BUF_SIZE
|
||||
if ( ! paging ) {
|
||||
#endif
|
||||
@@ -151,9 +169,9 @@ char File::Read(unsigned int o) {
|
||||
} else if ( o >= offset && (o < (offset+len)) ) {
|
||||
return buffer[o-offset];
|
||||
} else {
|
||||
stream.clear();
|
||||
stream.seekg(o,std::ios_base::beg);
|
||||
return stream.peek();
|
||||
clearerr(stream);
|
||||
fseek(stream, o, SEEK_SET);
|
||||
return ungetc(getc(stream), stream);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -161,7 +179,7 @@ char File::Read(unsigned int o) {
|
||||
//
|
||||
// Returns the cursor position
|
||||
//
|
||||
unsigned int File::Tell() {
|
||||
unsigned int IfcSpfStream::Tell() {
|
||||
#ifdef BUF_SIZE
|
||||
return offset + ptr;
|
||||
#else
|
||||
@@ -172,7 +190,7 @@ unsigned int File::Tell() {
|
||||
//
|
||||
// Increments cursor and reads new chunk if necessary
|
||||
//
|
||||
void File::Inc() {
|
||||
void IfcSpfStream::Inc() {
|
||||
if ( ++ptr == len ) {
|
||||
#ifdef BUF_SIZE
|
||||
if ( paging ) ReadBuffer();
|
||||
@@ -184,13 +202,14 @@ void File::Inc() {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
const char current = File::Peek();
|
||||
if ( current == '\n' || current == '\r' ) File::Inc();
|
||||
const char current = IfcSpfStream::Peek();
|
||||
if ( current == '\n' || current == '\r' ) IfcSpfStream::Inc();
|
||||
}
|
||||
|
||||
Tokens::Tokens(IfcParse::File *f) {
|
||||
Tokens::Tokens(IfcParse::IfcSpfStream *s, IfcParse::IfcFile* f) {
|
||||
file = f;
|
||||
decoder = new IfcCharacterDecoder(f);
|
||||
stream = s;
|
||||
decoder = new IfcCharacterDecoder(s);
|
||||
}
|
||||
|
||||
Tokens::~Tokens() {
|
||||
@@ -202,38 +221,38 @@ Tokens::~Tokens() {
|
||||
//
|
||||
Token Tokens::Next() {
|
||||
|
||||
if ( file->eof ) return TokenPtr();
|
||||
if ( stream->eof ) return TokenPtr();
|
||||
|
||||
char c;
|
||||
|
||||
// Trim whitespace
|
||||
while ( !file->eof ) {
|
||||
c = file->Peek();
|
||||
if ( (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) file->Inc();
|
||||
while ( !stream->eof ) {
|
||||
c = stream->Peek();
|
||||
if ( (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) stream->Inc();
|
||||
else break;
|
||||
}
|
||||
|
||||
if ( file->eof ) return TokenPtr();
|
||||
unsigned int pos = file->Tell();
|
||||
if ( stream->eof ) return TokenPtr();
|
||||
unsigned int pos = stream->Tell();
|
||||
|
||||
bool inString = false;
|
||||
bool inComment = false;
|
||||
|
||||
// If the cursor is at [()=,;$*] we know token consists of single char
|
||||
if ( c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '$' || c == '*' ) {
|
||||
file->Inc();
|
||||
stream->Inc();
|
||||
return TokenPtr(c);
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
|
||||
char p = 0;
|
||||
while ( ! file->eof ) {
|
||||
while ( ! stream->eof ) {
|
||||
|
||||
// Read character and increment pointer if not starting a new token
|
||||
char c = file->Peek();
|
||||
char c = stream->Peek();
|
||||
if ( len && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
||||
file->Inc();
|
||||
stream->Inc();
|
||||
|
||||
// Skip whitespace if not in comment or string
|
||||
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
||||
@@ -247,7 +266,7 @@ Token Tokens::Next() {
|
||||
|
||||
p = c;
|
||||
}
|
||||
if ( len ) return TokenPtr(pos);
|
||||
if ( len ) return TokenPtr(this,pos);
|
||||
else return TokenPtr();
|
||||
}
|
||||
|
||||
@@ -256,18 +275,18 @@ Token Tokens::Next() {
|
||||
// Omits whitespace and comments
|
||||
//
|
||||
std::string Tokens::TokenString(unsigned int offset) {
|
||||
const bool was_eof = file->eof;
|
||||
unsigned int old_offset = file->Tell();
|
||||
file->Seek(offset);
|
||||
const bool was_eof = stream->eof;
|
||||
unsigned int old_offset = stream->Tell();
|
||||
stream->Seek(offset);
|
||||
bool inString = false;
|
||||
bool inComment = false;
|
||||
std::string buffer;
|
||||
buffer.reserve(128);
|
||||
char p = 0;
|
||||
while ( ! file->eof ) {
|
||||
char c = file->Peek();
|
||||
while ( ! stream->eof ) {
|
||||
char c = stream->Peek();
|
||||
if ( buffer.size() && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
||||
file->Inc();
|
||||
stream->Inc();
|
||||
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
||||
if ( !inComment ) buffer.push_back(c);
|
||||
if ( inComment && p == '*' && c == '/' ) inComment = false;
|
||||
@@ -275,8 +294,8 @@ std::string Tokens::TokenString(unsigned int offset) {
|
||||
else if ( !inComment && c == '\'' ) return *decoder;
|
||||
p = c;
|
||||
}
|
||||
if ( was_eof ) file->eof = true;
|
||||
else file->Seek(old_offset);
|
||||
if ( was_eof ) stream->eof = true;
|
||||
else stream->Seek(old_offset);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -284,33 +303,32 @@ std::string Tokens::TokenString(unsigned int offset) {
|
||||
// Functions for creating Tokens from an arbitary file offset.
|
||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
||||
//
|
||||
Token IfcParse::TokenPtr(unsigned int offset) { return offset + 128; }
|
||||
Token IfcParse::TokenPtr(char c) { return c; }
|
||||
Token IfcParse::TokenPtr() { return 0; }
|
||||
Token IfcParse::TokenPtr(Tokens* tokens, unsigned int offset) { return Token(tokens,offset); }
|
||||
Token IfcParse::TokenPtr(char c) { return Token((Tokens*)0,(unsigned) c); }
|
||||
Token IfcParse::TokenPtr() { return Token((Tokens*)0,0); }
|
||||
|
||||
//
|
||||
// Functions to convert Tokens to binary data
|
||||
//
|
||||
unsigned int TokenFunc::Offset(Token t) { return t - 128; }
|
||||
bool TokenFunc::startsWith(Token t, char c) {
|
||||
return Ifc::file->Read(Offset(t)) == c;
|
||||
bool TokenFunc::startsWith(const Token& t, char c) {
|
||||
return t.first->stream->Read(t.second) == c;
|
||||
}
|
||||
bool TokenFunc::isOperator(Token t, char op) {
|
||||
return (t < 128) && (!op || op == t);
|
||||
bool TokenFunc::isOperator(const Token& t, char op) {
|
||||
return (!t.first) && (!op || op == t.second);
|
||||
}
|
||||
bool TokenFunc::isIdentifier(Token t) {
|
||||
bool TokenFunc::isIdentifier(const Token& t) {
|
||||
return ! isOperator(t) && startsWith(t, '#');
|
||||
}
|
||||
bool TokenFunc::isString(Token t) {
|
||||
bool TokenFunc::isString(const Token& t) {
|
||||
return ! isOperator(t) && startsWith(t, '\'');
|
||||
}
|
||||
bool TokenFunc::isEnumeration(Token t) {
|
||||
bool TokenFunc::isEnumeration(const Token& t) {
|
||||
return ! isOperator(t) && startsWith(t, '.');
|
||||
}
|
||||
bool TokenFunc::isDatatype(Token t) {
|
||||
bool TokenFunc::isDatatype(const Token& t) {
|
||||
return ! isOperator(t) && startsWith(t, 'I');
|
||||
}
|
||||
int TokenFunc::asInt(Token t) {
|
||||
int TokenFunc::asInt(const Token& t) {
|
||||
const std::string str = asString(t);
|
||||
// In case of an ENTITY_INSTANCE_NAME skip the leading #
|
||||
const char* start = str.c_str() + (isIdentifier(t) ? 1 : 0);
|
||||
@@ -319,31 +337,31 @@ int TokenFunc::asInt(Token t) {
|
||||
if ( start == end ) throw IfcException("Token is not an integer or identifier");
|
||||
return (int) result;
|
||||
}
|
||||
bool TokenFunc::asBool(Token t) {
|
||||
bool TokenFunc::asBool(const Token& t) {
|
||||
const std::string str = asString(t);
|
||||
return str == "T";
|
||||
}
|
||||
double TokenFunc::asFloat(Token t) {
|
||||
double TokenFunc::asFloat(const Token& t) {
|
||||
const std::string str = asString(t);
|
||||
return (double) atof(str.c_str());
|
||||
}
|
||||
std::string TokenFunc::asString(Token t) {
|
||||
std::string TokenFunc::asString(const Token& t) {
|
||||
if ( isOperator(t,'$') ) return "";
|
||||
else if ( isOperator(t) ) throw IfcException("Token is not a string");
|
||||
std::string str = Ifc::tokens->TokenString(t - 128);
|
||||
std::string str = t.first->TokenString(t.second);
|
||||
return isString(t) || isEnumeration(t) ? str.substr(1,str.size()-2) : str;
|
||||
}
|
||||
std::string TokenFunc::toString(Token t) {
|
||||
if ( isOperator(t) ) return std::string ( (char*) &t, 1 );
|
||||
else return Ifc::tokens->TokenString(t - 128);
|
||||
std::string TokenFunc::toString(const Token& t) {
|
||||
if ( isOperator(t) ) return std::string ( (char*) &t.second , 1 );
|
||||
else return t.first->TokenString(t.second);
|
||||
}
|
||||
|
||||
|
||||
TokenArgument::TokenArgument(Token t) {
|
||||
TokenArgument::TokenArgument(const Token& t) {
|
||||
token = t;
|
||||
}
|
||||
|
||||
EntityArgument::EntityArgument(Ifc2x3::Type::Enum ty, Token t) {
|
||||
EntityArgument::EntityArgument(Ifc2x3::Type::Enum ty, const Token& t) {
|
||||
entity = new IfcUtil::IfcArgumentSelect(ty,new TokenArgument(t));
|
||||
}
|
||||
|
||||
@@ -352,10 +370,11 @@ EntityArgument::EntityArgument(Ifc2x3::Type::Enum ty, Token t) {
|
||||
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
||||
//
|
||||
ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
||||
while( Token next = t->Next() ) {
|
||||
if ( TokenFunc::isOperator(next,',') ) continue;
|
||||
if ( TokenFunc::isOperator(next,')') ) break;
|
||||
if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
|
||||
Token next = t->Next();
|
||||
while( next.second || next.first ) {
|
||||
if ( TokenFunc::isOperator(next,',') ) {}
|
||||
else if ( TokenFunc::isOperator(next,')') ) break;
|
||||
else if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
|
||||
else {
|
||||
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
|
||||
if ( TokenFunc::isDatatype(next) ) {
|
||||
@@ -363,13 +382,14 @@ ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
||||
try {
|
||||
Push ( new EntityArgument(Ifc2x3::Type::FromString(TokenFunc::asString(next)),t->Next()) );
|
||||
} catch ( IfcException& e ) {
|
||||
Ifc::LogMessage("Error",e.what());
|
||||
Logger::Message(Logger::LOG_ERROR,e.what());
|
||||
}
|
||||
t->Next();
|
||||
} else {
|
||||
Push ( new TokenArgument(next) );
|
||||
}
|
||||
}
|
||||
next = t->Next();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,11 +474,7 @@ TokenArgument::operator std::string() const { return TokenFunc::asString(token);
|
||||
TokenArgument::operator std::vector<double>() const { throw IfcException("Argument is not a list of floats"); }
|
||||
TokenArgument::operator std::vector<int>() const { throw IfcException("Argument is not a list of ints"); }
|
||||
TokenArgument::operator std::vector<std::string>() const { throw IfcException("Argument is not a list of strings"); }
|
||||
TokenArgument::operator IfcUtil::IfcSchemaEntity() const { return Ifc::EntityById(TokenFunc::asInt(token)); }
|
||||
/*TokenArgument::operator IfcUtil::IfcAbstractSelect::ptr() const {
|
||||
//TODO Fix memory leak
|
||||
return new IfcUtil::IfcEntitySelect(*this);
|
||||
}*/
|
||||
TokenArgument::operator IfcUtil::IfcSchemaEntity() const { return token.first->file->EntityById(TokenFunc::asInt(token)); }
|
||||
TokenArgument::operator IfcEntities() const { throw IfcException("Argument is not a list of entities"); }
|
||||
unsigned int TokenArgument::Size() const { return 1; }
|
||||
ArgumentPtr TokenArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
||||
@@ -496,19 +512,21 @@ EntityArgument::~EntityArgument() { delete entity; }
|
||||
//
|
||||
// Reads an Entity from the list of Tokens
|
||||
//
|
||||
Entity::Entity(unsigned int i, Tokens* t) {
|
||||
Token datatype = t->Next();
|
||||
Entity::Entity(unsigned int i, IfcFile* f) { //: file(f) {
|
||||
file = f;
|
||||
Token datatype = f->tokens->Next();
|
||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
||||
_id = i;
|
||||
args = ArgumentPtr();
|
||||
offset = TokenFunc::Offset(datatype);
|
||||
offset = datatype.second;
|
||||
}
|
||||
|
||||
//
|
||||
// Reads an Entity from the list of Tokens at the specified offset in the file
|
||||
//
|
||||
Entity::Entity(unsigned int i, Tokens* t, unsigned int o) {
|
||||
Entity::Entity(unsigned int i, IfcFile* f, unsigned int o) { // : file(f) {
|
||||
file = f;
|
||||
std::vector<unsigned int> ids;
|
||||
_id = i;
|
||||
offset = o;
|
||||
@@ -539,16 +557,16 @@ unsigned int Entity::getArgumentCount() {
|
||||
//
|
||||
void Entity::Load(std::vector<unsigned int>& ids, bool seek) {
|
||||
if ( seek ) {
|
||||
Ifc::file->Seek(offset);
|
||||
Token datatype = Ifc::tokens->Next();
|
||||
file->tokens->stream->Seek(offset);
|
||||
Token datatype = file->tokens->Next();
|
||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
||||
}
|
||||
Token open = Ifc::tokens->Next();
|
||||
args = new ArgumentList(Ifc::tokens, ids);
|
||||
unsigned int old_offset = Ifc::file->Tell();
|
||||
Token semilocon = Ifc::tokens->Next();
|
||||
if ( ! TokenFunc::isOperator(semilocon,';') ) Ifc::file->Seek(old_offset);
|
||||
Token open = file->tokens->Next();
|
||||
args = new ArgumentList(file->tokens, ids);
|
||||
unsigned int old_offset = file->tokens->stream->Tell();
|
||||
Token semilocon = file->tokens->Next();
|
||||
if ( ! TokenFunc::isOperator(semilocon,';') ) file->tokens->stream->Seek(old_offset);
|
||||
}
|
||||
|
||||
Ifc2x3::Type::Enum Entity::type() const {
|
||||
@@ -589,7 +607,7 @@ Entity::~Entity() {
|
||||
//
|
||||
IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c) {
|
||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||
IfcEntities all = Ifc::EntitiesByReference(_id);
|
||||
IfcEntities all = file->EntitiesByReference(_id);
|
||||
if ( ! all ) return l;
|
||||
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
||||
if ( c == Ifc2x3::Type::ALL || (*it)->is(c) ) {
|
||||
@@ -612,44 +630,55 @@ IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a
|
||||
bool Entity::is(Ifc2x3::Type::Enum v) const { return _type == v; }
|
||||
unsigned int Entity::id() { return _id; }
|
||||
|
||||
IfcFile::IfcFile() {
|
||||
file = 0;
|
||||
lastId = 0;
|
||||
tokens = 0;
|
||||
MaxId = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Parses the IFC file in fn
|
||||
// Creates the maps
|
||||
// Gets the unit definitins from the file
|
||||
//
|
||||
bool Ifc::Init(const std::string& fn) {
|
||||
return Ifc::Init(new File(fn));
|
||||
bool IfcFile::Init(const std::string& fn) {
|
||||
return IfcFile::Init(new IfcSpfStream(fn));
|
||||
}
|
||||
bool Ifc::Init(std::istream& f, int len) {
|
||||
return Ifc::Init(new File(f,len));
|
||||
bool IfcFile::Init(std::istream& f, int len) {
|
||||
return IfcFile::Init(new IfcSpfStream(f,len));
|
||||
}
|
||||
bool Ifc::Init(void* data, int len) {
|
||||
return Ifc::Init(new File(data,len));
|
||||
bool IfcFile::Init(void* data, int len) {
|
||||
return IfcFile::Init(new IfcSpfStream(data,len));
|
||||
}
|
||||
bool Ifc::Init(IfcParse::File* f) {
|
||||
bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||
Ifc2x3::InitStringMap();
|
||||
file = f;
|
||||
if ( ! file->valid ) return false;
|
||||
tokens = new Tokens (file);
|
||||
Token token = 0;
|
||||
Token previous = 0;
|
||||
tokens = new Tokens (file,this);
|
||||
Token token = TokenPtr();
|
||||
Token previous = TokenPtr();
|
||||
unsigned int currentId = 0;
|
||||
lastId = 0;
|
||||
int x = 0;
|
||||
EntityPtr e;
|
||||
IfcUtil::IfcSchemaEntity entity = 0;
|
||||
if ( log1 ) std::cout << "Scanning file..." << std::endl;
|
||||
Logger::Status("Scanning file...");
|
||||
while ( ! file->eof ) {
|
||||
if ( currentId ) {
|
||||
try {
|
||||
e = new Entity(currentId,tokens);
|
||||
e = new Entity(currentId,this);
|
||||
entity = Ifc2x3::SchemaEntity(e);
|
||||
} catch (IfcException ex) {
|
||||
currentId = 0;
|
||||
Ifc::LogMessage("Error",ex.what());
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
continue;
|
||||
}
|
||||
if ( log1 && !((++x)%1000) ) std::cout << "\r#" << currentId << " " << std::flush;
|
||||
// Update the status after every 1000 instances parsed
|
||||
if ( !((++x)%1000) ) {
|
||||
std::stringstream ss; ss << "\r#" << currentId;
|
||||
Logger::Status(ss.str(), false);
|
||||
}
|
||||
if ( entity->is(Ifc2x3::Type::IfcRoot) ) {
|
||||
Ifc2x3::IfcRoot::ptr ifc_root = (Ifc2x3::IfcRoot::ptr) entity;
|
||||
try {
|
||||
@@ -657,11 +686,11 @@ bool Ifc::Init(IfcParse::File* f) {
|
||||
if ( byguid.find(guid) != byguid.end() ) {
|
||||
std::stringstream ss;
|
||||
ss << "Overwriting entity with guid " << guid;
|
||||
Ifc::LogMessage("Warning",ss.str());
|
||||
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||
}
|
||||
byguid[guid] = ifc_root;
|
||||
} catch (IfcException ex) {
|
||||
Ifc::LogMessage("Error",ex.what());
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
}
|
||||
}
|
||||
Ifc2x3::Type::Enum ty = entity->type();
|
||||
@@ -677,16 +706,16 @@ bool Ifc::Init(IfcParse::File* f) {
|
||||
if ( byid.find(currentId) != byid.end() ) {
|
||||
std::stringstream ss;
|
||||
ss << "Overwriting entity with id " << currentId;
|
||||
Ifc::LogMessage("Warning",ss.str());
|
||||
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||
}
|
||||
byid[currentId] = entity;
|
||||
currentId = 0;
|
||||
} else {
|
||||
try { token = tokens->Next(); }
|
||||
catch (... ) { token = 0; }
|
||||
catch (... ) { token = TokenPtr(); }
|
||||
}
|
||||
if ( ! token ) break;
|
||||
if ( previous && TokenFunc::isIdentifier(previous) ) {
|
||||
if ( ! (token.second || token.first) ) break;
|
||||
if ( (previous.second || previous.first) && TokenFunc::isIdentifier(previous) ) {
|
||||
int id = TokenFunc::asInt(previous);
|
||||
if ( TokenFunc::isOperator(token,'=') ) {
|
||||
currentId = id;
|
||||
@@ -701,88 +730,32 @@ bool Ifc::Init(IfcParse::File* f) {
|
||||
}
|
||||
previous = token;
|
||||
}
|
||||
|
||||
if ( log1 ) std::cout << "\rDone scanning file " << std::endl;
|
||||
|
||||
Ifc2x3::IfcUnitAssignment::list unit_assignments = EntitiesByType<Ifc2x3::IfcUnitAssignment>();
|
||||
IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list();
|
||||
if ( unit_assignments->Size() ) {
|
||||
Ifc2x3::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin();
|
||||
units = unit_assignment->Units();
|
||||
}
|
||||
if ( ! units ) {
|
||||
// No units eh... Since tolerances and deflection are specified internally in meters
|
||||
// we will try to find another indication of the model size.
|
||||
Ifc2x3::IfcExtrudedAreaSolid::list extrusions = EntitiesByType<Ifc2x3::IfcExtrudedAreaSolid>();
|
||||
if ( ! extrusions->Size() ) return true;
|
||||
double max_height = -1.0f;
|
||||
for ( Ifc2x3::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) {
|
||||
const double depth = (*it)->Depth();
|
||||
if ( depth > max_height ) max_height = depth;
|
||||
}
|
||||
if ( max_height > 100.0f ) Ifc::LengthUnit = 0.001f;
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) {
|
||||
const IfcUtil::IfcAbstractSelect::ptr base = *it;
|
||||
Ifc2x3::IfcSIUnit::ptr unit = Ifc2x3::IfcSIUnit::ptr();
|
||||
double value = 1.0f;
|
||||
if ( base->is(Ifc2x3::Type::IfcConversionBasedUnit) ) {
|
||||
const Ifc2x3::IfcConversionBasedUnit::ptr u = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcConversionBasedUnit>(base);
|
||||
const Ifc2x3::IfcMeasureWithUnit::ptr u2 = u->ConversionFactor();
|
||||
Ifc2x3::IfcUnit u3 = u2->UnitComponent();
|
||||
if ( u3->is(Ifc2x3::Type::IfcSIUnit) ) {
|
||||
unit = (Ifc2x3::IfcSIUnit*) u3;
|
||||
}
|
||||
Ifc2x3::IfcValue v = u2->ValueComponent();
|
||||
IfcUtil::IfcArgumentSelect* v2 = (IfcUtil::IfcArgumentSelect*) v;
|
||||
const double f = *v2->wrappedValue();
|
||||
value *= f;
|
||||
} else if ( base->is(Ifc2x3::Type::IfcSIUnit) ) {
|
||||
unit = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcSIUnit>(base);
|
||||
}
|
||||
if ( unit ) {
|
||||
if ( unit->hasPrefix() ) {
|
||||
value *= UnitPrefixToValue(unit->Prefix());
|
||||
}
|
||||
Ifc2x3::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
|
||||
if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
|
||||
Ifc::LengthUnit = value;
|
||||
} else if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
|
||||
Ifc::PlaneAngleUnit = value;
|
||||
Ifc::hasPlaneAngleUnit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( IfcException ex ) {
|
||||
Ifc::LogMessage("Error",ex.what());
|
||||
}
|
||||
Logger::Status("\rDone scanning file ");
|
||||
return true;
|
||||
}
|
||||
|
||||
IfcEntities Ifc::EntitiesByType(Ifc2x3::Type::Enum t) {
|
||||
IfcEntities IfcFile::EntitiesByType(Ifc2x3::Type::Enum t) {
|
||||
MapEntitiesByType::const_iterator it = bytype.find(t);
|
||||
return (it == bytype.end()) ? IfcEntities() : it->second;
|
||||
}
|
||||
IfcEntities Ifc::EntitiesByReference(int t) {
|
||||
IfcEntities IfcFile::EntitiesByReference(int t) {
|
||||
MapEntitiesByRef::const_iterator it = byref.find(t);
|
||||
return (it == byref.end()) ? IfcEntities() : it->second;
|
||||
}
|
||||
IfcUtil::IfcSchemaEntity Ifc::EntityById(int id) {
|
||||
IfcUtil::IfcSchemaEntity IfcFile::EntityById(int id) {
|
||||
MapEntityById::const_iterator it = byid.find(id);
|
||||
if ( it == byid.end() ) {
|
||||
MapOffsetById::const_iterator it2 = offsets.find(id);
|
||||
if ( it2 == offsets.end() ) throw IfcException("Entity not found");
|
||||
const unsigned int offset = (*it2).second;
|
||||
EntityPtr e = EntityPtr(new Entity(id,Ifc::tokens,offset));
|
||||
EntityPtr e = EntityPtr(new Entity(id,this,offset));
|
||||
IfcUtil::IfcSchemaEntity entity = Ifc2x3::SchemaEntity(e);
|
||||
byid[id] = entity;
|
||||
return entity;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
Ifc2x3::IfcRoot::ptr Ifc::EntityByGuid(const std::string& guid) {
|
||||
Ifc2x3::IfcRoot::ptr IfcFile::EntityByGuid(const std::string& guid) {
|
||||
MapEntityByGuid::const_iterator it = byguid.find(guid);
|
||||
if ( it == byguid.end() ) {
|
||||
throw IfcException("Entity not found");
|
||||
@@ -795,77 +768,19 @@ IfcException::IfcException(std::string e) { error = e; }
|
||||
IfcException::~IfcException() throw () {}
|
||||
const char* IfcException::what() const throw() { return error.c_str(); }
|
||||
|
||||
void Ifc::Dispose() {
|
||||
// FIXME: Test destructor to delete entity and arg allocations
|
||||
IfcFile::~IfcFile() {
|
||||
for( MapEntityById::const_iterator it = byid.begin(); it != byid.end(); ++ it ) {
|
||||
delete it->second->entity;
|
||||
delete it->second;
|
||||
}
|
||||
bytype.clear();
|
||||
byid.clear();
|
||||
byref.clear();
|
||||
file->Close();
|
||||
delete file;
|
||||
delete tokens;
|
||||
offsets.clear();
|
||||
log_stream.str("");
|
||||
}
|
||||
|
||||
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v ) {
|
||||
if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_EXA ) return (double) 1e18;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PETA ) return (double) 1e15;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_TERA ) return (double) 1e12;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_GIGA ) return (double) 1e9;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MEGA ) return (double) 1e6;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_KILO ) return (double) 1e3;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_HECTO ) return (double) 1e2;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECA ) return (double) 1;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECI ) return (double) 1e-1;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_CENTI ) return (double) 1e-2;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MILLI ) return (double) 1e-3;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MICRO ) return (double) 1e-6;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_NANO ) return (double) 1e-9;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PICO ) return (double) 1e-12;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_FEMTO ) return (double) 1e-15;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_ATTO ) return (double) 1e-18;
|
||||
else return 1.0f;
|
||||
}
|
||||
void Ifc::SetOutput(std::ostream* l1, std::ostream* l2) {
|
||||
log1 = l1;
|
||||
log2 = l2;
|
||||
if ( ! log2 ) {
|
||||
log2 = &log_stream;
|
||||
}
|
||||
}
|
||||
void Ifc::LogMessage(const std::string& type, const std::string& message, const IfcAbstractEntityPtr entity) {
|
||||
if ( log2 ) {
|
||||
(*log2) << "[" << type << "] " << message << std::endl;
|
||||
if ( entity ) (*log2) << entity->toString() << std::endl;
|
||||
}
|
||||
}
|
||||
std::string Ifc::GetLog() {
|
||||
return log_stream.str();
|
||||
}
|
||||
MapEntityById::const_iterator Ifc::First() {
|
||||
MapEntityById::const_iterator IfcFile::begin() const {
|
||||
return byid.begin();
|
||||
}
|
||||
MapEntityById::const_iterator Ifc::Last() {
|
||||
MapEntityById::const_iterator IfcFile::end() const {
|
||||
return byid.end();
|
||||
}
|
||||
|
||||
File* Ifc::file = 0;
|
||||
std::ostream* Ifc::log1 = 0;
|
||||
std::ostream* Ifc::log2 = 0;
|
||||
unsigned int Ifc::lastId = 0;
|
||||
Tokens* Ifc::tokens = 0;
|
||||
double Ifc::LengthUnit = 1.0f;
|
||||
double Ifc::PlaneAngleUnit = 1.0f;
|
||||
bool Ifc::hasPlaneAngleUnit = false;
|
||||
bool Ifc::SewShells = false;
|
||||
int Ifc::CircleSegments = 32;
|
||||
MapEntitiesByType Ifc::bytype;
|
||||
MapEntityById Ifc::byid;
|
||||
MapEntityByGuid Ifc::byguid;
|
||||
MapEntitiesByRef Ifc::byref;
|
||||
MapOffsetById Ifc::offsets;
|
||||
std::stringstream Ifc::log_stream;
|
||||
int Ifc::Verbosity = 2;
|
||||
|
||||
+59
-65
@@ -27,7 +27,7 @@
|
||||
#ifndef IFCPARSE_H
|
||||
#define IFCPARSE_H
|
||||
|
||||
#define IFCOPENSHELL_VERSION "0.3.0-rc3"
|
||||
#define IFCOPENSHELL_VERSION "0.3.0"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@@ -47,56 +47,59 @@ namespace IfcParse {
|
||||
|
||||
class Entity;
|
||||
class Entities;
|
||||
class IfcFile;
|
||||
typedef Entity* EntityPtr;
|
||||
typedef SHARED_PTR<Entities> EntitiesPtr;
|
||||
|
||||
typedef unsigned int Token;
|
||||
class Tokens;
|
||||
typedef std::pair<Tokens*,unsigned> Token;
|
||||
|
||||
/// Provides functions to convert Tokens to binary data
|
||||
/// Tokens are merely offsets to where they can be read in the file
|
||||
class TokenFunc {
|
||||
private:
|
||||
static bool startsWith(Token t, char c);
|
||||
static bool startsWith(const Token& t, char c);
|
||||
public:
|
||||
/// Returns the offset at which the token is read from the file
|
||||
static unsigned int Offset(Token t);
|
||||
// static unsigned int Offset(const Token& t);
|
||||
/// Returns whether the token can be interpreted as a string
|
||||
static bool isString(Token t);
|
||||
static bool isString(const Token& t);
|
||||
/// Returns whether the token can be interpreted as an identifier
|
||||
static bool isIdentifier(Token t);
|
||||
static bool isIdentifier(const Token& t);
|
||||
/// Returns whether the token can be interpreted as an syntactical operator
|
||||
static bool isOperator(Token t, char op = 0);
|
||||
static bool isOperator(const Token& t, char op = 0);
|
||||
/// Returns whether the token can be interpreted as an enumerated value
|
||||
static bool isEnumeration(Token t);
|
||||
static bool isEnumeration(const Token& t);
|
||||
/// Returns whether the token can be interpreted as an datatype name
|
||||
static bool isDatatype(Token t);
|
||||
static bool isDatatype(const Token& t);
|
||||
/// Returns the token interpreted as an integer
|
||||
static int asInt(Token t);
|
||||
static int asInt(const Token& t);
|
||||
/// Returns the token interpreted as an boolean (.T. or .F.)
|
||||
static bool asBool(Token t);
|
||||
static bool asBool(const Token& t);
|
||||
/// Returns the token as a floating point number
|
||||
static double asFloat(Token t);
|
||||
static double asFloat(const Token& t);
|
||||
/// Returns the token as a string (without the dot or apostrophe)
|
||||
static std::string asString(Token t);
|
||||
static std::string asString(const Token& t);
|
||||
/// Returns a string representation of the token (including the dot or apostrophe)
|
||||
static std::string toString(Token t);
|
||||
static std::string toString(const Token& t);
|
||||
};
|
||||
|
||||
//
|
||||
// Functions for creating Tokens from an arbitary file offset
|
||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
||||
//
|
||||
Token TokenPtr(unsigned int offset);
|
||||
Token TokenPtr(Tokens* tokens, unsigned int offset);
|
||||
Token TokenPtr(char c);
|
||||
Token TokenPtr();
|
||||
|
||||
/// A stream of tokens to be read from a File.
|
||||
/// A stream of tokens to be read from a IfcSpfStream.
|
||||
class Tokens {
|
||||
private:
|
||||
File* file;
|
||||
IfcCharacterDecoder* decoder;
|
||||
public:
|
||||
Tokens(File* f);
|
||||
IfcSpfStream* stream;
|
||||
IfcFile* file;
|
||||
Tokens(IfcSpfStream* s, IfcFile* f);
|
||||
Token Next();
|
||||
~Tokens();
|
||||
std::string TokenString(unsigned int offset);
|
||||
@@ -136,7 +139,7 @@ namespace IfcParse {
|
||||
|
||||
public:
|
||||
Token token;
|
||||
TokenArgument(Token t);
|
||||
TokenArgument(const Token& t);
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator double() const;
|
||||
@@ -160,7 +163,7 @@ namespace IfcParse {
|
||||
private:
|
||||
IfcUtil::IfcArgumentSelect* entity;
|
||||
public:
|
||||
EntityArgument(Ifc2x3::Type::Enum ty, Token t);
|
||||
EntityArgument(Ifc2x3::Type::Enum ty, const Token& t);
|
||||
~EntityArgument();
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
@@ -183,15 +186,16 @@ namespace IfcParse {
|
||||
/// ============================
|
||||
class Entity : public IfcAbstractEntity {
|
||||
private:
|
||||
//IfcFile* file;
|
||||
ArgumentPtr args;
|
||||
Ifc2x3::Type::Enum _type;
|
||||
public:
|
||||
/// The EXPRESS ENTITY_NAME
|
||||
/// The EXPRESS ENTITY_INSTANCE_NAME
|
||||
unsigned int _id;
|
||||
/// The offset at which the entity is read
|
||||
unsigned int offset;
|
||||
Entity(unsigned int i, Tokens* t);
|
||||
Entity(unsigned int i, Tokens* t, unsigned int o);
|
||||
Entity(unsigned int i, IfcFile* t);
|
||||
Entity(unsigned int i, IfcFile* t, unsigned int o);
|
||||
~Entity();
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
|
||||
@@ -204,10 +208,9 @@ namespace IfcParse {
|
||||
bool is(Ifc2x3::Type::Enum v) const;
|
||||
unsigned int id();
|
||||
};
|
||||
}
|
||||
|
||||
typedef IfcUtil::IfcSchemaEntity IfcEntity;
|
||||
typedef IfcEntities IfcEntities;
|
||||
//typedef IfcEntities IfcEntities;
|
||||
typedef std::map<Ifc2x3::Type::Enum,IfcEntities> MapEntitiesByType;
|
||||
typedef std::map<unsigned int,IfcEntity> MapEntityById;
|
||||
typedef std::map<std::string,Ifc2x3::IfcRoot::ptr> MapEntityByGuid;
|
||||
@@ -216,65 +219,56 @@ typedef std::map<unsigned int,unsigned int> MapOffsetById;
|
||||
|
||||
/// This class provides several static convenience functions and variables
|
||||
/// and provide access to the entities in an IFC file
|
||||
class Ifc {
|
||||
class IfcFile {
|
||||
private:
|
||||
static MapEntityById byid;
|
||||
static MapEntitiesByType bytype;
|
||||
static MapEntitiesByRef byref;
|
||||
static MapEntityByGuid byguid;
|
||||
static MapOffsetById offsets;
|
||||
static unsigned int lastId;
|
||||
static std::ostream* log1;
|
||||
static std::ostream* log2;
|
||||
static std::stringstream log_stream;
|
||||
MapEntityById byid;
|
||||
MapEntitiesByType bytype;
|
||||
MapEntitiesByRef byref;
|
||||
MapEntityByGuid byguid;
|
||||
MapOffsetById offsets;
|
||||
unsigned int lastId;
|
||||
unsigned int MaxId;
|
||||
public:
|
||||
/// Returns the first entity in the file, this probably is the entity with the lowest id (EXPRESS ENTITY_NAME)
|
||||
static MapEntityById::const_iterator First();
|
||||
/// Returns the last entity in the file, this probably is the entity with the highes id (EXPRESS ENTITY_NAME)
|
||||
static MapEntityById::const_iterator Last();
|
||||
/// Determines to what stream respectively progress and errors are logged
|
||||
static void SetOutput(std::ostream* l1, std::ostream* l2);
|
||||
/// Log a message to the output stream
|
||||
static void LogMessage(const std::string& type, const std::string& message, const IfcAbstractEntityPtr entity=0);
|
||||
static IfcParse::File* file;
|
||||
static IfcParse::Tokens* tokens;
|
||||
typedef MapEntityById::const_iterator const_iterator;
|
||||
IfcFile();
|
||||
~IfcFile();
|
||||
/// Returns the first entity in the file, this probably is the entity with the lowest id (EXPRESS ENTITY_INSTANCE_NAME)
|
||||
const_iterator begin() const;
|
||||
/// Returns the last entity in the file, this probably is the entity with the highes id (EXPRESS ENTITY_INSTANCE_NAME)
|
||||
const_iterator end() const;
|
||||
IfcParse::IfcSpfStream* file;
|
||||
IfcParse::Tokens* tokens;
|
||||
/// Returns all entities in the file that match the template argument.
|
||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||
/// IfcWall will also return IfcWallStandardCase entities
|
||||
template <class T>
|
||||
static typename T::list EntitiesByType() {
|
||||
typename T::list EntitiesByType() {
|
||||
IfcEntities e = EntitiesByType(T::Class());
|
||||
typename T::list l ( new IfcTemplatedEntityList<T>() );
|
||||
if ( e && e->Size() )
|
||||
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) {
|
||||
l->push(reinterpret_pointer_cast<IfcUtil::IfcBaseClass,T>(*it));
|
||||
}
|
||||
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) {
|
||||
l->push(reinterpret_pointer_cast<IfcUtil::IfcBaseClass,T>(*it));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
/// Returns all entities in the file that match the positional argument.
|
||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||
/// IfcWall will also return IfcWallStandardCase entities
|
||||
static IfcEntities EntitiesByType(Ifc2x3::Type::Enum t);
|
||||
IfcEntities EntitiesByType(Ifc2x3::Type::Enum t);
|
||||
/// Returns all entities in the file that reference the id
|
||||
static IfcEntities EntitiesByReference(int id);
|
||||
IfcEntities EntitiesByReference(int id);
|
||||
/// Returns the entity with the specified id
|
||||
static IfcEntity EntityById(int id);
|
||||
IfcEntity EntityById(int id);
|
||||
/// Returns the entity with the specified GlobalId
|
||||
static Ifc2x3::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
||||
static bool Init(const std::string& fn);
|
||||
static bool Init(std::istream& fn, int len);
|
||||
static bool Init(void* data, int len);
|
||||
static bool Init(IfcParse::File* f);
|
||||
static std::string GetLog();
|
||||
static void Dispose();
|
||||
static bool hasPlaneAngleUnit;
|
||||
static bool SewShells;
|
||||
static double LengthUnit;
|
||||
static double PlaneAngleUnit;
|
||||
static int CircleSegments;
|
||||
static int Verbosity;
|
||||
Ifc2x3::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
||||
bool Init(const std::string& fn);
|
||||
bool Init(std::istream& fn, int len);
|
||||
bool Init(void* data, int len);
|
||||
bool Init(IfcParse::IfcSpfStream* f);
|
||||
};
|
||||
|
||||
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v );
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -62,3 +62,35 @@ IfcUtil::IfcArgumentSelect::IfcArgumentSelect(Ifc2x3::Type::Enum t, ArgumentPtr
|
||||
ArgumentPtr IfcUtil::IfcArgumentSelect::wrappedValue() { return arg; }
|
||||
bool IfcUtil::IfcArgumentSelect::isSimpleType() { return true; }
|
||||
IfcUtil::IfcArgumentSelect::~IfcArgumentSelect() { delete arg; }
|
||||
|
||||
void Logger::SetOutput(std::ostream* l1, std::ostream* l2) {
|
||||
log1 = l1;
|
||||
log2 = l2;
|
||||
if ( ! log2 ) {
|
||||
log2 = &log_stream;
|
||||
}
|
||||
}
|
||||
void Logger::Message(Logger::Severity type, const std::string& message, const IfcAbstractEntityPtr entity) {
|
||||
if ( log2 && type >= verbosity ) {
|
||||
(*log2) << "[" << severity_strings[type] << "] " << message << std::endl;
|
||||
if ( entity ) (*log2) << entity->toString() << std::endl;
|
||||
}
|
||||
}
|
||||
void Logger::Status(const std::string& message, bool new_line) {
|
||||
if ( log1 ) {
|
||||
(*log1) << message;
|
||||
if ( new_line ) (*log1) << std::endl;
|
||||
else (*log1) << std::flush;
|
||||
}
|
||||
}
|
||||
std::string Logger::GetLog() {
|
||||
return log_stream.str();
|
||||
}
|
||||
void Logger::Verbosity(Logger::Severity v) { verbosity = v; }
|
||||
Logger::Severity Logger::Verbosity() { return verbosity; }
|
||||
|
||||
std::ostream* Logger::log1 = 0;
|
||||
std::ostream* Logger::log2 = 0;
|
||||
std::stringstream Logger::log_stream;
|
||||
Logger::Severity Logger::verbosity = Logger::LOG_NOTICE;
|
||||
const char* Logger::severity_strings[] = { "Notice","Warning","Error" };
|
||||
+30
-2
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include "../ifcparse/SharedPointer.h"
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
@@ -132,9 +133,14 @@ namespace IfcUtil {
|
||||
};
|
||||
}
|
||||
|
||||
namespace IfcParse {
|
||||
class IfcFile;
|
||||
}
|
||||
|
||||
class Argument {
|
||||
protected:
|
||||
public:
|
||||
//void* file;
|
||||
//public:
|
||||
virtual operator int() const = 0;
|
||||
virtual operator bool() const = 0;
|
||||
virtual operator double() const = 0;
|
||||
@@ -154,6 +160,7 @@ public:
|
||||
|
||||
class IfcAbstractEntity {
|
||||
public:
|
||||
IfcParse::IfcFile* file;
|
||||
virtual IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL) = 0;
|
||||
virtual IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) = 0;
|
||||
virtual std::string datatype() = 0;
|
||||
@@ -166,4 +173,25 @@ public:
|
||||
virtual unsigned int id() = 0;
|
||||
};
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
typedef enum { LOG_NOTICE, LOG_WARNING, LOG_ERROR } Severity;
|
||||
private:
|
||||
static std::ostream* log1;
|
||||
static std::ostream* log2;
|
||||
static std::stringstream log_stream;
|
||||
static Severity verbosity;
|
||||
static const char* severity_strings[];
|
||||
public:
|
||||
/// Determines to what stream respectively progress and errors are logged
|
||||
static void SetOutput(std::ostream* l1, std::ostream* l2);
|
||||
/// Determines the types of log messages to get logged
|
||||
static void Verbosity(Severity v);
|
||||
static Severity Verbosity();
|
||||
/// Log a message to the output stream
|
||||
static void Message(Severity type, const std::string& message, const IfcAbstractEntityPtr entity=0);
|
||||
static void Status(const std::string& message, bool new_line=true);
|
||||
static std::string GetLog();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/********************************************************************************
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
|
||||
+2
-19
@@ -24,6 +24,8 @@ namespace IfcGeomObjects {
|
||||
const int CONVERT_BACK_UNITS = 3;
|
||||
const int USE_BREP_DATA = 4;
|
||||
const int SEW_SHELLS = 5;
|
||||
const int FASTER_BOOLEANS = 6;
|
||||
const int FORCE_CCW_FACE_ORIENTATION = 7;
|
||||
|
||||
class IfcMesh {
|
||||
public:
|
||||
@@ -43,21 +45,6 @@ namespace IfcGeomObjects {
|
||||
std::string type;
|
||||
std::string guid;
|
||||
std::vector<float> matrix;
|
||||
const std::vector<int> name_as_intvector() {
|
||||
std::vector<int> r;
|
||||
for ( std::string::const_iterator it = name.begin(); it != name.end(); ++ it ) r.push_back(*it);
|
||||
return r;
|
||||
}
|
||||
const std::vector<int> type_as_intvector() {
|
||||
std::vector<int> r;
|
||||
for ( std::string::const_iterator it = type.begin(); it != type.end(); ++ it ) r.push_back(*it);
|
||||
return r;
|
||||
}
|
||||
const std::vector<int> guid_as_intvector() {
|
||||
std::vector<int> r;
|
||||
for ( std::string::const_iterator it = guid.begin(); it != guid.end(); ++ it ) r.push_back(*it);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
class IfcGeomObject : public IfcObject {
|
||||
@@ -68,13 +55,9 @@ namespace IfcGeomObjects {
|
||||
bool Next();
|
||||
const IfcGeomObject* Get();
|
||||
bool Init(const std::string fn);
|
||||
bool InitUCS2(const char* fn) {
|
||||
return Init(std::string(fn+1));
|
||||
}
|
||||
void Settings(int setting, bool value);
|
||||
int Progress();
|
||||
const IfcObject* GetObject(int id);
|
||||
bool CleanUp();
|
||||
std::string GetLog();
|
||||
|
||||
};
|
||||
+2
-1
@@ -63,7 +63,8 @@ scn.render.resolution_x = 2048
|
||||
scn.render.resolution_y = 2048
|
||||
scn.world.horizon_color = (1,1,1)
|
||||
scn.world.ambient_color = (0.05,0.05,0.05)
|
||||
scn.render.color_mode = 'RGBA'
|
||||
try: scn.render.color_mode = 'RGBA'
|
||||
except: scn.render.image_settings.color_mode = 'RGBA'
|
||||
|
||||
for m in bpy.data.materials: m.specular_intensity = 0
|
||||
def material(name,settings):
|
||||
|
||||
Reference in New Issue
Block a user