1 // Created on: 1995-07-18
2 // Created by: Joelle CHAUVET
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified: Mon Jan 12 10:50:10 1998
18 // gestion automatique de l'origine et de l'orientation
19 // avec la methode ArrangeWires
20 // Modified: Mon Jan 19 10:11:56 1998
21 // traitement des cas particuliers cylindre, cone, plan
22 // (methodes DetectKPart et CreateKPart)
23 // Modified: Mon Feb 23 09:28:46 1998
24 // traitement des sections avec nombre d'elements different
25 // + quelques ameliorations pour les cas particuliers
26 // + cas de la derniere section ponctuelle
27 // Modified: Mon Apr 6 15:47:44 1998
28 // traitement des cas particuliers deplace dans BRepFill
29 // Modified: Thu Apr 30 15:24:17 1998
30 // separation sections fermees / sections ouvertes + debug
31 // Modified: Fri Jul 10 11:23:35 1998
32 // surface de CreateSmoothed par concatenation,approximation
33 // et segmentation (PRO13924, CTS21295)
34 // Modified: Tue Jul 21 16:48:35 1998
35 // pb de ratio (BUC60281)
36 // Modified: Thu Jul 23 11:38:36 1998
37 // sections bouclantes
38 // Modified: Fri Aug 28 10:13:44 1998
39 // traitement des sections ponctuelles
40 // dans l'historique (cf. loft06 et loft09)
41 // et dans le cas des solides
42 // Modified: Tue Nov 3 10:06:15 1998
43 // utilisation de BRepFill_CompatibleWires
45 #include <BRep_Builder.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepBuilderAPI_FindPlane.hxx>
48 #include <BRepBuilderAPI_MakeFace.hxx>
49 #include <BRepClass3d_SolidClassifier.hxx>
50 #include <BRepFill_CompatibleWires.hxx>
51 #include <BRepFill_Generator.hxx>
52 #include <BRepLib.hxx>
53 #include <BRepOffsetAPI_ThruSections.hxx>
54 #include <BRepTools_WireExplorer.hxx>
55 #include <BSplCLib.hxx>
56 #include <Geom2d_Line.hxx>
57 #include <Geom_BezierCurve.hxx>
58 #include <Geom_BSplineCurve.hxx>
59 #include <Geom_BSplineSurface.hxx>
60 #include <Geom_Conic.hxx>
61 #include <Geom_Curve.hxx>
62 #include <Geom_Plane.hxx>
63 #include <Geom_TrimmedCurve.hxx>
64 #include <GeomAbs_Shape.hxx>
65 #include <GeomConvert.hxx>
66 #include <GeomConvert_ApproxCurve.hxx>
67 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
68 #include <GeomFill_AppSurf.hxx>
69 #include <GeomFill_Line.hxx>
70 #include <GeomFill_SectionGenerator.hxx>
71 #include <gp_Dir2d.hxx>
73 #include <gp_Pnt2d.hxx>
74 #include <Precision.hxx>
75 #include <Standard_DomainError.hxx>
76 #include <Standard_NullObject.hxx>
77 #include <TColgp_Array1OfPnt.hxx>
80 #include <TopLoc_Location.hxx>
82 #include <TopoDS_Edge.hxx>
83 #include <TopoDS_Face.hxx>
84 #include <TopoDS_Iterator.hxx>
85 #include <TopoDS_Shape.hxx>
86 #include <TopoDS_Solid.hxx>
87 #include <TopoDS_Vertex.hxx>
88 #include <TopoDS_Wire.hxx>
89 #include <TopTools_Array1OfShape.hxx>
90 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
91 #include <TopTools_ListIteratorOfListOfShape.hxx>
93 //=======================================================================
94 //function : PreciseUpar
95 //purpose : pins the u-parameter of surface close to U-knot
97 //=======================================================================
98 static Standard_Real PreciseUpar(const Standard_Real anUpar,
99 const Handle(Geom_BSplineSurface)& aSurface)
101 Standard_Real Tol = Precision::PConfusion();
102 Standard_Integer i1, i2;
104 aSurface->LocateU(anUpar, Tol, i1, i2);
105 Standard_Real U1 = aSurface->UKnot(i1);
106 Standard_Real U2 = aSurface->UKnot(i2);
108 Standard_Real NewU = anUpar;
110 NewU = (anUpar - U1 < U2 - anUpar)? U1 : U2;
114 //=======================================================================
115 //function : PerformPlan
116 //purpose : Construct a plane of filling if exists
117 //=======================================================================
119 static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
120 const Standard_Real presPln,
121 TopoDS_Face& theFace)
123 Standard_Boolean isDegen = Standard_True;
124 TopoDS_Iterator iter(W);
125 for (; iter.More(); iter.Next())
127 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
128 if (!BRep_Tool::Degenerated(anEdge))
129 isDegen = Standard_False;
132 return Standard_True;
134 Standard_Boolean Ok = Standard_False;
136 BRepBuilderAPI_FindPlane Searcher( W, presPln );
137 if (Searcher.Found())
139 theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
142 else // try to find another surface
144 BRepBuilderAPI_MakeFace MF( W );
156 //=============================================================================
157 //function : IsSameOriented
158 //purpose : Checks whether aFace is oriented to the same side as aShell or not
159 //=============================================================================
161 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
162 const TopoDS_Shape& aShell)
164 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
165 TopoDS_Shape anEdge = Explo.Current();
166 TopAbs_Orientation Or1 = anEdge.Orientation();
168 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
169 TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
171 const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
172 TopoDS_Shape theEdge;
173 for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
175 theEdge = Explo.Current();
176 if (theEdge.IsSame(anEdge))
180 TopAbs_Orientation Or2 = theEdge.Orientation();
182 return Standard_False;
183 return Standard_True;
186 //=======================================================================
187 //function : MakeSolid
189 //=======================================================================
191 static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
192 const TopoDS_Wire& wire2, const Standard_Real presPln,
193 TopoDS_Face& face1, TopoDS_Face& face2)
196 StdFail_NotDone::Raise("Thrusections is not build");
197 Standard_Boolean B = shell.Closed();
202 // It is necessary to close the extremities
203 B = PerformPlan(wire1, presPln, face1);
205 B = PerformPlan(wire2, presPln, face2);
207 if (!face1.IsNull() && !IsSameOriented( face1, shell ))
209 if (!face2.IsNull() && !IsSameOriented( face2, shell ))
213 BB.Add(shell, face1);
215 BB.Add(shell, face2);
217 shell.Closed(Standard_True);
224 BB.Add(solid, shell);
226 // verify the orientation the solid
227 BRepClass3d_SolidClassifier clas3d(solid);
228 clas3d.PerformInfinitePoint(Precision::Confusion());
229 if (clas3d.State() == TopAbs_IN) {
231 TopoDS_Shape aLocalShape = shell.Reversed();
232 BB.Add(solid, TopoDS::Shell(aLocalShape));
233 // B.Add(solid, TopoDS::Shell(newShell.Reversed()));
236 solid.Closed(Standard_True);
241 //=======================================================================
242 //function : BRepOffsetAPI_ThruSections
244 //=======================================================================
246 BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid, const Standard_Boolean ruled,
247 const Standard_Real pres3d):
248 myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d)
250 myWCheck = Standard_True;
251 //----------------------------
252 myParamType = Approx_ChordLength;
254 myContinuity = GeomAbs_C2;
255 myCritWeights[0] = .4;
256 myCritWeights[1] = .2;
257 myCritWeights[2] = .4;
258 myUseSmoothing = Standard_False;
262 //=======================================================================
265 //=======================================================================
267 void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
268 const Standard_Real pres3d)
273 myWCheck = Standard_True;
274 //----------------------------
275 myParamType = Approx_ChordLength;
277 myContinuity = GeomAbs_C2;
278 myCritWeights[0] = .4;
279 myCritWeights[1] = .2;
280 myCritWeights[2] = .4;
281 myUseSmoothing = Standard_False;
286 //=======================================================================
289 //=======================================================================
291 void BRepOffsetAPI_ThruSections::AddWire(const TopoDS_Wire& wire)
293 myWires.Append(wire);
296 //=======================================================================
297 //function : AddVertex
299 //=======================================================================
301 void BRepOffsetAPI_ThruSections::AddVertex(const TopoDS_Vertex& aVertex)
306 BB.MakeEdge( DegEdge );
307 BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) );
308 BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) );
309 BB.Degenerated( DegEdge, Standard_True );
312 BB.MakeWire( DegWire );
313 BB.Add( DegWire, DegEdge );
314 DegWire.Closed( Standard_True );
316 myWires.Append( DegWire );
319 //=======================================================================
320 //function : CheckCompatibility
322 //=======================================================================
324 void BRepOffsetAPI_ThruSections::CheckCompatibility(const Standard_Boolean check)
330 //=======================================================================
333 //=======================================================================
335 void BRepOffsetAPI_ThruSections::Build()
337 //Check set of section for right configuration of punctual sections
339 TopExp_Explorer explo;
340 for (i = 2; i <= myWires.Length()-1; i++)
342 Standard_Boolean wdeg = Standard_True;
343 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
345 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
346 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
349 Standard_Failure::Raise("Wrong usage of punctual sections");
351 if (myWires.Length() <= 2)
353 Standard_Boolean wdeg = Standard_True;
354 for (i = 1; i <= myWires.Length(); i++)
355 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
357 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
358 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
361 Standard_Failure::Raise("Wrong usage of punctual sections");
365 // compute origin and orientation on wires to avoid twisted results
366 // and update wires to have same number of edges
368 // use BRepFill_CompatibleWires
369 TopTools_SequenceOfShape WorkingSections;
370 WorkingSections.Clear();
371 TopTools_DataMapOfShapeListOfShape WorkingMap;
374 // Calculate the working sections
375 BRepFill_CompatibleWires Georges(myWires);
377 if (Georges.IsDone()) {
378 WorkingSections = Georges.Shape();
379 WorkingMap = Georges.Generated();
381 myWires = WorkingSections;
385 // Calculate the resulting shape
386 if (myWires.Length() == 2 || myIsRuled) {
387 // create a ruled shell
391 // create a smoothed shell
395 catch (Standard_Failure)
400 // Encode the Regularities
401 BRepLib::EncodeRegularity(myShape);
405 //=======================================================================
406 //function : CreateRuled
408 //=======================================================================
410 void BRepOffsetAPI_ThruSections::CreateRuled()
412 Standard_Integer nbSects = myWires.Length();
413 BRepFill_Generator aGene;
414 // for (Standard_Integer i=1; i<=nbSects; i++) {
416 for (i=1; i<=nbSects; i++) {
417 aGene.AddWire(TopoDS::Wire(myWires(i)));
420 TopoDS_Shell shell = aGene.Shell();
424 // check if the first wire is the same as the last
425 Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ;
434 // verify the orientation of the solid
435 BRepClass3d_SolidClassifier clas3d(solid);
436 clas3d.PerformInfinitePoint(Precision::Confusion());
437 if (clas3d.State() == TopAbs_IN) {
439 TopoDS_Shape aLocalShape = shell.Reversed();
440 B.Add(solid, TopoDS::Shell(aLocalShape));
441 // B.Add(solid, TopoDS::Shell(shell.Reversed()));
449 TopoDS_Wire wire1 = TopoDS::Wire(myWires.First());
450 TopoDS_Wire wire2 = TopoDS::Wire(myWires.Last());
451 myShape = MakeSolid(shell, wire1, wire2, myPres3d, myFirst, myLast);
464 BRepTools_WireExplorer anExp1, anExp2;
465 TopTools_IndexedDataMapOfShapeListOfShape M;
466 TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, TopAbs_FACE, M);
467 TopTools_ListIteratorOfListOfShape it;
469 TopTools_IndexedDataMapOfShapeListOfShape MV;
470 TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
472 for (i=1; i<=nbSects-1; i++) {
474 const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
475 const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
480 Standard_Boolean tantque = anExp1.More() && anExp2.More();
484 const TopoDS_Shape& edge1 = anExp1.Current();
485 const TopoDS_Shape& edge2 = anExp2.Current();
486 Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
487 Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
489 TopTools_MapOfShape MapFaces;
491 TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
492 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
493 MapFaces.Add(it.Value());
497 for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
498 MapFaces.Add(it.Value());
503 TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
504 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
505 const TopoDS_Shape& Face = it.Value();
506 if (MapFaces.Contains(Face)) {
507 myGenerated.Bind(edge1, Face);
513 for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
514 const TopoDS_Shape& Face = it.Value();
515 if (MapFaces.Contains(Face)) {
516 myGenerated.Bind(edge1, Face);
522 if (!degen1) anExp1.Next();
523 if (!degen2) anExp2.Next();
525 tantque = anExp1.More() && anExp2.More();
526 if (degen1) tantque = anExp2.More();
527 if (degen2) tantque = anExp1.More();
535 //=======================================================================
536 //function : CreateSmoothed
538 //=======================================================================
540 void BRepOffsetAPI_ThruSections::CreateSmoothed()
543 Standard_Integer nbSects = myWires.Length();
544 BRepTools_WireExplorer anExp;
546 Standard_Boolean w1Point = Standard_True;
547 // check if the first wire is punctual
548 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
549 w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current()));
552 Standard_Boolean w2Point = Standard_True;
553 // check if the last wire is punctual
554 for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) {
555 w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current()));
558 Standard_Boolean vClosed = Standard_False;
559 // check if the first wire is the same as last
560 if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True;
562 // find the dimension
563 Standard_Integer nbEdges=0;
565 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
570 for(anExp.Init(TopoDS::Wire(myWires(2))); anExp.More(); anExp.Next()) {
575 // recover the shapes
576 Standard_Boolean uClosed = Standard_True;
577 TopTools_Array1OfShape shapes(1, nbSects*nbEdges);
578 Standard_Integer nb=0, i, j;
580 for (i=1; i<=nbSects; i++) {
581 const TopoDS_Wire& wire = TopoDS::Wire(myWires(i));
582 if (!wire.Closed()) {
583 // check if the vertices are the same
584 TopoDS_Vertex V1, V2;
585 TopExp::Vertices(wire,V1,V2);
586 if ( !V1.IsSame(V2)) uClosed = Standard_False;
588 if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) {
589 // if the wire is punctual
590 anExp.Init(TopoDS::Wire(wire));
591 for(j=1; j<=nbEdges; j++) {
593 shapes(nb) = anExp.Current();
598 for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
600 shapes(nb) = anExp.Current();
605 // create the new surface
609 TopoDS_Edge edge, edge1, edge2, edge3, edge4, couture;
610 TopTools_Array1OfShape vcouture(1, nbEdges);
615 TopoDS_Wire newW1, newW2;
616 BRep_Builder BW1, BW2;
621 TopoDS_Vertex v1f,v1l,v2f,v2l;
623 Standard_Integer nbPnts = 21;
624 TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
626 // concatenate each section to get a total surface that will be segmented
627 Handle(Geom_BSplineSurface) TS;
628 TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed);
634 TopoDS_Shape firstEdge;
635 for (i=1; i<=nbEdges; i++) {
637 // segmentation of TS
638 Handle(Geom_BSplineSurface) surface;
639 surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy());
640 Standard_Real Ui1,Ui2,V0,V1;
643 Ui1 = PreciseUpar(Ui1, surface);
644 Ui2 = PreciseUpar(Ui2, surface);
645 V0 = surface->VKnot(surface->FirstVKnotIndex());
646 V1 = surface->VKnot(surface->LastVKnotIndex());
647 surface->Segment(Ui1,Ui2,V0,V1);
650 edge = TopoDS::Edge(shapes(i));
651 TopExp::Vertices(edge,v1f,v1l);
652 if (edge.Orientation() == TopAbs_REVERSED)
653 TopExp::Vertices(edge,v1l,v1f);
656 edge = TopoDS::Edge(shapes((nbSects-1)*nbEdges+i));
657 TopExp::Vertices(edge,v2f,v2l);
658 if (edge.Orientation() == TopAbs_REVERSED)
659 TopExp::Vertices(edge,v2l,v2f);
662 B.MakeFace(face, surface, Precision::Confusion());
667 // make the missing edges
668 Standard_Real f1, f2, l1, l2;
669 surface->Bounds(f1,l1,f2,l2);
673 // copy the degenerated edge
674 TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
675 edge1 = TopoDS::Edge(aLocalShape);
676 // edge1 = TopoDS::Edge(shapes(1).EmptyCopied());
677 edge1.Orientation(TopAbs_FORWARD);
680 B.MakeEdge(edge1, surface->VIso(f2), Precision::Confusion());
682 v1f.Orientation(TopAbs_FORWARD);
684 v1l.Orientation(TopAbs_REVERSED);
686 B.Range(edge1, f1, l1);
687 // processing of looping sections
688 // store edges of the 1st section
695 edge2 = TopoDS::Edge(vcouture(i));
698 // copy of the degenerated edge
699 TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
700 edge2 = TopoDS::Edge(aLocalShape);
701 // edge2 = TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
702 edge2.Orientation(TopAbs_FORWARD);
705 B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
707 v2f.Orientation(TopAbs_FORWARD);
709 v2l.Orientation(TopAbs_REVERSED);
711 B.Range(edge2, f1, l1);
718 B.MakeEdge(edge3, surface->UIso(f1), Precision::Confusion());
719 v1f.Orientation(TopAbs_FORWARD);
721 v2f.Orientation(TopAbs_REVERSED);
723 B.Range(edge3, f2, l2);
734 if ( uClosed && i==nbEdges) {
738 B.MakeEdge(edge4, surface->UIso(l1), Precision::Confusion());
739 v1l.Orientation(TopAbs_FORWARD);
741 v2l.Orientation(TopAbs_REVERSED);
743 B.Range(edge4, f2, l2);
754 new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
755 new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
756 Precision::Confusion());
757 B.Range(edge1,face,f1,l1);
760 B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
761 Precision::Confusion());
762 B.Range(edge1,face,f1,l1);
763 B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
764 Precision::Confusion());
765 B.Range(edge2,face,f1,l1);
768 if ( uClosed && nbEdges ==1 ) {
770 new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
771 new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
772 Precision::Confusion());
773 B.Range(edge3,face,f2,l2);
777 B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
778 Precision::Confusion());
779 B.Range(edge3,face,f2,l2);
780 B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
781 Precision::Confusion());
782 B.Range(edge4,face,f2,l2);
787 // complete newW1 newW2
788 TopoDS_Edge edge12 = edge1;
789 TopoDS_Edge edge22 = edge2;
792 BW1.Add(newW1, edge12);
793 BW2.Add(newW2, edge22);
796 myGenerated.Bind(firstEdge, face);
799 if (uClosed && w1Point && w2Point)
800 shell.Closed(Standard_True);
810 // verify the orientation the solid
811 BRepClass3d_SolidClassifier clas3d(solid);
812 clas3d.PerformInfinitePoint(Precision::Confusion());
813 if (clas3d.State() == TopAbs_IN) {
815 TopoDS_Shape aLocalShape = shell.Reversed();
816 B.Add(solid, TopoDS::Shell(aLocalShape));
817 // B.Add(solid, TopoDS::Shell(shell.Reversed()));
824 myShape = MakeSolid(shell, newW1, newW2, myPres3d, myFirst, myLast);
835 TopExp_Explorer ex(myShape,TopAbs_EDGE);
837 const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
838 B.SameRange(CurE, Standard_False);
839 B.SameParameter(CurE, Standard_False);
840 Standard_Real tol = BRep_Tool::Tolerance(CurE);
841 BRepLib::SameParameter(CurE,tol);
846 //=======================================================================
847 //function : EdgeToBSpline
848 //purpose : auxiliary -- get curve from edge and convert it to bspline
849 // parameterized from 0 to 1
850 //=======================================================================
852 // NOTE: this code duplicates the same function in BRepFill_NSections.cxx
853 static Handle(Geom_BSplineCurve) EdgeToBSpline (const TopoDS_Edge& theEdge)
855 Handle(Geom_BSplineCurve) aBSCurve;
856 if (BRep_Tool::Degenerated(theEdge)) {
857 // degenerated edge : construction of a point curve
858 TColStd_Array1OfReal aKnots (1,2);
862 TColStd_Array1OfInteger aMults (1,2);
866 TColgp_Array1OfPnt aPoles(1,2);
867 TopoDS_Vertex vf, vl;
868 TopExp::Vertices(theEdge,vl,vf);
869 aPoles(1) = BRep_Tool::Pnt(vf);
870 aPoles(2) = BRep_Tool::Pnt(vl);
872 aBSCurve = new Geom_BSplineCurve (aPoles, aKnots, aMults, 1);
876 // get the curve of the edge
877 TopLoc_Location aLoc;
878 Standard_Real aFirst, aLast;
879 Handle(Geom_Curve) aCurve = BRep_Tool::Curve (theEdge, aLoc, aFirst, aLast);
881 Standard_NullObject::Raise("Null 3D curve in edge");
883 // convert its part used by edge to bspline; note that if edge curve is bspline,
884 // conversion made via trimmed curve is still needed -- it will copy it, segment
885 // as appropriate, and remove periodicity if it is periodic (deadly for approximator)
886 Handle(Geom_TrimmedCurve) aTrimCurve = new Geom_TrimmedCurve (aCurve, aFirst, aLast);
888 // special treatment of conic curve
889 if (aTrimCurve->BasisCurve()->IsKind(STANDARD_TYPE(Geom_Conic)))
891 const Handle(Geom_Curve)& aCurveTrimmed = aTrimCurve; // to avoid ambiguity
892 GeomConvert_ApproxCurve anAppr (aCurveTrimmed, Precision::Confusion(), GeomAbs_C1, 16, 14);
893 if (anAppr.HasResult())
894 aBSCurve = anAppr.Curve();
898 if (aBSCurve.IsNull())
899 aBSCurve = GeomConvert::CurveToBSplineCurve (aTrimCurve);
901 // apply transformation if needed
902 if (! aLoc.IsIdentity())
903 aBSCurve->Transform (aLoc.Transformation());
905 // reparameterize to [0,1]
906 TColStd_Array1OfReal aKnots (1, aBSCurve->NbKnots());
907 aBSCurve->Knots (aKnots);
908 BSplCLib::Reparametrize (0., 1., aKnots);
909 aBSCurve->SetKnots (aKnots);
912 // reverse curve if edge is reversed
913 if (theEdge.Orientation() == TopAbs_REVERSED)
919 //=======================================================================
920 //function : TotalSurf
922 //=======================================================================
924 Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
925 TotalSurf(const TopTools_Array1OfShape& shapes,
926 const Standard_Integer NbSects,
927 const Standard_Integer NbEdges,
928 const Standard_Boolean w1Point,
929 const Standard_Boolean w2Point,
930 const Standard_Boolean vClosed) const
932 Standard_Integer i,j,jdeb=1,jfin=NbSects;
935 GeomFill_SectionGenerator section;
936 Handle(Geom_BSplineSurface) surface;
937 Handle(Geom_BSplineCurve) BS, BS1;
938 Handle(Geom_TrimmedCurve) curvTrim;
942 TopoDS_Edge edge = TopoDS::Edge(shapes(1));
943 TopExp::Vertices(edge,vl,vf);
944 TColgp_Array1OfPnt Extremities(1,2);
945 Extremities(1) = BRep_Tool::Pnt(vf);
946 Extremities(2) = BRep_Tool::Pnt(vl);
947 TColStd_Array1OfReal Bounds(1,2);
950 TColStd_Array1OfInteger Mult(1,2);
953 Handle(Geom_BSplineCurve) BSPoint
954 = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
955 section.AddCurve(BSPoint);
962 for (j=jdeb; j<=jfin; j++) {
964 // case of looping sections
965 if (j==jfin && vClosed) {
966 section.AddCurve(BS1);
970 // read the first edge to initialise CompBS;
971 TopoDS_Edge aPrevEdge = TopoDS::Edge (shapes((j-1)*NbEdges+1));
972 Handle(Geom_BSplineCurve) curvBS = EdgeToBSpline (aPrevEdge);
975 GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
977 for (i=2; i<=NbEdges; i++) {
979 TopoDS_Edge aNextEdge = TopoDS::Edge (shapes((j-1)*NbEdges+i));
980 Standard_Real aTolV = Precision::Confusion();
981 TopExp::Vertices(aNextEdge,vf,vl);
982 aTolV = Max(aTolV, BRep_Tool::Tolerance(vf));
983 aTolV = Max(aTolV, BRep_Tool::Tolerance(vl));
984 aTolV = Min(aTolV, 1.e-3);
985 curvBS = EdgeToBSpline (aNextEdge);
988 CompBS.Add(curvBS, aTolV, Standard_True, Standard_False, 1);
991 // return the final section
992 BS = CompBS.BSplineCurve();
993 section.AddCurve(BS);
995 // case of looping sections
996 if (j==jdeb && vClosed) {
1004 TopoDS_Edge edge = TopoDS::Edge(shapes(NbSects*NbEdges));
1005 TopExp::Vertices(edge,vl,vf);
1006 TColgp_Array1OfPnt Extremities(1,2);
1007 Extremities(1) = BRep_Tool::Pnt(vf);
1008 Extremities(2) = BRep_Tool::Pnt(vl);
1009 TColStd_Array1OfReal Bounds(1,2);
1012 TColStd_Array1OfInteger Mult(1,2);
1015 Handle(Geom_BSplineCurve) BSPoint
1016 = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
1017 section.AddCurve(BSPoint);
1020 section.Perform(Precision::PConfusion());
1021 Handle(GeomFill_Line) line = new GeomFill_Line(NbSects);
1023 Standard_Integer nbIt = 3;
1024 if(myPres3d <= 1.e-3) nbIt = 0;
1026 Standard_Integer degmin = 2, degmax = Max(myDegMax, degmin);
1027 Standard_Boolean SpApprox = Standard_True;
1029 GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt);
1030 anApprox.SetContinuity(myContinuity);
1032 if(myUseSmoothing) {
1033 anApprox.SetCriteriumWeight(myCritWeights[0], myCritWeights[1], myCritWeights[2]);
1034 anApprox.PerformSmoothing(line, section);
1037 anApprox.SetParType(myParamType);
1038 anApprox.Perform(line, section, SpApprox);
1041 if(anApprox.IsDone()) {
1043 new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
1044 anApprox.SurfUKnots(), anApprox.SurfVKnots(),
1045 anApprox.SurfUMults(), anApprox.SurfVMults(),
1046 anApprox.UDegree(), anApprox.VDegree());
1053 //=======================================================================
1054 //function : FirstShape
1056 //=======================================================================
1058 const TopoDS_Shape& BRepOffsetAPI_ThruSections::FirstShape() const
1063 //=======================================================================
1064 //function : LastShape
1066 //=======================================================================
1068 const TopoDS_Shape& BRepOffsetAPI_ThruSections::LastShape() const
1073 //=======================================================================
1074 //function : GeneratedFace
1076 //=======================================================================
1078 TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge) const
1081 if (myGenerated.IsBound(edge)) {
1082 return myGenerated(edge);
1090 //=======================================================================
1091 //function : CriteriumWeight
1092 //purpose : returns the Weights associated to the criterium used in
1093 // the optimization.
1094 //=======================================================================
1096 void BRepOffsetAPI_ThruSections::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const
1098 W1 = myCritWeights[0];
1099 W2 = myCritWeights[1];
1100 W3 = myCritWeights[2];
1102 //=======================================================================
1103 //function : SetCriteriumWeight
1105 //=======================================================================
1107 void BRepOffsetAPI_ThruSections::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3)
1109 if (W1 < 0 || W2 < 0 || W3 < 0 ) Standard_DomainError::Raise();
1110 myCritWeights[0] = W1;
1111 myCritWeights[1] = W2;
1112 myCritWeights[2] = W3;
1114 //=======================================================================
1115 //function : SetContinuity
1117 //=======================================================================
1119 void BRepOffsetAPI_ThruSections::SetContinuity (const GeomAbs_Shape TheCont)
1121 myContinuity = TheCont;
1124 //=======================================================================
1125 //function : Continuity
1127 //=======================================================================
1129 GeomAbs_Shape BRepOffsetAPI_ThruSections::Continuity () const
1131 return myContinuity;
1134 //=======================================================================
1135 //function : SetParType
1137 //=======================================================================
1139 void BRepOffsetAPI_ThruSections::SetParType (const Approx_ParametrizationType ParType)
1141 myParamType = ParType;
1144 //=======================================================================
1145 //function : ParType
1147 //=======================================================================
1149 Approx_ParametrizationType BRepOffsetAPI_ThruSections::ParType () const
1154 //=======================================================================
1155 //function : SetMaxDegree
1157 //=======================================================================
1159 void BRepOffsetAPI_ThruSections:: SetMaxDegree(const Standard_Integer MaxDeg)
1164 //=======================================================================
1165 //function : MaxDegree
1167 //=======================================================================
1169 Standard_Integer BRepOffsetAPI_ThruSections::MaxDegree () const
1174 //=======================================================================
1175 //function : SetSmoothing
1177 //=======================================================================
1179 void BRepOffsetAPI_ThruSections::SetSmoothing(const Standard_Boolean UseVar)
1181 myUseSmoothing = UseVar;
1184 //=======================================================================
1185 //function : UseSmoothing
1187 //=======================================================================
1189 Standard_Boolean BRepOffsetAPI_ThruSections::UseSmoothing () const
1191 return myUseSmoothing;