/******************************************************************************** * * * This file is part of IfcOpenShell. * * * * IfcOpenShell is free software: you can redistribute it and/or modify * * it under the terms of the Lesser GNU General Public License as published by * * the Free Software Foundation, either version 3.0 of the License, or * * (at your option) any later version. * * * * IfcOpenShell is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * Lesser GNU General Public License for more details. * * * * You should have received a copy of the Lesser GNU General Public License * * along with this program. If not, see . * * * ********************************************************************************/ /******************************************************************************** * * * Implementations of the various conversion functions defined in IfcGeom.h * * * ********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../ifcgeom/IfcGeom.h" bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, TopoDS_Shape& result, const gp_Trsf& trsf2) { for ( Ifc2x3::IfcRelVoidsElement::it it = openings->begin(); it != openings->end(); ++ it ) { Ifc2x3::IfcRelVoidsElement::ptr v = *it; Ifc2x3::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement(); if ( fes->is(Ifc2x3::Type::IfcOpeningElement) ) { gp_Trsf trsf; IfcGeom::convert(fes->ObjectPlacement(),trsf); trsf.PreMultiply(trsf2.Inverted()); Ifc2x3::IfcProductRepresentation::ptr prodrep = fes->Representation(); if ( prodrep->is(Ifc2x3::Type::IfcProductDefinitionShape) ) { Ifc2x3::IfcProductDefinitionShape::ptr pds = reinterpret_pointer_cast(prodrep); Ifc2x3::IfcRepresentation::list reps = pds->Representations(); for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) { TopoDS_Shape s; IfcGeom::convert_shape(*it2,s); s.Move(trsf); const float opening_volume = shape_volume(s); if ( opening_volume <= ALMOST_ZERO ) Ifc::LogMessage("warning","Empty solid for:",fes->entity); const float original_shape_volume = shape_volume(result); result = BRepAlgoAPI_Cut(result,s); const float volume_after_subtraction = shape_volume(result); if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) ) Ifc::LogMessage("warning","Warning subtraction yields unchanged volume:",entity->entity); } } } } return true; } bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { BRepBuilderAPI_MakeFace mf(wire, false); BRepBuilderAPI_FaceError er = mf.Error(); if ( er == BRepBuilderAPI_NotPlanar ) { ShapeFix_ShapeTolerance FTol; FTol.SetTolerance(wire, 0.01, TopAbs_WIRE); mf.~BRepBuilderAPI_MakeFace(); new (&mf) BRepBuilderAPI_MakeFace(wire); er = mf.Error(); } 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; } float IfcGeom::shape_volume(const TopoDS_Shape& s) { GProp_GProps System; BRepGProp::VolumeProperties(s, System); return (float) System.Mass(); }