0023436: BRepOffsetAPI_ThruSections crashes when lofting through identical profiles
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_ThruSections.cxx
CommitLineData
b311480e 1// Created on: 1995-07-18
2// Created by: Joelle CHAUVET
3// Copyright (c) 1995-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21// Modified: Mon Jan 12 10:50:10 1998
7fd59977 22// gestion automatique de l'origine et de l'orientation
23// avec la methode ArrangeWires
24// Modified: Mon Jan 19 10:11:56 1998
7fd59977 25// traitement des cas particuliers cylindre, cone, plan
26// (methodes DetectKPart et CreateKPart)
27// Modified: Mon Feb 23 09:28:46 1998
7fd59977 28// traitement des sections avec nombre d'elements different
29// + quelques ameliorations pour les cas particuliers
30// + cas de la derniere section ponctuelle
31// Modified: Mon Apr 6 15:47:44 1998
7fd59977 32// traitement des cas particuliers deplace dans BRepFill
33// Modified: Thu Apr 30 15:24:17 1998
7fd59977 34// separation sections fermees / sections ouvertes + debug
35// Modified: Fri Jul 10 11:23:35 1998
7fd59977 36// surface de CreateSmoothed par concatenation,approximation
37// et segmentation (PRO13924, CTS21295)
38// Modified: Tue Jul 21 16:48:35 1998
7fd59977 39// pb de ratio (BUC60281)
40// Modified: Thu Jul 23 11:38:36 1998
7fd59977 41// sections bouclantes
42// Modified: Fri Aug 28 10:13:44 1998
7fd59977 43// traitement des sections ponctuelles
44// dans l'historique (cf. loft06 et loft09)
45// et dans le cas des solides
46// Modified: Tue Nov 3 10:06:15 1998
7fd59977 47// utilisation de BRepFill_CompatibleWires
b311480e 48
7fd59977 49
50#include <BRepOffsetAPI_ThruSections.ixx>
51
52#include <Precision.hxx>
53#include <Standard_DomainError.hxx>
54
55#include <gp_Pnt.hxx>
56#include <gp_Pnt2d.hxx>
57#include <gp_Dir2d.hxx>
58#include <TColgp_Array1OfPnt.hxx>
59
60#include <GeomAbs_Shape.hxx>
61#include <Geom_Curve.hxx>
62#include <Geom_BSplineSurface.hxx>
63#include <Geom_TrimmedCurve.hxx>
64#include <Geom_BezierCurve.hxx>
65#include <Geom_Conic.hxx>
66#include <Geom2d_Line.hxx>
67#include <GeomFill_Line.hxx>
68#include <GeomFill_AppSurf.hxx>
69#include <GeomFill_SectionGenerator.hxx>
70#include <GeomConvert_CompCurveToBSplineCurve.hxx>
71#include <GeomConvert.hxx>
72#include <GeomConvert_ApproxCurve.hxx>
73#include <Geom_BSplineCurve.hxx>
74#include <BSplCLib.hxx>
75
76#include <TopAbs.hxx>
77#include <TopoDS.hxx>
78#include <TopoDS_Solid.hxx>
79#include <TopoDS_Face.hxx>
80#include <TopoDS_Edge.hxx>
81#include <TopoDS_Vertex.hxx>
82#include <TopoDS_Wire.hxx>
83#include <TopLoc_Location.hxx>
84#include <TopTools_Array1OfShape.hxx>
85#include <TopTools_ListIteratorOfListOfShape.hxx>
86#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
87#include <TopExp.hxx>
88#include <TopoDS_Iterator.hxx>
89
90
91#include <BRep_Builder.hxx>
92#include <BRep_Tool.hxx>
93#include <BRepTools_WireExplorer.hxx>
94
95#include <BRepLib.hxx>
96#include <BRepClass3d_SolidClassifier.hxx>
97
98#include <BRepFill_Generator.hxx>
99#include <BRepFill_CompatibleWires.hxx>
100
101#include <BRepBuilderAPI_MakeFace.hxx>
102#include <BRepBuilderAPI_FindPlane.hxx>
103
104
aadab519 105//=======================================================================
106//function : PreciseUpar
107//purpose : pins the u-parameter of surface close to U-knot
108// to this U-knot
109//=======================================================================
110
111static Standard_Real PreciseUpar(const Standard_Real anUpar,
112 const Handle(Geom_BSplineSurface)& aSurface)
113{
114 Standard_Real Tol = Precision::PConfusion();
115 Standard_Integer i1, i2;
7fd59977 116
aadab519 117 aSurface->LocateU(anUpar, Tol, i1, i2);
118 Standard_Real U1 = aSurface->UKnot(i1);
119 Standard_Real U2 = aSurface->UKnot(i2);
120
121 Standard_Real NewU = anUpar;
122
123 NewU = (anUpar - U1 < U2 - anUpar)? U1 : U2;
124 return NewU;
125}
7fd59977 126
127//=======================================================================
128//function : PerformPlan
0d969553 129//purpose : Construct a plane of filling if exists
7fd59977 130//=======================================================================
131
132static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
133 const Standard_Real presPln,
134 TopoDS_Face& theFace)
135{
136 Standard_Boolean isDegen = Standard_True;
137 TopoDS_Iterator iter(W);
138 for (; iter.More(); iter.Next())
139 {
140 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
141 if (!BRep_Tool::Degenerated(anEdge))
142 isDegen = Standard_False;
143 }
144 if (isDegen)
145 return Standard_True;
146
147 Standard_Boolean Ok = Standard_False;
148 if (!W.IsNull()) {
149 BRepBuilderAPI_FindPlane Searcher( W, presPln );
150 if (Searcher.Found())
151 {
152 theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
153 Ok = Standard_True;
154 }
155 else // try to find another surface
156 {
157 BRepBuilderAPI_MakeFace MF( W );
158 if (MF.IsDone())
159 {
160 theFace = MF.Face();
161 Ok = Standard_True;
162 }
163 }
164 }
165
166 return Ok;
167}
168
169//=============================================================================
170//function : IsSameOriented
171//purpose : Checks whether aFace is oriented to the same side as aShell or not
172//=============================================================================
173
174static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
175 const TopoDS_Shape& aShell)
176{
177 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
178 TopoDS_Shape anEdge = Explo.Current();
179 TopAbs_Orientation Or1 = anEdge.Orientation();
180
181 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
182 TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
183
184 const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
185 TopoDS_Shape theEdge;
186 for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
187 {
188 theEdge = Explo.Current();
189 if (theEdge.IsSame(anEdge))
190 break;
191 }
192
193 TopAbs_Orientation Or2 = theEdge.Orientation();
194 if (Or1 == Or2)
195 return Standard_False;
196 return Standard_True;
197}
198
199//=======================================================================
200//function : MakeSolid
201//purpose :
202//=======================================================================
203
204static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
205 const TopoDS_Wire& wire2, const Standard_Real presPln,
206 TopoDS_Face& face1, TopoDS_Face& face2)
207{
208 if (shell.IsNull())
209 StdFail_NotDone::Raise("Thrusections is not build");
210 Standard_Boolean B = shell.Closed();
211 BRep_Builder BB;
212
213 if (!B)
214 {
0d969553 215 // It is necessary to close the extremities
7fd59977 216 B = PerformPlan(wire1, presPln, face1);
217 if (B) {
218 B = PerformPlan(wire2, presPln, face2);
219 if (B) {
220 if (!face1.IsNull() && !IsSameOriented( face1, shell ))
221 face1.Reverse();
222 if (!face2.IsNull() && !IsSameOriented( face2, shell ))
223 face2.Reverse();
224
225 if (!face1.IsNull())
226 BB.Add(shell, face1);
227 if (!face2.IsNull())
228 BB.Add(shell, face2);
229
230 shell.Closed(Standard_True);
231 }
232 }
233 }
234
235 TopoDS_Solid solid;
236 BB.MakeSolid(solid);
237 BB.Add(solid, shell);
238
239 // verify the orientation the solid
240 BRepClass3d_SolidClassifier clas3d(solid);
241 clas3d.PerformInfinitePoint(Precision::Confusion());
242 if (clas3d.State() == TopAbs_IN) {
243 BB.MakeSolid(solid);
244 TopoDS_Shape aLocalShape = shell.Reversed();
245 BB.Add(solid, TopoDS::Shell(aLocalShape));
246// B.Add(solid, TopoDS::Shell(newShell.Reversed()));
247 }
248
249 solid.Closed(Standard_True);
250 return solid;
251}
252
253
254//=======================================================================
255//function : BRepOffsetAPI_ThruSections
256//purpose :
257//=======================================================================
258
259BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid, const Standard_Boolean ruled,
260 const Standard_Real pres3d):
261 myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d)
262{
263 myWCheck = Standard_True;
264//----------------------------
265 myParamType = Approx_ChordLength;
266 myDegMax = 8;
267 myContinuity = GeomAbs_C2;
268 myCritWeights[0] = .4;
269 myCritWeights[1] = .2;
270 myCritWeights[2] = .4;
271 myUseSmoothing = Standard_False;
272}
273
274
275//=======================================================================
276//function : Init
277//purpose :
278//=======================================================================
279
280void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
281 const Standard_Real pres3d)
282{
283 myIsSolid = isSolid;
284 myIsRuled = ruled;
285 myPres3d = pres3d;
286 myWCheck = Standard_True;
287//----------------------------
288 myParamType = Approx_ChordLength;
289 myDegMax = 6;
290 myContinuity = GeomAbs_C2;
291 myCritWeights[0] = .4;
292 myCritWeights[1] = .2;
293 myCritWeights[2] = .4;
294 myUseSmoothing = Standard_False;
295
296}
297
298
299//=======================================================================
300//function : AddWire
301//purpose :
302//=======================================================================
303
304void BRepOffsetAPI_ThruSections::AddWire(const TopoDS_Wire& wire)
305{
306 myWires.Append(wire);
307}
308
309//=======================================================================
310//function : AddVertex
311//purpose :
312//=======================================================================
313
314void BRepOffsetAPI_ThruSections::AddVertex(const TopoDS_Vertex& aVertex)
315{
316 BRep_Builder BB;
317
318 TopoDS_Edge DegEdge;
319 BB.MakeEdge( DegEdge );
320 BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) );
321 BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) );
322 BB.Degenerated( DegEdge, Standard_True );
323 DegEdge.Closed( Standard_True );
324
325 TopoDS_Wire DegWire;
326 BB.MakeWire( DegWire );
327 BB.Add( DegWire, DegEdge );
328 DegWire.Closed( Standard_True );
329
330 myWires.Append( DegWire );
331}
332
333//=======================================================================
334//function : CheckCompatibility
335//purpose :
336//=======================================================================
337
338void BRepOffsetAPI_ThruSections::CheckCompatibility(const Standard_Boolean check)
339{
340 myWCheck = check;
341}
342
343
344//=======================================================================
345//function : Build
346//purpose :
347//=======================================================================
348
349void BRepOffsetAPI_ThruSections::Build()
350{
351 //Check set of section for right configuration of punctual sections
352 Standard_Integer i;
353 TopExp_Explorer explo;
354 for (i = 2; i <= myWires.Length()-1; i++)
355 {
356 Standard_Boolean wdeg = Standard_True;
357 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
358 {
359 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
360 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
361 }
362 if (wdeg)
363 Standard_Failure::Raise("Wrong usage of punctual sections");
364 }
365 if (myWires.Length() <= 2)
366 {
367 Standard_Boolean wdeg = Standard_True;
368 for (i = 1; i <= myWires.Length(); i++)
369 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
370 {
371 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
372 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
373 }
374 if (wdeg)
375 Standard_Failure::Raise("Wrong usage of punctual sections");
376 }
377
378 if (myWCheck) {
379 // compute origin and orientation on wires to avoid twisted results
380 // and update wires to have same number of edges
381
0d969553 382 // use BRepFill_CompatibleWires
7fd59977 383 TopTools_SequenceOfShape WorkingSections;
384 WorkingSections.Clear();
385 TopTools_DataMapOfShapeListOfShape WorkingMap;
386 WorkingMap.Clear();
387
0d969553 388 // Calculate the working sections
7fd59977 389 BRepFill_CompatibleWires Georges(myWires);
390 Georges.Perform();
391 if (Georges.IsDone()) {
392 WorkingSections = Georges.Shape();
393 WorkingMap = Georges.Generated();
394 }
395 myWires = WorkingSections;
396 }
397
0d969553 398 // Calculate the resulting shape
7fd59977 399 if (myWires.Length() == 2 || myIsRuled) {
400 // create a ruled shell
401 CreateRuled();
402 }
403 else {
404 // create a smoothed shell
405 CreateSmoothed();
406 }
407 // Encode the Regularities
408 BRepLib::EncodeRegularity(myShape);
409
410}
411
412
413//=======================================================================
414//function : CreateRuled
415//purpose :
416//=======================================================================
417
418void BRepOffsetAPI_ThruSections::CreateRuled()
419{
420 Standard_Integer nbSects = myWires.Length();
421 BRepFill_Generator aGene;
422// for (Standard_Integer i=1; i<=nbSects; i++) {
423 Standard_Integer i;
424 for (i=1; i<=nbSects; i++) {
425 aGene.AddWire(TopoDS::Wire(myWires(i)));
426 }
427 aGene.Perform();
428 TopoDS_Shell shell = aGene.Shell();
429
430 if (myIsSolid) {
431
0d969553 432 // check if the first wire is the same as the last
7fd59977 433 Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ;
434
435 if (vClosed) {
436
437 TopoDS_Solid solid;
438 BRep_Builder B;
439 B.MakeSolid(solid);
440 B.Add(solid, shell);
441
0d969553 442 // verify the orientation of the solid
7fd59977 443 BRepClass3d_SolidClassifier clas3d(solid);
444 clas3d.PerformInfinitePoint(Precision::Confusion());
445 if (clas3d.State() == TopAbs_IN) {
446 B.MakeSolid(solid);
447 TopoDS_Shape aLocalShape = shell.Reversed();
448 B.Add(solid, TopoDS::Shell(aLocalShape));
449// B.Add(solid, TopoDS::Shell(shell.Reversed()));
450 }
451 myShape = solid;
452
453 }
454
455 else {
456
457 TopoDS_Wire wire1 = TopoDS::Wire(myWires.First());
458 TopoDS_Wire wire2 = TopoDS::Wire(myWires.Last());
459 myShape = MakeSolid(shell, wire1, wire2, myPres3d, myFirst, myLast);
460
461 }
462
463 Done();
464 }
465
466 else {
467 myShape = shell;
468 Done();
469 }
470
471 // history
472 BRepTools_WireExplorer anExp1, anExp2;
473 TopTools_IndexedDataMapOfShapeListOfShape M;
474 TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, TopAbs_FACE, M);
475 TopTools_ListIteratorOfListOfShape it;
476
477 TopTools_IndexedDataMapOfShapeListOfShape MV;
478 TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
479
480 for (i=1; i<=nbSects-1; i++) {
481
482 const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
483 const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
484
485 anExp1.Init(wire1);
486 anExp2.Init(wire2);
487
488 Standard_Boolean tantque = anExp1.More() && anExp2.More();
489
490 while (tantque) {
491
492 const TopoDS_Shape& edge1 = anExp1.Current();
493 const TopoDS_Shape& edge2 = anExp2.Current();
494 Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
495 Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
496
497 TopTools_MapOfShape MapFaces;
498 if (degen2){
499 TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
500 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
501 MapFaces.Add(it.Value());
502 }
503 }
504 else {
505 for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
506 MapFaces.Add(it.Value());
507 }
508 }
509
510 if (degen1) {
511 TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
512 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
513 const TopoDS_Shape& Face = it.Value();
514 if (MapFaces.Contains(Face)) {
515 myGenerated.Bind(edge1, Face);
516 break;
517 }
518 }
519 }
520 else {
521 for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
522 const TopoDS_Shape& Face = it.Value();
523 if (MapFaces.Contains(Face)) {
524 myGenerated.Bind(edge1, Face);
525 break;
526 }
527 }
528 }
529
530 if (!degen1) anExp1.Next();
531 if (!degen2) anExp2.Next();
532
533 tantque = anExp1.More() && anExp2.More();
534 if (degen1) tantque = anExp2.More();
535 if (degen2) tantque = anExp1.More();
536
537 }
538
539 }
540
541}
542
543//=======================================================================
544//function : CreateSmoothed
545//purpose :
546//=======================================================================
547
548void BRepOffsetAPI_ThruSections::CreateSmoothed()
549{
550 // initialisation
551 Standard_Integer nbSects = myWires.Length();
552 BRepTools_WireExplorer anExp;
553
554 Standard_Boolean w1Point = Standard_True;
0d969553 555 // check if the first wire is punctual
7fd59977 556 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
557 w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current()));
558 }
559
560 Standard_Boolean w2Point = Standard_True;
0d969553 561 // check if the last wire is punctual
7fd59977 562 for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) {
563 w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current()));
564 }
565
566 Standard_Boolean vClosed = Standard_False;
0d969553 567 // check if the first wire is the same as last
7fd59977 568 if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True;
569
570 // find the dimension
571 Standard_Integer nbEdges=0;
572 if (!w1Point) {
573 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
574 nbEdges++;
575 }
576 }
577 else {
578 for(anExp.Init(TopoDS::Wire(myWires(2))); anExp.More(); anExp.Next()) {
579 nbEdges++;
580 }
581 }
582
583 // recover the shapes
584 Standard_Boolean uClosed = Standard_True;
585 TopTools_Array1OfShape shapes(1, nbSects*nbEdges);
586 Standard_Integer nb=0, i, j;
587
588 for (i=1; i<=nbSects; i++) {
589 const TopoDS_Wire& wire = TopoDS::Wire(myWires(i));
590 if (!wire.Closed()) {
0d969553 591 // check if the vertices are the same
7fd59977 592 TopoDS_Vertex V1, V2;
593 TopExp::Vertices(wire,V1,V2);
594 if ( !V1.IsSame(V2)) uClosed = Standard_False;
595 }
596 if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) {
0d969553 597 // if the wire is punctual
7fd59977 598 anExp.Init(TopoDS::Wire(wire));
599 for(j=1; j<=nbEdges; j++) {
600 nb++;
601 shapes(nb) = anExp.Current();
602 }
603 }
604 else {
0d969553 605 // otherwise
7fd59977 606 for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
607 nb++;
608 shapes(nb) = anExp.Current();
609 }
610 }
611 }
612
613 // create the new surface
614 TopoDS_Shell shell;
615 TopoDS_Face face;
616 TopoDS_Wire W;
617 TopoDS_Edge edge, edge1, edge2, edge3, edge4, couture;
618 TopTools_Array1OfShape vcouture(1, nbEdges);
619
620 BRep_Builder B;
621 B.MakeShell(shell);
622
623 TopoDS_Wire newW1, newW2;
624 BRep_Builder BW1, BW2;
625 BW1.MakeWire(newW1);
626 BW2.MakeWire(newW2);
627
628 TopLoc_Location loc;
629 TopoDS_Vertex v1f,v1l,v2f,v2l;
630
631 GeomFill_SectionGenerator section;
632 Standard_Integer nbPnts = 21;
633 TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
634
0d969553 635 // concatenate each section to get a total surface that will be segmented
7fd59977 636 Handle(Geom_BSplineSurface) TS;
637 TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed);
638
639 if(TS.IsNull()) {
640 return;
641 }
642
643 TopoDS_Shape firstEdge;
644 for (i=1; i<=nbEdges; i++) {
645
0d969553 646 // segmentation of TS
7fd59977 647 Handle(Geom_BSplineSurface) surface;
648 surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy());
649 Standard_Real Ui1,Ui2,V0,V1;
650 Ui1 = i-1;
651 Ui2 = i;
aadab519 652 Ui1 = PreciseUpar(Ui1, surface);
653 Ui2 = PreciseUpar(Ui2, surface);
7fd59977 654 V0 = surface->VKnot(surface->FirstVKnotIndex());
655 V1 = surface->VKnot(surface->LastVKnotIndex());
656 surface->Segment(Ui1,Ui2,V0,V1);
657
0d969553 658 // return vertices
7fd59977 659 edge = TopoDS::Edge(shapes(i));
660 TopExp::Vertices(edge,v1f,v1l);
661 if (edge.Orientation() == TopAbs_REVERSED)
662 TopExp::Vertices(edge,v1l,v1f);
663 firstEdge = edge;
664
665 edge = TopoDS::Edge(shapes((nbSects-1)*nbEdges+i));
666 TopExp::Vertices(edge,v2f,v2l);
667 if (edge.Orientation() == TopAbs_REVERSED)
668 TopExp::Vertices(edge,v2l,v2f);
669
670 // make the face
671 B.MakeFace(face, surface, Precision::Confusion());
672
673 // make the wire
674 B.MakeWire(W);
675
676 // make the missing edges
677 Standard_Real f1, f2, l1, l2;
678 surface->Bounds(f1,l1,f2,l2);
679
680 // --- edge 1
681 if ( w1Point ) {
0d969553 682 // copy the degenerated edge
7fd59977 683 TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
684 edge1 = TopoDS::Edge(aLocalShape);
685// edge1 = TopoDS::Edge(shapes(1).EmptyCopied());
686 edge1.Orientation(TopAbs_FORWARD);
687 }
688 else {
689 B.MakeEdge(edge1, surface->VIso(f2), Precision::Confusion());
690 }
691 v1f.Orientation(TopAbs_FORWARD);
692 B.Add(edge1, v1f);
693 v1l.Orientation(TopAbs_REVERSED);
694 B.Add(edge1, v1l);
695 B.Range(edge1, f1, l1);
0d969553
Y
696 // processing of looping sections
697 // store edges of the 1st section
7fd59977 698 if (vClosed)
699 vcouture(i) = edge1;
700
701
702 // --- edge 2
703 if (vClosed)
704 edge2 = TopoDS::Edge(vcouture(i));
705 else {
706 if ( w2Point ) {
0d969553 707 // copy of the degenerated edge
7fd59977 708 TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
709 edge2 = TopoDS::Edge(aLocalShape);
710// edge2 = TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
711 edge2.Orientation(TopAbs_FORWARD);
712 }
713 else {
714 B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
715 }
716 v2f.Orientation(TopAbs_FORWARD);
717 B.Add(edge2, v2f);
718 v2l.Orientation(TopAbs_REVERSED);
719 B.Add(edge2, v2l);
720 B.Range(edge2, f1, l1);
721 }
722 edge2.Reverse();
723
724
725 // --- edge 3
726 if (i==1) {
727 B.MakeEdge(edge3, surface->UIso(f1), Precision::Confusion());
728 v1f.Orientation(TopAbs_FORWARD);
729 B.Add(edge3, v1f);
730 v2f.Orientation(TopAbs_REVERSED);
731 B.Add(edge3, v2f);
732 B.Range(edge3, f2, l2);
733 if (uClosed) {
734 couture = edge3;
735 }
736 }
737 else {
738 edge3 = edge4;
739 }
740 edge3.Reverse();
741
742 // --- edge 4
743 if ( uClosed && i==nbEdges) {
744 edge4 = couture;
745 }
746 else {
747 B.MakeEdge(edge4, surface->UIso(l1), Precision::Confusion());
748 v1l.Orientation(TopAbs_FORWARD);
749 B.Add(edge4, v1l);
750 v2l.Orientation(TopAbs_REVERSED);
751 B.Add(edge4, v2l);
752 B.Range(edge4, f2, l2);
753 }
754
755 B.Add(W,edge1);
756 B.Add(W,edge4);
757 B.Add(W,edge2);
758 B.Add(W,edge3);
759
760 // set PCurve
761 if (vClosed) {
762 B.UpdateEdge(edge1,
763 new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
764 new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
765 Precision::Confusion());
766 B.Range(edge1,face,f1,l1);
767 }
768 else {
769 B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
770 Precision::Confusion());
771 B.Range(edge1,face,f1,l1);
772 B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
773 Precision::Confusion());
774 B.Range(edge2,face,f1,l1);
775 }
776
777 if ( uClosed && nbEdges ==1 ) {
778 B.UpdateEdge(edge3,
779 new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
780 new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
781 Precision::Confusion());
782 B.Range(edge3,face,f2,l2);
783
784 }
785 else {
786 B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
787 Precision::Confusion());
788 B.Range(edge3,face,f2,l2);
789 B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
790 Precision::Confusion());
791 B.Range(edge4,face,f2,l2);
792 }
793 B.Add(face,W);
794 B.Add(shell, face);
795
796 // complete newW1 newW2
797 TopoDS_Edge edge12 = edge1;
798 TopoDS_Edge edge22 = edge2;
799 edge12.Reverse();
800 edge22.Reverse();
801 BW1.Add(newW1, edge12);
802 BW2.Add(newW2, edge22);
803
804 // history
805 myGenerated.Bind(firstEdge, face);
806 }
807
808 if (uClosed && w1Point && w2Point)
809 shell.Closed(Standard_True);
810
811 if (myIsSolid) {
812
813 if (vClosed) {
814
815 TopoDS_Solid solid;
816 BRep_Builder B;
817 B.MakeSolid(solid);
818 B.Add(solid, shell);
819
820 // verify the orientation the solid
821 BRepClass3d_SolidClassifier clas3d(solid);
822 clas3d.PerformInfinitePoint(Precision::Confusion());
823 if (clas3d.State() == TopAbs_IN) {
824 B.MakeSolid(solid);
825 TopoDS_Shape aLocalShape = shell.Reversed();
826 B.Add(solid, TopoDS::Shell(aLocalShape));
827// B.Add(solid, TopoDS::Shell(shell.Reversed()));
828 }
829 myShape = solid;
830
831 }
832
833 else {
834 myShape = MakeSolid(shell, newW1, newW2, myPres3d, myFirst, myLast);
835 }
836
837 Done();
838 }
839
840 else {
841 myShape = shell;
842 Done();
843 }
844
845 TopExp_Explorer ex(myShape,TopAbs_EDGE);
846 while (ex.More()) {
847 const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
848 B.SameRange(CurE, Standard_False);
849 B.SameParameter(CurE, Standard_False);
850 Standard_Real tol = BRep_Tool::Tolerance(CurE);
851 BRepLib::SameParameter(CurE,tol);
852 ex.Next();
853 }
854}
855
856//=======================================================================
857//function : TotalSurf
858//purpose :
859//=======================================================================
860
861Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
862 TotalSurf(const TopTools_Array1OfShape& shapes,
863 const Standard_Integer NbSects,
864 const Standard_Integer NbEdges,
865 const Standard_Boolean w1Point,
866 const Standard_Boolean w2Point,
867 const Standard_Boolean vClosed) const
868{
869 Standard_Integer i,j,jdeb=1,jfin=NbSects;
870 TopoDS_Edge edge;
871 TopLoc_Location loc;
872 Standard_Real first, last;
873 TopoDS_Vertex vf,vl;
874
875 GeomFill_SectionGenerator section;
876 Handle(Geom_BSplineSurface) surface;
877 Handle(Geom_BSplineCurve) BS, BS1;
878 Handle(Geom_TrimmedCurve) curvTrim;
879 Handle(Geom_BSplineCurve) curvBS;
880
881 if (w1Point) {
882 jdeb++;
883 edge = TopoDS::Edge(shapes(1));
884 TopExp::Vertices(edge,vl,vf);
885 TColgp_Array1OfPnt Extremities(1,2);
886 Extremities(1) = BRep_Tool::Pnt(vf);
887 Extremities(2) = BRep_Tool::Pnt(vl);
888 TColStd_Array1OfReal Bounds(1,2);
889 Bounds(1) = 0.;
890 Bounds(2) = 1.;
891 Standard_Integer Deg = 1;
892 TColStd_Array1OfInteger Mult(1,2);
893 Mult(1) = Deg+1;
894 Mult(2) = Deg+1;
895 Handle(Geom_BSplineCurve) BSPoint
896 = new Geom_BSplineCurve(Extremities,Bounds,Mult,Deg);
897 section.AddCurve(BSPoint);
898 }
899
900 if (w2Point) {
901 jfin--;
902 }
903
904 for (j=jdeb; j<=jfin; j++) {
905
0d969553 906 // case of looping sections
7fd59977 907 if (j==jfin && vClosed) {
908 section.AddCurve(BS1);
909 }
910
911 else {
912 // read the first edge to initialise CompBS;
913 edge = TopoDS::Edge(shapes((j-1)*NbEdges+1));
914 if (BRep_Tool::Degenerated(edge)) {
0d969553 915 // degenerated edge : construction of a punctual curve
7fd59977 916 TopExp::Vertices(edge,vl,vf);
917 TColgp_Array1OfPnt Extremities(1,2);
918 Extremities(1) = BRep_Tool::Pnt(vf);
919 Extremities(2) = BRep_Tool::Pnt(vl);
920 Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
921 curvTrim = new Geom_TrimmedCurve(curv,
922 curv->FirstParameter(),
923 curv->LastParameter());
924 }
925 else {
0d969553 926 // recover the curve on the edge
7fd59977 927 Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
928 curvTrim = new Geom_TrimmedCurve(curv, first, last);
929 curvTrim->Transform(loc.Transformation());
930 }
931 if (edge.Orientation() == TopAbs_REVERSED) {
932 curvTrim->Reverse();
933 }
934
0d969553 935 // transformation into BSpline reparameterized on [i-1,i]
7fd59977 936 curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
937 if (curvBS.IsNull()) {
938 Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
939 if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
940 {
941 GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
942 if (appr.HasResult())
943 curvBS = appr.Curve();
944 }
945 if (curvBS.IsNull())
946 curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
947 }
948 TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
949 curvBS->Knots(BSK);
950 BSplCLib::Reparametrize(0.,1.,BSK);
951 curvBS->SetKnots(BSK);
952
0d969553 953 // initialization
7fd59977 954 GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
955
956 for (i=2; i<=NbEdges; i++) {
957 // read the edge
958 edge = TopoDS::Edge(shapes((j-1)*NbEdges+i));
959 if (BRep_Tool::Degenerated(edge)) {
0d969553 960 // degenerated edge : construction of a punctual curve
7fd59977 961 TopExp::Vertices(edge,vl,vf);
962 TColgp_Array1OfPnt Extremities(1,2);
963 Extremities(1) = BRep_Tool::Pnt(vf);
964 Extremities(2) = BRep_Tool::Pnt(vl);
965 Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
966 curvTrim = new Geom_TrimmedCurve(curv,
967 curv->FirstParameter(),
968 curv->LastParameter());
969 }
970 else {
0d969553 971 // return the curve on the edge
7fd59977 972 Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
973 curvTrim = new Geom_TrimmedCurve(curv, first, last);
974 curvTrim->Transform(loc.Transformation());
975 }
976 if (edge.Orientation() == TopAbs_REVERSED) {
977 curvTrim->Reverse();
978 }
979
0d969553 980 // transformation into BSpline reparameterized on [i-1,i]
7fd59977 981 curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
982 if (curvBS.IsNull()) {
983 Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
984 if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
985 {
986 GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
987 if (appr.HasResult())
988 curvBS = appr.Curve();
989 }
990 if (curvBS.IsNull())
991 curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
992 }
993 TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
994 curvBS->Knots(BSK);
995 BSplCLib::Reparametrize(i-1,i,BSK);
996 curvBS->SetKnots(BSK);
997
998 // concatenation
999 CompBS.Add(curvBS,
1000 Precision::Confusion(),
1001 Standard_True,
1002 Standard_False,
1003 1);
1004 }
1005
0d969553 1006 // return the final section
7fd59977 1007 BS = CompBS.BSplineCurve();
1008 section.AddCurve(BS);
1009
0d969553 1010 // case of looping sections
7fd59977 1011 if (j==jdeb && vClosed) {
1012 BS1 = BS;
1013 }
1014
1015 }
1016 }
1017
1018 if (w2Point) {
1019 edge = TopoDS::Edge(shapes(NbSects*NbEdges));
1020 TopExp::Vertices(edge,vl,vf);
1021 TColgp_Array1OfPnt Extremities(1,2);
1022 Extremities(1) = BRep_Tool::Pnt(vf);
1023 Extremities(2) = BRep_Tool::Pnt(vl);
1024 TColStd_Array1OfReal Bounds(1,2);
1025 Bounds(1) = 0.;
1026 Bounds(2) = 1.;
1027 Standard_Integer Deg = 1;
1028 TColStd_Array1OfInteger Mult(1,2);
1029 Mult(1) = Deg+1;
1030 Mult(2) = Deg+1;
1031 Handle(Geom_BSplineCurve) BSPoint
1032 = new Geom_BSplineCurve(Extremities,Bounds,Mult,Deg);
1033 section.AddCurve(BSPoint);
1034 }
1035
1036 section.Perform(Precision::PConfusion());
1037 Handle(GeomFill_Line) line = new GeomFill_Line(NbSects);
1038
1039 Standard_Integer nbIt = 3;
1040 if(myPres3d <= 1.e-3) nbIt = 0;
1041
1042 Standard_Integer degmin = 2, degmax = Max(myDegMax, degmin);
1043 Standard_Boolean SpApprox = Standard_True;
1044
1045 GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt);
1046 anApprox.SetContinuity(myContinuity);
1047
1048 if(myUseSmoothing) {
1049 anApprox.SetCriteriumWeight(myCritWeights[0], myCritWeights[1], myCritWeights[2]);
1050 anApprox.PerformSmoothing(line, section);
1051 }
1052 else {
1053 anApprox.SetParType(myParamType);
1054 anApprox.Perform(line, section, SpApprox);
1055 }
1056
1057 if(anApprox.IsDone()) {
1058 surface =
1059 new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
1060 anApprox.SurfUKnots(), anApprox.SurfVKnots(),
1061 anApprox.SurfUMults(), anApprox.SurfVMults(),
1062 anApprox.UDegree(), anApprox.VDegree());
1063 }
1064
1065 return surface;
1066
1067}
1068
1069//=======================================================================
1070//function : FirstShape
1071//purpose :
1072//=======================================================================
1073
1074const TopoDS_Shape& BRepOffsetAPI_ThruSections::FirstShape() const
1075{
1076 return myFirst;
1077}
1078
1079//=======================================================================
1080//function : LastShape
1081//purpose :
1082//=======================================================================
1083
1084const TopoDS_Shape& BRepOffsetAPI_ThruSections::LastShape() const
1085{
1086 return myLast;
1087}
1088
1089//=======================================================================
1090//function : GeneratedFace
1091//purpose :
1092//=======================================================================
1093
1094TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge) const
1095{
1096 TopoDS_Shape bid;
1097 if (myGenerated.IsBound(edge)) {
1098 return myGenerated(edge);
1099 }
1100 else {
1101 return bid;
1102 }
1103}
1104
1105
1106//=======================================================================
1107//function : CriteriumWeight
0d969553 1108//purpose : returns the Weights associated to the criterium used in
7fd59977 1109// the optimization.
1110//=======================================================================
1111//
1112void BRepOffsetAPI_ThruSections::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const
1113{
1114 W1 = myCritWeights[0];
1115 W2 = myCritWeights[1];
1116 W3 = myCritWeights[2];
1117}
1118//=======================================================================
1119//function : SetCriteriumWeight
1120//purpose :
1121//=======================================================================
1122
1123void BRepOffsetAPI_ThruSections::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3)
1124{
1125 if (W1 < 0 || W2 < 0 || W3 < 0 ) Standard_DomainError::Raise();
1126 myCritWeights[0] = W1;
1127 myCritWeights[1] = W2;
1128 myCritWeights[2] = W3;
1129}
1130//=======================================================================
1131//function : SetContinuity
1132//purpose :
1133//=======================================================================
1134
1135void BRepOffsetAPI_ThruSections::SetContinuity (const GeomAbs_Shape TheCont)
1136{
1137 myContinuity = TheCont;
1138}
1139
1140//=======================================================================
1141//function : Continuity
1142//purpose :
1143//=======================================================================
1144
1145GeomAbs_Shape BRepOffsetAPI_ThruSections::Continuity () const
1146{
1147 return myContinuity;
1148}
1149
1150//=======================================================================
1151//function : SetParType
1152//purpose :
1153//=======================================================================
1154
1155void BRepOffsetAPI_ThruSections::SetParType (const Approx_ParametrizationType ParType)
1156{
1157 myParamType = ParType;
1158}
1159
1160//=======================================================================
1161//function : ParType
1162//purpose :
1163//=======================================================================
1164
1165Approx_ParametrizationType BRepOffsetAPI_ThruSections::ParType () const
1166{
1167 return myParamType;
1168}
1169
1170//=======================================================================
1171//function : SetMaxDegree
1172//purpose :
1173//=======================================================================
1174
1175void BRepOffsetAPI_ThruSections:: SetMaxDegree(const Standard_Integer MaxDeg)
1176{
1177 myDegMax = MaxDeg;
1178}
1179
1180//=======================================================================
1181//function : MaxDegree
1182//purpose :
1183//=======================================================================
1184
1185Standard_Integer BRepOffsetAPI_ThruSections::MaxDegree () const
1186{
1187 return myDegMax;
1188}
1189
1190//=======================================================================
1191//function : SetSmoothing
1192//purpose :
1193//=======================================================================
1194
1195void BRepOffsetAPI_ThruSections::SetSmoothing(const Standard_Boolean UseVar)
1196{
1197 myUseSmoothing = UseVar;
1198}
1199
1200//=======================================================================
1201//function : UseSmoothing
1202//purpose :
1203//=======================================================================
1204
1205Standard_Boolean BRepOffsetAPI_ThruSections::UseSmoothing () const
1206{
1207 return myUseSmoothing;
1208}
1209
1210
1211
1212
1213