mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +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_Solid.hxx>
|
||||
|
||||
#include <BRepFilletAPI_MakeFillet2d.hxx>
|
||||
|
||||
#include <TopLoc_Location.hxx>
|
||||
|
||||
bool IfcGeom::convert(IfcSchema::ExtrudedAreaSolid* IfcExtrudedAreaSolid, TopoDS_Shape& shape) {
|
||||
@@ -273,7 +275,7 @@ bool IfcGeom::convert(IfcSchema::ArbitraryProfileDefWithVoids* IfcArbitraryProfi
|
||||
face = TopoDS::Face(sfs.Shape());
|
||||
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 y = IfcRectangleProfileDef->Height() / 2.0f * Ifc::LengthUnit;
|
||||
|
||||
@@ -282,21 +284,90 @@ bool IfcGeom::convert(IfcSchema::RectangleProfileDef* IfcRectangleProfileDef,cla
|
||||
return false;
|
||||
}
|
||||
|
||||
gp_Trsf2d trsf;
|
||||
IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcRectangleProfileDef->Placement().get(),trsf);
|
||||
|
||||
gp_XY p1 (-x,-y);trsf.Transforms(p1);gp_Pnt P1(p1.X(),p1.Y(),0.0f);
|
||||
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);
|
||||
gp_XY p4 (-x, y);trsf.Transforms(p4);gp_Pnt P4(p4.X(),p4.Y(),0.0f);
|
||||
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P2,P3));
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P3,P4));
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P4,P1));
|
||||
wire = w.Wire();
|
||||
return true;
|
||||
gp_Trsf2d trsf2d;
|
||||
IfcGeom::convert((IfcSchema::Axis2Placement2D*)IfcRectangleProfileDef->Placement().get(),trsf2d);
|
||||
float coords[8] = {-x,-y,x,-y,x,y,-x,y};
|
||||
return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::IShapeProfileDef* IfcIShapeProfileDef,class TopoDS_Face& face) {
|
||||
const float x = IfcIShapeProfileDef->Width() / 2.0f * Ifc::LengthUnit;
|
||||
const float y = IfcIShapeProfileDef->Depth() / 2.0f * Ifc::LengthUnit;
|
||||
const float d1 = IfcIShapeProfileDef->WebThickness() / 2.0f * Ifc::LengthUnit;
|
||||
const float d2 = IfcIShapeProfileDef->FlangeThickness() * Ifc::LengthUnit;
|
||||
bool doFillet = false;
|
||||
float f;
|
||||
try {
|
||||
f = IfcIShapeProfileDef->FilletRadius() * Ifc::LengthUnit;
|
||||
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) {
|
||||
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;
|
||||
face = mf.Face();
|
||||
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;
|
||||
curvar.reserve(64);
|
||||
bool inStr = false;
|
||||
bool inComment = false;
|
||||
char c[1] = "";
|
||||
char p[1] = "";
|
||||
int state = -1;
|
||||
int previousPos = -1;
|
||||
args = 0;
|
||||
@@ -187,8 +189,8 @@ Entity::Entity(std::istream* ss, std::vector<int>& refs, bool sub) {
|
||||
id = -1;
|
||||
do {
|
||||
ss->read(c,1);
|
||||
if ( !inStr && ((*c) == ' ' || (*c) == '\r' || (*c) == '\n' || (*c) == '\t') ) continue;
|
||||
if ( curvar.size() && !inStr && ( term(*c) || term(*curvar.rbegin())) ) {
|
||||
if ( !inComment && !inStr && ((*c) == ' ' || (*c) == '\r' || (*c) == '\n' || (*c) == '\t') ) continue;
|
||||
if ( curvar.size() && !inComment && !inStr && ( term(*c) || term(*curvar.rbegin())) ) {
|
||||
Argument* v = new Argument(curvar);
|
||||
curvar.clear();
|
||||
curvar.push_back(*c);
|
||||
@@ -234,8 +236,12 @@ Entity::Entity(std::istream* ss, std::vector<int>& refs, bool sub) {
|
||||
}
|
||||
previousPos = ss->tellg();
|
||||
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) );
|
||||
}
|
||||
Entity::~Entity() {
|
||||
@@ -316,8 +322,7 @@ EntityPtr Entities::operator[] (int i) {
|
||||
Entities::Entities() {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
File::File(std::string fn, bool debug) {
|
||||
File::File(const std::string& fn, bool debug) {
|
||||
valid = false;
|
||||
std::ifstream f(fn.c_str());
|
||||
if ( ! f.is_open() ) return;
|
||||
@@ -392,7 +397,7 @@ EntitiesPtr Ifc::EntitiesByReference(int t) {
|
||||
EntityPtr Ifc::EntityById(int id) {
|
||||
return f->EntityById(id);
|
||||
}
|
||||
bool Ifc::Init(std::string fn) {
|
||||
bool Ifc::Init(const std::string& fn) {
|
||||
f = new File(fn, false);
|
||||
IfcEntity IfcUnitAssigment = *EntitiesByType(IfcSchema::Enum::IfcUnitAssignment)->begin();
|
||||
IfcEntities units = ((IfcSchema::UnitAssignment*)IfcUnitAssigment.get())->Units();
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace IfcParse {
|
||||
std::map<int,EntitiesPtr> byref;
|
||||
bool valid;
|
||||
|
||||
File(std::string fn, bool debug = false);
|
||||
File(const std::string& fn, bool debug = false);
|
||||
EntitiesPtr EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
||||
EntitiesPtr EntitiesByReference(int id);
|
||||
EntityPtr EntityById(int id);
|
||||
@@ -186,7 +186,7 @@ public:
|
||||
static IfcEntities EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
||||
static IfcEntities EntitiesByReference(int id);
|
||||
static IfcEntity EntityById(int id);
|
||||
static bool Init(std::string fn);
|
||||
static bool Init(const std::string& fn);
|
||||
static void Dispose();
|
||||
static float LengthUnit;
|
||||
static float PlaneAngleUnit;
|
||||
|
||||
@@ -114,7 +114,7 @@ IFC_REF(ArbitraryProfileDefWithVoids,Polyline,2)
|
||||
IFC_REFS(ArbitraryProfileDefWithVoids,Voids,3)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_WIRE_CLASS(RectangleProfileDef)
|
||||
IFC_FACE_CLASS(RectangleProfileDef)
|
||||
IFC_REF(RectangleProfileDef,Placement,2)
|
||||
IFC_FLT(RectangleProfileDef,Width,3)
|
||||
IFC_FLT(RectangleProfileDef,Height,4)
|
||||
@@ -131,6 +131,34 @@ IFC_FLT(CircleHollowProfileDef,Radius,3)
|
||||
IFC_FLT(CircleHollowProfileDef,WallThickness,4)
|
||||
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_REF(Circle,Placement,0)
|
||||
IFC_FLT(Circle,Radius,1)
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace IfcGeom {
|
||||
bool convert_curve(const IfcEntity L, Handle(Geom_Curve)& 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 profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user