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