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>
92 #include <BRepAdaptor_Surface.hxx>
94 //=======================================================================
95 //function : PreciseUpar
96 //purpose : pins the u-parameter of surface close to U-knot
98 //=======================================================================
99 static Standard_Real PreciseUpar(const Standard_Real anUpar,
100 const Handle(Geom_BSplineSurface)& aSurface)
102 Standard_Real Tol = Precision::PConfusion();
103 Standard_Integer i1, i2;
105 aSurface->LocateU(anUpar, Tol, i1, i2);
106 Standard_Real U1 = aSurface->UKnot(i1);
107 Standard_Real U2 = aSurface->UKnot(i2);
109 Standard_Real NewU = anUpar;
111 NewU = (anUpar - U1 < U2 - anUpar)? U1 : U2;
115 //=======================================================================
116 //function : PerformPlan
117 //purpose : Construct a plane of filling if exists
118 //=======================================================================
120 static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
121 const Standard_Real presPln,
122 TopoDS_Face& theFace)
124 Standard_Boolean isDegen = Standard_True;
125 TopoDS_Iterator iter(W);
126 for (; iter.More(); iter.Next())
128 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
129 if (!BRep_Tool::Degenerated(anEdge))
130 isDegen = Standard_False;
133 return Standard_True;
135 Standard_Boolean Ok = Standard_False;
137 BRepBuilderAPI_FindPlane Searcher( W, presPln );
138 if (Searcher.Found())
140 theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
143 else // try to find another surface
145 BRepBuilderAPI_MakeFace MF( W );
157 //=============================================================================
158 //function : IsSameOriented
159 //purpose : Checks whether aFace is oriented to the same side as aShell or not
160 //=============================================================================
162 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
163 const TopoDS_Shape& aShell)
165 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
166 TopoDS_Shape anEdge = Explo.Current();
167 TopAbs_Orientation Or1 = anEdge.Orientation();
169 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
170 TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
172 const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
173 TopoDS_Shape theEdge;
174 for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
176 theEdge = Explo.Current();
177 if (theEdge.IsSame(anEdge))
181 TopAbs_Orientation Or2 = theEdge.Orientation();
183 return Standard_False;
184 return Standard_True;
187 //=======================================================================
188 //function : MakeSolid
190 //=======================================================================
192 static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
193 const TopoDS_Wire& wire2, const Standard_Real presPln,
194 TopoDS_Face& face1, TopoDS_Face& face2)
197 throw StdFail_NotDone("Thrusections is not build");
198 Standard_Boolean B = shell.Closed();
203 // It is necessary to close the extremities
204 B = PerformPlan(wire1, presPln, face1);
206 B = PerformPlan(wire2, presPln, face2);
208 if (!face1.IsNull() && !IsSameOriented( face1, shell ))
210 if (!face2.IsNull() && !IsSameOriented( face2, shell ))
214 BB.Add(shell, face1);
216 BB.Add(shell, face2);
218 shell.Closed(Standard_True);
225 BB.Add(solid, shell);
227 // verify the orientation the solid
228 BRepClass3d_SolidClassifier clas3d(solid);
229 clas3d.PerformInfinitePoint(Precision::Confusion());
230 if (clas3d.State() == TopAbs_IN) {
232 TopoDS_Shape aLocalShape = shell.Reversed();
233 BB.Add(solid, TopoDS::Shell(aLocalShape));
234 // B.Add(solid, TopoDS::Shell(newShell.Reversed()));
237 solid.Closed(Standard_True);
242 //=======================================================================
243 //function : BRepOffsetAPI_ThruSections
245 //=======================================================================
247 BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid,
248 const Standard_Boolean ruled,
249 const Standard_Real pres3d):
250 myNbEdgesInSection(0),
251 myIsSolid(isSolid), myIsRuled(ruled),
253 myDegen1(Standard_False), myDegen2(Standard_False)
255 myWCheck = Standard_True;
256 //----------------------------
257 myParamType = Approx_ChordLength;
259 myContinuity = GeomAbs_C2;
260 myCritWeights[0] = .4;
261 myCritWeights[1] = .2;
262 myCritWeights[2] = .4;
263 myUseSmoothing = Standard_False;
267 //=======================================================================
270 //=======================================================================
272 void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
273 const Standard_Real pres3d)
278 myWCheck = Standard_True;
279 //----------------------------
280 myParamType = Approx_ChordLength;
282 myContinuity = GeomAbs_C2;
283 myCritWeights[0] = .4;
284 myCritWeights[1] = .2;
285 myCritWeights[2] = .4;
286 myUseSmoothing = Standard_False;
291 //=======================================================================
294 //=======================================================================
296 void BRepOffsetAPI_ThruSections::AddWire(const TopoDS_Wire& wire)
298 myWires.Append(wire);
299 myInputWires.Append(wire);
302 //=======================================================================
303 //function : AddVertex
305 //=======================================================================
307 void BRepOffsetAPI_ThruSections::AddVertex(const TopoDS_Vertex& aVertex)
312 BB.MakeEdge( DegEdge );
313 BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) );
314 BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) );
315 BB.Degenerated( DegEdge, Standard_True );
318 BB.MakeWire( DegWire );
319 BB.Add( DegWire, DegEdge );
320 DegWire.Closed( Standard_True );
322 myWires.Append( DegWire );
323 myInputWires.Append(DegWire);
326 //=======================================================================
327 //function : CheckCompatibility
329 //=======================================================================
331 void BRepOffsetAPI_ThruSections::CheckCompatibility(const Standard_Boolean check)
337 //=======================================================================
340 //=======================================================================
342 void BRepOffsetAPI_ThruSections::Build()
344 //Check set of section for right configuration of punctual sections
346 TopExp_Explorer explo;
347 for (i = 2; i <= myWires.Length()-1; i++)
349 Standard_Boolean wdeg = Standard_True;
350 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
352 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
353 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
356 throw Standard_Failure("Wrong usage of punctual sections");
358 if (myWires.Length() <= 2)
360 Standard_Boolean wdeg = Standard_True;
361 for (i = 1; i <= myWires.Length(); i++)
363 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
365 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
366 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
371 throw Standard_Failure("Wrong usage of punctual sections");
375 myNbEdgesInSection = 0;
378 // compute origin and orientation on wires to avoid twisted results
379 // and update wires to have same number of edges
381 // use BRepFill_CompatibleWires
382 TopTools_SequenceOfShape WorkingSections;
383 WorkingSections.Clear();
384 TopTools_DataMapOfShapeListOfShape WorkingMap;
387 // Calculate the working sections
388 BRepFill_CompatibleWires Georges(myWires);
390 if (Georges.IsDone()) {
391 WorkingSections = Georges.Shape();
392 WorkingMap = Georges.Generated();
393 myDegen1 = Georges.IsDegeneratedFirstSection();
394 myDegen2 = Georges.IsDegeneratedLastSection();
395 //For each sub-edge of each section
397 Standard_Integer IndFirstSec = 1;
398 if (Georges.IsDegeneratedFirstSection())
400 TopoDS_Wire aWorkingSection = TopoDS::Wire(WorkingSections(IndFirstSec));
401 myNbEdgesInSection += aWorkingSection.NbChildren();
402 for (Standard_Integer ii = 1; ii <= myWires.Length(); ii++)
404 TopoDS_Iterator itw(myWires(ii));
405 for (; itw.More(); itw.Next())
407 const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
408 Standard_Integer aSign = 1;
409 TopoDS_Vertex Vfirst, Vlast;
410 TopExp::Vertices(anEdge, Vfirst, Vlast);
411 TopTools_ListOfShape aNewEdges = Georges.GeneratedShapes(anEdge);
412 TColStd_ListOfInteger IList;
413 aWorkingSection = TopoDS::Wire(WorkingSections(ii));
414 Standard_Integer NbNewEdges = aNewEdges.Extent();
415 TopTools_ListIteratorOfListOfShape itl(aNewEdges);
416 for (Standard_Integer kk = 1; itl.More(); itl.Next(),kk++)
418 const TopoDS_Edge& aNewEdge = TopoDS::Edge(itl.Value());
419 Standard_Integer inde = 1;
420 BRepTools_WireExplorer wexp(aWorkingSection);
421 for (; wexp.More(); wexp.Next(), inde++)
423 const TopoDS_Shape& aWorkingEdge = wexp.Current();
424 if (aWorkingEdge.IsSame(aNewEdge))
426 aSign = (aWorkingEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
431 if (kk == 1 || kk == NbNewEdges)
433 //For each sub-vertex of each section
434 //we save its index of new edge
435 TopoDS_Vertex NewVfirst, NewVlast;
436 TopExp::Vertices(aNewEdge, NewVfirst, NewVlast);
437 if (NewVfirst.IsSame(Vfirst) && !myVertexIndex.IsBound(Vfirst))
438 myVertexIndex.Bind(Vfirst, aSign*inde);
439 if (NewVlast.IsSame(Vlast) && !myVertexIndex.IsBound(Vlast))
440 myVertexIndex.Bind(Vlast, aSign*(-inde));
443 myEdgeNewIndices.Bind(anEdge, IList);
447 myWires = WorkingSections;
452 for (Standard_Integer ii = 1; ii <= myWires.Length(); ii++)
454 TopExp_Explorer Explo(myWires(ii), TopAbs_EDGE);
455 Standard_Integer inde = 1;
456 for (; Explo.More(); Explo.Next(),inde++)
458 anEdge = TopoDS::Edge(Explo.Current());
459 TColStd_ListOfInteger IList;
461 myEdgeNewIndices.Bind(anEdge, IList);
462 TopoDS_Vertex V1, V2;
463 TopExp::Vertices(anEdge, V1, V2);
464 if (!myVertexIndex.IsBound(V1))
465 myVertexIndex.Bind(V1, inde);
466 if (!myVertexIndex.IsBound(V2))
467 myVertexIndex.Bind(V2, -inde);
470 if (inde > myNbEdgesInSection)
471 myNbEdgesInSection = inde;
472 if (inde == 1 && BRep_Tool::Degenerated(anEdge))
475 myDegen1 = Standard_True;
477 myDegen2 = Standard_True;
483 // Calculate the resulting shape
484 if (myWires.Length() == 2 || myIsRuled) {
485 // create a ruled shell
489 // create a smoothed shell
493 catch (Standard_Failure const&)
498 // Encode the Regularities
499 BRepLib::EncodeRegularity(myShape);
503 //=======================================================================
504 //function : CreateRuled
506 //=======================================================================
508 void BRepOffsetAPI_ThruSections::CreateRuled()
510 Standard_Integer nbSects = myWires.Length();
511 BRepFill_Generator aGene;
512 // for (Standard_Integer i=1; i<=nbSects; i++) {
514 for (i=1; i<=nbSects; i++) {
515 aGene.AddWire(TopoDS::Wire(myWires(i)));
518 TopoDS_Shell shell = aGene.Shell();
522 // check if the first wire is the same as the last
523 Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ;
532 // verify the orientation of the solid
533 BRepClass3d_SolidClassifier clas3d(solid);
534 clas3d.PerformInfinitePoint(Precision::Confusion());
535 if (clas3d.State() == TopAbs_IN) {
537 TopoDS_Shape aLocalShape = shell.Reversed();
538 B.Add(solid, TopoDS::Shell(aLocalShape));
539 // B.Add(solid, TopoDS::Shell(shell.Reversed()));
547 TopoDS_Wire wire1 = TopoDS::Wire(myWires.First());
548 TopoDS_Wire wire2 = TopoDS::Wire(myWires.Last());
549 myShape = MakeSolid(shell, wire1, wire2, myPres3d, myFirst, myLast);
562 BRepTools_WireExplorer anExp1, anExp2;
563 TopTools_IndexedDataMapOfShapeListOfShape M;
564 TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, TopAbs_FACE, M);
565 TopTools_ListIteratorOfListOfShape it;
567 TopTools_IndexedDataMapOfShapeListOfShape MV;
568 TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
570 for (i=1; i<=nbSects-1; i++) {
572 const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
573 const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
578 Standard_Boolean tantque = anExp1.More() && anExp2.More();
582 const TopoDS_Shape& edge1 = anExp1.Current();
583 const TopoDS_Shape& edge2 = anExp2.Current();
584 Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
585 Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
587 TopTools_MapOfShape MapFaces;
589 TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
590 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
591 MapFaces.Add(it.Value());
595 for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
596 MapFaces.Add(it.Value());
601 TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
602 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
603 const TopoDS_Shape& Face = it.Value();
604 if (MapFaces.Contains(Face)) {
605 myEdgeFace.Bind(edge1, Face);
611 for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
612 const TopoDS_Shape& Face = it.Value();
613 if (MapFaces.Contains(Face)) {
614 myEdgeFace.Bind(edge1, Face);
620 if (!degen1) anExp1.Next();
621 if (!degen2) anExp2.Next();
623 tantque = anExp1.More() && anExp2.More();
624 if (degen1) tantque = anExp2.More();
625 if (degen2) tantque = anExp1.More();
633 //=======================================================================
634 //function : CreateSmoothed
636 //=======================================================================
638 void BRepOffsetAPI_ThruSections::CreateSmoothed()
641 Standard_Integer nbSects = myWires.Length();
642 BRepTools_WireExplorer anExp;
644 Standard_Boolean w1Point = Standard_True;
645 // check if the first wire is punctual
646 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
647 w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current()));
650 Standard_Boolean w2Point = Standard_True;
651 // check if the last wire is punctual
652 for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) {
653 w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current()));
656 Standard_Boolean vClosed = Standard_False;
657 // check if the first wire is the same as last
658 if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True;
660 // find the dimension
661 Standard_Integer nbEdges=0;
663 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
668 for(anExp.Init(TopoDS::Wire(myWires(2))); anExp.More(); anExp.Next()) {
673 // recover the shapes
674 Standard_Boolean uClosed = Standard_True;
675 TopTools_Array1OfShape shapes(1, nbSects*nbEdges);
676 Standard_Integer nb=0, i, j;
678 for (i=1; i<=nbSects; i++) {
679 const TopoDS_Wire& wire = TopoDS::Wire(myWires(i));
680 if (!wire.Closed()) {
681 // check if the vertices are the same
682 TopoDS_Vertex V1, V2;
683 TopExp::Vertices(wire,V1,V2);
684 if ( !V1.IsSame(V2)) uClosed = Standard_False;
686 if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) {
687 // if the wire is punctual
688 anExp.Init(TopoDS::Wire(wire));
689 for(j=1; j<=nbEdges; j++) {
691 shapes(nb) = anExp.Current();
696 for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
698 shapes(nb) = anExp.Current();
703 // create the new surface
707 TopoDS_Edge edge, edge1, edge2, edge3, edge4, couture;
708 TopTools_Array1OfShape vcouture(1, nbEdges);
713 TopoDS_Wire newW1, newW2;
714 BRep_Builder BW1, BW2;
719 TopoDS_Vertex v1f,v1l,v2f,v2l;
721 Standard_Integer nbPnts = 21;
722 TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
724 // concatenate each section to get a total surface that will be segmented
725 Handle(Geom_BSplineSurface) TS;
726 TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed);
732 TopoDS_Shape firstEdge;
733 for (i=1; i<=nbEdges; i++) {
735 // segmentation of TS
736 Handle(Geom_BSplineSurface) surface;
737 surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy());
738 Standard_Real Ui1,Ui2,V0,V1;
741 Ui1 = PreciseUpar(Ui1, surface);
742 Ui2 = PreciseUpar(Ui2, surface);
743 V0 = surface->VKnot(surface->FirstVKnotIndex());
744 V1 = surface->VKnot(surface->LastVKnotIndex());
745 surface->Segment(Ui1,Ui2,V0,V1);
748 edge = TopoDS::Edge(shapes(i));
749 TopExp::Vertices(edge,v1f,v1l);
750 if (edge.Orientation() == TopAbs_REVERSED)
751 TopExp::Vertices(edge,v1l,v1f);
754 edge = TopoDS::Edge(shapes((nbSects-1)*nbEdges+i));
755 TopExp::Vertices(edge,v2f,v2l);
756 if (edge.Orientation() == TopAbs_REVERSED)
757 TopExp::Vertices(edge,v2l,v2f);
760 B.MakeFace(face, surface, Precision::Confusion());
765 // make the missing edges
766 Standard_Real f1, f2, l1, l2;
767 surface->Bounds(f1,l1,f2,l2);
771 // copy the degenerated edge
772 TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
773 edge1 = TopoDS::Edge(aLocalShape);
774 // edge1 = TopoDS::Edge(shapes(1).EmptyCopied());
775 edge1.Orientation(TopAbs_FORWARD);
778 B.MakeEdge(edge1, surface->VIso(f2), Precision::Confusion());
780 v1f.Orientation(TopAbs_FORWARD);
782 v1l.Orientation(TopAbs_REVERSED);
784 B.Range(edge1, f1, l1);
785 // processing of looping sections
786 // store edges of the 1st section
793 edge2 = TopoDS::Edge(vcouture(i));
796 // copy of the degenerated edge
797 TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
798 edge2 = TopoDS::Edge(aLocalShape);
799 // edge2 = TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
800 edge2.Orientation(TopAbs_FORWARD);
803 B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
805 v2f.Orientation(TopAbs_FORWARD);
807 v2l.Orientation(TopAbs_REVERSED);
809 B.Range(edge2, f1, l1);
816 B.MakeEdge(edge3, surface->UIso(f1), Precision::Confusion());
817 v1f.Orientation(TopAbs_FORWARD);
819 v2f.Orientation(TopAbs_REVERSED);
821 B.Range(edge3, f2, l2);
832 if ( uClosed && i==nbEdges) {
836 B.MakeEdge(edge4, surface->UIso(l1), Precision::Confusion());
837 v1l.Orientation(TopAbs_FORWARD);
839 v2l.Orientation(TopAbs_REVERSED);
841 B.Range(edge4, f2, l2);
852 new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
853 new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
854 Precision::Confusion());
855 B.Range(edge1,face,f1,l1);
858 B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
859 Precision::Confusion());
860 B.Range(edge1,face,f1,l1);
861 B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
862 Precision::Confusion());
863 B.Range(edge2,face,f1,l1);
866 if ( uClosed && nbEdges ==1 ) {
868 new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
869 new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
870 Precision::Confusion());
871 B.Range(edge3,face,f2,l2);
875 B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
876 Precision::Confusion());
877 B.Range(edge3,face,f2,l2);
878 B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
879 Precision::Confusion());
880 B.Range(edge4,face,f2,l2);
885 // complete newW1 newW2
886 TopoDS_Edge edge12 = edge1;
887 TopoDS_Edge edge22 = edge2;
890 BW1.Add(newW1, edge12);
891 BW2.Add(newW2, edge22);
894 myEdgeFace.Bind(firstEdge, face);
897 if (uClosed && w1Point && w2Point)
898 shell.Closed(Standard_True);
908 // verify the orientation the solid
909 BRepClass3d_SolidClassifier clas3d(solid);
910 clas3d.PerformInfinitePoint(Precision::Confusion());
911 if (clas3d.State() == TopAbs_IN) {
913 TopoDS_Shape aLocalShape = shell.Reversed();
914 B.Add(solid, TopoDS::Shell(aLocalShape));
915 // B.Add(solid, TopoDS::Shell(shell.Reversed()));
922 myShape = MakeSolid(shell, newW1, newW2, myPres3d, myFirst, myLast);
933 TopExp_Explorer ex(myShape,TopAbs_EDGE);
935 const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
936 B.SameRange(CurE, Standard_False);
937 B.SameParameter(CurE, Standard_False);
938 Standard_Real tol = BRep_Tool::Tolerance(CurE);
939 BRepLib::SameParameter(CurE,tol);
944 //=======================================================================
945 //function : EdgeToBSpline
946 //purpose : auxiliary -- get curve from edge and convert it to bspline
947 // parameterized from 0 to 1
948 //=======================================================================
950 // NOTE: this code duplicates the same function in BRepFill_NSections.cxx
951 static Handle(Geom_BSplineCurve) EdgeToBSpline (const TopoDS_Edge& theEdge)
953 Handle(Geom_BSplineCurve) aBSCurve;
954 if (BRep_Tool::Degenerated(theEdge)) {
955 // degenerated edge : construction of a point curve
956 TColStd_Array1OfReal aKnots (1,2);
960 TColStd_Array1OfInteger aMults (1,2);
964 TColgp_Array1OfPnt aPoles(1,2);
965 TopoDS_Vertex vf, vl;
966 TopExp::Vertices(theEdge,vl,vf);
967 aPoles(1) = BRep_Tool::Pnt(vf);
968 aPoles(2) = BRep_Tool::Pnt(vl);
970 aBSCurve = new Geom_BSplineCurve (aPoles, aKnots, aMults, 1);
974 // get the curve of the edge
975 TopLoc_Location aLoc;
976 Standard_Real aFirst, aLast;
977 Handle(Geom_Curve) aCurve = BRep_Tool::Curve (theEdge, aLoc, aFirst, aLast);
979 throw Standard_NullObject("Null 3D curve in edge");
981 // convert its part used by edge to bspline; note that if edge curve is bspline,
982 // conversion made via trimmed curve is still needed -- it will copy it, segment
983 // as appropriate, and remove periodicity if it is periodic (deadly for approximator)
984 Handle(Geom_TrimmedCurve) aTrimCurve = new Geom_TrimmedCurve (aCurve, aFirst, aLast);
986 // special treatment of conic curve
987 if (aTrimCurve->BasisCurve()->IsKind(STANDARD_TYPE(Geom_Conic)))
989 const Handle(Geom_Curve)& aCurveTrimmed = aTrimCurve; // to avoid ambiguity
990 GeomConvert_ApproxCurve anAppr (aCurveTrimmed, Precision::Confusion(), GeomAbs_C1, 16, 14);
991 if (anAppr.HasResult())
992 aBSCurve = anAppr.Curve();
996 if (aBSCurve.IsNull())
997 aBSCurve = GeomConvert::CurveToBSplineCurve (aTrimCurve);
999 // apply transformation if needed
1000 if (! aLoc.IsIdentity())
1001 aBSCurve->Transform (aLoc.Transformation());
1003 // reparameterize to [0,1]
1004 TColStd_Array1OfReal aKnots (1, aBSCurve->NbKnots());
1005 aBSCurve->Knots (aKnots);
1006 BSplCLib::Reparametrize (0., 1., aKnots);
1007 aBSCurve->SetKnots (aKnots);
1010 // reverse curve if edge is reversed
1011 if (theEdge.Orientation() == TopAbs_REVERSED)
1012 aBSCurve->Reverse();
1017 //=======================================================================
1018 //function : TotalSurf
1020 //=======================================================================
1022 Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
1023 TotalSurf(const TopTools_Array1OfShape& shapes,
1024 const Standard_Integer NbSects,
1025 const Standard_Integer NbEdges,
1026 const Standard_Boolean w1Point,
1027 const Standard_Boolean w2Point,
1028 const Standard_Boolean vClosed) const
1030 Standard_Integer i,j,jdeb=1,jfin=NbSects;
1031 TopoDS_Vertex vf,vl;
1033 GeomFill_SectionGenerator section;
1034 Handle(Geom_BSplineSurface) surface;
1035 Handle(Geom_BSplineCurve) BS, BS1;
1036 Handle(Geom_TrimmedCurve) curvTrim;
1040 TopoDS_Edge edge = TopoDS::Edge(shapes(1));
1041 TopExp::Vertices(edge,vl,vf);
1042 TColgp_Array1OfPnt Extremities(1,2);
1043 Extremities(1) = BRep_Tool::Pnt(vf);
1044 Extremities(2) = BRep_Tool::Pnt(vl);
1045 TColStd_Array1OfReal Bounds(1,2);
1048 TColStd_Array1OfInteger Mult(1,2);
1051 Handle(Geom_BSplineCurve) BSPoint
1052 = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
1053 section.AddCurve(BSPoint);
1060 for (j=jdeb; j<=jfin; j++) {
1062 // case of looping sections
1063 if (j==jfin && vClosed) {
1064 section.AddCurve(BS1);
1068 // read the first edge to initialise CompBS;
1069 TopoDS_Edge aPrevEdge = TopoDS::Edge (shapes((j-1)*NbEdges+1));
1070 Handle(Geom_BSplineCurve) curvBS = EdgeToBSpline (aPrevEdge);
1073 GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
1075 for (i=2; i<=NbEdges; i++) {
1077 TopoDS_Edge aNextEdge = TopoDS::Edge (shapes((j-1)*NbEdges+i));
1078 Standard_Real aTolV = Precision::Confusion();
1079 TopExp::Vertices(aNextEdge,vf,vl);
1080 aTolV = Max(aTolV, BRep_Tool::Tolerance(vf));
1081 aTolV = Max(aTolV, BRep_Tool::Tolerance(vl));
1082 aTolV = Min(aTolV, 1.e-3);
1083 curvBS = EdgeToBSpline (aNextEdge);
1086 CompBS.Add(curvBS, aTolV, Standard_True, Standard_False, 1);
1089 // return the final section
1090 BS = CompBS.BSplineCurve();
1091 section.AddCurve(BS);
1093 // case of looping sections
1094 if (j==jdeb && vClosed) {
1102 TopoDS_Edge edge = TopoDS::Edge(shapes(NbSects*NbEdges));
1103 TopExp::Vertices(edge,vl,vf);
1104 TColgp_Array1OfPnt Extremities(1,2);
1105 Extremities(1) = BRep_Tool::Pnt(vf);
1106 Extremities(2) = BRep_Tool::Pnt(vl);
1107 TColStd_Array1OfReal Bounds(1,2);
1110 TColStd_Array1OfInteger Mult(1,2);
1113 Handle(Geom_BSplineCurve) BSPoint
1114 = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
1115 section.AddCurve(BSPoint);
1118 section.Perform(Precision::PConfusion());
1119 Handle(GeomFill_Line) line = new GeomFill_Line(NbSects);
1121 Standard_Integer nbIt = 3;
1122 if(myPres3d <= 1.e-3) nbIt = 0;
1124 Standard_Integer degmin = 2, degmax = Max(myDegMax, degmin);
1125 Standard_Boolean SpApprox = Standard_True;
1127 GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt);
1128 anApprox.SetContinuity(myContinuity);
1130 if(myUseSmoothing) {
1131 anApprox.SetCriteriumWeight(myCritWeights[0], myCritWeights[1], myCritWeights[2]);
1132 anApprox.PerformSmoothing(line, section);
1135 anApprox.SetParType(myParamType);
1136 anApprox.Perform(line, section, SpApprox);
1139 if(anApprox.IsDone()) {
1141 new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
1142 anApprox.SurfUKnots(), anApprox.SurfVKnots(),
1143 anApprox.SurfUMults(), anApprox.SurfVMults(),
1144 anApprox.UDegree(), anApprox.VDegree());
1151 //=======================================================================
1152 //function : FirstShape
1154 //=======================================================================
1156 const TopoDS_Shape& BRepOffsetAPI_ThruSections::FirstShape() const
1161 //=======================================================================
1162 //function : LastShape
1164 //=======================================================================
1166 const TopoDS_Shape& BRepOffsetAPI_ThruSections::LastShape() const
1171 //=======================================================================
1172 //function : Generated
1174 //=======================================================================
1175 const TopTools_ListOfShape&
1176 BRepOffsetAPI_ThruSections::Generated(const TopoDS_Shape& S)
1178 myGenerated.Clear();
1180 TopTools_SequenceOfShape AllFaces;
1181 TopExp_Explorer Explo(myShape, TopAbs_FACE);
1182 for (; Explo.More(); Explo.Next())
1183 AllFaces.Append(Explo.Current());
1185 if (S.ShapeType() == TopAbs_EDGE)
1187 if (!myEdgeNewIndices.IsBound(S))
1190 const TColStd_ListOfInteger& Indices = myEdgeNewIndices(S);
1191 //Append the faces corresponding to <Indices>
1192 //These faces "grow" from the first section
1193 TColStd_ListIteratorOfListOfInteger itl(Indices);
1194 for (; itl.More(); itl.Next())
1196 Standard_Integer IndOfFace = itl.Value();
1197 myGenerated.Append(AllFaces(IndOfFace));
1201 //Append the next faces corresponding to <Indices>
1202 for (Standard_Integer i = 2; i < myWires.Length(); i++)
1203 for (itl.Initialize(Indices); itl.More(); itl.Next())
1205 Standard_Integer IndOfFace = itl.Value();
1206 IndOfFace += (i-1)*myNbEdgesInSection;
1207 myGenerated.Append(AllFaces(IndOfFace));
1210 else if (S.ShapeType() == TopAbs_VERTEX)
1212 if (!myVertexIndex.IsBound(S))
1215 TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1217 Standard_Boolean IsDegen [2] = {Standard_False, Standard_False};
1218 if (myDegen1 || myDegen2)
1220 TopoDS_Shape EndSections [2];
1221 EndSections[0] = myWires(1);
1222 EndSections[1] = myWires(myWires.Length());
1223 for (Standard_Integer i = 0; i < 2; i++)
1225 if (i == 0 && !myDegen1)
1227 if (i == 1 && !myDegen2)
1230 Explo.Init(EndSections[i], TopAbs_VERTEX);
1231 const TopoDS_Shape& aVertex = Explo.Current();
1232 if (S.IsSame(aVertex))
1234 IsDegen[i] = Standard_True;
1239 // Only one of <IsDegen> can be True:
1240 // in case of one vertex for start and end degenerated sections
1241 // IsDegen[0] is True;
1242 if (IsDegen[0] || IsDegen[1])
1244 //For start or end degenerated section
1245 //we return the whole bunch of longitudinal edges
1246 TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1247 TopTools_IndexedMapOfShape Emap;
1248 const TopTools_ListOfShape& Elist = VEmap.FindFromKey(S);
1249 TopTools_ListIteratorOfListOfShape itl(Elist);
1250 for (; itl.More(); itl.Next())
1252 const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
1253 if (!BRep_Tool::Degenerated(anEdge))
1255 TopoDS_Vertex VV [2];
1256 TopExp::Vertices(anEdge, VV[0], VV[1]);
1257 //Comprehensive check for possible case of
1258 //one vertex for start and end degenerated sections:
1259 //we must take only outgoing or only ingoing edges
1260 if ((IsDegen[0] && S.IsSame(VV[0])) ||
1261 (IsDegen[1] && S.IsSame(VV[1])))
1265 for (Standard_Integer j = 1; j <= Emap.Extent(); j++)
1267 TopoDS_Edge anEdge = TopoDS::Edge(Emap(j));
1268 myGenerated.Append(anEdge);
1271 Standard_Integer i,k;
1272 for (i = 2,k = myWires.Length()-1; i < myWires.Length(); i++,k--)
1274 Standard_Integer IndOfSec = (IsDegen[0])? i : k;
1275 TopoDS_Vertex aVertex = (IsDegen[0])?
1276 TopExp::LastVertex(anEdge) : TopExp::FirstVertex(anEdge);
1277 const TopTools_ListOfShape& EElist = VEmap.FindFromKey(aVertex);
1278 TopTools_IndexedMapOfShape EmapOfSection;
1279 TopExp::MapShapes(myWires(IndOfSec), TopAbs_EDGE, EmapOfSection);
1280 TopoDS_Edge NextEdge;
1281 for (itl.Initialize(EElist); itl.More(); itl.Next())
1283 NextEdge = TopoDS::Edge(itl.Value());
1284 if (!NextEdge.IsSame(anEdge) &&
1285 !EmapOfSection.Contains(NextEdge))
1288 myGenerated.Append(NextEdge);
1294 } //end of if (IsDegen[0] || IsDegen[1])
1296 Standard_Integer Eindex = myVertexIndex(S);
1297 Standard_Integer Vindex = (Eindex > 0)? 0 : 1;
1298 Eindex = Abs(Eindex);
1299 const TopoDS_Wire& FirstSection = TopoDS::Wire(myWires(1));
1300 TopoDS_Edge FirstEdge;
1301 TopoDS_Vertex FirstVertexOfFirstEdge;
1302 BRepTools_WireExplorer wexp(FirstSection);
1303 for (Standard_Integer inde = 1; wexp.More(); wexp.Next(),inde++)
1305 FirstEdge = wexp.Current();
1306 FirstVertexOfFirstEdge = wexp.CurrentVertex();
1311 //Find the first longitudinal edge
1312 TopoDS_Face FirstFace = TopoDS::Face(AllFaces(Eindex));
1313 FirstFace.Orientation(TopAbs_FORWARD);
1314 Explo.Init(FirstFace, TopAbs_EDGE);
1316 BRepAdaptor_Surface BAsurf(FirstFace, Standard_False);
1317 TopoDS_Vertex FirstVertex;
1318 TopExp::MapShapesAndAncestors(FirstFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1319 if (myDegen1 && BAsurf.GetType() == GeomAbs_Plane)
1321 //There are only 3 edges in the face in this case:
1322 //we take 1-st or 3-rd edge
1328 anEdge = TopoDS::Edge(Explo.Current());
1332 TopoDS_Shape FirstEdgeInFace;
1333 FirstEdgeInFace = Explo.Current();
1334 TopoDS_Vertex VV [2];
1335 TopExp::Vertices(FirstEdge, VV[0], VV[1]);
1338 if (VV[0].IsSame(FirstVertexOfFirstEdge))
1339 FirstVertex = VV[0];
1341 FirstVertex = VV[1];
1345 if (VV[0].IsSame(FirstVertexOfFirstEdge))
1346 FirstVertex = VV[1];
1348 FirstVertex = VV[0];
1350 const TopTools_ListOfShape& Elist = VEmap.FindFromKey(FirstVertex);
1351 TopTools_ListIteratorOfListOfShape itl(Elist);
1352 TopAbs_Orientation anEdgeOr = (Vindex == 0)? TopAbs_REVERSED : TopAbs_FORWARD;
1353 for (; itl.More(); itl.Next())
1355 anEdge = TopoDS::Edge(itl.Value());
1356 if (!anEdge.IsSame(FirstEdgeInFace) &&
1357 !BRep_Tool::Degenerated(anEdge) &&
1358 anEdge.Orientation() == anEdgeOr)
1362 myGenerated.Append(anEdge);
1364 //Find the chain of longitudinal edges from first to last
1365 for (Standard_Integer i = 2; i < myWires.Length(); i++)
1367 FirstVertex = TopExp::LastVertex(anEdge);
1368 const TopTools_ListOfShape& Elist1 = VEmap.FindFromKey(FirstVertex);
1369 FirstEdge = (anEdge.IsSame(Elist1.First()))?
1370 TopoDS::Edge(Elist1.Last()) : TopoDS::Edge(Elist1.First());
1371 Eindex += myNbEdgesInSection;
1372 FirstFace = TopoDS::Face(AllFaces(Eindex));
1373 FirstFace.Orientation(TopAbs_FORWARD);
1375 TopExp::MapShapesAndAncestors(FirstFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1376 const TopTools_ListOfShape& Elist2 = VEmap.FindFromKey(FirstVertex);
1377 anEdge = (FirstEdge.IsSame(Elist2.First()))?
1378 TopoDS::Edge(Elist2.Last()) : TopoDS::Edge(Elist2.First());
1379 myGenerated.Append(anEdge);
1386 //=======================================================================
1387 //function : GeneratedFace
1389 //=======================================================================
1391 TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge) const
1394 if (myEdgeFace.IsBound(edge)) {
1395 return myEdgeFace(edge);
1403 //=======================================================================
1404 //function : CriteriumWeight
1405 //purpose : returns the Weights associated to the criterium used in
1406 // the optimization.
1407 //=======================================================================
1409 void BRepOffsetAPI_ThruSections::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const
1411 W1 = myCritWeights[0];
1412 W2 = myCritWeights[1];
1413 W3 = myCritWeights[2];
1415 //=======================================================================
1416 //function : SetCriteriumWeight
1418 //=======================================================================
1420 void BRepOffsetAPI_ThruSections::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3)
1422 if (W1 < 0 || W2 < 0 || W3 < 0 ) throw Standard_DomainError();
1423 myCritWeights[0] = W1;
1424 myCritWeights[1] = W2;
1425 myCritWeights[2] = W3;
1427 //=======================================================================
1428 //function : SetContinuity
1430 //=======================================================================
1432 void BRepOffsetAPI_ThruSections::SetContinuity (const GeomAbs_Shape TheCont)
1434 myContinuity = TheCont;
1437 //=======================================================================
1438 //function : Continuity
1440 //=======================================================================
1442 GeomAbs_Shape BRepOffsetAPI_ThruSections::Continuity () const
1444 return myContinuity;
1447 //=======================================================================
1448 //function : SetParType
1450 //=======================================================================
1452 void BRepOffsetAPI_ThruSections::SetParType (const Approx_ParametrizationType ParType)
1454 myParamType = ParType;
1457 //=======================================================================
1458 //function : ParType
1460 //=======================================================================
1462 Approx_ParametrizationType BRepOffsetAPI_ThruSections::ParType () const
1467 //=======================================================================
1468 //function : SetMaxDegree
1470 //=======================================================================
1472 void BRepOffsetAPI_ThruSections:: SetMaxDegree(const Standard_Integer MaxDeg)
1477 //=======================================================================
1478 //function : MaxDegree
1480 //=======================================================================
1482 Standard_Integer BRepOffsetAPI_ThruSections::MaxDegree () const
1487 //=======================================================================
1488 //function : SetSmoothing
1490 //=======================================================================
1492 void BRepOffsetAPI_ThruSections::SetSmoothing(const Standard_Boolean UseVar)
1494 myUseSmoothing = UseVar;
1497 //=======================================================================
1498 //function : UseSmoothing
1500 //=======================================================================
1502 Standard_Boolean BRepOffsetAPI_ThruSections::UseSmoothing () const
1504 return myUseSmoothing;