mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 14:31:39 +00:00
New IfcGeomObjects setting to force alignment of TopoDS_Face normal to CCW orientation
Removed static Ifc class, renamed to non-static IfcFile. IfcFile renamed to IfcSpfStream Introduced Logger class
This commit is contained in:
@@ -29,10 +29,11 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Redirect the output (both progress and log) to stdout
|
// 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]
|
// 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;
|
std::cout << "Unable to parse .ifc file" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -53,12 +54,7 @@ int main(int argc, char** argv) {
|
|||||||
// we need to cast them to IfcWindows. Since these properties
|
// we need to cast them to IfcWindows. Since these properties
|
||||||
// are optional we need to make sure the properties are
|
// are optional we need to make sure the properties are
|
||||||
// defined for the window in question before accessing them.
|
// defined for the window in question before accessing them.
|
||||||
//
|
IfcBuildingElement::list elements = file.EntitiesByType<IfcBuildingElement>();
|
||||||
// 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>();
|
|
||||||
|
|
||||||
std::cout << "Found " << elements->Size() << " elements in " << argv[1] << ":" << std::endl;
|
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);
|
const IfcWindow::ptr window = reinterpret_pointer_cast<IfcBuildingElement,IfcWindow>(element);
|
||||||
|
|
||||||
if ( window->hasOverallWidth() && window->hasOverallHeight() ) {
|
if ( window->hasOverallWidth() && window->hasOverallHeight() ) {
|
||||||
const float area = window->OverallWidth()*window->OverallHeight() * (Ifc::LengthUnit*Ifc::LengthUnit);
|
const double area = window->OverallWidth()*window->OverallHeight();
|
||||||
std::cout << "This window has an area of " << area << "m2" << std::endl;
|
std::cout << "The area of this window is " << area << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -47,16 +47,32 @@ namespace IfcGeom {
|
|||||||
// Tolerances and settings for various geometrical operations:
|
// Tolerances and settings for various geometrical operations:
|
||||||
enum GeomValue {
|
enum GeomValue {
|
||||||
// Specifies the deflection of the mesher
|
// Specifies the deflection of the mesher
|
||||||
|
// Default: 0.001m / 1mm
|
||||||
GV_DEFLECTION_TOLERANCE,
|
GV_DEFLECTION_TOLERANCE,
|
||||||
// Specifies the tolerance of the wire builder, most notably for trimmed curves
|
// Specifies the tolerance of the wire builder, most notably for trimmed curves
|
||||||
|
// Defailt: 0.0001m / 0.1mm
|
||||||
GV_WIRE_CREATION_TOLERANCE,
|
GV_WIRE_CREATION_TOLERANCE,
|
||||||
// Specifies the minimal area of a face to be included in an IfcConnectedFaceset
|
// Specifies the minimal area of a face to be included in an IfcConnectedFaceset
|
||||||
|
// Default: 0.000001m 0.01cm2
|
||||||
GV_MINIMAL_FACE_AREA,
|
GV_MINIMAL_FACE_AREA,
|
||||||
// Specifies the treshold distance under which cartesian points are deemed equal
|
// Specifies the treshold distance under which cartesian points are deemed equal
|
||||||
|
// Default: 0.00001m / 0.01mm
|
||||||
GV_POINT_EQUALITY_TOLERANCE,
|
GV_POINT_EQUALITY_TOLERANCE,
|
||||||
// Specifies maximum number of faces for a shell to be sewed. Sewing shells
|
// Specifies maximum number of faces for a shell to be sewed. Sewing shells
|
||||||
// that consist of many faces is really detrimental for the performance.
|
// that consist of many faces is really detrimental for the performance.
|
||||||
GV_MAX_FACES_TO_SEW
|
// 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_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
#include "../ifcgeom/IfcGeom.h"
|
#include "../ifcgeom/IfcGeom.h"
|
||||||
|
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve) {
|
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; }
|
if ( r <= 0.0f ) { return false; }
|
||||||
gp_Trsf trsf;
|
gp_Trsf trsf;
|
||||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||||
@@ -94,8 +94,8 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
|
bool IfcGeom::convert(const Ifc2x3::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
|
||||||
double x = l->SemiAxis1() * Ifc::LengthUnit;
|
double x = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
double y = l->SemiAxis2() * Ifc::LengthUnit;
|
double y = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
if ( x == 0.0f || y == 0.0f || y > x ) { return false; }
|
if ( x == 0.0f || y == 0.0f || y > x ) { return false; }
|
||||||
gp_Trsf trsf;
|
gp_Trsf trsf;
|
||||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
#include <ShapeFix_Solid.hxx>
|
#include <ShapeFix_Solid.hxx>
|
||||||
|
|
||||||
#include <TopLoc_Location.hxx>
|
#include <TopLoc_Location.hxx>
|
||||||
|
#include <BRepGProp_Face.hxx>
|
||||||
|
|
||||||
#include "../ifcgeom/IfcGeom.h"
|
#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::list bounds = l->Bounds();
|
||||||
Ifc2x3::IfcFaceBound::it it = bounds->begin();
|
Ifc2x3::IfcFaceBound::it it = bounds->begin();
|
||||||
Ifc2x3::IfcLoop::ptr loop = (*it)->Bound();
|
Ifc2x3::IfcLoop::ptr loop = (*it)->Bound();
|
||||||
TopoDS_Wire wire;
|
TopoDS_Wire outer_wire;
|
||||||
if ( ! IfcGeom::convert_wire(loop,wire) ) return false;
|
if ( ! IfcGeom::convert_wire(loop,outer_wire) ) return false;
|
||||||
BRepBuilderAPI_MakeFace mf (wire);
|
BRepBuilderAPI_MakeFace mf (outer_wire);
|
||||||
BRepBuilderAPI_FaceError er = mf.Error();
|
BRepBuilderAPI_FaceError er = mf.Error();
|
||||||
if ( er == BRepBuilderAPI_NotPlanar ) {
|
if ( er == BRepBuilderAPI_NotPlanar ) {
|
||||||
ShapeFix_ShapeTolerance FTol;
|
ShapeFix_ShapeTolerance FTol;
|
||||||
FTol.SetTolerance(wire, 0.01, TopAbs_WIRE);
|
FTol.SetTolerance(outer_wire, 0.01, TopAbs_WIRE);
|
||||||
mf.~BRepBuilderAPI_MakeFace();
|
mf.~BRepBuilderAPI_MakeFace();
|
||||||
new (&mf) BRepBuilderAPI_MakeFace(wire);
|
new (&mf) BRepBuilderAPI_MakeFace(outer_wire);
|
||||||
er = mf.Error();
|
er = mf.Error();
|
||||||
}
|
}
|
||||||
if ( er != BRepBuilderAPI_FaceDone ) return false;
|
if ( er != BRepBuilderAPI_FaceDone ) return false;
|
||||||
@@ -116,6 +117,65 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
|
|||||||
return false;
|
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
|
// It might be a good idea to globally discard faces
|
||||||
// smaller than a certain treshold value. But for now
|
// smaller than a certain treshold value. But for now
|
||||||
// only when processing IfcConnectedFacesets the small
|
// only when processing IfcConnectedFacesets the small
|
||||||
@@ -145,11 +205,11 @@ bool IfcGeom::convert(const Ifc2x3::IfcArbitraryProfileDefWithVoids::ptr l, Topo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face& face) {
|
bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face& face) {
|
||||||
const double x = l->XDim() / 2.0f * Ifc::LengthUnit;
|
const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double y = l->YDim() / 2.0f * Ifc::LengthUnit;
|
const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
|
|
||||||
if ( x == 0.0f || y == 0.0f ) {
|
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;
|
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);
|
return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face);
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) {
|
bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||||
const double x = l->OverallWidth() / 2.0f * Ifc::LengthUnit;
|
const double x = l->OverallWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double y = l->OverallDepth() / 2.0f * Ifc::LengthUnit;
|
const double y = l->OverallDepth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double d1 = l->WebThickness() / 2.0f * Ifc::LengthUnit;
|
const double d1 = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double d2 = l->FlangeThickness() * Ifc::LengthUnit;
|
const double d2 = l->FlangeThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
bool doFillet = l->hasFilletRadius();
|
bool doFillet = l->hasFilletRadius();
|
||||||
double f;
|
double f;
|
||||||
if ( doFillet ) {
|
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 ) {
|
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;
|
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);
|
return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face);
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) {
|
bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||||
const double x = l->Depth() / 2.0f * Ifc::LengthUnit;
|
const double x = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double y = l->Width() / 2.0f * Ifc::LengthUnit;
|
const double y = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double d1 = l->WallThickness() * Ifc::LengthUnit;
|
const double d1 = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double d2 = l->Girth() * Ifc::LengthUnit;
|
const double d2 = l->Girth() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
bool doFillet = l->hasInternalFilletRadius();
|
bool doFillet = l->hasInternalFilletRadius();
|
||||||
double f1,f2;
|
double f1,f2;
|
||||||
if ( doFillet ) {
|
if ( doFillet ) {
|
||||||
f1 = l->InternalFilletRadius() * Ifc::LengthUnit;
|
f1 = l->InternalFilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
f2 = f1 + d1;
|
f2 = f1 + d1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) {
|
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;
|
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);
|
return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face);
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) {
|
bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||||
const double y = l->Depth() / 2.0f * Ifc::LengthUnit;
|
const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double x = l->Width() / 2.0f * Ifc::LengthUnit;
|
const double x = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double d = l->Thickness() * Ifc::LengthUnit;
|
const double d = l->Thickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
bool doEdgeFillet = l->hasEdgeRadius();
|
bool doEdgeFillet = l->hasEdgeRadius();
|
||||||
bool doFillet = l->hasFilletRadius();
|
bool doFillet = l->hasFilletRadius();
|
||||||
double f1 = 0.0f;
|
double f1 = 0.0f;
|
||||||
double f2 = 0.0f;
|
double f2 = 0.0f;
|
||||||
if (doFillet) {
|
if (doFillet) {
|
||||||
f1 = l->FilletRadius() * Ifc::LengthUnit;
|
f1 = l->FilletRadius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
}
|
}
|
||||||
if ( doEdgeFillet) {
|
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 ) {
|
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;
|
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);
|
return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face);
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& 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 ) {
|
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;
|
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);
|
return IfcGeom::convert_wire_to_face(w,face);
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Face& face) {
|
bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Face& face) {
|
||||||
const double r = l->Radius() * Ifc::LengthUnit;
|
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
const double t = l->WallThickness() * Ifc::LengthUnit;
|
const double t = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||||
|
|
||||||
if ( r == 0.0f || t == 0.0f ) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
|||||||
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
||||||
TopoDS_Shape entity_shape;
|
TopoDS_Shape entity_shape;
|
||||||
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
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();
|
entity_shape = BRepBuilderAPI_GTransform(entity_shape_unlocated,entity_shape_gtrsf,true).Shape();
|
||||||
} else {
|
} else {
|
||||||
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
||||||
@@ -175,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 TopoDS_Shape& opening_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(*(it4->second),opening_shape_solid);
|
||||||
const gp_GTrsf& opening_shape_gtrsf = *(it4->first);
|
const gp_GTrsf& opening_shape_gtrsf = *(it4->first);
|
||||||
if ( opening_shape_gtrsf.Form() == gp_Other ) {
|
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
|
const TopoDS_Shape& opening_shape = opening_shape_gtrsf.Form() == gp_Other
|
||||||
? BRepBuilderAPI_GTransform(opening_shape_unlocated,opening_shape_gtrsf,true).Shape()
|
? BRepBuilderAPI_GTransform(opening_shape_unlocated,opening_shape_gtrsf,true).Shape()
|
||||||
: opening_shape_unlocated.Moved(opening_shape_gtrsf.Trsf());
|
: opening_shape_unlocated.Moved(opening_shape_gtrsf.Trsf());
|
||||||
|
|
||||||
double opening_volume, original_shape_volume;
|
double opening_volume, original_shape_volume;
|
||||||
if ( Ifc::Verbosity > 1 ) {
|
if ( Logger::Verbosity() >= Logger::LOG_WARNING ) {
|
||||||
opening_volume = shape_volume(opening_shape);
|
opening_volume = shape_volume(opening_shape);
|
||||||
if ( opening_volume <= ALMOST_ZERO )
|
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);
|
original_shape_volume = shape_volume(entity_shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,17 +198,17 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
|||||||
bool is_valid = analyser.IsValid() != 0;
|
bool is_valid = analyser.IsValid() != 0;
|
||||||
if ( is_valid ) {
|
if ( is_valid ) {
|
||||||
entity_shape = brep_cut;
|
entity_shape = brep_cut;
|
||||||
if ( Ifc::Verbosity > 1 ) {
|
if ( Logger::Verbosity() >= Logger::LOG_WARNING ) {
|
||||||
const double volume_after_subtraction = shape_volume(entity_shape);
|
const double volume_after_subtraction = shape_volume(entity_shape);
|
||||||
|
|
||||||
if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) )
|
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 {
|
} else {
|
||||||
Ifc::LogMessage("Error","Invalid result from subtraction:",entity->entity);
|
Logger::Message(Logger::LOG_ERROR,"Invalid result from subtraction:",entity->entity);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ifc::LogMessage("Error","Failed to process subtraction:",entity->entity);
|
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",entity->entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const
|
|||||||
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
||||||
TopoDS_Shape entity_shape;
|
TopoDS_Shape entity_shape;
|
||||||
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
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();
|
entity_shape = BRepBuilderAPI_GTransform(entity_shape_unlocated,entity_shape_gtrsf,true).Shape();
|
||||||
} else {
|
} else {
|
||||||
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
||||||
@@ -295,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
|
// Apparently processing the boolean operation failed or resulted in an invalid result
|
||||||
// in which case the original shape without the subtractions is returned instead
|
// in which case the original shape without the subtractions is returned instead
|
||||||
// we try convert the openings in the original way, one by one.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +429,10 @@ static double deflection_tolerance = 0.001;
|
|||||||
static double wire_creation_tolerance = 0.0001;
|
static double wire_creation_tolerance = 0.0001;
|
||||||
static double minimal_face_area = 0.000001;
|
static double minimal_face_area = 0.000001;
|
||||||
static double point_equality_tolerance = 0.00001;
|
static double point_equality_tolerance = 0.00001;
|
||||||
static double max_faces_to_sew = 1000;
|
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) {
|
void IfcGeom::SetValue(GeomValue var, double value) {
|
||||||
switch (var) {
|
switch (var) {
|
||||||
@@ -448,6 +451,15 @@ void IfcGeom::SetValue(GeomValue var, double value) {
|
|||||||
case GV_MAX_FACES_TO_SEW:
|
case GV_MAX_FACES_TO_SEW:
|
||||||
max_faces_to_sew = value;
|
max_faces_to_sew = value;
|
||||||
break;
|
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:
|
default:
|
||||||
assert(!"never reach here");
|
assert(!"never reach here");
|
||||||
}
|
}
|
||||||
@@ -465,6 +477,15 @@ double IfcGeom::GetValue(GeomValue var) {
|
|||||||
return point_equality_tolerance;
|
return point_equality_tolerance;
|
||||||
case GV_MAX_FACES_TO_SEW:
|
case GV_MAX_FACES_TO_SEW:
|
||||||
return 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");
|
assert(!"never reach here");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -91,9 +91,9 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianPoint::ptr l, gp_Pnt& point) {
|
|||||||
IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point)
|
IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point)
|
||||||
std::vector<double> xyz = l->Coordinates();
|
std::vector<double> xyz = l->Coordinates();
|
||||||
point = gp_Pnt(
|
point = gp_Pnt(
|
||||||
xyz.size() ? (xyz[0]*Ifc::LengthUnit) : 0.0f,
|
xyz.size() ? (xyz[0]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||||
xyz.size() > 1 ? (xyz[1]*Ifc::LengthUnit) : 0.0f,
|
xyz.size() > 1 ? (xyz[1]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f,
|
||||||
xyz.size() > 2 ? (xyz[2]*Ifc::LengthUnit) : 0.0f
|
xyz.size() > 2 ? (xyz[2]*IfcGeom::GetValue(GV_LENGTH_UNIT)) : 0.0f
|
||||||
);
|
);
|
||||||
CACHE(IfcCartesianPoint,l,point)
|
CACHE(IfcCartesianPoint,l,point)
|
||||||
return true;
|
return true;
|
||||||
@@ -113,7 +113,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcVector::ptr l, gp_Vec& v) {
|
|||||||
IN_CACHE(IfcVector,l,gp_Vec,v)
|
IN_CACHE(IfcVector,l,gp_Vec,v)
|
||||||
gp_Dir d;
|
gp_Dir d;
|
||||||
IfcGeom::convert(l->Orientation(),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)
|
CACHE(IfcVector,l,v)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+108
-17
@@ -51,9 +51,9 @@ bool convert_back_units = false;
|
|||||||
bool use_faster_booleans = false;
|
bool use_faster_booleans = false;
|
||||||
|
|
||||||
int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
|
int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
|
||||||
const float X = convert_back_units ? (float) (p.X() / Ifc::LengthUnit) : (float)p.X();
|
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() / Ifc::LengthUnit) : (float)p.Y();
|
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() / Ifc::LengthUnit) : (float)p.Z();
|
const float Z = convert_back_units ? (float) (p.Z() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Z();
|
||||||
int i = (int) verts.size() / 3;
|
int i = (int) verts.size() / 3;
|
||||||
if ( weld_vertices ) {
|
if ( weld_vertices ) {
|
||||||
const VertKey key = VertKey(X,std::pair<float,float>(Y,Z));
|
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_world_coords = false;
|
||||||
bool use_brep_data = false;
|
bool use_brep_data = false;
|
||||||
|
|
||||||
|
static IfcParse::IfcFile* ifc_file = 0;
|
||||||
|
|
||||||
IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||||
id = i;
|
id = i;
|
||||||
|
|
||||||
@@ -102,10 +104,10 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
|||||||
|
|
||||||
// Triangulate the shape
|
// Triangulate the shape
|
||||||
try {
|
try {
|
||||||
//BRepTools::Clean(s);
|
// BRepTools::Clean(s);
|
||||||
BRepMesh::Mesh(s, IfcGeom::GetValue(IfcGeom::GV_DEFLECTION_TOLERANCE));
|
BRepMesh::Mesh(s, IfcGeom::GetValue(IfcGeom::GV_DEFLECTION_TOLERANCE));
|
||||||
} catch(...) {
|
} 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;
|
continue;
|
||||||
}
|
}
|
||||||
TopExp_Explorer exp;
|
TopExp_Explorer exp;
|
||||||
@@ -401,7 +403,7 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
|||||||
IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes);
|
IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes);
|
||||||
}
|
}
|
||||||
} catch(...) {
|
} 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 ) {
|
if ( use_world_coords ) {
|
||||||
for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
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;
|
std::vector<IfcGeomObjects::IfcObject*> returned_objects;
|
||||||
bool IfcGeomObjects::CleanUp() {
|
bool IfcGeomObjects::CleanUp() {
|
||||||
Ifc::Dispose();
|
// TODO: Correctly implement destructor for IfcFile
|
||||||
|
delete ifc_file;
|
||||||
IfcGeom::Cache::Purge();
|
IfcGeom::Cache::Purge();
|
||||||
for ( std::vector<IfcGeomObjects::IfcObject*>::const_iterator it = returned_objects.begin();
|
for ( std::vector<IfcGeomObjects::IfcObject*>::const_iterator it = returned_objects.begin();
|
||||||
it != returned_objects.end();
|
it != returned_objects.end();
|
||||||
@@ -465,7 +468,7 @@ bool IfcGeomObjects::CleanUp() {
|
|||||||
const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
||||||
IfcObject* ifc_object = 0;
|
IfcObject* ifc_object = 0;
|
||||||
try {
|
try {
|
||||||
const IfcEntity& ifc_entity = Ifc::EntityById(id);
|
const IfcParse::IfcEntity& ifc_entity = ifc_file->EntityById(id);
|
||||||
if ( ifc_entity->is(Ifc2x3::Type::IfcProduct) ) {
|
if ( ifc_entity->is(Ifc2x3::Type::IfcProduct) ) {
|
||||||
Ifc2x3::IfcProduct::ptr ifc_product = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,Ifc2x3::IfcProduct>(ifc_entity);
|
Ifc2x3::IfcProduct::ptr ifc_product = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,Ifc2x3::IfcProduct>(ifc_entity);
|
||||||
int parent_id = -1;
|
int parent_id = -1;
|
||||||
@@ -488,11 +491,93 @@ const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
|||||||
const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
|
const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
|
||||||
return current_geom_obj;
|
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) {
|
bool IfcGeomObjects::Init(const std::string fn) {
|
||||||
return IfcGeomObjects::Init(fn, 0, 0);
|
return IfcGeomObjects::Init(fn, 0, 0);
|
||||||
}
|
}
|
||||||
bool _Init() {
|
bool _Init() {
|
||||||
shapereps = Ifc::EntitiesByType<Ifc2x3::IfcShapeRepresentation>();
|
IfcGeomObjects::InitUnits();
|
||||||
|
|
||||||
|
shapereps = ifc_file->EntitiesByType<Ifc2x3::IfcShapeRepresentation>();
|
||||||
if ( ! shapereps ) return false;
|
if ( ! shapereps ) return false;
|
||||||
|
|
||||||
outer = shapereps->begin();
|
outer = shapereps->begin();
|
||||||
@@ -506,18 +591,21 @@ bool _Init() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool IfcGeomObjects::Init(const std::string fn, std::ostream* log1, std::ostream* log2) {
|
bool IfcGeomObjects::Init(const std::string fn, std::ostream* log1, std::ostream* log2) {
|
||||||
Ifc::SetOutput(log1,log2);
|
Logger::SetOutput(log1,log2);
|
||||||
if ( !Ifc::Init(fn) ) return false;
|
ifc_file = new IfcParse::IfcFile();
|
||||||
|
if ( !ifc_file->Init(fn) ) return false;
|
||||||
return _Init();
|
return _Init();
|
||||||
}
|
}
|
||||||
bool IfcGeomObjects::Init(std::istream& f, int len, std::ostream* log1, std::ostream* log2) {
|
bool IfcGeomObjects::Init(std::istream& f, int len, std::ostream* log1, std::ostream* log2) {
|
||||||
Ifc::SetOutput(log1,log2);
|
Logger::SetOutput(log1,log2);
|
||||||
if ( !Ifc::Init(f, len) ) return false;
|
ifc_file = new IfcParse::IfcFile();
|
||||||
|
if ( !ifc_file->Init(f, len) ) return false;
|
||||||
return _Init();
|
return _Init();
|
||||||
}
|
}
|
||||||
bool IfcGeomObjects::Init(void* data, int len) {
|
bool IfcGeomObjects::Init(void* data, int len) {
|
||||||
Ifc::SetOutput(0,0);
|
Logger::SetOutput(0,0);
|
||||||
if ( !Ifc::Init(data, len) ) return false;
|
ifc_file = new IfcParse::IfcFile();
|
||||||
|
if ( !ifc_file->Init(data, len) ) return false;
|
||||||
return _Init();
|
return _Init();
|
||||||
}
|
}
|
||||||
void IfcGeomObjects::Settings(int setting, bool value) {
|
void IfcGeomObjects::Settings(int setting, bool value) {
|
||||||
@@ -538,7 +626,10 @@ void IfcGeomObjects::Settings(int setting, bool value) {
|
|||||||
use_faster_booleans = value;
|
use_faster_booleans = value;
|
||||||
break;
|
break;
|
||||||
case SEW_SHELLS:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,5 +637,5 @@ int IfcGeomObjects::Progress() {
|
|||||||
return 100 * done / total;
|
return 100 * done / total;
|
||||||
}
|
}
|
||||||
std::string IfcGeomObjects::GetLog() {
|
std::string IfcGeomObjects::GetLog() {
|
||||||
return Ifc::GetLog();
|
return Logger::GetLog();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ namespace IfcGeomObjects {
|
|||||||
// Specifies whether to compose IfcOpeningElements into a single compound
|
// Specifies whether to compose IfcOpeningElements into a single compound
|
||||||
// in order to speed up the processing of opening subtractions.
|
// in order to speed up the processing of opening subtractions.
|
||||||
const int FASTER_BOOLEANS = 6;
|
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.
|
// 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);
|
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(const std::string fn);
|
||||||
bool Init(void* data, int len);
|
bool Init(void* data, int len);
|
||||||
bool Init(const std::string fn, std::ostream* log1= 0, std::ostream* log2= 0);
|
bool Init(const std::string fn, std::ostream* log1= 0, std::ostream* log2= 0);
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& shape) {
|
bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& shape) {
|
||||||
TopoDS_Face face;
|
TopoDS_Face face;
|
||||||
if ( ! IfcGeom::convert_face(l->SweptArea(),face) ) return false;
|
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;
|
gp_Trsf trsf;
|
||||||
IfcGeom::convert(l->Position(),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);
|
const double first_operand_volume = shape_volume(s1);
|
||||||
if ( first_operand_volume <= ALMOST_ZERO )
|
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) ) {
|
if ( !IfcGeom::convert_shape(l->SecondOperand(),s2) ) {
|
||||||
shape = s1;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
|||||||
if ( ! is_halfspace ) {
|
if ( ! is_halfspace ) {
|
||||||
const double second_operand_volume = shape_volume(s2);
|
const double second_operand_volume = shape_volume(s2);
|
||||||
if ( second_operand_volume <= ALMOST_ZERO )
|
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;
|
bool valid_cut = false;
|
||||||
@@ -211,7 +211,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
|||||||
if ( is_valid ) {
|
if ( is_valid ) {
|
||||||
shape = result;
|
shape = result;
|
||||||
valid_cut = true;
|
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 ) {
|
if ( valid_cut ) {
|
||||||
const double volume_after_subtraction = shape_volume(shape);
|
const double volume_after_subtraction = shape_volume(shape);
|
||||||
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
|
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 {
|
} else {
|
||||||
Ifc::LogMessage("Error","Failed to process subtraction:",l->entity);
|
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",l->entity);
|
||||||
shape = s1;
|
shape = s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
|||||||
Ifc2x3::IfcFace::list faces = l->CfsFaces();
|
Ifc2x3::IfcFace::list faces = l->CfsFaces();
|
||||||
bool facesAdded = false;
|
bool facesAdded = false;
|
||||||
const unsigned int num_faces = faces->Size();
|
const unsigned int num_faces = faces->Size();
|
||||||
if ( Ifc::SewShells && num_faces < GetValue(GV_MAX_FACES_TO_SEW) ) {
|
if ( num_faces < GetValue(GV_MAX_FACES_TO_SEW) ) {
|
||||||
BRepOffsetAPI_Sewing builder;
|
BRepOffsetAPI_Sewing builder;
|
||||||
builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||||
builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||||
@@ -305,7 +305,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
|||||||
builder.Add(face);
|
builder.Add(face);
|
||||||
facesAdded = true;
|
facesAdded = true;
|
||||||
} else {
|
} else {
|
||||||
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
|
Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ! facesAdded ) return false;
|
if ( ! facesAdded ) return false;
|
||||||
@@ -326,7 +326,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
|||||||
builder.Add(compound,face);
|
builder.Add(compound,face);
|
||||||
facesAdded = true;
|
facesAdded = true;
|
||||||
} else {
|
} else {
|
||||||
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
|
Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ! facesAdded ) return false;
|
if ( ! facesAdded ) return false;
|
||||||
|
|||||||
@@ -83,62 +83,58 @@
|
|||||||
#include "../ifcgeom/IfcGeom.h"
|
#include "../ifcgeom/IfcGeom.h"
|
||||||
|
|
||||||
bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) {
|
bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) {
|
||||||
if ( ! Ifc::hasPlaneAngleUnit ) {
|
if ( IfcGeom::GetValue(GV_PLANEANGLE_UNIT)>0 ) {
|
||||||
Ifc::LogMessage("Warning","Creating a composite curve without unit information:",l->entity);
|
Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity);
|
||||||
|
|
||||||
// Temporarily pretend we do have unit information
|
// Temporarily pretend we do have unit information
|
||||||
Ifc::hasPlaneAngleUnit = true;
|
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,1.0);
|
||||||
|
|
||||||
bool succes_radians = false;
|
bool succes_radians = false;
|
||||||
bool succes_degrees = false;
|
bool succes_degrees = false;
|
||||||
bool use_radians = false;
|
bool use_radians = false;
|
||||||
bool use_degrees = false;
|
bool use_degrees = false;
|
||||||
|
|
||||||
// First try radians
|
// First try radians
|
||||||
Ifc::PlaneAngleUnit = 1.0f;
|
TopoDS_Wire wire_radians, wire_degrees;
|
||||||
TopoDS_Wire wire_radians, wire_degrees;
|
|
||||||
try {
|
try {
|
||||||
succes_radians = IfcGeom::convert(l,wire_radians);
|
succes_radians = IfcGeom::convert(l,wire_radians);
|
||||||
} catch (...) {}
|
} catch (...) {}
|
||||||
|
|
||||||
// Now try degrees
|
// Now try degrees
|
||||||
Ifc::PlaneAngleUnit = 0.0174532925199433f;
|
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,0.0174532925199433);
|
||||||
try {
|
try {
|
||||||
succes_degrees = IfcGeom::convert(l,wire_degrees);
|
succes_degrees = IfcGeom::convert(l,wire_degrees);
|
||||||
} catch (...) {}
|
} catch (...) {}
|
||||||
|
|
||||||
// Restore to unknown unit state
|
// Restore to unknown unit state
|
||||||
Ifc::PlaneAngleUnit = 1.0f;
|
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,-1.0);
|
||||||
Ifc::hasPlaneAngleUnit = false;
|
|
||||||
|
|
||||||
if ( succes_degrees && ! succes_radians ) {
|
if ( succes_degrees && ! succes_radians ) {
|
||||||
use_degrees = true;
|
use_degrees = true;
|
||||||
} else if ( succes_radians && ! succes_degrees ) {
|
} else if ( succes_radians && ! succes_degrees ) {
|
||||||
use_radians = true;
|
use_radians = true;
|
||||||
} else if ( succes_radians && succes_degrees ) {
|
} else if ( succes_radians && succes_degrees ) {
|
||||||
if ( wire_degrees.Closed() && ! wire_radians.Closed() ) {
|
if ( wire_degrees.Closed() && ! wire_radians.Closed() ) {
|
||||||
use_degrees = true;
|
use_degrees = true;
|
||||||
} else if ( wire_radians.Closed() && ! wire_degrees.Closed() ) {
|
} else if ( wire_radians.Closed() && ! wire_degrees.Closed() ) {
|
||||||
use_radians = true;
|
use_radians = true;
|
||||||
} else {
|
} else {
|
||||||
// No heuristic left to prefer the one over the other,
|
// No heuristic left to prefer the one over the other,
|
||||||
// apparently both variants are equally succesful.
|
// apparently both variants are equally succesful.
|
||||||
// The curve might be composed of only straight segments.
|
// The curve might be composed of only straight segments.
|
||||||
// Let's go with the wire created using radians as that
|
// Let's go with the wire created using radians as that
|
||||||
// at least is a SI unit.
|
// at least is a SI unit.
|
||||||
use_radians = true;
|
use_radians = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( use_radians ) {
|
|
||||||
Ifc::LogMessage("Notice","Used radians to create composite curve");
|
|
||||||
wire = wire_radians;
|
|
||||||
} else if ( use_degrees ) {
|
|
||||||
Ifc::LogMessage("Notice","Used degrees to create composite curve");
|
|
||||||
wire = wire_degrees;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ifc2x3::IfcCompositeCurveSegment::list segments = l->Segments();
|
Ifc2x3::IfcCompositeCurveSegment::list segments = l->Segments();
|
||||||
BRepBuilderAPI_MakeWire w;
|
BRepBuilderAPI_MakeWire w;
|
||||||
@@ -147,7 +143,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
|||||||
const Ifc2x3::IfcCurve::ptr curve = (*it)->ParentCurve();
|
const Ifc2x3::IfcCurve::ptr curve = (*it)->ParentCurve();
|
||||||
TopoDS_Wire wire2;
|
TopoDS_Wire wire2;
|
||||||
if ( ! IfcGeom::convert_wire(curve,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;
|
continue;
|
||||||
}
|
}
|
||||||
if ( ! (*it)->SameSense() ) wire2.Reverse();
|
if ( ! (*it)->SameSense() ) wire2.Reverse();
|
||||||
@@ -166,7 +162,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
|||||||
w.Add(wire2);
|
w.Add(wire2);
|
||||||
//last_vertex = w.Vertex();
|
//last_vertex = w.Vertex();
|
||||||
if ( w.Error() != BRepBuilderAPI_WireDone ) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +172,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
|||||||
bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||||
Ifc2x3::IfcCurve::ptr basis_curve = l->BasisCurve();
|
Ifc2x3::IfcCurve::ptr basis_curve = l->BasisCurve();
|
||||||
bool isConic = basis_curve->is(Ifc2x3::Type::IfcConic);
|
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;
|
Handle(Geom_Curve) curve;
|
||||||
if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false;
|
if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false;
|
||||||
bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
|
bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
|
||||||
@@ -209,7 +205,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
|||||||
BRepBuilderAPI_EdgeError err = e.Error();
|
BRepBuilderAPI_EdgeError err = e.Error();
|
||||||
if ( err == BRepBuilderAPI_PointProjectionFailed ) {
|
if ( err == BRepBuilderAPI_PointProjectionFailed ) {
|
||||||
w.Add(BRepBuilderAPI_MakeEdge(sense_agreement ? pnt1 : pnt2,sense_agreement ? pnt2 : pnt1));
|
w.Add(BRepBuilderAPI_MakeEdge(sense_agreement ? pnt1 : pnt2,sense_agreement ? pnt2 : pnt1));
|
||||||
Ifc::LogMessage("Warning","Point projection failed for:",l->entity);
|
Logger::Message(Logger::LOG_WARNING,"Point projection failed for:",l->entity);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
w.Add(e.Edge());
|
w.Add(e.Edge());
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ using namespace IfcUtil;
|
|||||||
|
|
||||||
bool IfcGeom::convert_shapes(const IfcBaseClass* l, ShapeList& r) {
|
bool IfcGeom::convert_shapes(const IfcBaseClass* l, ShapeList& r) {
|
||||||
#include "IfcRegisterConvertShapes.h"
|
#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;
|
return false;
|
||||||
}
|
}
|
||||||
bool IfcGeom::is_shape_collection(const IfcBaseClass* l) {
|
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);
|
std::map<int,TopoDS_Shape>::const_iterator it = Cache::Shape.find(id);
|
||||||
if ( it != Cache::Shape.end() ) { r = it->second; return &(it->second); }
|
if ( it != Cache::Shape.end() ) { r = it->second; return &(it->second); }
|
||||||
#include "IfcRegisterConvertShape.h"
|
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) {
|
bool IfcGeom::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) {
|
||||||
#include "IfcRegisterConvertWire.h"
|
#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;
|
return false;
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert_face(const IfcBaseClass* l, TopoDS_Face& r) {
|
bool IfcGeom::convert_face(const IfcBaseClass* l, TopoDS_Face& r) {
|
||||||
#include "IfcRegisterConvertFace.h"
|
#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;
|
return false;
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) {
|
bool IfcGeom::convert_curve(const IfcBaseClass* l, Handle(Geom_Curve)& r) {
|
||||||
#include "IfcRegisterConvertCurve.h"
|
#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;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
#include <gp_Trsf.hxx>
|
#include <gp_Trsf.hxx>
|
||||||
#include <gp_Trsf2d.hxx>
|
#include <gp_Trsf2d.hxx>
|
||||||
|
|
||||||
|
#include "../ifcparse/IfcUtil.h"
|
||||||
#include "../ifcparse/IfcParse.h"
|
#include "../ifcparse/IfcParse.h"
|
||||||
|
|
||||||
using namespace Ifc2x3;
|
using namespace Ifc2x3;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
return &(Cache::Shape[id]); \
|
return &(Cache::Shape[id]); \
|
||||||
} \
|
} \
|
||||||
} catch(...) { } \
|
} catch(...) { } \
|
||||||
Ifc::LogMessage("Error","Failed to convert:",l->entity); \
|
Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
#include "IfcRegisterDef.h"
|
#include "IfcRegisterDef.h"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
try { \
|
try { \
|
||||||
return IfcGeom::convert((T*)l,r); \
|
return IfcGeom::convert((T*)l,r); \
|
||||||
} catch (...) { } \
|
} catch (...) { } \
|
||||||
Ifc::LogMessage("Error","Failed to convert:",l->entity); \
|
Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
#include "IfcRegisterDef.h"
|
#include "IfcRegisterDef.h"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* *
|
* *
|
||||||
* This file is part of IfcOpenShell. *
|
* This file is part of IfcOpenShell. *
|
||||||
* *
|
* *
|
||||||
@@ -87,7 +87,7 @@ void IfcCharacterDecoder::addChar(std::stringstream& s,const UChar32& ch) {
|
|||||||
s.put(substitution_character);
|
s.put(substitution_character);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::File* f) {
|
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::IfcSpfStream* f) {
|
||||||
file = f;
|
file = f;
|
||||||
#ifdef HAVE_ICU
|
#ifdef HAVE_ICU
|
||||||
if (destination) ucnv_close(destination);
|
if (destination) ucnv_close(destination);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace IfcParse {
|
|||||||
|
|
||||||
class IfcCharacterDecoder {
|
class IfcCharacterDecoder {
|
||||||
private:
|
private:
|
||||||
IfcParse::File* file;
|
IfcParse::IfcSpfStream* file;
|
||||||
#ifdef HAVE_ICU
|
#ifdef HAVE_ICU
|
||||||
static UConverter* destination;
|
static UConverter* destination;
|
||||||
static UConverter* converter;
|
static UConverter* converter;
|
||||||
@@ -65,7 +65,7 @@ namespace IfcParse {
|
|||||||
#else
|
#else
|
||||||
static char substitution_character;
|
static char substitution_character;
|
||||||
#endif
|
#endif
|
||||||
IfcCharacterDecoder(IfcParse::File* file);
|
IfcCharacterDecoder(IfcParse::IfcSpfStream* file);
|
||||||
~IfcCharacterDecoder();
|
~IfcCharacterDecoder();
|
||||||
void dryRun();
|
void dryRun();
|
||||||
operator std::string();
|
operator std::string();
|
||||||
|
|||||||
@@ -39,14 +39,14 @@
|
|||||||
//const int BUF_SIZE = (128 * 1024 * 1024);
|
//const int BUF_SIZE = (128 * 1024 * 1024);
|
||||||
|
|
||||||
namespace IfcParse {
|
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
|
/// The file is interpreted as a sequence of tokens which are lazily
|
||||||
/// interpreted only when requested. If the size of the file is
|
/// interpreted only when requested. If the size of the file is
|
||||||
/// larger than BUF_SIZE, the file is split into seperate pages, of
|
/// larger than BUF_SIZE, the file is split into seperate pages, of
|
||||||
/// which only one is simultaneously kept in memory, for files
|
/// which only one is simultaneously kept in memory, for files
|
||||||
/// that define their entities not in a sequential nature, this is
|
/// that define their entities not in a sequential nature, this is
|
||||||
/// detrimental for the performance of the parser.
|
/// detrimental for the performance of the parser.
|
||||||
class File {
|
class IfcSpfStream {
|
||||||
private:
|
private:
|
||||||
std::ifstream stream;
|
std::ifstream stream;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
@@ -61,9 +61,9 @@ namespace IfcParse {
|
|||||||
bool valid;
|
bool valid;
|
||||||
bool eof;
|
bool eof;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
File(const std::string& fn);
|
IfcSpfStream(const std::string& fn);
|
||||||
File(std::istream& f, int len);
|
IfcSpfStream(std::istream& f, int len);
|
||||||
File(void* data, int len);
|
IfcSpfStream(void* data, int len);
|
||||||
/// Returns the character at the cursor
|
/// Returns the character at the cursor
|
||||||
char Peek();
|
char Peek();
|
||||||
/// Returns the character at specified offset
|
/// Returns the character at specified offset
|
||||||
|
|||||||
+127
-224
@@ -1,4 +1,4 @@
|
|||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* *
|
* *
|
||||||
* This file is part of IfcOpenShell. *
|
* This file is part of IfcOpenShell. *
|
||||||
* *
|
* *
|
||||||
@@ -33,7 +33,7 @@ using namespace IfcParse;
|
|||||||
//
|
//
|
||||||
// Opens the file, gets the filesize and reads a chunk in memory
|
// 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;
|
eof = false;
|
||||||
stream.open(fn.c_str(),std::ios_base::binary);
|
stream.open(fn.c_str(),std::ios_base::binary);
|
||||||
if ( ! stream.good() ) {
|
if ( ! stream.good() ) {
|
||||||
@@ -56,7 +56,7 @@ File::File(const std::string& fn) {
|
|||||||
ReadBuffer(false);
|
ReadBuffer(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
File::File(std::istream& f, int l) {
|
IfcSpfStream::IfcSpfStream(std::istream& f, int l) {
|
||||||
eof = false;
|
eof = false;
|
||||||
size = l;
|
size = l;
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
@@ -70,7 +70,7 @@ File::File(std::istream& f, int l) {
|
|||||||
len = l;
|
len = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
File::File(void* data, int l) {
|
IfcSpfStream::IfcSpfStream(void* data, int l) {
|
||||||
eof = false;
|
eof = false;
|
||||||
size = l;
|
size = l;
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
@@ -83,15 +83,17 @@ File::File(void* data, int l) {
|
|||||||
len = l;
|
len = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::Close() {
|
void IfcSpfStream::Close() {
|
||||||
stream.close();
|
#ifdef BUF_SIZE
|
||||||
|
if ( paging ) stream.close();
|
||||||
|
#endif
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reads a chunk of BUF_SIZE in memory and increments cursor if requested
|
// 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
|
#ifdef BUF_SIZE
|
||||||
if ( inc ) {
|
if ( inc ) {
|
||||||
offset += len;
|
offset += len;
|
||||||
@@ -108,12 +110,17 @@ void File::ReadBuffer(bool inc) {
|
|||||||
len = (unsigned int) stream.gcount();
|
len = (unsigned int) stream.gcount();
|
||||||
eof = len == 0;
|
eof = len == 0;
|
||||||
ptr = 0;
|
ptr = 0;
|
||||||
|
#ifdef BUF_SIZE
|
||||||
|
if (!paging) stream.close();
|
||||||
|
#else
|
||||||
|
stream.close();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Seeks an arbitrary position in the file
|
// Seeks an arbitrary position in the file
|
||||||
//
|
//
|
||||||
void File::Seek(unsigned int o) {
|
void IfcSpfStream::Seek(unsigned int o) {
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
if ( !paging ) {
|
if ( !paging ) {
|
||||||
#endif
|
#endif
|
||||||
@@ -135,14 +142,14 @@ void File::Seek(unsigned int o) {
|
|||||||
//
|
//
|
||||||
// Returns the character at the cursor
|
// Returns the character at the cursor
|
||||||
//
|
//
|
||||||
char File::Peek() {
|
char IfcSpfStream::Peek() {
|
||||||
return buffer[ptr];
|
return buffer[ptr];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns the character at specified offset
|
// Returns the character at specified offset
|
||||||
//
|
//
|
||||||
char File::Read(unsigned int o) {
|
char IfcSpfStream::Read(unsigned int o) {
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
if ( ! paging ) {
|
if ( ! paging ) {
|
||||||
#endif
|
#endif
|
||||||
@@ -161,7 +168,7 @@ char File::Read(unsigned int o) {
|
|||||||
//
|
//
|
||||||
// Returns the cursor position
|
// Returns the cursor position
|
||||||
//
|
//
|
||||||
unsigned int File::Tell() {
|
unsigned int IfcSpfStream::Tell() {
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
return offset + ptr;
|
return offset + ptr;
|
||||||
#else
|
#else
|
||||||
@@ -172,7 +179,7 @@ unsigned int File::Tell() {
|
|||||||
//
|
//
|
||||||
// Increments cursor and reads new chunk if necessary
|
// Increments cursor and reads new chunk if necessary
|
||||||
//
|
//
|
||||||
void File::Inc() {
|
void IfcSpfStream::Inc() {
|
||||||
if ( ++ptr == len ) {
|
if ( ++ptr == len ) {
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
if ( paging ) ReadBuffer();
|
if ( paging ) ReadBuffer();
|
||||||
@@ -184,13 +191,14 @@ void File::Inc() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
const char current = File::Peek();
|
const char current = IfcSpfStream::Peek();
|
||||||
if ( current == '\n' || current == '\r' ) File::Inc();
|
if ( current == '\n' || current == '\r' ) IfcSpfStream::Inc();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokens::Tokens(IfcParse::File *f) {
|
Tokens::Tokens(IfcParse::IfcSpfStream *s, IfcParse::IfcFile* f) {
|
||||||
file = f;
|
file = f;
|
||||||
decoder = new IfcCharacterDecoder(f);
|
stream = s;
|
||||||
|
decoder = new IfcCharacterDecoder(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokens::~Tokens() {
|
Tokens::~Tokens() {
|
||||||
@@ -202,38 +210,38 @@ Tokens::~Tokens() {
|
|||||||
//
|
//
|
||||||
Token Tokens::Next() {
|
Token Tokens::Next() {
|
||||||
|
|
||||||
if ( file->eof ) return TokenPtr();
|
if ( stream->eof ) return TokenPtr();
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
// Trim whitespace
|
// Trim whitespace
|
||||||
while ( !file->eof ) {
|
while ( !stream->eof ) {
|
||||||
c = file->Peek();
|
c = stream->Peek();
|
||||||
if ( (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) file->Inc();
|
if ( (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) stream->Inc();
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( file->eof ) return TokenPtr();
|
if ( stream->eof ) return TokenPtr();
|
||||||
unsigned int pos = file->Tell();
|
unsigned int pos = stream->Tell();
|
||||||
|
|
||||||
bool inString = false;
|
bool inString = false;
|
||||||
bool inComment = false;
|
bool inComment = false;
|
||||||
|
|
||||||
// If the cursor is at [()=,;$*] we know token consists of single char
|
// If the cursor is at [()=,;$*] we know token consists of single char
|
||||||
if ( c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '$' || c == '*' ) {
|
if ( c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '$' || c == '*' ) {
|
||||||
file->Inc();
|
stream->Inc();
|
||||||
return TokenPtr(c);
|
return TokenPtr(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
char p = 0;
|
char p = 0;
|
||||||
while ( ! file->eof ) {
|
while ( ! stream->eof ) {
|
||||||
|
|
||||||
// Read character and increment pointer if not starting a new token
|
// 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;
|
if ( len && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
||||||
file->Inc();
|
stream->Inc();
|
||||||
|
|
||||||
// Skip whitespace if not in comment or string
|
// Skip whitespace if not in comment or string
|
||||||
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
||||||
@@ -247,7 +255,7 @@ Token Tokens::Next() {
|
|||||||
|
|
||||||
p = c;
|
p = c;
|
||||||
}
|
}
|
||||||
if ( len ) return TokenPtr(pos);
|
if ( len ) return TokenPtr(this,pos);
|
||||||
else return TokenPtr();
|
else return TokenPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,18 +264,18 @@ Token Tokens::Next() {
|
|||||||
// Omits whitespace and comments
|
// Omits whitespace and comments
|
||||||
//
|
//
|
||||||
std::string Tokens::TokenString(unsigned int offset) {
|
std::string Tokens::TokenString(unsigned int offset) {
|
||||||
const bool was_eof = file->eof;
|
const bool was_eof = stream->eof;
|
||||||
unsigned int old_offset = file->Tell();
|
unsigned int old_offset = stream->Tell();
|
||||||
file->Seek(offset);
|
stream->Seek(offset);
|
||||||
bool inString = false;
|
bool inString = false;
|
||||||
bool inComment = false;
|
bool inComment = false;
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
buffer.reserve(128);
|
buffer.reserve(128);
|
||||||
char p = 0;
|
char p = 0;
|
||||||
while ( ! file->eof ) {
|
while ( ! stream->eof ) {
|
||||||
char c = file->Peek();
|
char c = stream->Peek();
|
||||||
if ( buffer.size() && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
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 && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
||||||
if ( !inComment ) buffer.push_back(c);
|
if ( !inComment ) buffer.push_back(c);
|
||||||
if ( inComment && p == '*' && c == '/' ) inComment = false;
|
if ( inComment && p == '*' && c == '/' ) inComment = false;
|
||||||
@@ -275,8 +283,8 @@ std::string Tokens::TokenString(unsigned int offset) {
|
|||||||
else if ( !inComment && c == '\'' ) return *decoder;
|
else if ( !inComment && c == '\'' ) return *decoder;
|
||||||
p = c;
|
p = c;
|
||||||
}
|
}
|
||||||
if ( was_eof ) file->eof = true;
|
if ( was_eof ) stream->eof = true;
|
||||||
else file->Seek(old_offset);
|
else stream->Seek(old_offset);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,33 +292,32 @@ std::string Tokens::TokenString(unsigned int offset) {
|
|||||||
// Functions for creating Tokens from an arbitary file offset.
|
// Functions for creating Tokens from an arbitary file offset.
|
||||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
||||||
//
|
//
|
||||||
Token IfcParse::TokenPtr(unsigned int offset) { return offset + 128; }
|
Token IfcParse::TokenPtr(Tokens* tokens, unsigned int offset) { return Token(tokens,offset); }
|
||||||
Token IfcParse::TokenPtr(char c) { return c; }
|
Token IfcParse::TokenPtr(char c) { return Token((Tokens*)0,(unsigned) c); }
|
||||||
Token IfcParse::TokenPtr() { return 0; }
|
Token IfcParse::TokenPtr() { return Token((Tokens*)0,0); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// Functions to convert Tokens to binary data
|
// Functions to convert Tokens to binary data
|
||||||
//
|
//
|
||||||
unsigned int TokenFunc::Offset(Token t) { return t - 128; }
|
bool TokenFunc::startsWith(const Token& t, char c) {
|
||||||
bool TokenFunc::startsWith(Token t, char c) {
|
return t.first->stream->Read(t.second) == c;
|
||||||
return Ifc::file->Read(Offset(t)) == c;
|
|
||||||
}
|
}
|
||||||
bool TokenFunc::isOperator(Token t, char op) {
|
bool TokenFunc::isOperator(const Token& t, char op) {
|
||||||
return (t < 128) && (!op || op == t);
|
return (!t.first) && (!op || op == t.second);
|
||||||
}
|
}
|
||||||
bool TokenFunc::isIdentifier(Token t) {
|
bool TokenFunc::isIdentifier(const Token& t) {
|
||||||
return ! isOperator(t) && startsWith(t, '#');
|
return ! isOperator(t) && startsWith(t, '#');
|
||||||
}
|
}
|
||||||
bool TokenFunc::isString(Token t) {
|
bool TokenFunc::isString(const Token& t) {
|
||||||
return ! isOperator(t) && startsWith(t, '\'');
|
return ! isOperator(t) && startsWith(t, '\'');
|
||||||
}
|
}
|
||||||
bool TokenFunc::isEnumeration(Token t) {
|
bool TokenFunc::isEnumeration(const Token& t) {
|
||||||
return ! isOperator(t) && startsWith(t, '.');
|
return ! isOperator(t) && startsWith(t, '.');
|
||||||
}
|
}
|
||||||
bool TokenFunc::isDatatype(Token t) {
|
bool TokenFunc::isDatatype(const Token& t) {
|
||||||
return ! isOperator(t) && startsWith(t, 'I');
|
return ! isOperator(t) && startsWith(t, 'I');
|
||||||
}
|
}
|
||||||
int TokenFunc::asInt(Token t) {
|
int TokenFunc::asInt(const Token& t) {
|
||||||
const std::string str = asString(t);
|
const std::string str = asString(t);
|
||||||
// In case of an ENTITY_INSTANCE_NAME skip the leading #
|
// In case of an ENTITY_INSTANCE_NAME skip the leading #
|
||||||
const char* start = str.c_str() + (isIdentifier(t) ? 1 : 0);
|
const char* start = str.c_str() + (isIdentifier(t) ? 1 : 0);
|
||||||
@@ -319,31 +326,31 @@ int TokenFunc::asInt(Token t) {
|
|||||||
if ( start == end ) throw IfcException("Token is not an integer or identifier");
|
if ( start == end ) throw IfcException("Token is not an integer or identifier");
|
||||||
return (int) result;
|
return (int) result;
|
||||||
}
|
}
|
||||||
bool TokenFunc::asBool(Token t) {
|
bool TokenFunc::asBool(const Token& t) {
|
||||||
const std::string str = asString(t);
|
const std::string str = asString(t);
|
||||||
return str == "T";
|
return str == "T";
|
||||||
}
|
}
|
||||||
double TokenFunc::asFloat(Token t) {
|
double TokenFunc::asFloat(const Token& t) {
|
||||||
const std::string str = asString(t);
|
const std::string str = asString(t);
|
||||||
return (double) atof(str.c_str());
|
return (double) atof(str.c_str());
|
||||||
}
|
}
|
||||||
std::string TokenFunc::asString(Token t) {
|
std::string TokenFunc::asString(const Token& t) {
|
||||||
if ( isOperator(t,'$') ) return "";
|
if ( isOperator(t,'$') ) return "";
|
||||||
else if ( isOperator(t) ) throw IfcException("Token is not a string");
|
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;
|
return isString(t) || isEnumeration(t) ? str.substr(1,str.size()-2) : str;
|
||||||
}
|
}
|
||||||
std::string TokenFunc::toString(Token t) {
|
std::string TokenFunc::toString(const Token& t) {
|
||||||
if ( isOperator(t) ) return std::string ( (char*) &t, 1 );
|
if ( isOperator(t) ) return std::string ( (char*) &t.second , 1 );
|
||||||
else return Ifc::tokens->TokenString(t - 128);
|
else return t.first->TokenString(t.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TokenArgument::TokenArgument(Token t) {
|
TokenArgument::TokenArgument(const Token& t) {
|
||||||
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));
|
entity = new IfcUtil::IfcArgumentSelect(ty,new TokenArgument(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,10 +359,11 @@ EntityArgument::EntityArgument(Ifc2x3::Type::Enum ty, Token t) {
|
|||||||
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
||||||
//
|
//
|
||||||
ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
||||||
while( Token next = t->Next() ) {
|
Token next = t->Next();
|
||||||
if ( TokenFunc::isOperator(next,',') ) continue;
|
while( next.second || next.first ) {
|
||||||
if ( TokenFunc::isOperator(next,')') ) break;
|
if ( TokenFunc::isOperator(next,',') ) {}
|
||||||
if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
|
else if ( TokenFunc::isOperator(next,')') ) break;
|
||||||
|
else if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
|
||||||
else {
|
else {
|
||||||
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
|
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
|
||||||
if ( TokenFunc::isDatatype(next) ) {
|
if ( TokenFunc::isDatatype(next) ) {
|
||||||
@@ -363,13 +371,14 @@ ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
|||||||
try {
|
try {
|
||||||
Push ( new EntityArgument(Ifc2x3::Type::FromString(TokenFunc::asString(next)),t->Next()) );
|
Push ( new EntityArgument(Ifc2x3::Type::FromString(TokenFunc::asString(next)),t->Next()) );
|
||||||
} catch ( IfcException& e ) {
|
} catch ( IfcException& e ) {
|
||||||
Ifc::LogMessage("Error",e.what());
|
Logger::Message(Logger::LOG_ERROR,e.what());
|
||||||
}
|
}
|
||||||
t->Next();
|
t->Next();
|
||||||
} else {
|
} else {
|
||||||
Push ( new TokenArgument(next) );
|
Push ( new TokenArgument(next) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
next = t->Next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,11 +463,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<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<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 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::IfcSchemaEntity() const { return token.first->file->EntityById(TokenFunc::asInt(token)); }
|
||||||
/*TokenArgument::operator IfcUtil::IfcAbstractSelect::ptr() const {
|
|
||||||
//TODO Fix memory leak
|
|
||||||
return new IfcUtil::IfcEntitySelect(*this);
|
|
||||||
}*/
|
|
||||||
TokenArgument::operator IfcEntities() const { throw IfcException("Argument is not a list of entities"); }
|
TokenArgument::operator IfcEntities() const { throw IfcException("Argument is not a list of entities"); }
|
||||||
unsigned int TokenArgument::Size() const { return 1; }
|
unsigned int TokenArgument::Size() const { return 1; }
|
||||||
ArgumentPtr TokenArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
ArgumentPtr TokenArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
||||||
@@ -496,19 +501,21 @@ EntityArgument::~EntityArgument() { delete entity; }
|
|||||||
//
|
//
|
||||||
// Reads an Entity from the list of Tokens
|
// Reads an Entity from the list of Tokens
|
||||||
//
|
//
|
||||||
Entity::Entity(unsigned int i, Tokens* t) {
|
Entity::Entity(unsigned int i, IfcFile* f) { //: file(f) {
|
||||||
Token datatype = t->Next();
|
file = f;
|
||||||
|
Token datatype = f->tokens->Next();
|
||||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||||
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
||||||
_id = i;
|
_id = i;
|
||||||
args = ArgumentPtr();
|
args = ArgumentPtr();
|
||||||
offset = TokenFunc::Offset(datatype);
|
offset = datatype.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reads an Entity from the list of Tokens at the specified offset in the file
|
// 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;
|
std::vector<unsigned int> ids;
|
||||||
_id = i;
|
_id = i;
|
||||||
offset = o;
|
offset = o;
|
||||||
@@ -539,16 +546,16 @@ unsigned int Entity::getArgumentCount() {
|
|||||||
//
|
//
|
||||||
void Entity::Load(std::vector<unsigned int>& ids, bool seek) {
|
void Entity::Load(std::vector<unsigned int>& ids, bool seek) {
|
||||||
if ( seek ) {
|
if ( seek ) {
|
||||||
Ifc::file->Seek(offset);
|
file->tokens->stream->Seek(offset);
|
||||||
Token datatype = Ifc::tokens->Next();
|
Token datatype = file->tokens->Next();
|
||||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||||
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
||||||
}
|
}
|
||||||
Token open = Ifc::tokens->Next();
|
Token open = file->tokens->Next();
|
||||||
args = new ArgumentList(Ifc::tokens, ids);
|
args = new ArgumentList(file->tokens, ids);
|
||||||
unsigned int old_offset = Ifc::file->Tell();
|
unsigned int old_offset = file->tokens->stream->Tell();
|
||||||
Token semilocon = Ifc::tokens->Next();
|
Token semilocon = file->tokens->Next();
|
||||||
if ( ! TokenFunc::isOperator(semilocon,';') ) Ifc::file->Seek(old_offset);
|
if ( ! TokenFunc::isOperator(semilocon,';') ) file->tokens->stream->Seek(old_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ifc2x3::Type::Enum Entity::type() const {
|
Ifc2x3::Type::Enum Entity::type() const {
|
||||||
@@ -589,7 +596,7 @@ Entity::~Entity() {
|
|||||||
//
|
//
|
||||||
IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c) {
|
IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c) {
|
||||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||||
IfcEntities all = Ifc::EntitiesByReference(_id);
|
IfcEntities all = file->EntitiesByReference(_id);
|
||||||
if ( ! all ) return l;
|
if ( ! all ) return l;
|
||||||
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
||||||
if ( c == Ifc2x3::Type::ALL || (*it)->is(c) ) {
|
if ( c == Ifc2x3::Type::ALL || (*it)->is(c) ) {
|
||||||
@@ -612,44 +619,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; }
|
bool Entity::is(Ifc2x3::Type::Enum v) const { return _type == v; }
|
||||||
unsigned int Entity::id() { return _id; }
|
unsigned int Entity::id() { return _id; }
|
||||||
|
|
||||||
|
IfcFile::IfcFile() {
|
||||||
|
file = 0;
|
||||||
|
lastId = 0;
|
||||||
|
tokens = 0;
|
||||||
|
MaxId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parses the IFC file in fn
|
// Parses the IFC file in fn
|
||||||
// Creates the maps
|
// Creates the maps
|
||||||
// Gets the unit definitins from the file
|
// Gets the unit definitins from the file
|
||||||
//
|
//
|
||||||
bool Ifc::Init(const std::string& fn) {
|
bool IfcFile::Init(const std::string& fn) {
|
||||||
return Ifc::Init(new File(fn));
|
return IfcFile::Init(new IfcSpfStream(fn));
|
||||||
}
|
}
|
||||||
bool Ifc::Init(std::istream& f, int len) {
|
bool IfcFile::Init(std::istream& f, int len) {
|
||||||
return Ifc::Init(new File(f,len));
|
return IfcFile::Init(new IfcSpfStream(f,len));
|
||||||
}
|
}
|
||||||
bool Ifc::Init(void* data, int len) {
|
bool IfcFile::Init(void* data, int len) {
|
||||||
return Ifc::Init(new File(data,len));
|
return IfcFile::Init(new IfcSpfStream(data,len));
|
||||||
}
|
}
|
||||||
bool Ifc::Init(IfcParse::File* f) {
|
bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||||
Ifc2x3::InitStringMap();
|
Ifc2x3::InitStringMap();
|
||||||
file = f;
|
file = f;
|
||||||
if ( ! file->valid ) return false;
|
if ( ! file->valid ) return false;
|
||||||
tokens = new Tokens (file);
|
tokens = new Tokens (file,this);
|
||||||
Token token = 0;
|
Token token = TokenPtr();
|
||||||
Token previous = 0;
|
Token previous = TokenPtr();
|
||||||
unsigned int currentId = 0;
|
unsigned int currentId = 0;
|
||||||
lastId = 0;
|
lastId = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
EntityPtr e;
|
EntityPtr e;
|
||||||
IfcUtil::IfcSchemaEntity entity = 0;
|
IfcUtil::IfcSchemaEntity entity = 0;
|
||||||
if ( log1 ) (*log1) << "Scanning file..." << std::endl;
|
Logger::Status("Scanning file...");
|
||||||
while ( ! file->eof ) {
|
while ( ! file->eof ) {
|
||||||
if ( currentId ) {
|
if ( currentId ) {
|
||||||
try {
|
try {
|
||||||
e = new Entity(currentId,tokens);
|
e = new Entity(currentId,this);
|
||||||
entity = Ifc2x3::SchemaEntity(e);
|
entity = Ifc2x3::SchemaEntity(e);
|
||||||
} catch (IfcException ex) {
|
} catch (IfcException ex) {
|
||||||
currentId = 0;
|
currentId = 0;
|
||||||
Ifc::LogMessage("Error",ex.what());
|
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( log1 && !((++x)%1000) ) (*log1) << "\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());
|
||||||
|
}
|
||||||
if ( entity->is(Ifc2x3::Type::IfcRoot) ) {
|
if ( entity->is(Ifc2x3::Type::IfcRoot) ) {
|
||||||
Ifc2x3::IfcRoot::ptr ifc_root = (Ifc2x3::IfcRoot::ptr) entity;
|
Ifc2x3::IfcRoot::ptr ifc_root = (Ifc2x3::IfcRoot::ptr) entity;
|
||||||
try {
|
try {
|
||||||
@@ -657,11 +675,11 @@ bool Ifc::Init(IfcParse::File* f) {
|
|||||||
if ( byguid.find(guid) != byguid.end() ) {
|
if ( byguid.find(guid) != byguid.end() ) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Overwriting entity with guid " << guid;
|
ss << "Overwriting entity with guid " << guid;
|
||||||
Ifc::LogMessage("Warning",ss.str());
|
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||||
}
|
}
|
||||||
byguid[guid] = ifc_root;
|
byguid[guid] = ifc_root;
|
||||||
} catch (IfcException ex) {
|
} catch (IfcException ex) {
|
||||||
Ifc::LogMessage("Error",ex.what());
|
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ifc2x3::Type::Enum ty = entity->type();
|
Ifc2x3::Type::Enum ty = entity->type();
|
||||||
@@ -677,16 +695,16 @@ bool Ifc::Init(IfcParse::File* f) {
|
|||||||
if ( byid.find(currentId) != byid.end() ) {
|
if ( byid.find(currentId) != byid.end() ) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Overwriting entity with id " << currentId;
|
ss << "Overwriting entity with id " << currentId;
|
||||||
Ifc::LogMessage("Warning",ss.str());
|
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||||
}
|
}
|
||||||
byid[currentId] = entity;
|
byid[currentId] = entity;
|
||||||
currentId = 0;
|
currentId = 0;
|
||||||
} else {
|
} else {
|
||||||
try { token = tokens->Next(); }
|
try { token = tokens->Next(); }
|
||||||
catch (... ) { token = 0; }
|
catch (... ) { token = TokenPtr(); }
|
||||||
}
|
}
|
||||||
if ( ! token ) break;
|
if ( ! (token.second || token.first) ) break;
|
||||||
if ( previous && TokenFunc::isIdentifier(previous) ) {
|
if ( (previous.second || previous.first) && TokenFunc::isIdentifier(previous) ) {
|
||||||
int id = TokenFunc::asInt(previous);
|
int id = TokenFunc::asInt(previous);
|
||||||
if ( TokenFunc::isOperator(token,'=') ) {
|
if ( TokenFunc::isOperator(token,'=') ) {
|
||||||
currentId = id;
|
currentId = id;
|
||||||
@@ -701,89 +719,32 @@ bool Ifc::Init(IfcParse::File* f) {
|
|||||||
}
|
}
|
||||||
previous = token;
|
previous = token;
|
||||||
}
|
}
|
||||||
|
Logger::Status("\rDone scanning file ");
|
||||||
if ( log1 ) (*log1) << "\rDone scanning file " << std::endl;
|
|
||||||
|
|
||||||
hasPlaneAngleUnit = false;
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcEntities Ifc::EntitiesByType(Ifc2x3::Type::Enum t) {
|
IfcEntities IfcFile::EntitiesByType(Ifc2x3::Type::Enum t) {
|
||||||
MapEntitiesByType::const_iterator it = bytype.find(t);
|
MapEntitiesByType::const_iterator it = bytype.find(t);
|
||||||
return (it == bytype.end()) ? IfcEntities() : it->second;
|
return (it == bytype.end()) ? IfcEntities() : it->second;
|
||||||
}
|
}
|
||||||
IfcEntities Ifc::EntitiesByReference(int t) {
|
IfcEntities IfcFile::EntitiesByReference(int t) {
|
||||||
MapEntitiesByRef::const_iterator it = byref.find(t);
|
MapEntitiesByRef::const_iterator it = byref.find(t);
|
||||||
return (it == byref.end()) ? IfcEntities() : it->second;
|
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);
|
MapEntityById::const_iterator it = byid.find(id);
|
||||||
if ( it == byid.end() ) {
|
if ( it == byid.end() ) {
|
||||||
MapOffsetById::const_iterator it2 = offsets.find(id);
|
MapOffsetById::const_iterator it2 = offsets.find(id);
|
||||||
if ( it2 == offsets.end() ) throw IfcException("Entity not found");
|
if ( it2 == offsets.end() ) throw IfcException("Entity not found");
|
||||||
const unsigned int offset = (*it2).second;
|
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);
|
IfcUtil::IfcSchemaEntity entity = Ifc2x3::SchemaEntity(e);
|
||||||
byid[id] = entity;
|
byid[id] = entity;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
return it->second;
|
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);
|
MapEntityByGuid::const_iterator it = byguid.find(guid);
|
||||||
if ( it == byguid.end() ) {
|
if ( it == byguid.end() ) {
|
||||||
throw IfcException("Entity not found");
|
throw IfcException("Entity not found");
|
||||||
@@ -796,77 +757,19 @@ IfcException::IfcException(std::string e) { error = e; }
|
|||||||
IfcException::~IfcException() throw () {}
|
IfcException::~IfcException() throw () {}
|
||||||
const char* IfcException::what() const throw() { return error.c_str(); }
|
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 ) {
|
for( MapEntityById::const_iterator it = byid.begin(); it != byid.end(); ++ it ) {
|
||||||
delete it->second->entity;
|
delete it->second->entity;
|
||||||
delete it->second;
|
delete it->second;
|
||||||
}
|
}
|
||||||
bytype.clear();
|
|
||||||
byid.clear();
|
|
||||||
byref.clear();
|
|
||||||
file->Close();
|
|
||||||
delete file;
|
delete file;
|
||||||
delete tokens;
|
delete tokens;
|
||||||
offsets.clear();
|
|
||||||
log_stream.str("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v ) {
|
MapEntityById::const_iterator IfcFile::begin() const {
|
||||||
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() {
|
|
||||||
return byid.begin();
|
return byid.begin();
|
||||||
}
|
}
|
||||||
MapEntityById::const_iterator Ifc::Last() {
|
MapEntityById::const_iterator IfcFile::end() const {
|
||||||
return byid.end();
|
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
@@ -1,4 +1,4 @@
|
|||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* *
|
* *
|
||||||
* This file is part of IfcOpenShell. *
|
* This file is part of IfcOpenShell. *
|
||||||
* *
|
* *
|
||||||
@@ -47,56 +47,59 @@ namespace IfcParse {
|
|||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
class Entities;
|
class Entities;
|
||||||
|
class IfcFile;
|
||||||
typedef Entity* EntityPtr;
|
typedef Entity* EntityPtr;
|
||||||
typedef SHARED_PTR<Entities> EntitiesPtr;
|
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
|
/// Provides functions to convert Tokens to binary data
|
||||||
/// Tokens are merely offsets to where they can be read in the file
|
/// Tokens are merely offsets to where they can be read in the file
|
||||||
class TokenFunc {
|
class TokenFunc {
|
||||||
private:
|
private:
|
||||||
static bool startsWith(Token t, char c);
|
static bool startsWith(const Token& t, char c);
|
||||||
public:
|
public:
|
||||||
/// Returns the offset at which the token is read from the file
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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.)
|
/// 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
|
/// 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)
|
/// 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)
|
/// 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
|
// Functions for creating Tokens from an arbitary file offset
|
||||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
// 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(char c);
|
||||||
Token TokenPtr();
|
Token TokenPtr();
|
||||||
|
|
||||||
/// A stream of tokens to be read from a File.
|
/// A stream of tokens to be read from a IfcSpfStream.
|
||||||
class Tokens {
|
class Tokens {
|
||||||
private:
|
private:
|
||||||
File* file;
|
|
||||||
IfcCharacterDecoder* decoder;
|
IfcCharacterDecoder* decoder;
|
||||||
public:
|
public:
|
||||||
Tokens(File* f);
|
IfcSpfStream* stream;
|
||||||
|
IfcFile* file;
|
||||||
|
Tokens(IfcSpfStream* s, IfcFile* f);
|
||||||
Token Next();
|
Token Next();
|
||||||
~Tokens();
|
~Tokens();
|
||||||
std::string TokenString(unsigned int offset);
|
std::string TokenString(unsigned int offset);
|
||||||
@@ -136,7 +139,7 @@ namespace IfcParse {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Token token;
|
Token token;
|
||||||
TokenArgument(Token t);
|
TokenArgument(const Token& t);
|
||||||
operator int() const;
|
operator int() const;
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
operator double() const;
|
operator double() const;
|
||||||
@@ -160,7 +163,7 @@ namespace IfcParse {
|
|||||||
private:
|
private:
|
||||||
IfcUtil::IfcArgumentSelect* entity;
|
IfcUtil::IfcArgumentSelect* entity;
|
||||||
public:
|
public:
|
||||||
EntityArgument(Ifc2x3::Type::Enum ty, Token t);
|
EntityArgument(Ifc2x3::Type::Enum ty, const Token& t);
|
||||||
~EntityArgument();
|
~EntityArgument();
|
||||||
operator int() const;
|
operator int() const;
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
@@ -183,15 +186,16 @@ namespace IfcParse {
|
|||||||
/// ============================
|
/// ============================
|
||||||
class Entity : public IfcAbstractEntity {
|
class Entity : public IfcAbstractEntity {
|
||||||
private:
|
private:
|
||||||
|
//IfcFile* file;
|
||||||
ArgumentPtr args;
|
ArgumentPtr args;
|
||||||
Ifc2x3::Type::Enum _type;
|
Ifc2x3::Type::Enum _type;
|
||||||
public:
|
public:
|
||||||
/// The EXPRESS ENTITY_NAME
|
/// The EXPRESS ENTITY_INSTANCE_NAME
|
||||||
unsigned int _id;
|
unsigned int _id;
|
||||||
/// The offset at which the entity is read
|
/// The offset at which the entity is read
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
Entity(unsigned int i, Tokens* t);
|
Entity(unsigned int i, IfcFile* t);
|
||||||
Entity(unsigned int i, Tokens* t, unsigned int o);
|
Entity(unsigned int i, IfcFile* t, unsigned int o);
|
||||||
~Entity();
|
~Entity();
|
||||||
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
|
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
|
||||||
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
|
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;
|
bool is(Ifc2x3::Type::Enum v) const;
|
||||||
unsigned int id();
|
unsigned int id();
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
typedef IfcUtil::IfcSchemaEntity IfcEntity;
|
typedef IfcUtil::IfcSchemaEntity IfcEntity;
|
||||||
typedef IfcEntities IfcEntities;
|
//typedef IfcEntities IfcEntities;
|
||||||
typedef std::map<Ifc2x3::Type::Enum,IfcEntities> MapEntitiesByType;
|
typedef std::map<Ifc2x3::Type::Enum,IfcEntities> MapEntitiesByType;
|
||||||
typedef std::map<unsigned int,IfcEntity> MapEntityById;
|
typedef std::map<unsigned int,IfcEntity> MapEntityById;
|
||||||
typedef std::map<std::string,Ifc2x3::IfcRoot::ptr> MapEntityByGuid;
|
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
|
/// This class provides several static convenience functions and variables
|
||||||
/// and provide access to the entities in an IFC file
|
/// and provide access to the entities in an IFC file
|
||||||
class Ifc {
|
class IfcFile {
|
||||||
private:
|
private:
|
||||||
static MapEntityById byid;
|
MapEntityById byid;
|
||||||
static MapEntitiesByType bytype;
|
MapEntitiesByType bytype;
|
||||||
static MapEntitiesByRef byref;
|
MapEntitiesByRef byref;
|
||||||
static MapEntityByGuid byguid;
|
MapEntityByGuid byguid;
|
||||||
static MapOffsetById offsets;
|
MapOffsetById offsets;
|
||||||
static unsigned int lastId;
|
unsigned int lastId;
|
||||||
static std::ostream* log1;
|
unsigned int MaxId;
|
||||||
static std::ostream* log2;
|
|
||||||
static std::stringstream log_stream;
|
|
||||||
public:
|
public:
|
||||||
/// Returns the first entity in the file, this probably is the entity with the lowest id (EXPRESS ENTITY_NAME)
|
typedef MapEntityById::const_iterator const_iterator;
|
||||||
static MapEntityById::const_iterator First();
|
IfcFile();
|
||||||
/// Returns the last entity in the file, this probably is the entity with the highes id (EXPRESS ENTITY_NAME)
|
~IfcFile();
|
||||||
static MapEntityById::const_iterator Last();
|
/// Returns the first entity in the file, this probably is the entity with the lowest id (EXPRESS ENTITY_INSTANCE_NAME)
|
||||||
/// Determines to what stream respectively progress and errors are logged
|
const_iterator begin() const;
|
||||||
static void SetOutput(std::ostream* l1, std::ostream* l2);
|
/// Returns the last entity in the file, this probably is the entity with the highes id (EXPRESS ENTITY_INSTANCE_NAME)
|
||||||
/// Log a message to the output stream
|
const_iterator end() const;
|
||||||
static void LogMessage(const std::string& type, const std::string& message, const IfcAbstractEntityPtr entity=0);
|
IfcParse::IfcSpfStream* file;
|
||||||
static IfcParse::File* file;
|
IfcParse::Tokens* tokens;
|
||||||
static IfcParse::Tokens* tokens;
|
|
||||||
/// Returns all entities in the file that match the template argument.
|
/// Returns all entities in the file that match the template argument.
|
||||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||||
/// IfcWall will also return IfcWallStandardCase entities
|
/// IfcWall will also return IfcWallStandardCase entities
|
||||||
template <class T>
|
template <class T>
|
||||||
static typename T::list EntitiesByType() {
|
typename T::list EntitiesByType() {
|
||||||
IfcEntities e = EntitiesByType(T::Class());
|
IfcEntities e = EntitiesByType(T::Class());
|
||||||
typename T::list l ( new IfcTemplatedEntityList<T>() );
|
typename T::list l ( new IfcTemplatedEntityList<T>() );
|
||||||
if ( e && e->Size() )
|
if ( e && e->Size() )
|
||||||
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) {
|
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) {
|
||||||
l->push(reinterpret_pointer_cast<IfcUtil::IfcBaseClass,T>(*it));
|
l->push(reinterpret_pointer_cast<IfcUtil::IfcBaseClass,T>(*it));
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
/// Returns all entities in the file that match the positional argument.
|
/// Returns all entities in the file that match the positional argument.
|
||||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||||
/// IfcWall will also return IfcWallStandardCase entities
|
/// 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
|
/// 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
|
/// Returns the entity with the specified id
|
||||||
static IfcEntity EntityById(int id);
|
IfcEntity EntityById(int id);
|
||||||
/// Returns the entity with the specified GlobalId
|
/// Returns the entity with the specified GlobalId
|
||||||
static Ifc2x3::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
Ifc2x3::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
||||||
static bool Init(const std::string& fn);
|
bool Init(const std::string& fn);
|
||||||
static bool Init(std::istream& fn, int len);
|
bool Init(std::istream& fn, int len);
|
||||||
static bool Init(void* data, int len);
|
bool Init(void* data, int len);
|
||||||
static bool Init(IfcParse::File* f);
|
bool Init(IfcParse::IfcSpfStream* 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v );
|
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -62,3 +62,35 @@ IfcUtil::IfcArgumentSelect::IfcArgumentSelect(Ifc2x3::Type::Enum t, ArgumentPtr
|
|||||||
ArgumentPtr IfcUtil::IfcArgumentSelect::wrappedValue() { return arg; }
|
ArgumentPtr IfcUtil::IfcArgumentSelect::wrappedValue() { return arg; }
|
||||||
bool IfcUtil::IfcArgumentSelect::isSimpleType() { return true; }
|
bool IfcUtil::IfcArgumentSelect::isSimpleType() { return true; }
|
||||||
IfcUtil::IfcArgumentSelect::~IfcArgumentSelect() { delete arg; }
|
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;
|
||||||
|
char* Logger::severity_strings[] = { "Notice","Warning","Error" };
|
||||||
+29
-1
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "../ifcparse/SharedPointer.h"
|
#include "../ifcparse/SharedPointer.h"
|
||||||
#include "../ifcparse/Ifc2x3enum.h"
|
#include "../ifcparse/Ifc2x3enum.h"
|
||||||
@@ -132,9 +133,14 @@ namespace IfcUtil {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace IfcParse {
|
||||||
|
class IfcFile;
|
||||||
|
}
|
||||||
|
|
||||||
class Argument {
|
class Argument {
|
||||||
protected:
|
|
||||||
public:
|
public:
|
||||||
|
//void* file;
|
||||||
|
//public:
|
||||||
virtual operator int() const = 0;
|
virtual operator int() const = 0;
|
||||||
virtual operator bool() const = 0;
|
virtual operator bool() const = 0;
|
||||||
virtual operator double() const = 0;
|
virtual operator double() const = 0;
|
||||||
@@ -154,6 +160,7 @@ public:
|
|||||||
|
|
||||||
class IfcAbstractEntity {
|
class IfcAbstractEntity {
|
||||||
public:
|
public:
|
||||||
|
IfcParse::IfcFile* file;
|
||||||
virtual IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL) = 0;
|
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 IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) = 0;
|
||||||
virtual std::string datatype() = 0;
|
virtual std::string datatype() = 0;
|
||||||
@@ -166,4 +173,25 @@ public:
|
|||||||
virtual unsigned int id() = 0;
|
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 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 Logger::GetLog();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ namespace IfcGeomObjects {
|
|||||||
const int CONVERT_BACK_UNITS = 3;
|
const int CONVERT_BACK_UNITS = 3;
|
||||||
const int USE_BREP_DATA = 4;
|
const int USE_BREP_DATA = 4;
|
||||||
const int SEW_SHELLS = 5;
|
const int SEW_SHELLS = 5;
|
||||||
|
const int FASTER_BOOLEANS = 6;
|
||||||
|
const int FORCE_CCW_FACE_ORIENTATION = 7;
|
||||||
|
|
||||||
class IfcMesh {
|
class IfcMesh {
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user