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