// Created on: 1995-07-18 // Created by: Joelle CHAUVET // Copyright (c) 1995-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // Modified: Mon Jan 12 10:50:10 1998 // gestion automatique de l'origine et de l'orientation // avec la methode ArrangeWires // Modified: Mon Jan 19 10:11:56 1998 // traitement des cas particuliers cylindre, cone, plan // (methodes DetectKPart et CreateKPart) // Modified: Mon Feb 23 09:28:46 1998 // traitement des sections avec nombre d'elements different // + quelques ameliorations pour les cas particuliers // + cas de la derniere section ponctuelle // Modified: Mon Apr 6 15:47:44 1998 // traitement des cas particuliers deplace dans BRepFill // Modified: Thu Apr 30 15:24:17 1998 // separation sections fermees / sections ouvertes + debug // Modified: Fri Jul 10 11:23:35 1998 // surface de CreateSmoothed par concatenation,approximation // et segmentation (PRO13924, CTS21295) // Modified: Tue Jul 21 16:48:35 1998 // pb de ratio (BUC60281) // Modified: Thu Jul 23 11:38:36 1998 // sections bouclantes // Modified: Fri Aug 28 10:13:44 1998 // traitement des sections ponctuelles // dans l'historique (cf. loft06 et loft09) // et dans le cas des solides // Modified: Tue Nov 3 10:06:15 1998 // utilisation de BRepFill_CompatibleWires #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 #include #include #include //======================================================================= //function : PreciseUpar //purpose : pins the u-parameter of surface close to U-knot // to this U-knot //======================================================================= static Standard_Real PreciseUpar(const Standard_Real anUpar, const Handle(Geom_BSplineSurface)& aSurface) { Standard_Real Tol = Precision::PConfusion(); Standard_Integer i1, i2; aSurface->LocateU(anUpar, Tol, i1, i2); Standard_Real U1 = aSurface->UKnot(i1); Standard_Real U2 = aSurface->UKnot(i2); Standard_Real NewU = anUpar; NewU = (anUpar - U1 < U2 - anUpar)? U1 : U2; return NewU; } //======================================================================= //function : PerformPlan //purpose : Construct a plane of filling if exists //======================================================================= static Standard_Boolean PerformPlan(const TopoDS_Wire& W, const Standard_Real presPln, TopoDS_Face& theFace) { Standard_Boolean isDegen = Standard_True; TopoDS_Iterator iter(W); for (; iter.More(); iter.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value()); if (!BRep_Tool::Degenerated(anEdge)) isDegen = Standard_False; } if (isDegen) return Standard_True; Standard_Boolean Ok = Standard_False; if (!W.IsNull()) { BRepBuilderAPI_FindPlane Searcher( W, presPln ); if (Searcher.Found()) { theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W); Ok = Standard_True; } else // try to find another surface { BRepBuilderAPI_MakeFace MF( W ); if (MF.IsDone()) { theFace = MF.Face(); Ok = Standard_True; } } } return Ok; } //============================================================================= //function : IsSameOriented //purpose : Checks whether aFace is oriented to the same side as aShell or not //============================================================================= static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace, const TopoDS_Shape& aShell) { TopExp_Explorer Explo(aFace, TopAbs_EDGE); TopoDS_Shape anEdge = Explo.Current(); TopAbs_Orientation Or1 = anEdge.Orientation(); TopTools_IndexedDataMapOfShapeListOfShape EFmap; TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap ); const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First(); TopoDS_Shape theEdge; for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next()) { theEdge = Explo.Current(); if (theEdge.IsSame(anEdge)) break; } TopAbs_Orientation Or2 = theEdge.Orientation(); if (Or1 == Or2) return Standard_False; return Standard_True; } //======================================================================= //function : MakeSolid //purpose : //======================================================================= static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1, const TopoDS_Wire& wire2, const Standard_Real presPln, TopoDS_Face& face1, TopoDS_Face& face2) { if (shell.IsNull()) throw StdFail_NotDone("Thrusections is not build"); Standard_Boolean B = shell.Closed(); BRep_Builder BB; if (!B) { // It is necessary to close the extremities B = PerformPlan(wire1, presPln, face1); if (B) { B = PerformPlan(wire2, presPln, face2); if (B) { if (!face1.IsNull() && !IsSameOriented( face1, shell )) face1.Reverse(); if (!face2.IsNull() && !IsSameOriented( face2, shell )) face2.Reverse(); if (!face1.IsNull()) BB.Add(shell, face1); if (!face2.IsNull()) BB.Add(shell, face2); shell.Closed(Standard_True); } } } TopoDS_Solid solid; BB.MakeSolid(solid); BB.Add(solid, shell); // verify the orientation the solid BRepClass3d_SolidClassifier clas3d(solid); clas3d.PerformInfinitePoint(Precision::Confusion()); if (clas3d.State() == TopAbs_IN) { BB.MakeSolid(solid); TopoDS_Shape aLocalShape = shell.Reversed(); BB.Add(solid, TopoDS::Shell(aLocalShape)); // B.Add(solid, TopoDS::Shell(newShell.Reversed())); } solid.Closed(Standard_True); return solid; } //======================================================================= //function : BRepOffsetAPI_ThruSections //purpose : //======================================================================= BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid, const Standard_Boolean ruled, const Standard_Real pres3d): myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d) { myWCheck = Standard_True; //---------------------------- myParamType = Approx_ChordLength; myDegMax = 8; myContinuity = GeomAbs_C2; myCritWeights[0] = .4; myCritWeights[1] = .2; myCritWeights[2] = .4; myUseSmoothing = Standard_False; } //======================================================================= //function : Init //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled, const Standard_Real pres3d) { myIsSolid = isSolid; myIsRuled = ruled; myPres3d = pres3d; myWCheck = Standard_True; //---------------------------- myParamType = Approx_ChordLength; myDegMax = 6; myContinuity = GeomAbs_C2; myCritWeights[0] = .4; myCritWeights[1] = .2; myCritWeights[2] = .4; myUseSmoothing = Standard_False; } //======================================================================= //function : AddWire //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::AddWire(const TopoDS_Wire& wire) { myWires.Append(wire); } //======================================================================= //function : AddVertex //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::AddVertex(const TopoDS_Vertex& aVertex) { BRep_Builder BB; TopoDS_Edge DegEdge; BB.MakeEdge( DegEdge ); BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) ); BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) ); BB.Degenerated( DegEdge, Standard_True ); TopoDS_Wire DegWire; BB.MakeWire( DegWire ); BB.Add( DegWire, DegEdge ); DegWire.Closed( Standard_True ); myWires.Append( DegWire ); } //======================================================================= //function : CheckCompatibility //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::CheckCompatibility(const Standard_Boolean check) { myWCheck = check; } //======================================================================= //function : Build //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::Build() { //Check set of section for right configuration of punctual sections Standard_Integer i; TopExp_Explorer explo; for (i = 2; i <= myWires.Length()-1; i++) { Standard_Boolean wdeg = Standard_True; for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current()); wdeg = wdeg && (BRep_Tool::Degenerated(anEdge)); } if (wdeg) throw Standard_Failure("Wrong usage of punctual sections"); } if (myWires.Length() <= 2) { Standard_Boolean wdeg = Standard_True; for (i = 1; i <= myWires.Length(); i++) for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current()); wdeg = wdeg && (BRep_Tool::Degenerated(anEdge)); } if (wdeg) throw Standard_Failure("Wrong usage of punctual sections"); } if (myWCheck) { // compute origin and orientation on wires to avoid twisted results // and update wires to have same number of edges // use BRepFill_CompatibleWires TopTools_SequenceOfShape WorkingSections; WorkingSections.Clear(); TopTools_DataMapOfShapeListOfShape WorkingMap; WorkingMap.Clear(); // Calculate the working sections BRepFill_CompatibleWires Georges(myWires); Georges.Perform(); if (Georges.IsDone()) { WorkingSections = Georges.Shape(); WorkingMap = Georges.Generated(); } myWires = WorkingSections; } try { // Calculate the resulting shape if (myWires.Length() == 2 || myIsRuled) { // create a ruled shell CreateRuled(); } else { // create a smoothed shell CreateSmoothed(); } } catch (Standard_Failure) { NotDone(); return; } // Encode the Regularities BRepLib::EncodeRegularity(myShape); } //======================================================================= //function : CreateRuled //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::CreateRuled() { Standard_Integer nbSects = myWires.Length(); BRepFill_Generator aGene; // for (Standard_Integer i=1; i<=nbSects; i++) { Standard_Integer i; for (i=1; i<=nbSects; i++) { aGene.AddWire(TopoDS::Wire(myWires(i))); } aGene.Perform(); TopoDS_Shell shell = aGene.Shell(); if (myIsSolid) { // check if the first wire is the same as the last Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ; if (vClosed) { TopoDS_Solid solid; BRep_Builder B; B.MakeSolid(solid); B.Add(solid, shell); // verify the orientation of the solid BRepClass3d_SolidClassifier clas3d(solid); clas3d.PerformInfinitePoint(Precision::Confusion()); if (clas3d.State() == TopAbs_IN) { B.MakeSolid(solid); TopoDS_Shape aLocalShape = shell.Reversed(); B.Add(solid, TopoDS::Shell(aLocalShape)); // B.Add(solid, TopoDS::Shell(shell.Reversed())); } myShape = solid; } else { TopoDS_Wire wire1 = TopoDS::Wire(myWires.First()); TopoDS_Wire wire2 = TopoDS::Wire(myWires.Last()); myShape = MakeSolid(shell, wire1, wire2, myPres3d, myFirst, myLast); } Done(); } else { myShape = shell; Done(); } // history BRepTools_WireExplorer anExp1, anExp2; TopTools_IndexedDataMapOfShapeListOfShape M; TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, TopAbs_FACE, M); TopTools_ListIteratorOfListOfShape it; TopTools_IndexedDataMapOfShapeListOfShape MV; TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV); for (i=1; i<=nbSects-1; i++) { const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i)); const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1)); anExp1.Init(wire1); anExp2.Init(wire2); Standard_Boolean tantque = anExp1.More() && anExp2.More(); while (tantque) { const TopoDS_Shape& edge1 = anExp1.Current(); const TopoDS_Shape& edge2 = anExp2.Current(); Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current()); Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current()); TopTools_MapOfShape MapFaces; if (degen2){ TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2)); for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) { MapFaces.Add(it.Value()); } } else { for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) { MapFaces.Add(it.Value()); } } if (degen1) { TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1)); for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) { const TopoDS_Shape& Face = it.Value(); if (MapFaces.Contains(Face)) { myGenerated.Bind(edge1, Face); break; } } } else { for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) { const TopoDS_Shape& Face = it.Value(); if (MapFaces.Contains(Face)) { myGenerated.Bind(edge1, Face); break; } } } if (!degen1) anExp1.Next(); if (!degen2) anExp2.Next(); tantque = anExp1.More() && anExp2.More(); if (degen1) tantque = anExp2.More(); if (degen2) tantque = anExp1.More(); } } } //======================================================================= //function : CreateSmoothed //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::CreateSmoothed() { // initialisation Standard_Integer nbSects = myWires.Length(); BRepTools_WireExplorer anExp; Standard_Boolean w1Point = Standard_True; // check if the first wire is punctual for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) { w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current())); } Standard_Boolean w2Point = Standard_True; // check if the last wire is punctual for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) { w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current())); } Standard_Boolean vClosed = Standard_False; // check if the first wire is the same as last if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True; // find the dimension Standard_Integer nbEdges=0; if (!w1Point) { for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) { nbEdges++; } } else { for(anExp.Init(TopoDS::Wire(myWires(2))); anExp.More(); anExp.Next()) { nbEdges++; } } // recover the shapes Standard_Boolean uClosed = Standard_True; TopTools_Array1OfShape shapes(1, nbSects*nbEdges); Standard_Integer nb=0, i, j; for (i=1; i<=nbSects; i++) { const TopoDS_Wire& wire = TopoDS::Wire(myWires(i)); if (!wire.Closed()) { // check if the vertices are the same TopoDS_Vertex V1, V2; TopExp::Vertices(wire,V1,V2); if ( !V1.IsSame(V2)) uClosed = Standard_False; } if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) { // if the wire is punctual anExp.Init(TopoDS::Wire(wire)); for(j=1; j<=nbEdges; j++) { nb++; shapes(nb) = anExp.Current(); } } else { // otherwise for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) { nb++; shapes(nb) = anExp.Current(); } } } // create the new surface TopoDS_Shell shell; TopoDS_Face face; TopoDS_Wire W; TopoDS_Edge edge, edge1, edge2, edge3, edge4, couture; TopTools_Array1OfShape vcouture(1, nbEdges); BRep_Builder B; B.MakeShell(shell); TopoDS_Wire newW1, newW2; BRep_Builder BW1, BW2; BW1.MakeWire(newW1); BW2.MakeWire(newW2); TopLoc_Location loc; TopoDS_Vertex v1f,v1l,v2f,v2l; Standard_Integer nbPnts = 21; TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects); // concatenate each section to get a total surface that will be segmented Handle(Geom_BSplineSurface) TS; TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed); if(TS.IsNull()) { return; } TopoDS_Shape firstEdge; for (i=1; i<=nbEdges; i++) { // segmentation of TS Handle(Geom_BSplineSurface) surface; surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy()); Standard_Real Ui1,Ui2,V0,V1; Ui1 = i-1; Ui2 = i; Ui1 = PreciseUpar(Ui1, surface); Ui2 = PreciseUpar(Ui2, surface); V0 = surface->VKnot(surface->FirstVKnotIndex()); V1 = surface->VKnot(surface->LastVKnotIndex()); surface->Segment(Ui1,Ui2,V0,V1); // return vertices edge = TopoDS::Edge(shapes(i)); TopExp::Vertices(edge,v1f,v1l); if (edge.Orientation() == TopAbs_REVERSED) TopExp::Vertices(edge,v1l,v1f); firstEdge = edge; edge = TopoDS::Edge(shapes((nbSects-1)*nbEdges+i)); TopExp::Vertices(edge,v2f,v2l); if (edge.Orientation() == TopAbs_REVERSED) TopExp::Vertices(edge,v2l,v2f); // make the face B.MakeFace(face, surface, Precision::Confusion()); // make the wire B.MakeWire(W); // make the missing edges Standard_Real f1, f2, l1, l2; surface->Bounds(f1,l1,f2,l2); // --- edge 1 if ( w1Point ) { // copy the degenerated edge TopoDS_Shape aLocalShape = shapes(1).EmptyCopied(); edge1 = TopoDS::Edge(aLocalShape); // edge1 = TopoDS::Edge(shapes(1).EmptyCopied()); edge1.Orientation(TopAbs_FORWARD); } else { B.MakeEdge(edge1, surface->VIso(f2), Precision::Confusion()); } v1f.Orientation(TopAbs_FORWARD); B.Add(edge1, v1f); v1l.Orientation(TopAbs_REVERSED); B.Add(edge1, v1l); B.Range(edge1, f1, l1); // processing of looping sections // store edges of the 1st section if (vClosed) vcouture(i) = edge1; // --- edge 2 if (vClosed) edge2 = TopoDS::Edge(vcouture(i)); else { if ( w2Point ) { // copy of the degenerated edge TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied(); edge2 = TopoDS::Edge(aLocalShape); // edge2 = TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied()); edge2.Orientation(TopAbs_FORWARD); } else { B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion()); } v2f.Orientation(TopAbs_FORWARD); B.Add(edge2, v2f); v2l.Orientation(TopAbs_REVERSED); B.Add(edge2, v2l); B.Range(edge2, f1, l1); } edge2.Reverse(); // --- edge 3 if (i==1) { B.MakeEdge(edge3, surface->UIso(f1), Precision::Confusion()); v1f.Orientation(TopAbs_FORWARD); B.Add(edge3, v1f); v2f.Orientation(TopAbs_REVERSED); B.Add(edge3, v2f); B.Range(edge3, f2, l2); if (uClosed) { couture = edge3; } } else { edge3 = edge4; } edge3.Reverse(); // --- edge 4 if ( uClosed && i==nbEdges) { edge4 = couture; } else { B.MakeEdge(edge4, surface->UIso(l1), Precision::Confusion()); v1l.Orientation(TopAbs_FORWARD); B.Add(edge4, v1l); v2l.Orientation(TopAbs_REVERSED); B.Add(edge4, v2l); B.Range(edge4, f2, l2); } B.Add(W,edge1); B.Add(W,edge4); B.Add(W,edge2); B.Add(W,edge3); // set PCurve if (vClosed) { B.UpdateEdge(edge1, new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)), new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face, Precision::Confusion()); B.Range(edge1,face,f1,l1); } else { B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face, Precision::Confusion()); B.Range(edge1,face,f1,l1); B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face, Precision::Confusion()); B.Range(edge2,face,f1,l1); } if ( uClosed && nbEdges ==1 ) { B.UpdateEdge(edge3, new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)), new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face, Precision::Confusion()); B.Range(edge3,face,f2,l2); } else { B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face, Precision::Confusion()); B.Range(edge3,face,f2,l2); B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face, Precision::Confusion()); B.Range(edge4,face,f2,l2); } B.Add(face,W); B.Add(shell, face); // complete newW1 newW2 TopoDS_Edge edge12 = edge1; TopoDS_Edge edge22 = edge2; edge12.Reverse(); edge22.Reverse(); BW1.Add(newW1, edge12); BW2.Add(newW2, edge22); // history myGenerated.Bind(firstEdge, face); } if (uClosed && w1Point && w2Point) shell.Closed(Standard_True); if (myIsSolid) { if (vClosed) { TopoDS_Solid solid; B.MakeSolid(solid); B.Add(solid, shell); // verify the orientation the solid BRepClass3d_SolidClassifier clas3d(solid); clas3d.PerformInfinitePoint(Precision::Confusion()); if (clas3d.State() == TopAbs_IN) { B.MakeSolid(solid); TopoDS_Shape aLocalShape = shell.Reversed(); B.Add(solid, TopoDS::Shell(aLocalShape)); // B.Add(solid, TopoDS::Shell(shell.Reversed())); } myShape = solid; } else { myShape = MakeSolid(shell, newW1, newW2, myPres3d, myFirst, myLast); } Done(); } else { myShape = shell; Done(); } TopExp_Explorer ex(myShape,TopAbs_EDGE); while (ex.More()) { const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current()); B.SameRange(CurE, Standard_False); B.SameParameter(CurE, Standard_False); Standard_Real tol = BRep_Tool::Tolerance(CurE); BRepLib::SameParameter(CurE,tol); ex.Next(); } } //======================================================================= //function : EdgeToBSpline //purpose : auxiliary -- get curve from edge and convert it to bspline // parameterized from 0 to 1 //======================================================================= // NOTE: this code duplicates the same function in BRepFill_NSections.cxx static Handle(Geom_BSplineCurve) EdgeToBSpline (const TopoDS_Edge& theEdge) { Handle(Geom_BSplineCurve) aBSCurve; if (BRep_Tool::Degenerated(theEdge)) { // degenerated edge : construction of a point curve TColStd_Array1OfReal aKnots (1,2); aKnots(1) = 0.; aKnots(2) = 1.; TColStd_Array1OfInteger aMults (1,2); aMults(1) = 2; aMults(2) = 2; TColgp_Array1OfPnt aPoles(1,2); TopoDS_Vertex vf, vl; TopExp::Vertices(theEdge,vl,vf); aPoles(1) = BRep_Tool::Pnt(vf); aPoles(2) = BRep_Tool::Pnt(vl); aBSCurve = new Geom_BSplineCurve (aPoles, aKnots, aMults, 1); } else { // get the curve of the edge TopLoc_Location aLoc; Standard_Real aFirst, aLast; Handle(Geom_Curve) aCurve = BRep_Tool::Curve (theEdge, aLoc, aFirst, aLast); if (aCurve.IsNull()) throw Standard_NullObject("Null 3D curve in edge"); // convert its part used by edge to bspline; note that if edge curve is bspline, // conversion made via trimmed curve is still needed -- it will copy it, segment // as appropriate, and remove periodicity if it is periodic (deadly for approximator) Handle(Geom_TrimmedCurve) aTrimCurve = new Geom_TrimmedCurve (aCurve, aFirst, aLast); // special treatment of conic curve if (aTrimCurve->BasisCurve()->IsKind(STANDARD_TYPE(Geom_Conic))) { const Handle(Geom_Curve)& aCurveTrimmed = aTrimCurve; // to avoid ambiguity GeomConvert_ApproxCurve anAppr (aCurveTrimmed, Precision::Confusion(), GeomAbs_C1, 16, 14); if (anAppr.HasResult()) aBSCurve = anAppr.Curve(); } // general case if (aBSCurve.IsNull()) aBSCurve = GeomConvert::CurveToBSplineCurve (aTrimCurve); // apply transformation if needed if (! aLoc.IsIdentity()) aBSCurve->Transform (aLoc.Transformation()); // reparameterize to [0,1] TColStd_Array1OfReal aKnots (1, aBSCurve->NbKnots()); aBSCurve->Knots (aKnots); BSplCLib::Reparametrize (0., 1., aKnots); aBSCurve->SetKnots (aKnots); } // reverse curve if edge is reversed if (theEdge.Orientation() == TopAbs_REVERSED) aBSCurve->Reverse(); return aBSCurve; } //======================================================================= //function : TotalSurf //purpose : //======================================================================= Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections:: TotalSurf(const TopTools_Array1OfShape& shapes, const Standard_Integer NbSects, const Standard_Integer NbEdges, const Standard_Boolean w1Point, const Standard_Boolean w2Point, const Standard_Boolean vClosed) const { Standard_Integer i,j,jdeb=1,jfin=NbSects; TopoDS_Vertex vf,vl; GeomFill_SectionGenerator section; Handle(Geom_BSplineSurface) surface; Handle(Geom_BSplineCurve) BS, BS1; Handle(Geom_TrimmedCurve) curvTrim; if (w1Point) { jdeb++; TopoDS_Edge edge = TopoDS::Edge(shapes(1)); TopExp::Vertices(edge,vl,vf); TColgp_Array1OfPnt Extremities(1,2); Extremities(1) = BRep_Tool::Pnt(vf); Extremities(2) = BRep_Tool::Pnt(vl); TColStd_Array1OfReal Bounds(1,2); Bounds(1) = 0.; Bounds(2) = 1.; TColStd_Array1OfInteger Mult(1,2); Mult(1) = 2; Mult(2) = 2; Handle(Geom_BSplineCurve) BSPoint = new Geom_BSplineCurve(Extremities,Bounds,Mult,1); section.AddCurve(BSPoint); } if (w2Point) { jfin--; } for (j=jdeb; j<=jfin; j++) { // case of looping sections if (j==jfin && vClosed) { section.AddCurve(BS1); } else { // read the first edge to initialise CompBS; TopoDS_Edge aPrevEdge = TopoDS::Edge (shapes((j-1)*NbEdges+1)); Handle(Geom_BSplineCurve) curvBS = EdgeToBSpline (aPrevEdge); // initialization GeomConvert_CompCurveToBSplineCurve CompBS(curvBS); for (i=2; i<=NbEdges; i++) { // read the edge TopoDS_Edge aNextEdge = TopoDS::Edge (shapes((j-1)*NbEdges+i)); Standard_Real aTolV = Precision::Confusion(); TopExp::Vertices(aNextEdge,vf,vl); aTolV = Max(aTolV, BRep_Tool::Tolerance(vf)); aTolV = Max(aTolV, BRep_Tool::Tolerance(vl)); aTolV = Min(aTolV, 1.e-3); curvBS = EdgeToBSpline (aNextEdge); // concatenation CompBS.Add(curvBS, aTolV, Standard_True, Standard_False, 1); } // return the final section BS = CompBS.BSplineCurve(); section.AddCurve(BS); // case of looping sections if (j==jdeb && vClosed) { BS1 = BS; } } } if (w2Point) { TopoDS_Edge edge = TopoDS::Edge(shapes(NbSects*NbEdges)); TopExp::Vertices(edge,vl,vf); TColgp_Array1OfPnt Extremities(1,2); Extremities(1) = BRep_Tool::Pnt(vf); Extremities(2) = BRep_Tool::Pnt(vl); TColStd_Array1OfReal Bounds(1,2); Bounds(1) = 0.; Bounds(2) = 1.; TColStd_Array1OfInteger Mult(1,2); Mult(1) = 2; Mult(2) = 2; Handle(Geom_BSplineCurve) BSPoint = new Geom_BSplineCurve(Extremities,Bounds,Mult,1); section.AddCurve(BSPoint); } section.Perform(Precision::PConfusion()); Handle(GeomFill_Line) line = new GeomFill_Line(NbSects); Standard_Integer nbIt = 3; if(myPres3d <= 1.e-3) nbIt = 0; Standard_Integer degmin = 2, degmax = Max(myDegMax, degmin); Standard_Boolean SpApprox = Standard_True; GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt); anApprox.SetContinuity(myContinuity); if(myUseSmoothing) { anApprox.SetCriteriumWeight(myCritWeights[0], myCritWeights[1], myCritWeights[2]); anApprox.PerformSmoothing(line, section); } else { anApprox.SetParType(myParamType); anApprox.Perform(line, section, SpApprox); } if(anApprox.IsDone()) { surface = new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(), anApprox.SurfUKnots(), anApprox.SurfVKnots(), anApprox.SurfUMults(), anApprox.SurfVMults(), anApprox.UDegree(), anApprox.VDegree()); } return surface; } //======================================================================= //function : FirstShape //purpose : //======================================================================= const TopoDS_Shape& BRepOffsetAPI_ThruSections::FirstShape() const { return myFirst; } //======================================================================= //function : LastShape //purpose : //======================================================================= const TopoDS_Shape& BRepOffsetAPI_ThruSections::LastShape() const { return myLast; } //======================================================================= //function : GeneratedFace //purpose : //======================================================================= TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge) const { TopoDS_Shape bid; if (myGenerated.IsBound(edge)) { return myGenerated(edge); } else { return bid; } } //======================================================================= //function : CriteriumWeight //purpose : returns the Weights associated to the criterium used in // the optimization. //======================================================================= // void BRepOffsetAPI_ThruSections::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const { W1 = myCritWeights[0]; W2 = myCritWeights[1]; W3 = myCritWeights[2]; } //======================================================================= //function : SetCriteriumWeight //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3) { if (W1 < 0 || W2 < 0 || W3 < 0 ) throw Standard_DomainError(); myCritWeights[0] = W1; myCritWeights[1] = W2; myCritWeights[2] = W3; } //======================================================================= //function : SetContinuity //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::SetContinuity (const GeomAbs_Shape TheCont) { myContinuity = TheCont; } //======================================================================= //function : Continuity //purpose : //======================================================================= GeomAbs_Shape BRepOffsetAPI_ThruSections::Continuity () const { return myContinuity; } //======================================================================= //function : SetParType //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::SetParType (const Approx_ParametrizationType ParType) { myParamType = ParType; } //======================================================================= //function : ParType //purpose : //======================================================================= Approx_ParametrizationType BRepOffsetAPI_ThruSections::ParType () const { return myParamType; } //======================================================================= //function : SetMaxDegree //purpose : //======================================================================= void BRepOffsetAPI_ThruSections:: SetMaxDegree(const Standard_Integer MaxDeg) { myDegMax = MaxDeg; } //======================================================================= //function : MaxDegree //purpose : //======================================================================= Standard_Integer BRepOffsetAPI_ThruSections::MaxDegree () const { return myDegMax; } //======================================================================= //function : SetSmoothing //purpose : //======================================================================= void BRepOffsetAPI_ThruSections::SetSmoothing(const Standard_Boolean UseVar) { myUseSmoothing = UseVar; } //======================================================================= //function : UseSmoothing //purpose : //======================================================================= Standard_Boolean BRepOffsetAPI_ThruSections::UseSmoothing () const { return myUseSmoothing; }