mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 11:23:43 +00:00
- Parsing: support for comments
- Geometry: support for some complex filleted profiles ( e.g. IfcIShapeProfileDef, IfcCShapeProfileDef )
This commit is contained in:
+116
-16
@@ -71,6 +71,8 @@
|
|||||||
#include <ShapeFix_ShapeTolerance.hxx>
|
#include <ShapeFix_ShapeTolerance.hxx>
|
||||||
#include <ShapeFix_Solid.hxx>
|
#include <ShapeFix_Solid.hxx>
|
||||||
|
|
||||||
|
#include <BRepFilletAPI_MakeFillet2d.hxx>
|
||||||
|
|
||||||
#include <TopLoc_Location.hxx>
|
#include <TopLoc_Location.hxx>
|
||||||
|
|
||||||
bool IfcGeom::convert(IfcSchema::ExtrudedAreaSolid* IfcExtrudedAreaSolid, TopoDS_Shape& shape) {
|
bool IfcGeom::convert(IfcSchema::ExtrudedAreaSolid* IfcExtrudedAreaSolid, TopoDS_Shape& shape) {
|
||||||
@@ -273,7 +275,7 @@ bool IfcGeom::convert(IfcSchema::ArbitraryProfileDefWithVoids* IfcArbitraryProfi
|
|||||||
face = TopoDS::Face(sfs.Shape());
|
face = TopoDS::Face(sfs.Shape());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(IfcSchema::RectangleProfileDef* IfcRectangleProfileDef,class TopoDS_Wire& wire) {
|
bool IfcGeom::convert(IfcSchema::RectangleProfileDef* IfcRectangleProfileDef,class TopoDS_Face& face) {
|
||||||
const float x = IfcRectangleProfileDef->Width() / 2.0f * Ifc::LengthUnit;
|
const float x = IfcRectangleProfileDef->Width() / 2.0f * Ifc::LengthUnit;
|
||||||
const float y = IfcRectangleProfileDef->Height() / 2.0f * Ifc::LengthUnit;
|
const float y = IfcRectangleProfileDef->Height() / 2.0f * Ifc::LengthUnit;
|
||||||
|
|
||||||
@@ -282,21 +284,90 @@ bool IfcGeom::convert(IfcSchema::RectangleProfileDef* IfcRectangleProfileDef,cla
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gp_Trsf2d trsf;
|
gp_Trsf2d trsf2d;
|
||||||
IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcRectangleProfileDef->Placement().get(),trsf);
|
IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcRectangleProfileDef->Placement().get(),trsf2d);
|
||||||
|
float coords[8] = {-x,-y,x,-y,x,y,-x,y};
|
||||||
gp_XY p1 (-x,-y);trsf.Transforms(p1);gp_Pnt P1(p1.X(),p1.Y(),0.0f);
|
return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face);
|
||||||
gp_XY p2 ( x,-y);trsf.Transforms(p2);gp_Pnt P2(p2.X(),p2.Y(),0.0f);
|
}
|
||||||
gp_XY p3 ( x, y);trsf.Transforms(p3);gp_Pnt P3(p3.X(),p3.Y(),0.0f);
|
bool IfcGeom::convert(IfcSchema::IShapeProfileDef* IfcIShapeProfileDef,class TopoDS_Face& face) {
|
||||||
gp_XY p4 (-x, y);trsf.Transforms(p4);gp_Pnt P4(p4.X(),p4.Y(),0.0f);
|
const float x = IfcIShapeProfileDef->Width() / 2.0f * Ifc::LengthUnit;
|
||||||
|
const float y = IfcIShapeProfileDef->Depth() / 2.0f * Ifc::LengthUnit;
|
||||||
BRepBuilderAPI_MakeWire w;
|
const float d1 = IfcIShapeProfileDef->WebThickness() / 2.0f * Ifc::LengthUnit;
|
||||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
const float d2 = IfcIShapeProfileDef->FlangeThickness() * Ifc::LengthUnit;
|
||||||
w.Add(BRepBuilderAPI_MakeEdge(P2,P3));
|
bool doFillet = false;
|
||||||
w.Add(BRepBuilderAPI_MakeEdge(P3,P4));
|
float f;
|
||||||
w.Add(BRepBuilderAPI_MakeEdge(P4,P1));
|
try {
|
||||||
wire = w.Wire();
|
f = IfcIShapeProfileDef->FilletRadius() * Ifc::LengthUnit;
|
||||||
return true;
|
doFillet = true;
|
||||||
|
} catch ( IfcParse::IfcException& ) {}
|
||||||
|
|
||||||
|
if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) {
|
||||||
|
std::cout << "[Notice] Skipping zero sized profile:" << std::endl << IfcIShapeProfileDef->toString() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gp_Trsf2d trsf2d;
|
||||||
|
IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcIShapeProfileDef->Placement().get(),trsf2d);
|
||||||
|
|
||||||
|
float coords[24] = {-x,-y,x,-y,x,-y+d2,d1,-y+d2,d1,y-d2,x,y-d2,x,y,-x,y,-x,y-d2,-d1,y-d2,-d1,-y+d2,-x,-y+d2};
|
||||||
|
int fillets[4] = {3,4,9,10};
|
||||||
|
float radii[4] = {f,f,f,f};
|
||||||
|
return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face);
|
||||||
|
}
|
||||||
|
bool IfcGeom::convert(IfcSchema::CShapeProfileDef* IfcCShapeProfileDef,class TopoDS_Face& face) {
|
||||||
|
const float x = IfcCShapeProfileDef->Depth() / 2.0f * Ifc::LengthUnit;
|
||||||
|
const float y = IfcCShapeProfileDef->Width() / 2.0f * Ifc::LengthUnit;
|
||||||
|
const float d1 = IfcCShapeProfileDef->WallThickness() * Ifc::LengthUnit;
|
||||||
|
const float d2 = IfcCShapeProfileDef->Girth() * Ifc::LengthUnit;
|
||||||
|
bool doFillet = false;
|
||||||
|
float f1,f2;
|
||||||
|
try {
|
||||||
|
f1 = IfcCShapeProfileDef->InternalFilletRadius() * Ifc::LengthUnit;
|
||||||
|
f2 = f1 + d1;
|
||||||
|
doFillet = true;
|
||||||
|
} catch ( IfcParse::IfcException& ) {}
|
||||||
|
|
||||||
|
if ( x == 0.0f || y == 0.0f || d1 == 0.0f || d2 == 0.0f ) {
|
||||||
|
std::cout << "[Notice] Skipping zero sized profile:" << std::endl << IfcCShapeProfileDef->toString() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gp_Trsf2d trsf2d;
|
||||||
|
IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcCShapeProfileDef->Placement().get(),trsf2d);
|
||||||
|
|
||||||
|
float coords[24] = {-x,-y,x,-y,x,-y+d2,x-d1,-y+d2,x-d1,-y+d1,-x+d1,-y+d1,-x+d1,y-d1,x-d1,y-d1,x-d1,y-d2,x,y-d2,x,y,-x,y};
|
||||||
|
int fillets[8] = {0,1,4,5,6,7,10,11};
|
||||||
|
float radii[8] = {f2,f2,f1,f1,f1,f1,f2,f2};
|
||||||
|
return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face);
|
||||||
|
}
|
||||||
|
bool IfcGeom::convert(IfcSchema::LShapeProfileDef* IfcLShapeProfileDef,class TopoDS_Face& face) {
|
||||||
|
const float y = IfcLShapeProfileDef->Depth() / 2.0f * Ifc::LengthUnit;
|
||||||
|
const float x = IfcLShapeProfileDef->Width() / 2.0f * Ifc::LengthUnit;
|
||||||
|
const float d = IfcLShapeProfileDef->Thickness() * Ifc::LengthUnit;
|
||||||
|
bool doFillet = false;
|
||||||
|
float f1 = 0.0f;
|
||||||
|
float f2 = 0.0f;
|
||||||
|
try {
|
||||||
|
f1 = IfcLShapeProfileDef->FilletRadius() * Ifc::LengthUnit;
|
||||||
|
doFillet = true;
|
||||||
|
} catch ( IfcParse::IfcException& ) {}
|
||||||
|
try {
|
||||||
|
f2 = IfcLShapeProfileDef->EdgeRadius() * Ifc::LengthUnit;
|
||||||
|
doFillet = true;
|
||||||
|
} catch ( IfcParse::IfcException& ) {}
|
||||||
|
|
||||||
|
if ( x == 0.0f || y == 0.0f || d == 0.0f ) {
|
||||||
|
std::cout << "[Notice] Skipping zero sized profile:" << std::endl << IfcLShapeProfileDef->toString() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gp_Trsf2d trsf2d;
|
||||||
|
IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcLShapeProfileDef->Placement().get(),trsf2d);
|
||||||
|
|
||||||
|
float coords[12] = {-x,-y,x,-y,x,-y+d,-x+d,-y+d,-x+d,y,-x,y};
|
||||||
|
int fillets[3] = {2,3,4};
|
||||||
|
float radii[3] = {f2,f1,f2};
|
||||||
|
return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face);
|
||||||
}
|
}
|
||||||
bool IfcGeom::convert(IfcSchema::CircleProfileDef* IfcCircleProfileDef,class TopoDS_Wire& wire) {
|
bool IfcGeom::convert(IfcSchema::CircleProfileDef* IfcCircleProfileDef,class TopoDS_Wire& wire) {
|
||||||
const float r = IfcCircleProfileDef->Radius() * Ifc::LengthUnit;
|
const float r = IfcCircleProfileDef->Radius() * Ifc::LengthUnit;
|
||||||
@@ -505,4 +576,33 @@ bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
|
|||||||
if ( er != BRepBuilderAPI_FaceDone ) return false;
|
if ( er != BRepBuilderAPI_FaceDone ) return false;
|
||||||
face = mf.Face();
|
face = mf.Face();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
bool IfcGeom::profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face) {
|
||||||
|
TopoDS_Vertex* vertices = new TopoDS_Vertex[numVerts];
|
||||||
|
|
||||||
|
for ( int i = 0; i < numVerts; i ++ ) {
|
||||||
|
gp_XY xy (verts[2*i],verts[2*i+1]);
|
||||||
|
trsf.Transforms(xy);
|
||||||
|
vertices[i] = BRepBuilderAPI_MakeVertex(gp_Pnt(xy.X(),xy.Y(),0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
BRepBuilderAPI_MakeWire w;
|
||||||
|
for ( int i = 0; i < numVerts; i ++ )
|
||||||
|
w.Add(BRepBuilderAPI_MakeEdge(vertices[i],vertices[(i+1)%numVerts]));
|
||||||
|
|
||||||
|
IfcGeom::convert_wire_to_face(w.Wire(),face);
|
||||||
|
|
||||||
|
if ( numFillets ) {
|
||||||
|
BRepFilletAPI_MakeFillet2d fillet (face);
|
||||||
|
for ( int i = 0; i < numFillets; i ++ ) {
|
||||||
|
const float radius = filletRadii[i];
|
||||||
|
if ( radius < 1e-7 ) continue;
|
||||||
|
fillet.AddFillet(vertices[filletIndices[i]],radius);
|
||||||
|
}
|
||||||
|
fillet.Build();
|
||||||
|
face = TopoDS::Face(fillet.Shape());
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] vertices;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,9 @@ Entity::Entity(std::istream* ss, std::vector<int>& refs, bool sub) {
|
|||||||
std::string curvar;
|
std::string curvar;
|
||||||
curvar.reserve(64);
|
curvar.reserve(64);
|
||||||
bool inStr = false;
|
bool inStr = false;
|
||||||
|
bool inComment = false;
|
||||||
char c[1] = "";
|
char c[1] = "";
|
||||||
|
char p[1] = "";
|
||||||
int state = -1;
|
int state = -1;
|
||||||
int previousPos = -1;
|
int previousPos = -1;
|
||||||
args = 0;
|
args = 0;
|
||||||
@@ -187,8 +189,8 @@ Entity::Entity(std::istream* ss, std::vector<int>& refs, bool sub) {
|
|||||||
id = -1;
|
id = -1;
|
||||||
do {
|
do {
|
||||||
ss->read(c,1);
|
ss->read(c,1);
|
||||||
if ( !inStr && ((*c) == ' ' || (*c) == '\r' || (*c) == '\n' || (*c) == '\t') ) continue;
|
if ( !inComment && !inStr && ((*c) == ' ' || (*c) == '\r' || (*c) == '\n' || (*c) == '\t') ) continue;
|
||||||
if ( curvar.size() && !inStr && ( term(*c) || term(*curvar.rbegin())) ) {
|
if ( curvar.size() && !inComment && !inStr && ( term(*c) || term(*curvar.rbegin())) ) {
|
||||||
Argument* v = new Argument(curvar);
|
Argument* v = new Argument(curvar);
|
||||||
curvar.clear();
|
curvar.clear();
|
||||||
curvar.push_back(*c);
|
curvar.push_back(*c);
|
||||||
@@ -234,8 +236,12 @@ Entity::Entity(std::istream* ss, std::vector<int>& refs, bool sub) {
|
|||||||
}
|
}
|
||||||
previousPos = ss->tellg();
|
previousPos = ss->tellg();
|
||||||
delete v;
|
delete v;
|
||||||
} else curvar.push_back(*c);
|
}
|
||||||
if ( *c == '\'' ) inStr = !inStr;
|
else if ( ! inComment ) curvar.push_back(*c);
|
||||||
|
if ( !inComment && *c == '\'' ) inStr = !inStr;
|
||||||
|
else if ( !inStr && *p == '/' && *c == '*' ) { inComment = true; curvar.clear(); }
|
||||||
|
else if ( !inStr && *p == '*' && *c == '/' ) inComment = false;
|
||||||
|
p[0] = c[0];
|
||||||
} while ( !ss->eof() && (*c != ';' || inStr) );
|
} while ( !ss->eof() && (*c != ';' || inStr) );
|
||||||
}
|
}
|
||||||
Entity::~Entity() {
|
Entity::~Entity() {
|
||||||
@@ -316,8 +322,7 @@ EntityPtr Entities::operator[] (int i) {
|
|||||||
Entities::Entities() {
|
Entities::Entities() {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
File::File(const std::string& fn, bool debug) {
|
||||||
File::File(std::string fn, bool debug) {
|
|
||||||
valid = false;
|
valid = false;
|
||||||
std::ifstream f(fn.c_str());
|
std::ifstream f(fn.c_str());
|
||||||
if ( ! f.is_open() ) return;
|
if ( ! f.is_open() ) return;
|
||||||
@@ -392,7 +397,7 @@ EntitiesPtr Ifc::EntitiesByReference(int t) {
|
|||||||
EntityPtr Ifc::EntityById(int id) {
|
EntityPtr Ifc::EntityById(int id) {
|
||||||
return f->EntityById(id);
|
return f->EntityById(id);
|
||||||
}
|
}
|
||||||
bool Ifc::Init(std::string fn) {
|
bool Ifc::Init(const std::string& fn) {
|
||||||
f = new File(fn, false);
|
f = new File(fn, false);
|
||||||
IfcEntity IfcUnitAssigment = *EntitiesByType(IfcSchema::Enum::IfcUnitAssignment)->begin();
|
IfcEntity IfcUnitAssigment = *EntitiesByType(IfcSchema::Enum::IfcUnitAssignment)->begin();
|
||||||
IfcEntities units = ((IfcSchema::UnitAssignment*)IfcUnitAssigment.get())->Units();
|
IfcEntities units = ((IfcSchema::UnitAssignment*)IfcUnitAssigment.get())->Units();
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ namespace IfcParse {
|
|||||||
std::map<int,EntitiesPtr> byref;
|
std::map<int,EntitiesPtr> byref;
|
||||||
bool valid;
|
bool valid;
|
||||||
|
|
||||||
File(std::string fn, bool debug = false);
|
File(const std::string& fn, bool debug = false);
|
||||||
EntitiesPtr EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
EntitiesPtr EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
||||||
EntitiesPtr EntitiesByReference(int id);
|
EntitiesPtr EntitiesByReference(int id);
|
||||||
EntityPtr EntityById(int id);
|
EntityPtr EntityById(int id);
|
||||||
@@ -186,7 +186,7 @@ public:
|
|||||||
static IfcEntities EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
static IfcEntities EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
||||||
static IfcEntities EntitiesByReference(int id);
|
static IfcEntities EntitiesByReference(int id);
|
||||||
static IfcEntity EntityById(int id);
|
static IfcEntity EntityById(int id);
|
||||||
static bool Init(std::string fn);
|
static bool Init(const std::string& fn);
|
||||||
static void Dispose();
|
static void Dispose();
|
||||||
static float LengthUnit;
|
static float LengthUnit;
|
||||||
static float PlaneAngleUnit;
|
static float PlaneAngleUnit;
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ IFC_REF(ArbitraryProfileDefWithVoids,Polyline,2)
|
|||||||
IFC_REFS(ArbitraryProfileDefWithVoids,Voids,3)
|
IFC_REFS(ArbitraryProfileDefWithVoids,Voids,3)
|
||||||
IFC_END_CLASS
|
IFC_END_CLASS
|
||||||
|
|
||||||
IFC_WIRE_CLASS(RectangleProfileDef)
|
IFC_FACE_CLASS(RectangleProfileDef)
|
||||||
IFC_REF(RectangleProfileDef,Placement,2)
|
IFC_REF(RectangleProfileDef,Placement,2)
|
||||||
IFC_FLT(RectangleProfileDef,Width,3)
|
IFC_FLT(RectangleProfileDef,Width,3)
|
||||||
IFC_FLT(RectangleProfileDef,Height,4)
|
IFC_FLT(RectangleProfileDef,Height,4)
|
||||||
@@ -131,6 +131,34 @@ IFC_FLT(CircleHollowProfileDef,Radius,3)
|
|||||||
IFC_FLT(CircleHollowProfileDef,WallThickness,4)
|
IFC_FLT(CircleHollowProfileDef,WallThickness,4)
|
||||||
IFC_END_CLASS
|
IFC_END_CLASS
|
||||||
|
|
||||||
|
IFC_FACE_CLASS(IShapeProfileDef)
|
||||||
|
IFC_REF(IShapeProfileDef,Placement,2)
|
||||||
|
IFC_FLT(IShapeProfileDef,Width,3)
|
||||||
|
IFC_FLT(IShapeProfileDef,Depth,4)
|
||||||
|
IFC_FLT(IShapeProfileDef,WebThickness,5)
|
||||||
|
IFC_FLT(IShapeProfileDef,FlangeThickness,6)
|
||||||
|
IFC_FLT(IShapeProfileDef,FilletRadius,7)
|
||||||
|
IFC_END_CLASS
|
||||||
|
|
||||||
|
IFC_FACE_CLASS(CShapeProfileDef)
|
||||||
|
IFC_REF(CShapeProfileDef,Placement,2)
|
||||||
|
IFC_FLT(CShapeProfileDef,Width,3)
|
||||||
|
IFC_FLT(CShapeProfileDef,Depth,4)
|
||||||
|
IFC_FLT(CShapeProfileDef,WallThickness,5)
|
||||||
|
IFC_FLT(CShapeProfileDef,Girth,6)
|
||||||
|
IFC_FLT(CShapeProfileDef,InternalFilletRadius,7)
|
||||||
|
IFC_END_CLASS
|
||||||
|
|
||||||
|
IFC_FACE_CLASS(LShapeProfileDef)
|
||||||
|
IFC_REF(LShapeProfileDef,Placement,2)
|
||||||
|
IFC_FLT(LShapeProfileDef,Depth,3)
|
||||||
|
IFC_FLT(LShapeProfileDef,Width,4)
|
||||||
|
IFC_FLT(LShapeProfileDef,Thickness,5)
|
||||||
|
IFC_FLT(LShapeProfileDef,FilletRadius,6)
|
||||||
|
IFC_FLT(LShapeProfileDef,EdgeRadius,7)
|
||||||
|
IFC_FLT(LShapeProfileDef,LegSlope,8)
|
||||||
|
IFC_END_CLASS
|
||||||
|
|
||||||
IFC_CURVE_CLASS(Circle)
|
IFC_CURVE_CLASS(Circle)
|
||||||
IFC_REF(Circle,Placement,0)
|
IFC_REF(Circle,Placement,0)
|
||||||
IFC_FLT(Circle,Radius,1)
|
IFC_FLT(Circle,Radius,1)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace IfcGeom {
|
|||||||
bool convert_curve(const IfcEntity L, Handle(Geom_Curve)& result);
|
bool convert_curve(const IfcEntity L, Handle(Geom_Curve)& result);
|
||||||
bool convert_face(const IfcEntity L, TopoDS_Face& result);
|
bool convert_face(const IfcEntity L, TopoDS_Face& result);
|
||||||
bool convert_openings(const IfcSchema::BuildingElement* IfcBuildingElement, const IfcEntities openings, TopoDS_Shape& result, const gp_Trsf& trsf);
|
bool convert_openings(const IfcSchema::BuildingElement* IfcBuildingElement, const IfcEntities openings, TopoDS_Shape& result, const gp_Trsf& trsf);
|
||||||
|
bool profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user