bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_Shape& shape) { TopoDS_Shape halfspace; if ( ! IfcGeom::Kernel::convert((IfcSchema::IfcHalfSpaceSolid*)l,halfspace) ) return false; TopoDS_Wire wire; if ( ! convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false; gp_Trsf trsf; if ( ! convert(l->Position(),trsf) ) return false; TColgp_SequenceOfPnt points; if (wire_to_sequence_of_point(wire, points)) { remove_duplicate_points_from_loop(points, wire.Closed()); // Note: wire always closed, as per if statement above remove_collinear_points_from_loop(points, wire.Closed()); sequence_of_point_to_wire(points, wire, wire.Closed()); } TopoDS_Shape prism = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200)); gp_Trsf down; down.SetTranslation(gp_Vec(0,0,-100.0)); // `trsf` and `down` both have a unit scale factor prism.Move(trsf*down); shape = BRepAlgoAPI_Common(halfspace,prism); return true; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& result) { IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList(); BRepBuilderAPI_MakeWire mw; for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) { IfcSchema::IfcOrientedEdge* e = *it; IfcSchema::IfcPoint* pnt1 = ((IfcSchema::IfcVertexPoint*) e->EdgeStart())->VertexGeometry(); IfcSchema::IfcPoint* pnt2 = ((IfcSchema::IfcVertexPoint*) e->EdgeEnd())->VertexGeometry(); if (!pnt1->is(IfcSchema::Type::IfcCartesianPoint) || !pnt2->is(IfcSchema::Type::IfcCartesianPoint)) { Logger::Message(Logger::LOG_ERROR, "Only IfcCartesianPoints are supported for VertexGeometry", l->entity); return false; } gp_Pnt p1, p2; if (!IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt1), p1) || !IfcGeom::Kernel::convert(((IfcSchema::IfcCartesianPoint*)pnt2), p2)) { return false; } mw.Add(BRepBuilderAPI_MakeEdge(p1, p2)); continue; IfcSchema::IfcEdge* base = e->EdgeElement(); TopoDS_Wire w; if (convert_wire(e->EdgeElement(), w)) { if (!e->Orientation()) w.Reverse(); mw.Add(w); } } result = mw; return true; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace* l, TopoDS_Shape& shape) { TopoDS_Shape halfspace; if ( ! IfcGeom::Kernel::convert((IfcSchema::IfcHalfSpaceSolid*)l,halfspace) ) return false; TopoDS_Wire wire; if ( ! convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false; gp_Trsf trsf; convert(l->Position(),trsf); TopoDS_Shape prism = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200)); gp_Trsf down; down.SetTranslation(gp_Vec(0,0,-100.0)); prism.Move(trsf*down); shape = BRepAlgoAPI_Common(halfspace,prism); return true; }
bool FaceMakerCheese::Wire_Compare::operator() (const TopoDS_Wire& w1, const TopoDS_Wire& w2) { Bnd_Box box1, box2; if (!w1.IsNull()) { BRepBndLib::Add(w1, box1); box1.SetGap(0.0); } if (!w2.IsNull()) { BRepBndLib::Add(w2, box2); box2.SetGap(0.0); } return box1.SquareExtent() < box2.SquareExtent(); }
//! return true if w1 bbox is bigger than w2 bbox //NOTE: this won't necessarily sort the OuterWire correctly (ex smaller wire, same bbox) /*static*/bool EdgeWalker::wireCompare(const TopoDS_Wire& w1, const TopoDS_Wire& w2) { Bnd_Box box1, box2; if (!w1.IsNull()) { BRepBndLib::Add(w1, box1); box1.SetGap(0.0); } if (!w2.IsNull()) { BRepBndLib::Add(w2, box2); box2.SetGap(0.0); } return box1.SquareExtent() > box2.SquareExtent(); }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcEdgeLoop* l, TopoDS_Wire& result) { IfcSchema::IfcOrientedEdge::list::ptr li = l->EdgeList(); BRepBuilderAPI_MakeWire mw; for (IfcSchema::IfcOrientedEdge::list::it it = li->begin(); it != li->end(); ++it) { TopoDS_Wire w; if (convert_wire(*it, w)) { if (!(*it)->Orientation()) w.Reverse(); TopoDS_Iterator topoit(w, false); for (; topoit.More(); topoit.Next()) { const TopoDS_Edge& e = TopoDS::Edge(topoit.Value()); mw.Add(e); } // mw.Add(w); } } result = mw; return true; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcOrientedEdge* l, TopoDS_Wire& result) { if (convert_wire(l->EdgeElement(), result)) { if (!l->Orientation()) { result.Reverse(); } return true; } else { return false; } }
TopoDS_Wire TopoDSWireAdaptor(CompoundSegment* poly, bool inside) { std::list<TopoDS_Edge> edges; //if(inside) //poly->(); poly->GetEdges(edges); BRepLib_MakeWire wire_maker; std::list<TopoDS_Edge>::iterator It; for(It = edges.begin(); It != edges.end(); It++) { TopoDS_Edge &edge = *It; // BRepLib_BuildCurve3d( edge ); wire_maker.Add(edge); } TopoDS_Wire wire = wire_maker.Wire(); // if(inside) // wire = TopoDS::Wire(wire.Oriented(TopAbs_REVERSED)); // else wire = TopoDS::Wire(wire.Oriented(TopAbs_FORWARD)); return wire; }
void ProfileBased::getUpToFace(TopoDS_Face& upToFace, const TopoDS_Shape& support, const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, const std::string& method, const gp_Dir& dir, const double offset) { if ((method == "UpToLast") || (method == "UpToFirst")) { // Check for valid support object if (support.IsNull()) throw Base::ValueError("SketchBased: Up to face: No support in Sketch and no base feature!"); std::vector<Part::cutFaces> cfaces = Part::findAllFacesCutBy(support, sketchshape, dir); if (cfaces.empty()) throw Base::ValueError("SketchBased: Up to face: No faces found in this direction"); // Find nearest/furthest face std::vector<Part::cutFaces>::const_iterator it, it_near, it_far; it_near = it_far = cfaces.begin(); for (it = cfaces.begin(); it != cfaces.end(); it++) if (it->distsq > it_far->distsq) it_far = it; else if (it->distsq < it_near->distsq) it_near = it; upToFace = (method == "UpToLast" ? it_far->face : it_near->face); } // Check whether the face has limits or not. Unlimited faces have no wire // Note: Datum planes are always unlimited TopExp_Explorer Ex(upToFace,TopAbs_WIRE); if (Ex.More()) { // Remove the limits of the upToFace so that the extrusion works even if sketchshape is larger // than the upToFace bool remove_limits = false; for (Ex.Init(sketchshape,TopAbs_FACE); Ex.More(); Ex.Next()) { // Get outermost wire of sketch face TopoDS_Face sketchface = TopoDS::Face(Ex.Current()); TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(sketchface); if (!checkWireInsideFace(outerWire, upToFace, dir)) { remove_limits = true; break; } } // It must also be checked that all projected inner wires of the upToFace // lie outside the sketch shape. If this is not the case then the sketch // shape is not completely covered by the upToFace. See #0003141 if (!remove_limits) { TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(upToFace); for (Ex.Init(upToFace, TopAbs_WIRE); Ex.More(); Ex.Next()) { if (!outerWire.IsSame(Ex.Current())) { BRepProj_Projection proj(TopoDS::Wire(Ex.Current()), sketchshape, -dir); if (proj.More()) { remove_limits = true; break; } } } } if (remove_limits) { // Note: Using an unlimited face every time gives unnecessary failures for concave faces TopLoc_Location loc = upToFace.Location(); BRepAdaptor_Surface adapt(upToFace, Standard_False); // use the placement of the adapter, not of the upToFace loc = TopLoc_Location(adapt.Trsf()); BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface() #if OCC_VERSION_HEX >= 0x060502 , Precision::Confusion() #endif ); if (!mkFace.IsDone()) throw Base::ValueError("SketchBased: Up To Face: Failed to create unlimited face"); upToFace = TopoDS::Face(mkFace.Shape()); upToFace.Location(loc); } } // Check that the upToFace does not intersect the sketch face and // is not parallel to the extrusion direction (for simplicity, supportface is used instead of sketchshape) BRepAdaptor_Surface adapt1(TopoDS::Face(supportface)); BRepAdaptor_Surface adapt2(TopoDS::Face(upToFace)); if (adapt2.GetType() == GeomAbs_Plane) { if (adapt1.Plane().Axis().IsNormal(adapt2.Plane().Axis(), Precision::Confusion())) throw Base::ValueError("SketchBased: Up to face: Must not be parallel to extrusion direction!"); } // We must measure from sketchshape, not supportface, here BRepExtrema_DistShapeShape distSS(sketchshape, upToFace); if (distSS.Value() < Precision::Confusion()) throw Base::ValueError("SketchBased: Up to face: Must not intersect sketch!"); // Move the face in the extrusion direction // TODO: For non-planar faces, we could consider offsetting the surface if (fabs(offset) > Precision::Confusion()) { if (adapt2.GetType() == GeomAbs_Plane) { gp_Trsf mov; mov.SetTranslation(offset * gp_Vec(dir)); TopLoc_Location loc(mov); upToFace.Move(loc); } else { throw Base::TypeError("SketchBased: Up to Face: Offset not supported yet for non-planar faces"); } } }
void Extrusion::makeDraft(ExtrusionParameters params, const TopoDS_Shape& shape, std::list<TopoDS_Shape>& drafts) { double distanceFwd = tan(params.taperAngleFwd)*params.lengthFwd; double distanceRev = tan(params.taperAngleRev)*params.lengthRev; gp_Vec vecFwd = gp_Vec(params.dir)*params.lengthFwd; gp_Vec vecRev = gp_Vec(params.dir.Reversed())*params.lengthRev; bool bFwd = fabs(params.lengthFwd) > Precision::Confusion(); bool bRev = fabs(params.lengthRev) > Precision::Confusion(); bool bMid = !bFwd || !bRev || params.lengthFwd*params.lengthRev > 0.0; //include the source shape as loft section? TopoDS_Wire sourceWire; if (shape.IsNull()) Standard_Failure::Raise("Not a valid shape"); if (shape.ShapeType() == TopAbs_WIRE) { ShapeFix_Wire aFix; aFix.Load(TopoDS::Wire(shape)); aFix.FixReorder(); aFix.FixConnected(); aFix.FixClosed(); sourceWire = aFix.Wire(); } else if (shape.ShapeType() == TopAbs_FACE) { TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(TopoDS::Face(shape)); sourceWire = outerWire; } else if (shape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it(shape); for (; it.More(); it.Next()) { makeDraft(params, it.Value(), drafts); } } else { Standard_Failure::Raise("Only a wire or a face is supported"); } if (!sourceWire.IsNull()) { std::list<TopoDS_Wire> list_of_sections; //first. add wire for reversed part of extrusion if (bRev){ gp_Vec translation = vecRev; double offset = distanceRev; BRepOffsetAPI_MakeOffset mkOffset; #if OCC_VERSION_HEX >= 0x060800 mkOffset.Init(GeomAbs_Arc); #endif #if OCC_VERSION_HEX >= 0x070000 mkOffset.Init(GeomAbs_Intersection); #endif gp_Trsf mat; mat.SetTranslation(translation); TopLoc_Location loc(mat); TopoDS_Wire movedSourceWire = TopoDS::Wire(sourceWire.Moved(loc)); TopoDS_Shape offsetShape; if (fabs(offset)>Precision::Confusion()){ mkOffset.AddWire(movedSourceWire); mkOffset.Perform(offset); offsetShape = mkOffset.Shape(); } else { //stupid OCC doesn't understand, what to do when offset value is zero =/ offsetShape = movedSourceWire; } if (offsetShape.IsNull()) Standard_Failure::Raise("Tapered shape is empty"); TopAbs_ShapeEnum type = offsetShape.ShapeType(); if (type == TopAbs_WIRE) { list_of_sections.push_back(TopoDS::Wire(offsetShape)); } else if (type == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(offsetShape)); list_of_sections.push_back(mkWire.Wire()); } else { Standard_Failure::Raise("Tapered shape type is not supported"); } } //next. Add source wire as middle section. Order is important. if (bMid){ list_of_sections.push_back(sourceWire); } //finally. Forward extrusion offset wire. if (bFwd){ gp_Vec translation = vecFwd; double offset = distanceFwd; BRepOffsetAPI_MakeOffset mkOffset; #if OCC_VERSION_HEX >= 0x060800 mkOffset.Init(GeomAbs_Arc); #endif #if OCC_VERSION_HEX >= 0x070000 mkOffset.Init(GeomAbs_Intersection); #endif gp_Trsf mat; mat.SetTranslation(translation); TopLoc_Location loc(mat); TopoDS_Wire movedSourceWire = TopoDS::Wire(sourceWire.Moved(loc)); TopoDS_Shape offsetShape; if (fabs(offset)>Precision::Confusion()){ mkOffset.AddWire(movedSourceWire); mkOffset.Perform(offset); offsetShape = mkOffset.Shape(); } else { //stupid OCC doesn't understand, what to do when offset value is zero =/ offsetShape = movedSourceWire; } if (offsetShape.IsNull()) Standard_Failure::Raise("Tapered shape is empty"); TopAbs_ShapeEnum type = offsetShape.ShapeType(); if (type == TopAbs_WIRE) { list_of_sections.push_back(TopoDS::Wire(offsetShape)); } else if (type == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(offsetShape)); list_of_sections.push_back(mkWire.Wire()); } else { Standard_Failure::Raise("Tapered shape type is not supported"); } } //make loft BRepOffsetAPI_ThruSections mkGenerator(params.solid ? Standard_True : Standard_False, /*ruled=*/Standard_True); for (std::list<TopoDS_Wire>::const_iterator it = list_of_sections.begin(); it != list_of_sections.end(); ++it) { const TopoDS_Wire &wire = *it; mkGenerator.AddWire(wire); } try { #if defined(__GNUC__) && defined (FC_OS_LINUX) Base::SignalException se; #endif mkGenerator.Build(); drafts.push_back(mkGenerator.Shape()); } catch (Standard_Failure &){ throw; } catch (...) { throw Base::Exception("Unknown exception from BRepOffsetAPI_ThruSections"); } } }
//---------------------------------------------------------------- // Function: TopoDS_Shape level function to update the core Surface // for any movement or Boolean operation of the body. // Author: Jane Hu //---------------------------------------------------------------- CubitStatus OCCSurface::update_OCC_entity(TopoDS_Face& old_surface, TopoDS_Shape& new_surface, BRepBuilderAPI_MakeShape *op, TopoDS_Vertex* removed_vertex, LocOpe_SplitShape* sp) { //set the Wires TopTools_IndexedMapOfShape M, M2; TopoDS_Shape shape, shape2, shape_edge, shape_vertex; TopExp::MapShapes(old_surface, TopAbs_WIRE, M); TopTools_ListOfShape shapes; BRepFilletAPI_MakeFillet2d* test_op = NULL; for (int ii=1; ii<=M.Extent(); ii++) { TopoDS_Wire wire = TopoDS::Wire(M(ii)); TopTools_ListOfShape shapes; if(op) { test_op = dynamic_cast<BRepFilletAPI_MakeFillet2d*>(op); if(!test_op) shapes.Assign(op->Modified(wire)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(wire)); if(!new_surface.IsNull()) TopExp::MapShapes(new_surface,TopAbs_WIRE, M2); } else if(sp) shapes.Assign(sp->DescendantShapes(wire)); if (shapes.Extent() == 1) { shape = shapes.First(); if(M2.Extent() == 1) { shape2 = TopoDS::Wire(M2(1)); if(!shape.IsSame(shape2)) shape = shape2; } else if(M2.Extent() > 1) shape.Nullify(); } else if(shapes.Extent() > 1) shape.Nullify(); else if(op->IsDeleted(wire) || shapes.Extent() == 0) { TopTools_IndexedMapOfShape M_new; TopExp::MapShapes(new_surface, TopAbs_WIRE, M_new); if (M_new.Extent()== 1) shape = M_new(1); else shape.Nullify(); } else { shape = wire; continue; } //set curves BRepTools_WireExplorer Ex; for(Ex.Init(wire); Ex.More();Ex.Next()) { TopoDS_Edge edge = Ex.Current(); if(op && !test_op) { shapes.Assign(op->Modified(edge)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(edge)); } else if(sp) shapes.Assign(sp->DescendantShapes(edge)); if (shapes.Extent() == 1) { //in fillet creating mothod, one edge could generated a face, so check //it here. TopAbs_ShapeEnum type = shapes.First().TShape()->ShapeType(); if(type != TopAbs_EDGE) shape_edge.Nullify(); else shape_edge = shapes.First(); } else if (shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape_edge = it.Value(); OCCQueryEngine::instance()->copy_attributes(edge, shape_edge); } shape_edge.Nullify(); } else if (op->IsDeleted(edge)) shape_edge.Nullify(); else if (test_op) { if(!test_op->IsModified(edge)) shape_edge = edge; else shape_edge = (test_op->Modified(edge)).First(); } else shape_edge = edge; //update vertex TopoDS_Vertex vertex = Ex.CurrentVertex(); shapes.Clear(); if(test_op) assert(removed_vertex != NULL); if(op && ! test_op ) shapes.Assign(op->Modified(vertex)); else if(sp) shapes.Assign(sp->DescendantShapes(vertex)); if (shapes.Extent() == 1) shape_vertex = shapes.First(); else if(shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape_vertex = it.Value(); OCCQueryEngine::instance()->copy_attributes(vertex, shape_vertex); } shape_vertex.Nullify() ; } else if(op->IsDeleted(vertex) || (test_op && vertex.IsSame( *removed_vertex))) shape_vertex.Nullify() ; else shape_vertex = vertex; if(!vertex.IsSame(shape_vertex) ) OCCQueryEngine::instance()->update_OCC_map(vertex, shape_vertex); if (!edge.IsSame(shape_edge)) OCCQueryEngine::instance()->update_OCC_map(edge, shape_edge); } if (!wire.IsSame(shape)) OCCQueryEngine::instance()->update_OCC_map(wire, shape); } double dTOL = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); if (!old_surface.IsSame(new_surface)) { TopAbs_ShapeEnum shapetype = TopAbs_SHAPE; if(!new_surface.IsNull()) shapetype = new_surface.TShape()->ShapeType(); if(shapetype == TopAbs_FACE || new_surface.IsNull()) OCCQueryEngine::instance()->update_OCC_map(old_surface, new_surface); else { TopTools_IndexedMapOfShape M; TopExp::MapShapes(new_surface, TopAbs_FACE, M); TopoDS_Shape new_shape; if(M.Extent() == 1) new_shape = M(1); else if(M.Extent() > 1) { for(int i = 1; i <= M.Extent(); i++) { GProp_GProps myProps; BRepGProp::SurfaceProperties(old_surface, myProps); double orig_mass = myProps.Mass(); gp_Pnt orig_pnt = myProps.CentreOfMass(); BRepGProp::SurfaceProperties(M(i), myProps); double after_mass = myProps.Mass(); gp_Pnt after_pnt = myProps.CentreOfMass(); if(fabs(-after_mass + orig_mass) <= dTOL && orig_pnt.IsEqual(after_pnt, dTOL)) { new_shape = M(i); break; } } } OCCQueryEngine::instance()->update_OCC_map(old_surface, new_shape); } } return CUBIT_SUCCESS; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_MeasureDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IMeasure aCI (aFunction); Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; if (aType == CDG_MEASURE) { Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Shape for centre of mass calculation is null"); } gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aShapeBase); gp_Pnt aCenterMass = aPos.Location(); aShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape(); } else if (aType == VERTEX_BY_INDEX) { Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Shape for centre of mass calculation is null"); } int index = aCI.GetIndex(); gp_Pnt aVertex; if (aShapeBase.ShapeType() == TopAbs_VERTEX) { if ( index != 1 ) Standard_NullObject::Raise("Vertex index is out of range"); else aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase)); } else if (aShapeBase.ShapeType() == TopAbs_EDGE) { TopoDS_Vertex aV1, aV2; TopoDS_Edge anEdgeE = TopoDS::Edge(aShapeBase); TopExp::Vertices(anEdgeE, aV1, aV2); gp_Pnt aP1 = BRep_Tool::Pnt(aV1); gp_Pnt aP2 = BRep_Tool::Pnt(aV2); if (index < 0 || index > 1) Standard_NullObject::Raise("Vertex index is out of range"); if ( ( anEdgeE.Orientation() == TopAbs_FORWARD && index == 0 ) || ( anEdgeE.Orientation() == TopAbs_REVERSED && index == 1 ) ) aVertex = aP1; else aVertex = aP2; } else if (aShapeBase.ShapeType() == TopAbs_WIRE) { TopTools_IndexedMapOfShape anEdgeShapes; TopTools_IndexedMapOfShape aVertexShapes; TopoDS_Vertex aV1, aV2; TopoDS_Wire aWire = TopoDS::Wire(aShapeBase); TopExp_Explorer exp (aWire, TopAbs_EDGE); for (; exp.More(); exp.Next()) { anEdgeShapes.Add(exp.Current()); TopoDS_Edge E = TopoDS::Edge(exp.Current()); TopExp::Vertices(E, aV1, aV2); if ( aVertexShapes.Extent() == 0) aVertexShapes.Add(aV1); if ( !aV1.IsSame( aVertexShapes(aVertexShapes.Extent()) ) ) aVertexShapes.Add(aV1); if ( !aV2.IsSame( aVertexShapes(aVertexShapes.Extent()) ) ) aVertexShapes.Add(aV2); } if (index < 0 || index > aVertexShapes.Extent()) Standard_NullObject::Raise("Vertex index is out of range"); if (aWire.Orientation() == TopAbs_FORWARD) aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(index+1))); else aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(aVertexShapes.Extent() - index))); } else { Standard_NullObject::Raise("Shape for vertex calculation is not an edge or wire"); } aShape = BRepBuilderAPI_MakeVertex(aVertex).Shape(); } else if (aType == VECTOR_FACE_NORMALE) { // Face Handle(GEOM_Function) aRefBase = aCI.GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { Standard_NullObject::Raise("Face for normale calculation is null"); } if (aShapeBase.ShapeType() != TopAbs_FACE) { Standard_NullObject::Raise("Shape for normale calculation is not a face"); } TopoDS_Face aFace = TopoDS::Face(aShapeBase); // Point gp_Pnt p1 (0,0,0); Handle(GEOM_Function) aPntFunc = aCI.GetPoint(); if (!aPntFunc.IsNull()) { TopoDS_Shape anOptPnt = aPntFunc->GetValue(); if (anOptPnt.IsNull()) Standard_NullObject::Raise("Invalid shape given for point argument"); p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt)); } else { gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aFace); p1 = aPos.Location(); } // Point parameters on surface Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf); gp_Pnt2d pUV = aSurfAna->ValueOfUV(p1, Precision::Confusion()); // Normal direction gp_Vec Vec1,Vec2; BRepAdaptor_Surface SF (aFace); SF.D1(pUV.X(), pUV.Y(), p1, Vec1, Vec2); if (Vec1.Magnitude() < Precision::Confusion()) { gp_Vec tmpV; gp_Pnt tmpP; SF.D1(pUV.X(), pUV.Y()-0.1, tmpP, Vec1, tmpV); } else if (Vec2.Magnitude() < Precision::Confusion()) { gp_Vec tmpV; gp_Pnt tmpP; SF.D1(pUV.X()-0.1, pUV.Y(), tmpP, tmpV, Vec2); } gp_Vec V = Vec1.Crossed(Vec2); Standard_Real mod = V.Magnitude(); if (mod < Precision::Confusion()) Standard_NullObject::Raise("Normal vector of a face has null magnitude"); // Set length of normal vector to average radius of curvature Standard_Real radius = 0.0; GeomLProp_SLProps aProperties (aSurf, pUV.X(), pUV.Y(), 2, Precision::Confusion()); if (aProperties.IsCurvatureDefined()) { Standard_Real radius1 = Abs(aProperties.MinCurvature()); Standard_Real radius2 = Abs(aProperties.MaxCurvature()); if (Abs(radius1) > Precision::Confusion()) { radius = 1.0 / radius1; if (Abs(radius2) > Precision::Confusion()) { radius = (radius + 1.0 / radius2) / 2.0; } } else { if (Abs(radius2) > Precision::Confusion()) { radius = 1.0 / radius2; } } } // Set length of normal vector to average dimension of the face // (only if average radius of curvature is not appropriate) if (radius < Precision::Confusion()) { Bnd_Box B; Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax; BRepBndLib::Add(aFace, B); B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); radius = ((Xmax - Xmin) + (Ymax - Ymin) + (Zmax - Zmin)) / 3.0; } if (radius < Precision::Confusion()) radius = 1.0; V *= radius / mod; // consider the face orientation if (aFace.Orientation() == TopAbs_REVERSED || aFace.Orientation() == TopAbs_INTERNAL) { V = - V; } // Edge gp_Pnt p2 = p1.Translated(V); BRepBuilderAPI_MakeEdge aBuilder (p1, p2); if (!aBuilder.IsDone()) Standard_NullObject::Raise("Vector construction failed"); aShape = aBuilder.Shape(); } else { } if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); log.SetTouched(Label()); return 1; }
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds(); Handle(Geom_Surface) face_surface; const bool is_face_surface = l->is(IfcSchema::Type::IfcFaceSurface); if (is_face_surface) { IfcSchema::IfcFaceSurface* fs = (IfcSchema::IfcFaceSurface*) l; fs->FaceSurface(); // FIXME: Surfaces are interpreted as a TopoDS_Shape TopoDS_Shape surface_shape; if (!convert_shape(fs->FaceSurface(), surface_shape)) return false; // FIXME: Assert this obtaines the only face TopExp_Explorer exp(surface_shape, TopAbs_FACE); if (!exp.More()) return false; TopoDS_Face surface = TopoDS::Face(exp.Current()); face_surface = BRep_Tool::Surface(surface); } const int num_bounds = bounds->size(); int num_outer_bounds = 0; for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { IfcSchema::IfcFaceBound* bound = *it; if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++; } // The number of outer bounds should be one according to the schema. Also Open Cascade // expects this, but it is not strictly checked. Regardless, if the number is greater, // the face will still be processed as long as there are no holes. A compound of faces // is returned in that case. if (num_bounds > 1 && num_outer_bounds > 1 && num_bounds != num_outer_bounds) { Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity); return false; } TopoDS_Compound compound; BRep_Builder builder; if (num_outer_bounds > 1) { builder.MakeCompound(compound); } // The builder is initialized on the heap because of the various different moments // of initialization depending on the configuration of surfaces and boundaries. BRepBuilderAPI_MakeFace* mf = 0; bool success = false; int processed = 0; for (int process_interior = 0; process_interior <= 1; ++process_interior) { for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) { IfcSchema::IfcFaceBound* bound = *it; IfcSchema::IfcLoop* loop = bound->Bound(); bool same_sense = bound->Orientation(); const bool is_interior = !bound->is(IfcSchema::Type::IfcFaceOuterBound) && (num_bounds > 1) && (num_outer_bounds < num_bounds); // The exterior face boundary is processed first if (is_interior == !process_interior) continue; TopoDS_Wire wire; if (!convert_wire(loop, wire)) { Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity); delete mf; return false; } /* The approach below does not result in a significant speed-up if (loop->is(IfcSchema::Type::IfcPolyLoop) && processed == 0 && face_surface.IsNull()) { IfcSchema::IfcPolyLoop* polyloop = (IfcSchema::IfcPolyLoop*) loop; IfcSchema::IfcCartesianPoint::list::ptr points = polyloop->Polygon(); if (points->size() == 3) { // Help Open Cascade by finding the plane more efficiently IfcSchema::IfcCartesianPoint::list::it point_iterator = points->begin(); gp_Pnt a, b, c; convert(*point_iterator++, a); convert(*point_iterator++, b); convert(*point_iterator++, c); const gp_XYZ ab = (b.XYZ() - a.XYZ()); const gp_XYZ ac = (c.XYZ() - a.XYZ()); const gp_Vec cross = ab.Crossed(ac); if (cross.SquareMagnitude() > ALMOST_ZERO) { const gp_Dir n = cross; face_surface = new Geom_Plane(a, n); } } } */ if (!same_sense) { wire.Reverse(); } bool flattened_wire = false; if (!mf) { process_wire: if (face_surface.IsNull()) { mf = new BRepBuilderAPI_MakeFace(wire); } else { /// @todo check necessity of false here mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false); } /* BRepBuilderAPI_FaceError er = mf->Error(); if (er == BRepBuilderAPI_NotPlanar) { ShapeFix_ShapeTolerance FTol; FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE); delete mf; mf = new BRepBuilderAPI_MakeFace(wire); } */ if (mf->IsDone()) { TopoDS_Face outer_face_bound = mf->Face(); // In case of (non-planar) face surface, p-curves need to be computed. // For planar faces, Open Cascade generates p-curves on the fly. if (!face_surface.IsNull()) { TopExp_Explorer exp(outer_face_bound, TopAbs_EDGE); for (; exp.More(); exp.Next()) { const TopoDS_Edge& edge = TopoDS::Edge(exp.Current()); ShapeFix_Edge fix_edge; fix_edge.FixAddPCurve(edge, outer_face_bound, false, getValue(GV_PRECISION)); } } if (BRepCheck_Face(outer_face_bound).OrientationOfWires() == BRepCheck_BadOrientationOfSubshape) { wire.Reverse(); same_sense = !same_sense; delete mf; if (face_surface.IsNull()) { mf = new BRepBuilderAPI_MakeFace(wire); } else { mf = new BRepBuilderAPI_MakeFace(face_surface, wire); } ShapeFix_Face fix(mf->Face()); fix.FixOrientation(); fix.Perform(); outer_face_bound = fix.Face(); } // If the wires are reversed the face needs to be reversed as well in order // to maintain the counter-clock-wise ordering of the bounding wire's vertices. bool all_reversed = true; TopoDS_Iterator jt(outer_face_bound, false); for (; jt.More(); jt.Next()) { const TopoDS_Wire& w = TopoDS::Wire(jt.Value()); if ((w.Orientation() != TopAbs_REVERSED) == same_sense) { all_reversed = false; } } if (all_reversed) { outer_face_bound.Reverse(); } if (num_outer_bounds > 1) { builder.Add(compound, outer_face_bound); delete mf; mf = 0; } else if (num_bounds > 1) { // Reinitialize the builder to the outer face // bound in order to add holes more robustly. delete mf; // TODO: What about the face_surface? mf = new BRepBuilderAPI_MakeFace(outer_face_bound); } else { face = outer_face_bound; success = true; } } else { const bool non_planar = mf->Error() == BRepBuilderAPI_NotPlanar; delete mf; if (!non_planar || flattened_wire || !flatten_wire(wire)) { Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary", bound->entity); return false; } else { Logger::Message(Logger::LOG_ERROR, "Flattening face boundary", bound->entity); flattened_wire = true; goto process_wire; } } } else { mf->Add(wire); } processed ++; } } if (!success) { success = processed == num_bounds; if (success) { if (num_outer_bounds > 1) { face = compound; } else { success = success && mf->IsDone(); if (success) { face = mf->Face(); } } } } if (success) { ShapeFix_ShapeTolerance FTol; FTol.SetTolerance(face, getValue(GV_PRECISION), TopAbs_FACE); } delete mf; return success; }