- 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:
Thomas Krijnen
2012-03-13 11:56:52 +00:00
parent 2b27b86b34
commit 3bb008c89f
31 changed files with 60370 additions and 2054 deletions
+98 -15
View File
@@ -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());
}
}