mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 22:11:36 +00:00
- Switch to double precision
- Allow accessing entities by GlobalId - Some more support for writing back IFC - Prefix EXPRESS Enum values to avoid collisions - Fix a bug in the SenseAgreement of Cartesian trimmed curves - Use straight line segment in case point projection failed on trimmed curve - Add epsilon to polylines and -loops point equality test - Decompose a convex polygonal bounded halfspace into several unbounded halfspace and process only if they operate on a volume larger than some epsilon - No longer fail connected facesets if a single face is invalid - Updated IfcBlender for compatibility with Blender 2.62 - Added additional test files
This commit is contained in:
@@ -55,9 +55,13 @@ namespace IfcGeom {
|
||||
bool convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes);
|
||||
bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid);
|
||||
bool is_compound(const TopoDS_Shape& shape);
|
||||
bool is_convex(const TopoDS_Wire& wire);
|
||||
TopoDS_Shape halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent);
|
||||
gp_Pln plane_from_face(const TopoDS_Face& face);
|
||||
gp_Pnt point_above_plane(const gp_Pln& pln, bool agree=true);
|
||||
const TopoDS_Shape& ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid);
|
||||
bool profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
|
||||
float shape_volume(const TopoDS_Shape& s);
|
||||
bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
|
||||
double shape_volume(const TopoDS_Shape& s);
|
||||
namespace Cache {
|
||||
void Purge();
|
||||
void PurgeShapeCache();
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve) {
|
||||
const float r = l->Radius() * Ifc::LengthUnit;
|
||||
const double r = l->Radius() * Ifc::LengthUnit;
|
||||
if ( r <= 0.0f ) { return false; }
|
||||
gp_Trsf trsf;
|
||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||
@@ -94,8 +94,8 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
|
||||
float x = l->SemiAxis1() * Ifc::LengthUnit;
|
||||
float y = l->SemiAxis2() * Ifc::LengthUnit;
|
||||
double x = l->SemiAxis1() * Ifc::LengthUnit;
|
||||
double y = l->SemiAxis2() * Ifc::LengthUnit;
|
||||
if ( x == 0.0f || y == 0.0f || y > x ) { return false; }
|
||||
gp_Trsf trsf;
|
||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||
|
||||
@@ -108,8 +108,14 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
|
||||
if ( mf.IsDone() ) {
|
||||
ShapeFix_Shape sfs(mf.Face());
|
||||
sfs.Perform();
|
||||
face = TopoDS::Face(sfs.Shape());
|
||||
return true;
|
||||
TopoDS_Shape sfs_shape = sfs.Shape();
|
||||
bool is_face = sfs_shape.ShapeType() == TopAbs_FACE;
|
||||
if ( is_face ) {
|
||||
face = TopoDS::Face(sfs_shape);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -136,8 +142,8 @@ bool IfcGeom::convert(const Ifc2x3::IfcArbitraryProfileDefWithVoids::ptr l, Topo
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const float x = l->XDim() / 2.0f * Ifc::LengthUnit;
|
||||
const float y = l->YDim() / 2.0f * Ifc::LengthUnit;
|
||||
const double x = l->XDim() / 2.0f * Ifc::LengthUnit;
|
||||
const double y = l->YDim() / 2.0f * Ifc::LengthUnit;
|
||||
|
||||
if ( x == 0.0f || y == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
@@ -146,16 +152,16 @@ bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face&
|
||||
|
||||
gp_Trsf2d trsf2d;
|
||||
IfcGeom::convert(l->Position(),trsf2d);
|
||||
float coords[8] = {-x,-y,x,-y,x,y,-x,y};
|
||||
double coords[8] = {-x,-y,x,-y,x,y,-x,y};
|
||||
return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const float x = l->OverallWidth() / 2.0f * Ifc::LengthUnit;
|
||||
const float y = l->OverallDepth() / 2.0f * Ifc::LengthUnit;
|
||||
const float d1 = l->WebThickness() / 2.0f * Ifc::LengthUnit;
|
||||
const float d2 = l->FlangeThickness() * Ifc::LengthUnit;
|
||||
const double x = l->OverallWidth() / 2.0f * Ifc::LengthUnit;
|
||||
const double y = l->OverallDepth() / 2.0f * Ifc::LengthUnit;
|
||||
const double d1 = l->WebThickness() / 2.0f * Ifc::LengthUnit;
|
||||
const double d2 = l->FlangeThickness() * Ifc::LengthUnit;
|
||||
bool doFillet = l->hasFilletRadius();
|
||||
float f;
|
||||
double f;
|
||||
if ( doFillet ) {
|
||||
f = l->FilletRadius() * Ifc::LengthUnit;
|
||||
}
|
||||
@@ -168,18 +174,18 @@ bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
gp_Trsf2d trsf2d;
|
||||
IfcGeom::convert(l->Position(),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};
|
||||
double 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};
|
||||
double radii[4] = {f,f,f,f};
|
||||
return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const float x = l->Depth() / 2.0f * Ifc::LengthUnit;
|
||||
const float y = l->Width() / 2.0f * Ifc::LengthUnit;
|
||||
const float d1 = l->WallThickness() * Ifc::LengthUnit;
|
||||
const float d2 = l->Girth() * Ifc::LengthUnit;
|
||||
const double x = l->Depth() / 2.0f * Ifc::LengthUnit;
|
||||
const double y = l->Width() / 2.0f * Ifc::LengthUnit;
|
||||
const double d1 = l->WallThickness() * Ifc::LengthUnit;
|
||||
const double d2 = l->Girth() * Ifc::LengthUnit;
|
||||
bool doFillet = l->hasInternalFilletRadius();
|
||||
float f1,f2;
|
||||
double f1,f2;
|
||||
if ( doFillet ) {
|
||||
f1 = l->InternalFilletRadius() * Ifc::LengthUnit;
|
||||
f2 = f1 + d1;
|
||||
@@ -193,19 +199,19 @@ bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
gp_Trsf2d trsf2d;
|
||||
IfcGeom::convert(l->Position(),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};
|
||||
double 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};
|
||||
double 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(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const float y = l->Depth() / 2.0f * Ifc::LengthUnit;
|
||||
const float x = l->Width() / 2.0f * Ifc::LengthUnit;
|
||||
const float d = l->Thickness() * Ifc::LengthUnit;
|
||||
const double y = l->Depth() / 2.0f * Ifc::LengthUnit;
|
||||
const double x = l->Width() / 2.0f * Ifc::LengthUnit;
|
||||
const double d = l->Thickness() * Ifc::LengthUnit;
|
||||
bool doEdgeFillet = l->hasEdgeRadius();
|
||||
bool doFillet = l->hasFilletRadius();
|
||||
float f1 = 0.0f;
|
||||
float f2 = 0.0f;
|
||||
double f1 = 0.0f;
|
||||
double f2 = 0.0f;
|
||||
if (doFillet) {
|
||||
f1 = l->FilletRadius() * Ifc::LengthUnit;
|
||||
}
|
||||
@@ -220,13 +226,13 @@ bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
gp_Trsf2d trsf2d;
|
||||
IfcGeom::convert(l->Position(),trsf2d);
|
||||
|
||||
float coords[12] = {-x,-y,x,-y,x,-y+d,-x+d,-y+d,-x+d,y,-x,y};
|
||||
double 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};
|
||||
double radii[3] = {f2,f1,f2};
|
||||
return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const float r = l->Radius() * Ifc::LengthUnit;
|
||||
const double r = l->Radius() * Ifc::LengthUnit;
|
||||
if ( r == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
return false;
|
||||
@@ -243,8 +249,8 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& fac
|
||||
return IfcGeom::convert_wire_to_face(w,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const float r = l->Radius() * Ifc::LengthUnit;
|
||||
const float t = l->WallThickness() * Ifc::LengthUnit;
|
||||
const double r = l->Radius() * Ifc::LengthUnit;
|
||||
const double t = l->WallThickness() * Ifc::LengthUnit;
|
||||
|
||||
if ( r == 0.0f || t == 0.0f ) {
|
||||
Ifc::LogMessage("Notice","Skipping zero sized profile:",l->entity);
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
|
||||
#include <BRepBuilderAPI_GTransform.hxx>
|
||||
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
|
||||
#include <BRepGProp_Face.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
|
||||
@@ -102,7 +106,7 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Sh
|
||||
}
|
||||
|
||||
bool IfcGeom::is_compound(const TopoDS_Shape& shape) {
|
||||
bool has_solids = TopExp_Explorer(shape,TopAbs_SHELL).More() != 0;
|
||||
bool has_solids = TopExp_Explorer(shape,TopAbs_SOLID).More() != 0;
|
||||
bool has_shells = TopExp_Explorer(shape,TopAbs_SHELL).More() != 0;
|
||||
bool has_compounds = TopExp_Explorer(shape,TopAbs_COMPOUND).More() != 0;
|
||||
bool has_faces = TopExp_Explorer(shape,TopAbs_FACE).More() != 0;
|
||||
@@ -155,7 +159,7 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
||||
TopoDS_Shape entity_shape;
|
||||
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
||||
Ifc::LogMessage("warning","Applying non uniform transformation to:",entity->entity);
|
||||
Ifc::LogMessage("Warning","Applying non uniform transformation to:",entity->entity);
|
||||
entity_shape = BRepBuilderAPI_GTransform(entity_shape_unlocated,entity_shape_gtrsf,true).Shape();
|
||||
} else {
|
||||
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
||||
@@ -167,28 +171,39 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
const TopoDS_Shape& opening_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(*(it4->second),opening_shape_solid);
|
||||
const gp_GTrsf& opening_shape_gtrsf = *(it4->first);
|
||||
if ( opening_shape_gtrsf.Form() == gp_Other ) {
|
||||
Ifc::LogMessage("warning","Applying non uniform transformation to opening of:",entity->entity);
|
||||
Ifc::LogMessage("Warning","Applying non uniform transformation to opening of:",entity->entity);
|
||||
}
|
||||
const TopoDS_Shape& opening_shape = opening_shape_gtrsf.Form() == gp_Other
|
||||
? BRepBuilderAPI_GTransform(opening_shape_unlocated,opening_shape_gtrsf,true).Shape()
|
||||
: opening_shape_unlocated.Moved(opening_shape_gtrsf.Trsf());
|
||||
|
||||
const float opening_volume = shape_volume(opening_shape);
|
||||
const double opening_volume = shape_volume(opening_shape);
|
||||
if ( opening_volume <= ALMOST_ZERO )
|
||||
Ifc::LogMessage("warning","Empty opening for:",entity->entity);
|
||||
Ifc::LogMessage("Warning","Empty opening for:",entity->entity);
|
||||
|
||||
const float original_shape_volume = shape_volume(entity_shape);
|
||||
const double original_shape_volume = shape_volume(entity_shape);
|
||||
|
||||
BRepAlgoAPI_Cut brep_cut(entity_shape,opening_shape);
|
||||
|
||||
if ( brep_cut.IsDone() ) {
|
||||
entity_shape = brep_cut;
|
||||
TopoDS_Shape brep_cut_result = brep_cut;
|
||||
|
||||
BRepCheck_Analyzer analyser(brep_cut_result);
|
||||
bool is_valid = analyser.IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
entity_shape = brep_cut;
|
||||
const double volume_after_subtraction = shape_volume(entity_shape);
|
||||
|
||||
const float volume_after_subtraction = shape_volume(entity_shape);
|
||||
|
||||
if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) )
|
||||
Ifc::LogMessage("warning","Warning subtraction yields unchanged volume:",entity->entity);
|
||||
if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) )
|
||||
Ifc::LogMessage("Warning","Subtraction yields unchanged volume:",entity->entity);
|
||||
|
||||
} else {
|
||||
Ifc::LogMessage("Error","Invalid result from subtraction:",entity->entity);
|
||||
}
|
||||
} else {
|
||||
Ifc::LogMessage("Error","Failed to process subtraction:",entity->entity);
|
||||
}
|
||||
|
||||
}
|
||||
cut_shapes.push_back(IfcGeom::LocationShape(new gp_GTrsf(),new TopoDS_Shape(entity_shape)));
|
||||
}
|
||||
@@ -214,7 +229,7 @@ bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
|
||||
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) {
|
||||
bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face) {
|
||||
TopoDS_Vertex* vertices = new TopoDS_Vertex[numVerts];
|
||||
|
||||
for ( int i = 0; i < numVerts; i ++ ) {
|
||||
@@ -232,7 +247,7 @@ bool IfcGeom::profile_helper(int numVerts, float* verts, int numFillets, int* fi
|
||||
if ( numFillets ) {
|
||||
BRepFilletAPI_MakeFillet2d fillet (face);
|
||||
for ( int i = 0; i < numFillets; i ++ ) {
|
||||
const float radius = filletRadii[i];
|
||||
const double radius = filletRadii[i];
|
||||
if ( radius < 1e-7 ) continue;
|
||||
fillet.AddFillet(vertices[filletIndices[i]],radius);
|
||||
}
|
||||
@@ -243,8 +258,76 @@ bool IfcGeom::profile_helper(int numVerts, float* verts, int numFillets, int* fi
|
||||
delete[] vertices;
|
||||
return true;
|
||||
}
|
||||
float IfcGeom::shape_volume(const TopoDS_Shape& s) {
|
||||
double IfcGeom::shape_volume(const TopoDS_Shape& s) {
|
||||
GProp_GProps System;
|
||||
BRepGProp::VolumeProperties(s, System);
|
||||
return (float) System.Mass();
|
||||
return (double) System.Mass();
|
||||
}
|
||||
bool IfcGeom::is_convex(const TopoDS_Wire& wire) {
|
||||
for ( TopExp_Explorer exp1(wire,TopAbs_VERTEX); exp1.More(); exp1.Next() ) {
|
||||
TopoDS_Vertex V1 = TopoDS::Vertex(exp1.Current());
|
||||
gp_Pnt P1 = BRep_Tool::Pnt(V1);
|
||||
// Store the neighboring points
|
||||
std::vector<gp_Pnt> neighbors;
|
||||
for ( TopExp_Explorer exp3(wire,TopAbs_EDGE); exp3.More(); exp3.Next() ) {
|
||||
TopoDS_Edge edge = TopoDS::Edge(exp3.Current());
|
||||
std::vector<gp_Pnt> edge_points;
|
||||
for ( TopExp_Explorer exp2(edge,TopAbs_VERTEX); exp2.More(); exp2.Next() ) {
|
||||
TopoDS_Vertex V2 = TopoDS::Vertex(exp2.Current());
|
||||
gp_Pnt P2 = BRep_Tool::Pnt(V2);
|
||||
edge_points.push_back(P2);
|
||||
}
|
||||
if ( edge_points.size() != 2 ) continue;
|
||||
if ( edge_points[0].IsEqual(P1,0.0001)) neighbors.push_back(edge_points[1]);
|
||||
else if ( edge_points[1].IsEqual(P1,0.0001)) neighbors.push_back(edge_points[0]);
|
||||
}
|
||||
// There should be two of these
|
||||
if ( neighbors.size() != 2 ) return false;
|
||||
// Now find the non neighboring points
|
||||
std::vector<gp_Pnt> non_neighbors;
|
||||
for ( TopExp_Explorer exp2(wire,TopAbs_VERTEX); exp2.More(); exp2.Next() ) {
|
||||
TopoDS_Vertex V2 = TopoDS::Vertex(exp2.Current());
|
||||
gp_Pnt P2 = BRep_Tool::Pnt(V2);
|
||||
if ( P1.IsEqual(P2,0.0001) ) continue;
|
||||
bool found = false;
|
||||
for( std::vector<gp_Pnt>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++ it ) {
|
||||
if ( (*it).IsEqual(P2,0.0001) ) { found = true; break; }
|
||||
}
|
||||
if ( ! found ) non_neighbors.push_back(P2);
|
||||
}
|
||||
// Calculate the angle between the two edges of the vertex
|
||||
gp_Dir dir1(neighbors[0].XYZ() - P1.XYZ());
|
||||
gp_Dir dir2(neighbors[1].XYZ() - P1.XYZ());
|
||||
const double angle = acos(dir1.Dot(dir2)) + 0.0001;
|
||||
// Now for the non-neighbors see whether a greater angle can be found with one of the edges
|
||||
for ( std::vector<gp_Pnt>::const_iterator it = non_neighbors.begin(); it != non_neighbors.end(); ++ it ) {
|
||||
gp_Dir dir3((*it).XYZ() - P1.XYZ());
|
||||
const double angle2 = acos(dir3.Dot(dir1));
|
||||
const double angle3 = acos(dir3.Dot(dir2));
|
||||
if ( angle2 > angle || angle3 > angle ) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
TopoDS_Shape IfcGeom::halfspace_from_plane(const gp_Pln& pln,const gp_Pnt& cent) {
|
||||
TopoDS_Face face = BRepBuilderAPI_MakeFace(pln).Face();
|
||||
return BRepPrimAPI_MakeHalfSpace(face,cent).Solid();
|
||||
}
|
||||
gp_Pln IfcGeom::plane_from_face(const TopoDS_Face& face) {
|
||||
BRepGProp_Face prop(face);
|
||||
Standard_Real u1,u2,v1,v2;
|
||||
prop.Bounds(u1,u2,v1,v2);
|
||||
Standard_Real u = (u1+u2)/2.0;
|
||||
Standard_Real v = (v1+v2)/2.0;
|
||||
gp_Pnt p;
|
||||
gp_Vec n;
|
||||
prop.Normal(u,v,p,n);
|
||||
return gp_Pln(p,n);
|
||||
}
|
||||
gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) {
|
||||
if ( agree ) {
|
||||
return pln.Location().Translated(pln.Axis().Direction());
|
||||
} else {
|
||||
return pln.Location().Translated(-pln.Axis().Direction());
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ namespace IfcGeom {
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCartesianPoint::ptr l, gp_Pnt& point) {
|
||||
IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point)
|
||||
std::vector<float> xyz = l->Coordinates();
|
||||
std::vector<double> xyz = l->Coordinates();
|
||||
point = gp_Pnt(
|
||||
xyz.size() ? (xyz[0]*Ifc::LengthUnit) : 0.0f,
|
||||
xyz.size() > 1 ? (xyz[1]*Ifc::LengthUnit) : 0.0f,
|
||||
@@ -100,7 +100,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianPoint::ptr l, gp_Pnt& point) {
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcDirection::ptr l, gp_Dir& dir) {
|
||||
IN_CACHE(IfcDirection,l,gp_Dir,dir)
|
||||
std::vector<float> xyz = l->DirectionRatios();
|
||||
std::vector<double> xyz = l->DirectionRatios();
|
||||
dir = gp_Dir(
|
||||
xyz.size() ? xyz[0] : 0.0f,
|
||||
xyz.size() > 1 ? xyz[1] : 0.0f,
|
||||
@@ -179,9 +179,9 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3DnonUnifo
|
||||
if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse();
|
||||
trsf.SetTransformation(ax3);
|
||||
trsf.Invert();
|
||||
const float scale1 = l->hasScale() ? l->Scale() : 1.0f;
|
||||
const float scale2 = l->hasScale2() ? l->Scale2() : scale1;
|
||||
const float scale3 = l->hasScale3() ? l->Scale3() : scale1;
|
||||
const double scale1 = l->hasScale() ? l->Scale() : 1.0f;
|
||||
const double scale2 = l->hasScale2() ? l->Scale2() : scale1;
|
||||
const double scale3 = l->hasScale3() ? l->Scale3() : scale1;
|
||||
gtrsf = gp_GTrsf();
|
||||
gtrsf.SetValue(1,1,scale1);
|
||||
gtrsf.SetValue(2,2,scale2);
|
||||
@@ -200,8 +200,8 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2DnonUnifo
|
||||
const gp_Ax2d ax2d (gp_Pnt2d(origin.X(),origin.Y()),gp_Dir2d(axis1.X(),axis1.Y()));
|
||||
trsf.SetTransformation(ax2d);
|
||||
trsf.Invert();
|
||||
const float scale1 = l->hasScale() ? l->Scale() : 1.0f;
|
||||
const float scale2 = l->hasScale2() ? l->Scale2() : scale1;
|
||||
const double scale1 = l->hasScale() ? l->Scale() : 1.0f;
|
||||
const double scale2 = l->hasScale2() ? l->Scale2() : scale1;
|
||||
gtrsf = gp_GTrsf2d();
|
||||
gtrsf.SetValue(1,1,scale1);
|
||||
gtrsf.SetValue(2,2,scale2);
|
||||
|
||||
@@ -51,12 +51,12 @@ bool weld_vertices = true;
|
||||
bool convert_back_units = false;
|
||||
|
||||
int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
|
||||
const float X = convert_back_units ? (float)p.X() / Ifc::LengthUnit : (float)p.X();
|
||||
const float Y = convert_back_units ? (float)p.Y() / Ifc::LengthUnit : (float)p.Y();
|
||||
const float Z = convert_back_units ? (float)p.Z() / Ifc::LengthUnit : (float)p.Z();
|
||||
const double X = convert_back_units ? (double)p.X() / Ifc::LengthUnit : (double)p.X();
|
||||
const double Y = convert_back_units ? (double)p.Y() / Ifc::LengthUnit : (double)p.Y();
|
||||
const double Z = convert_back_units ? (double)p.Z() / Ifc::LengthUnit : (double)p.Z();
|
||||
int i = (int) verts.size() / 3;
|
||||
if ( weld_vertices ) {
|
||||
const VertKey key = VertKey(X,std::pair<float,float>(Y,Z));
|
||||
const VertKey key = VertKey(X,std::pair<double,double>(Y,Z));
|
||||
VertKeyMap::const_iterator it = welds.find(key);
|
||||
if ( it != welds.end() ) return it->second;
|
||||
i = (int) welds.size();
|
||||
@@ -146,9 +146,9 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
gp_Vec normal_direction;
|
||||
prop.Normal(uv.X(),uv.Y(),p,normal_direction);
|
||||
gp_Dir normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
|
||||
normals.push_back((float)normal.X());
|
||||
normals.push_back((float)normal.Y());
|
||||
normals.push_back((float)normal.Z());
|
||||
normals.push_back((double)normal.X());
|
||||
normals.push_back((double)normal.Y());
|
||||
normals.push_back((double)normal.Z());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,9 +168,9 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
const gp_XYZ v1 = pt2-pt1;
|
||||
const gp_XYZ v2 = pt3-pt2;
|
||||
gp_Dir normal = gp_Dir(v1^v2);
|
||||
normals.push_back((float)normal.X());
|
||||
normals.push_back((float)normal.Y());
|
||||
normals.push_back((float)normal.Z());
|
||||
normals.push_back((double)normal.X());
|
||||
normals.push_back((double)normal.Y());
|
||||
normals.push_back((double)normal.Z());
|
||||
*/
|
||||
|
||||
faces.push_back(dict[n1]);
|
||||
@@ -199,7 +199,7 @@ IfcGeomObjects::IfcObject::IfcObject(int my_id,
|
||||
// Convert the gp_Trsf into a 4x3 Matrix
|
||||
for( int i = 1; i < 5; ++ i )
|
||||
for ( int j = 1; j < 4; ++ j )
|
||||
matrix.push_back((float)trsf.Value(j,i));
|
||||
matrix.push_back((double)trsf.Value(j,i));
|
||||
|
||||
id = my_id;
|
||||
parent_id = p_id;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). *
|
||||
* *
|
||||
* IfcMesh is a class that represents a triangulated IfcShapeRepresentation. *
|
||||
* IfcMesh.verts is a 1 dimensional vector of float defining the cartesian *
|
||||
* IfcMesh.verts is a 1 dimensional vector of double defining the cartesian *
|
||||
* coordinates of the vertices of the triangulated shape in the format of *
|
||||
* [x1,y1,z1,..,xn,yn,zn] *
|
||||
* IfcMesh.faces is a 1 dimensional vector of int containing the indices of *
|
||||
@@ -75,18 +75,18 @@ namespace IfcGeomObjects {
|
||||
const int USE_BREP_DATA = 4;
|
||||
|
||||
typedef std::vector<int>::const_iterator IntIt;
|
||||
typedef std::vector<float>::const_iterator FltIt;
|
||||
typedef std::pair< float,std::pair<float,float> > VertKey;
|
||||
typedef std::vector<double>::const_iterator FltIt;
|
||||
typedef std::pair< double,std::pair<double,double> > VertKey;
|
||||
typedef std::map<VertKey,int> VertKeyMap;
|
||||
typedef std::pair<int,int> Edge;
|
||||
|
||||
class IfcMesh {
|
||||
public:
|
||||
int id;
|
||||
std::vector<float> verts;
|
||||
std::vector<double> verts;
|
||||
std::vector<int> faces;
|
||||
std::vector<int> edges;
|
||||
std::vector<float> normals;
|
||||
std::vector<double> normals;
|
||||
std::string brep_data;
|
||||
VertKeyMap welds;
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace IfcGeomObjects {
|
||||
std::string name;
|
||||
std::string type;
|
||||
std::string guid;
|
||||
std::vector<float> matrix;
|
||||
std::vector<double> matrix;
|
||||
IfcObject(int my_id, int p_id, const std::string& n, const std::string& t, const std::string& g, const gp_Trsf& trsf);
|
||||
};
|
||||
|
||||
|
||||
+140
-26
@@ -75,18 +75,21 @@
|
||||
|
||||
#include <TopLoc_Location.hxx>
|
||||
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepAlgoAPI_Common.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& shape) {
|
||||
TopoDS_Face face;
|
||||
if ( ! IfcGeom::convert_face(l->SweptArea(),face) ) return false;
|
||||
const float height = l->Depth() * Ifc::LengthUnit;
|
||||
const double height = l->Depth() * Ifc::LengthUnit;
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(l->Position(),trsf);
|
||||
|
||||
gp_Dir dir;
|
||||
convert(l->ExtrudedDirection(),dir);
|
||||
|
||||
|
||||
shape = BRepPrimAPI_MakePrism(face,height*dir);
|
||||
shape.Move(trsf);
|
||||
return ! shape.IsNull();
|
||||
@@ -117,11 +120,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcHalfSpaceSolid::ptr l, TopoDS_Shape& shap
|
||||
}
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcSurface,Ifc2x3::IfcPlane>(surface),pln);
|
||||
gp_Pnt pnt = pln.Location();
|
||||
bool reverse = l->AgreementFlag();
|
||||
if ( l->is(Ifc2x3::Type::IfcPolygonalBoundedHalfSpace) ) reverse = !reverse;
|
||||
if ( reverse ) pnt.Translate(-pln.Axis().Direction());
|
||||
else pnt.Translate(pln.Axis().Direction());
|
||||
const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction());
|
||||
shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid();
|
||||
return true;
|
||||
}
|
||||
@@ -132,10 +131,10 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr l, TopoDS_
|
||||
if ( ! IfcGeom::convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false;
|
||||
gp_Trsf trsf;
|
||||
convert(l->Position(),trsf);
|
||||
TopoDS_Shape extrusion = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200.0));
|
||||
TopoDS_Shape prism = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200));
|
||||
gp_Trsf down; down.SetTranslation(gp_Vec(0,0,-100.0));
|
||||
extrusion.Move(down*trsf);
|
||||
shape = BRepAlgoAPI_Cut(extrusion,halfspace);
|
||||
prism.Move(down*trsf);
|
||||
shape = BRepAlgoAPI_Common(halfspace,prism);
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcShellBasedSurfaceModel::ptr l, ShapeList& shapes) {
|
||||
@@ -150,33 +149,148 @@ bool IfcGeom::convert(const Ifc2x3::IfcShellBasedSurfaceModel::ptr l, ShapeList&
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shape& shape) {
|
||||
TopoDS_Shape s1, s2;
|
||||
TopoDS_Wire boundary_wire;
|
||||
Ifc2x3::IfcBooleanOperand operand2 = l->SecondOperand();
|
||||
bool is_halfspace = operand2->is(Ifc2x3::Type::IfcHalfSpaceSolid);
|
||||
bool is_bounded = operand2->is(Ifc2x3::Type::IfcPolygonalBoundedHalfSpace);
|
||||
bool is_convex_bound = false;
|
||||
|
||||
if ( ! IfcGeom::convert_shape(l->FirstOperand(),s1) )
|
||||
return false;
|
||||
|
||||
const float first_operand_volume = shape_volume(s1);
|
||||
|
||||
const double first_operand_volume = shape_volume(s1);
|
||||
if ( first_operand_volume <= ALMOST_ZERO )
|
||||
Ifc::LogMessage("warning","Empty solid for:",l->FirstOperand()->entity);
|
||||
|
||||
if ( ! IfcGeom::convert_shape(l->SecondOperand(),s2) ) {
|
||||
Ifc::LogMessage("Warning","Empty solid for:",l->FirstOperand()->entity);
|
||||
|
||||
if ( !IfcGeom::convert_shape(l->SecondOperand(),s2) ) {
|
||||
shape = s1;
|
||||
Ifc::LogMessage("Error","Failed to convert SecondOperand of:",l->SecondOperand()->entity);
|
||||
Ifc::LogMessage("Error","Failed to convert SecondOperand of:",l->entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! l->SecondOperand()->is(Ifc2x3::Type::IfcHalfSpaceSolid) ) {
|
||||
const float second_operand_volume = shape_volume(s2);
|
||||
if ( second_operand_volume <= ALMOST_ZERO )
|
||||
Ifc::LogMessage("warning","Empty solid for:",l->SecondOperand()->entity);
|
||||
if ( is_bounded ) {
|
||||
Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr ifc_bounded_halfspace =
|
||||
(Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr) operand2;
|
||||
IfcGeom::convert_wire(ifc_bounded_halfspace->PolygonalBoundary(),boundary_wire);
|
||||
is_convex_bound = is_convex(boundary_wire);
|
||||
}
|
||||
|
||||
shape = BRepAlgoAPI_Cut(s1,s2);
|
||||
if ( ! is_halfspace ) {
|
||||
const double second_operand_volume = shape_volume(s2);
|
||||
if ( second_operand_volume <= ALMOST_ZERO )
|
||||
Ifc::LogMessage("Warning","Empty solid for:",operand2->entity);
|
||||
}
|
||||
|
||||
const float volume_after_subtraction = shape_volume(shape);
|
||||
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
|
||||
Ifc::LogMessage("warning","Warning subtraction yields unchanged volume:",l->entity);
|
||||
bool valid_cut = false;
|
||||
if ( !is_bounded || !is_convex_bound ) {
|
||||
BRepAlgoAPI_Cut brep_cut(s1,s2);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
}
|
||||
}
|
||||
if ( !valid_cut && !is_bounded ) {
|
||||
Ifc2x3::IfcHalfSpaceSolid::ptr ifc_halfspace = (Ifc2x3::IfcHalfSpaceSolid::ptr) operand2;
|
||||
Ifc2x3::IfcSurface::ptr surface = ifc_halfspace->BaseSurface();
|
||||
if ( surface->is(Ifc2x3::Type::IfcPlane) ) {
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcSurface,Ifc2x3::IfcPlane>(surface),pln);
|
||||
gp_Pnt pnt = pln.Location();
|
||||
bool reverse = ifc_halfspace->AgreementFlag();
|
||||
gp_Vec direction = pln.Axis().Direction();
|
||||
if ( reverse ) direction *= -1;
|
||||
pnt.Translate(direction);
|
||||
pln.SetLocation(pln.Location().Translated(direction * -0.0001));
|
||||
TopoDS_Shape halfspace = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid();
|
||||
|
||||
BRepAlgoAPI_Cut brep_cut(s1,halfspace);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
Ifc::LogMessage("Warning","Slightly nudged the SecondOperand of:",l->entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr ifc_bounded_halfspace =
|
||||
(Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr) operand2;
|
||||
gp_Trsf trsf;
|
||||
convert(ifc_bounded_halfspace->Position(),trsf);
|
||||
TopoDS_Shape face = BRepBuilderAPI_MakeFace(boundary_wire).Face();
|
||||
TopoDS_Shape prism = BRepPrimAPI_MakePrism (boundary_wire,gp_Vec(0,0,1),1);
|
||||
prism.Move(trsf);
|
||||
face.Move(trsf);
|
||||
|
||||
gp_Pln pln = plane_from_face(TopoDS::Face(face));
|
||||
gp_Pnt pnt = point_above_plane(pln,ifc_bounded_halfspace->AgreementFlag());
|
||||
|
||||
TopoDS_Shape halfspace;
|
||||
Ifc2x3::IfcHalfSpaceSolid::ptr ifc_halfspace = (Ifc2x3::IfcHalfSpaceSolid::ptr) operand2;
|
||||
if ( ! IfcGeom::convert(ifc_halfspace,halfspace) ) return false;
|
||||
|
||||
TopoDS_Shape subtraction_volume = s1;
|
||||
double subtraction_volume_volume = shape_volume(subtraction_volume);
|
||||
|
||||
const double minimal_substraction_difference = subtraction_volume_volume * 0.0001;
|
||||
|
||||
BRepAlgoAPI_Common brep_common(subtraction_volume,halfspace);
|
||||
if ( brep_common.IsDone() ) {
|
||||
TopoDS_Shape brep_common_shape = brep_common;
|
||||
bool is_valid = BRepCheck_Analyzer(brep_common_shape).IsValid() != 0;
|
||||
double new_subtraction_volume_volume = shape_volume(brep_common_shape);
|
||||
double subtraction_volume_difference = subtraction_volume_volume - new_subtraction_volume_volume;
|
||||
if ( is_valid && subtraction_volume_difference > minimal_substraction_difference ) {
|
||||
subtraction_volume = brep_common_shape;
|
||||
subtraction_volume_volume = new_subtraction_volume_volume;
|
||||
}
|
||||
}
|
||||
|
||||
TopExp_Explorer exp(prism,TopAbs_FACE);
|
||||
while ( exp.More() ) {
|
||||
TopoDS_Shape halfspace = halfspace_from_plane(plane_from_face(TopoDS::Face(exp.Current())),pnt);
|
||||
BRepAlgoAPI_Common brep_common(subtraction_volume,halfspace);
|
||||
if ( brep_common.IsDone() ) {
|
||||
TopoDS_Shape brep_common_shape = brep_common;
|
||||
bool is_valid = BRepCheck_Analyzer(brep_common_shape).IsValid() != 0;
|
||||
double new_subtraction_volume_volume = shape_volume(brep_common_shape);
|
||||
double subtraction_volume_difference = subtraction_volume_volume - new_subtraction_volume_volume;
|
||||
if ( is_valid && subtraction_volume_difference > minimal_substraction_difference ) {
|
||||
subtraction_volume = brep_common_shape;
|
||||
subtraction_volume_volume = new_subtraction_volume_volume;
|
||||
}
|
||||
}
|
||||
exp.Next();
|
||||
}
|
||||
|
||||
BRepAlgoAPI_Cut brep_cut(s1,subtraction_volume);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( valid_cut ) {
|
||||
const double volume_after_subtraction = shape_volume(shape);
|
||||
if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
|
||||
Ifc::LogMessage("Warning","Subtraction yields unchanged volume:",l->entity);
|
||||
} else {
|
||||
Ifc::LogMessage("Error","Failed to process subtraction:",l->entity);
|
||||
shape = s1;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) {
|
||||
#ifdef FACESET_AS_COMPOUND
|
||||
@@ -223,8 +337,8 @@ bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, ShapeList& shapes) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
|
||||
Ifc2x3::IfcCartesianTransformationOperator3DnonUniform>(transform),gtrsf);
|
||||
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2DnonUniform) ) {
|
||||
return false;
|
||||
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3D) ) {
|
||||
return false;
|
||||
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3D) ) {
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
|
||||
Ifc2x3::IfcCartesianTransformationOperator3D>(transform),trsf);
|
||||
|
||||
@@ -138,16 +138,16 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
Ifc2x3::IfcCurve::ptr basis_curve = l->BasisCurve();
|
||||
bool isConic = basis_curve->is(Ifc2x3::Type::IfcConic);
|
||||
float parameterFactor = isConic ? Ifc::PlaneAngleUnit : Ifc::LengthUnit;
|
||||
double parameterFactor = isConic ? Ifc::PlaneAngleUnit : Ifc::LengthUnit;
|
||||
Handle(Geom_Curve) curve;
|
||||
if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false;
|
||||
bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::CARTESIAN;
|
||||
bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
|
||||
IfcUtil::IfcAbstractSelect::list trims1 = l->Trim1();
|
||||
IfcUtil::IfcAbstractSelect::list trims2 = l->Trim2();
|
||||
bool trimmed1 = false;
|
||||
bool trimmed2 = false;
|
||||
bool sense_agreement = l->SenseAgreement();
|
||||
float flt1;
|
||||
double flt1;
|
||||
gp_Pnt pnt1;
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = trims1->begin(); it != trims1->end(); it ++ ) {
|
||||
@@ -156,7 +156,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnt1 );
|
||||
trimmed1 = true;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) && !trim_cartesian ) {
|
||||
const float value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
flt1 = value * parameterFactor;
|
||||
trimmed1 = true;
|
||||
}
|
||||
@@ -166,18 +166,22 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) && trim_cartesian && trimmed1 ) {
|
||||
gp_Pnt pnt2;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnt2 );
|
||||
BRepBuilderAPI_MakeEdge e (curve,pnt1,pnt2);
|
||||
BRepBuilderAPI_MakeEdge e (curve,sense_agreement ? pnt1 : pnt2,sense_agreement ? pnt2 : pnt1);
|
||||
if ( ! e.IsDone() ) {
|
||||
BRepBuilderAPI_EdgeError err = e.Error();
|
||||
return false;
|
||||
if ( err == BRepBuilderAPI_PointProjectionFailed ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(sense_agreement ? pnt1 : pnt2,sense_agreement ? pnt2 : pnt1));
|
||||
Ifc::LogMessage("Warning","Point projection failed for:",l->entity);
|
||||
}
|
||||
} else {
|
||||
w.Add(e.Edge());
|
||||
}
|
||||
w.Add(e.Edge());
|
||||
trimmed2 = true;
|
||||
break;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) && !trim_cartesian && trimmed1 ) {
|
||||
const float value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
float flt2 = value * parameterFactor;
|
||||
if ( isConic && ALMOST_THE_SAME(fmod(flt2-flt1,(float)(PI*2.0)),0.0f) ) {
|
||||
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
double flt2 = value * parameterFactor;
|
||||
if ( isConic && ALMOST_THE_SAME(fmod(flt2-flt1,(double)(PI*2.0)),0.0f) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(curve));
|
||||
} else {
|
||||
BRepBuilderAPI_MakeEdge e (curve,sense_agreement ? flt1 : flt2,sense_agreement ? flt2 : flt1);
|
||||
@@ -197,7 +201,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolyline::ptr l, TopoDS_Wire& result) {
|
||||
gp_Pnt P1;gp_Pnt P2;
|
||||
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
IfcGeom::convert(*it,P2);
|
||||
if ( it != points->begin() && ( P1.X() != P2.X() || P1.Y() != P2.Y() || P1.Z() != P2.Z() ) )
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,0.0001) ) )
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
||||
P1 = P2;
|
||||
}
|
||||
@@ -213,13 +217,13 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolyLoop::ptr l, TopoDS_Wire& result) {
|
||||
int count = 0;
|
||||
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
IfcGeom::convert(*it,P2);
|
||||
if ( it != points->begin() && ( P1.X() != P2.X() || P1.Y() != P2.Y() || P1.Z() != P2.Z() ) ) {
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,0.0001) ) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
||||
count ++;
|
||||
} else if ( ! count ) F = P2;
|
||||
P1 = P2;
|
||||
}
|
||||
if ( P1.X() != F.X() || P1.Y() != F.Y() || P1.Z() != F.Z() ) {
|
||||
if ( !P1.IsEqual(F,0.0001) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,F));
|
||||
count ++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user