0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[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>
70737683 55#include <BRepTools_ReShape.hxx>
42cf5bc1 56#include <BSplCLib.hxx>
57#include <Geom2d_Line.hxx>
58#include <Geom_BezierCurve.hxx>
42cf5bc1 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>
42cf5bc1 78#include <TopExp.hxx>
79#include <TopLoc_Location.hxx>
7fd59977 80#include <TopoDS.hxx>
7fd59977 81#include <TopoDS_Edge.hxx>
42cf5bc1 82#include <TopoDS_Face.hxx>
83#include <TopoDS_Iterator.hxx>
84#include <TopoDS_Shape.hxx>
85#include <TopoDS_Solid.hxx>
7fd59977 86#include <TopoDS_Vertex.hxx>
87#include <TopoDS_Wire.hxx>
7fd59977 88#include <TopTools_Array1OfShape.hxx>
70737683 89#include <TopTools_DataMapOfShapeReal.hxx>
90#include <TopTools_DataMapIteratorOfDataMapOfShapeReal.hxx>
7fd59977 91#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
50258e77 92#include <BRepAdaptor_Surface.hxx>
7fd59977 93
aadab519 94//=======================================================================
95//function : PreciseUpar
96//purpose : pins the u-parameter of surface close to U-knot
97// to this U-knot
98//=======================================================================
aadab519 99static Standard_Real PreciseUpar(const Standard_Real anUpar,
e01907f1 100 const Handle(Geom_BSplineSurface)& aSurface)
aadab519 101{
102 Standard_Real Tol = Precision::PConfusion();
103 Standard_Integer i1, i2;
7fd59977 104
aadab519 105 aSurface->LocateU(anUpar, Tol, i1, i2);
106 Standard_Real U1 = aSurface->UKnot(i1);
107 Standard_Real U2 = aSurface->UKnot(i2);
108
109 Standard_Real NewU = anUpar;
110
111 NewU = (anUpar - U1 < U2 - anUpar)? U1 : U2;
112 return NewU;
113}
7fd59977 114
115//=======================================================================
116//function : PerformPlan
0d969553 117//purpose : Construct a plane of filling if exists
7fd59977 118//=======================================================================
119
120static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
e01907f1 121 const Standard_Real presPln,
122 TopoDS_Face& theFace)
7fd59977 123{
124 Standard_Boolean isDegen = Standard_True;
125 TopoDS_Iterator iter(W);
126 for (; iter.More(); iter.Next())
e01907f1 127 {
128 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
129 if (!BRep_Tool::Degenerated(anEdge))
130 isDegen = Standard_False;
131 }
7fd59977 132 if (isDegen)
133 return Standard_True;
134
135 Standard_Boolean Ok = Standard_False;
136 if (!W.IsNull()) {
137 BRepBuilderAPI_FindPlane Searcher( W, presPln );
138 if (Searcher.Found())
e01907f1 139 {
140 theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
141 Ok = Standard_True;
142 }
7fd59977 143 else // try to find another surface
e01907f1 144 {
145 BRepBuilderAPI_MakeFace MF( W );
146 if (MF.IsDone())
7fd59977 147 {
e01907f1 148 theFace = MF.Face();
149 Ok = Standard_True;
7fd59977 150 }
e01907f1 151 }
7fd59977 152 }
153
e01907f1 154 return Ok;
7fd59977 155}
156
157//=============================================================================
158//function : IsSameOriented
159//purpose : Checks whether aFace is oriented to the same side as aShell or not
160//=============================================================================
161
162static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
e01907f1 163 const TopoDS_Shape& aShell)
7fd59977 164{
165 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
166 TopoDS_Shape anEdge = Explo.Current();
167 TopAbs_Orientation Or1 = anEdge.Orientation();
168
169 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
170 TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
171
172 const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
173 TopoDS_Shape theEdge;
174 for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
e01907f1 175 {
176 theEdge = Explo.Current();
177 if (theEdge.IsSame(anEdge))
178 break;
179 }
7fd59977 180
181 TopAbs_Orientation Or2 = theEdge.Orientation();
182 if (Or1 == Or2)
183 return Standard_False;
184 return Standard_True;
185}
186
187//=======================================================================
188//function : MakeSolid
189//purpose :
190//=======================================================================
191
192static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
e01907f1 193 const TopoDS_Wire& wire2, const Standard_Real presPln,
194 TopoDS_Face& face1, TopoDS_Face& face2)
7fd59977 195{
196 if (shell.IsNull())
9775fa61 197 throw StdFail_NotDone("Thrusections is not build");
7fd59977 198 Standard_Boolean B = shell.Closed();
199 BRep_Builder BB;
200
201 if (!B)
e01907f1 202 {
203 // It is necessary to close the extremities
204 B = PerformPlan(wire1, presPln, face1);
205 if (B) {
206 B = PerformPlan(wire2, presPln, face2);
7fd59977 207 if (B) {
e01907f1 208 if (!face1.IsNull() && !IsSameOriented( face1, shell ))
209 face1.Reverse();
210 if (!face2.IsNull() && !IsSameOriented( face2, shell ))
211 face2.Reverse();
212
213 if (!face1.IsNull())
214 BB.Add(shell, face1);
215 if (!face2.IsNull())
216 BB.Add(shell, face2);
217
218 shell.Closed(Standard_True);
7fd59977 219 }
220 }
e01907f1 221 }
7fd59977 222
223 TopoDS_Solid solid;
224 BB.MakeSolid(solid);
225 BB.Add(solid, shell);
e01907f1 226
7fd59977 227 // verify the orientation the solid
228 BRepClass3d_SolidClassifier clas3d(solid);
229 clas3d.PerformInfinitePoint(Precision::Confusion());
230 if (clas3d.State() == TopAbs_IN) {
231 BB.MakeSolid(solid);
232 TopoDS_Shape aLocalShape = shell.Reversed();
233 BB.Add(solid, TopoDS::Shell(aLocalShape));
e01907f1 234 // B.Add(solid, TopoDS::Shell(newShell.Reversed()));
7fd59977 235 }
236
237 solid.Closed(Standard_True);
238 return solid;
239}
240
241
242//=======================================================================
243//function : BRepOffsetAPI_ThruSections
244//purpose :
245//=======================================================================
246
50258e77 247BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid,
248 const Standard_Boolean ruled,
249 const Standard_Real pres3d):
250 myNbEdgesInSection(0),
251 myIsSolid(isSolid), myIsRuled(ruled),
252 myPres3d(pres3d),
253 myDegen1(Standard_False), myDegen2(Standard_False)
7fd59977 254{
255 myWCheck = Standard_True;
70737683 256 myMutableInput = Standard_True;
e01907f1 257 //----------------------------
7fd59977 258 myParamType = Approx_ChordLength;
259 myDegMax = 8;
260 myContinuity = GeomAbs_C2;
261 myCritWeights[0] = .4;
262 myCritWeights[1] = .2;
263 myCritWeights[2] = .4;
264 myUseSmoothing = Standard_False;
3eb891ec 265 myStatus = BRepFill_ThruSectionErrorStatus_NotDone;
7fd59977 266}
267
268
269//=======================================================================
270//function : Init
271//purpose :
272//=======================================================================
273
274void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
e01907f1 275 const Standard_Real pres3d)
7fd59977 276{
277 myIsSolid = isSolid;
278 myIsRuled = ruled;
279 myPres3d = pres3d;
280 myWCheck = Standard_True;
70737683 281 myMutableInput = Standard_True;
e01907f1 282 //----------------------------
7fd59977 283 myParamType = Approx_ChordLength;
284 myDegMax = 6;
285 myContinuity = GeomAbs_C2;
286 myCritWeights[0] = .4;
287 myCritWeights[1] = .2;
288 myCritWeights[2] = .4;
289 myUseSmoothing = Standard_False;
3eb891ec 290 myStatus = BRepFill_ThruSectionErrorStatus_NotDone;
7fd59977 291}
292
293
294//=======================================================================
295//function : AddWire
296//purpose :
297//=======================================================================
298
299void BRepOffsetAPI_ThruSections::AddWire(const TopoDS_Wire& wire)
300{
301 myWires.Append(wire);
4f7d41ea 302 myInputWires.Append(wire);
7fd59977 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 );
7fd59977 319
320 TopoDS_Wire DegWire;
321 BB.MakeWire( DegWire );
322 BB.Add( DegWire, DegEdge );
323 DegWire.Closed( Standard_True );
324
325 myWires.Append( DegWire );
4f7d41ea 326 myInputWires.Append(DegWire);
7fd59977 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
d03c0898 345void BRepOffsetAPI_ThruSections::Build(const Message_ProgressRange& /*theRange*/)
7fd59977 346{
3eb891ec 347 myStatus = BRepFill_ThruSectionErrorStatus_Done;
70737683 348 myBFGenerator.Nullify();
7fd59977 349 //Check set of section for right configuration of punctual sections
350 Standard_Integer i;
351 TopExp_Explorer explo;
352 for (i = 2; i <= myWires.Length()-1; i++)
e01907f1 353 {
354 Standard_Boolean wdeg = Standard_True;
355 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
7fd59977 356 {
e01907f1 357 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
358 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
7fd59977 359 }
e01907f1 360 if (wdeg)
3eb891ec 361 {
362 myStatus = BRepFill_ThruSectionErrorStatus_WrongUsage;
363 return;
364 }
e01907f1 365 }
7fd59977 366 if (myWires.Length() <= 2)
e01907f1 367 {
368 Standard_Boolean wdeg = Standard_True;
369 for (i = 1; i <= myWires.Length(); i++)
c48e2889 370 {
e01907f1 371 for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
372 {
373 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
374 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
375 }
c48e2889 376 }
377 if (wdeg)
378 {
3eb891ec 379 myStatus = BRepFill_ThruSectionErrorStatus_WrongUsage;
380 return;
c48e2889 381 }
e01907f1 382 }
7fd59977 383
50258e77 384 myNbEdgesInSection = 0;
385
7fd59977 386 if (myWCheck) {
387 // compute origin and orientation on wires to avoid twisted results
388 // and update wires to have same number of edges
e01907f1 389
0d969553 390 // use BRepFill_CompatibleWires
7fd59977 391 TopTools_SequenceOfShape WorkingSections;
392 WorkingSections.Clear();
393 TopTools_DataMapOfShapeListOfShape WorkingMap;
394 WorkingMap.Clear();
e01907f1 395
0d969553 396 // Calculate the working sections
7fd59977 397 BRepFill_CompatibleWires Georges(myWires);
398 Georges.Perform();
399 if (Georges.IsDone()) {
400 WorkingSections = Georges.Shape();
401 WorkingMap = Georges.Generated();
50258e77 402 myDegen1 = Georges.IsDegeneratedFirstSection();
403 myDegen2 = Georges.IsDegeneratedLastSection();
404 //For each sub-edge of each section
405 //we save its splits
406 Standard_Integer IndFirstSec = 1;
407 if (Georges.IsDegeneratedFirstSection())
408 IndFirstSec = 2;
bf97419a 409 TopoDS_Wire aWorkingSection = TopoDS::Wire(WorkingSections(IndFirstSec));
b2d1851c 410 myNbEdgesInSection += aWorkingSection.NbChildren();
50258e77 411 for (Standard_Integer ii = 1; ii <= myWires.Length(); ii++)
412 {
bf97419a 413 TopoDS_Iterator itw(myWires(ii));
414 for (; itw.More(); itw.Next())
50258e77 415 {
bf97419a 416 const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
50258e77 417 Standard_Integer aSign = 1;
418 TopoDS_Vertex Vfirst, Vlast;
419 TopExp::Vertices(anEdge, Vfirst, Vlast);
b2fedee6 420 const TopTools_ListOfShape& aNewEdges = Georges.GeneratedShapes(anEdge);
50258e77 421 TColStd_ListOfInteger IList;
bf97419a 422 aWorkingSection = TopoDS::Wire(WorkingSections(ii));
50258e77 423 Standard_Integer NbNewEdges = aNewEdges.Extent();
424 TopTools_ListIteratorOfListOfShape itl(aNewEdges);
425 for (Standard_Integer kk = 1; itl.More(); itl.Next(),kk++)
426 {
427 const TopoDS_Edge& aNewEdge = TopoDS::Edge(itl.Value());
428 Standard_Integer inde = 1;
bf97419a 429 BRepTools_WireExplorer wexp(aWorkingSection);
430 for (; wexp.More(); wexp.Next(), inde++)
50258e77 431 {
bf97419a 432 const TopoDS_Shape& aWorkingEdge = wexp.Current();
50258e77 433 if (aWorkingEdge.IsSame(aNewEdge))
434 {
435 aSign = (aWorkingEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
436 break;
437 }
438 }
439 IList.Append(inde);
440 if (kk == 1 || kk == NbNewEdges)
441 {
442 //For each sub-vertex of each section
443 //we save its index of new edge
444 TopoDS_Vertex NewVfirst, NewVlast;
445 TopExp::Vertices(aNewEdge, NewVfirst, NewVlast);
446 if (NewVfirst.IsSame(Vfirst) && !myVertexIndex.IsBound(Vfirst))
447 myVertexIndex.Bind(Vfirst, aSign*inde);
448 if (NewVlast.IsSame(Vlast) && !myVertexIndex.IsBound(Vlast))
449 myVertexIndex.Bind(Vlast, aSign*(-inde));
450 }
451 }
452 myEdgeNewIndices.Bind(anEdge, IList);
453 }
454 }
7fd59977 455 }
3eb891ec 456 else
457 {
458 myStatus = Georges.GetStatus();
459 NotDone();
460 return;
461 }
462
7fd59977 463 myWires = WorkingSections;
50258e77 464 } //if (myWCheck)
465 else //no check
466 {
467 TopoDS_Edge anEdge;
468 for (Standard_Integer ii = 1; ii <= myWires.Length(); ii++)
469 {
470 TopExp_Explorer Explo(myWires(ii), TopAbs_EDGE);
471 Standard_Integer inde = 1;
472 for (; Explo.More(); Explo.Next(),inde++)
473 {
474 anEdge = TopoDS::Edge(Explo.Current());
475 TColStd_ListOfInteger IList;
476 IList.Append(inde);
477 myEdgeNewIndices.Bind(anEdge, IList);
478 TopoDS_Vertex V1, V2;
479 TopExp::Vertices(anEdge, V1, V2);
480 if (!myVertexIndex.IsBound(V1))
481 myVertexIndex.Bind(V1, inde);
482 if (!myVertexIndex.IsBound(V2))
483 myVertexIndex.Bind(V2, -inde);
484 }
485 inde--;
486 if (inde > myNbEdgesInSection)
487 myNbEdgesInSection = inde;
488 if (inde == 1 && BRep_Tool::Degenerated(anEdge))
489 {
490 if (ii == 1)
491 myDegen1 = Standard_True;
492 else
493 myDegen2 = Standard_True;
494 }
495 }
7fd59977 496 }
497
a4bb1420 498 try {
499 // Calculate the resulting shape
500 if (myWires.Length() == 2 || myIsRuled) {
501 // create a ruled shell
502 CreateRuled();
503 }
504 else {
505 // create a smoothed shell
506 CreateSmoothed();
507 }
7fd59977 508 }
a738b534 509 catch (Standard_Failure const&)
a4bb1420 510 {
511 NotDone();
512 return;
7fd59977 513 }
3eb891ec 514
515 if (myStatus != BRepFill_ThruSectionErrorStatus_Done)
516 {
517 NotDone();
518 return;
519 }
7fd59977 520 // Encode the Regularities
521 BRepLib::EncodeRegularity(myShape);
7fd59977 522}
523
524
525//=======================================================================
526//function : CreateRuled
527//purpose :
528//=======================================================================
529
530void BRepOffsetAPI_ThruSections::CreateRuled()
531{
532 Standard_Integer nbSects = myWires.Length();
70737683 533 myBFGenerator = new BRepFill_Generator();
534 myBFGenerator->SetMutableInput(IsMutableInput());
e01907f1 535 // for (Standard_Integer i=1; i<=nbSects; i++) {
7fd59977 536 Standard_Integer i;
70737683 537 for (i=1; i<=nbSects; i++)
538 {
539 myBFGenerator->AddWire(TopoDS::Wire(myWires(i)));
7fd59977 540 }
70737683 541 myBFGenerator->Perform();
3eb891ec 542 BRepFill_ThruSectionErrorStatus aStatus = myBFGenerator->GetStatus();
543 if (aStatus != BRepFill_ThruSectionErrorStatus_Done)
544 {
545 myStatus = aStatus;
546 return;
547 }
70737683 548 TopoDS_Shell shell = myBFGenerator->Shell();
7fd59977 549
550 if (myIsSolid) {
551
0d969553 552 // check if the first wire is the same as the last
7fd59977 553 Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ;
554
555 if (vClosed) {
556
70737683 557 TopoDS_Solid solid;
7fd59977 558 BRep_Builder B;
559 B.MakeSolid(solid);
560 B.Add(solid, shell);
e01907f1 561
0d969553 562 // verify the orientation of the solid
7fd59977 563 BRepClass3d_SolidClassifier clas3d(solid);
564 clas3d.PerformInfinitePoint(Precision::Confusion());
565 if (clas3d.State() == TopAbs_IN) {
e01907f1 566 B.MakeSolid(solid);
567 TopoDS_Shape aLocalShape = shell.Reversed();
568 B.Add(solid, TopoDS::Shell(aLocalShape));
569 // B.Add(solid, TopoDS::Shell(shell.Reversed()));
7fd59977 570 }
571 myShape = solid;
572
573 }
574
575 else {
70737683 576 //myBFGenerator stores the same 'myWires'
577 TopoDS_Wire wire1 = TopoDS::Wire(myBFGenerator->ResultShape(myWires.First()));
578 TopoDS_Wire wire2 = TopoDS::Wire(myBFGenerator->ResultShape(myWires.Last()));
7fd59977 579
7fd59977 580 myShape = MakeSolid(shell, wire1, wire2, myPres3d, myFirst, myLast);
581
582 }
583
584 Done();
585 }
586
587 else {
588 myShape = shell;
589 Done();
590 }
591
592 // history
593 BRepTools_WireExplorer anExp1, anExp2;
594 TopTools_IndexedDataMapOfShapeListOfShape M;
595 TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, TopAbs_FACE, M);
596 TopTools_ListIteratorOfListOfShape it;
597
598 TopTools_IndexedDataMapOfShapeListOfShape MV;
599 TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
e01907f1 600
7fd59977 601 for (i=1; i<=nbSects-1; i++) {
e01907f1 602
7fd59977 603 const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
604 const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
e01907f1 605
7fd59977 606 anExp1.Init(wire1);
607 anExp2.Init(wire2);
608
609 Standard_Boolean tantque = anExp1.More() && anExp2.More();
610
611 while (tantque) {
612
613 const TopoDS_Shape& edge1 = anExp1.Current();
614 const TopoDS_Shape& edge2 = anExp2.Current();
615 Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
616 Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
e01907f1 617
7fd59977 618 TopTools_MapOfShape MapFaces;
70737683 619 if (degen2)
620 {
621 TopoDS_Vertex Vdegen = TopoDS::Vertex(myBFGenerator->ResultShape(TopExp::FirstVertex(TopoDS::Edge(edge2))));
622 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next())
623 {
e01907f1 624 MapFaces.Add(it.Value());
625 }
7fd59977 626 }
70737683 627 else
628 {
629 for (it.Initialize(M.FindFromKey(myBFGenerator->ResultShape(edge2))); it.More(); it.Next())
630 {
e01907f1 631 MapFaces.Add(it.Value());
632 }
7fd59977 633 }
e01907f1 634
70737683 635 if (degen1)
636 {
637 TopoDS_Vertex Vdegen = TopoDS::Vertex(myBFGenerator->ResultShape(TopExp::FirstVertex(TopoDS::Edge(edge1))));
638 for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next())
639 {
e01907f1 640 const TopoDS_Shape& Face = it.Value();
70737683 641 if (MapFaces.Contains(Face))
642 {
50258e77 643 myEdgeFace.Bind(edge1, Face);
e01907f1 644 break;
645 }
646 }
7fd59977 647 }
648 else {
70737683 649 for (it.Initialize(M.FindFromKey(myBFGenerator->ResultShape(edge1))); it.More(); it.Next()) {
e01907f1 650 const TopoDS_Shape& Face = it.Value();
651 if (MapFaces.Contains(Face)) {
50258e77 652 myEdgeFace.Bind(edge1, Face);
e01907f1 653 break;
654 }
655 }
7fd59977 656 }
e01907f1 657
7fd59977 658 if (!degen1) anExp1.Next();
659 if (!degen2) anExp2.Next();
e01907f1 660
7fd59977 661 tantque = anExp1.More() && anExp2.More();
662 if (degen1) tantque = anExp2.More();
663 if (degen2) tantque = anExp1.More();
e01907f1 664
7fd59977 665 }
e01907f1 666
7fd59977 667 }
e01907f1 668
7fd59977 669}
670
671//=======================================================================
672//function : CreateSmoothed
673//purpose :
674//=======================================================================
675
676void BRepOffsetAPI_ThruSections::CreateSmoothed()
677{
678 // initialisation
679 Standard_Integer nbSects = myWires.Length();
680 BRepTools_WireExplorer anExp;
681
682 Standard_Boolean w1Point = Standard_True;
0d969553 683 // check if the first wire is punctual
7fd59977 684 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
685 w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current()));
686 }
687
688 Standard_Boolean w2Point = Standard_True;
0d969553 689 // check if the last wire is punctual
7fd59977 690 for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) {
691 w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current()));
692 }
693
694 Standard_Boolean vClosed = Standard_False;
0d969553 695 // check if the first wire is the same as last
7fd59977 696 if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True;
697
698 // find the dimension
699 Standard_Integer nbEdges=0;
700 if (!w1Point) {
701 for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
702 nbEdges++;
703 }
704 }
705 else {
706 for(anExp.Init(TopoDS::Wire(myWires(2))); anExp.More(); anExp.Next()) {
707 nbEdges++;
708 }
709 }
710
711 // recover the shapes
712 Standard_Boolean uClosed = Standard_True;
713 TopTools_Array1OfShape shapes(1, nbSects*nbEdges);
714 Standard_Integer nb=0, i, j;
715
716 for (i=1; i<=nbSects; i++) {
717 const TopoDS_Wire& wire = TopoDS::Wire(myWires(i));
718 if (!wire.Closed()) {
0d969553 719 // check if the vertices are the same
7fd59977 720 TopoDS_Vertex V1, V2;
721 TopExp::Vertices(wire,V1,V2);
722 if ( !V1.IsSame(V2)) uClosed = Standard_False;
723 }
724 if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) {
0d969553 725 // if the wire is punctual
7fd59977 726 anExp.Init(TopoDS::Wire(wire));
727 for(j=1; j<=nbEdges; j++) {
e01907f1 728 nb++;
729 shapes(nb) = anExp.Current();
7fd59977 730 }
731 }
732 else {
0d969553 733 // otherwise
7fd59977 734 for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
e01907f1 735 nb++;
736 shapes(nb) = anExp.Current();
7fd59977 737 }
738 }
739 }
740
741 // create the new surface
742 TopoDS_Shell shell;
743 TopoDS_Face face;
744 TopoDS_Wire W;
745 TopoDS_Edge edge, edge1, edge2, edge3, edge4, couture;
746 TopTools_Array1OfShape vcouture(1, nbEdges);
747
748 BRep_Builder B;
749 B.MakeShell(shell);
750
751 TopoDS_Wire newW1, newW2;
752 BRep_Builder BW1, BW2;
753 BW1.MakeWire(newW1);
754 BW2.MakeWire(newW2);
755
756 TopLoc_Location loc;
757 TopoDS_Vertex v1f,v1l,v2f,v2l;
758
7fd59977 759 Standard_Integer nbPnts = 21;
760 TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
761
0d969553 762 // concatenate each section to get a total surface that will be segmented
7fd59977 763 Handle(Geom_BSplineSurface) TS;
764 TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed);
765
766 if(TS.IsNull()) {
3eb891ec 767 myStatus = BRepFill_ThruSectionErrorStatus_Failed;
7fd59977 768 return;
769 }
770
771 TopoDS_Shape firstEdge;
772 for (i=1; i<=nbEdges; i++) {
773
0d969553 774 // segmentation of TS
7fd59977 775 Handle(Geom_BSplineSurface) surface;
776 surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy());
777 Standard_Real Ui1,Ui2,V0,V1;
778 Ui1 = i-1;
779 Ui2 = i;
aadab519 780 Ui1 = PreciseUpar(Ui1, surface);
781 Ui2 = PreciseUpar(Ui2, surface);
7fd59977 782 V0 = surface->VKnot(surface->FirstVKnotIndex());
783 V1 = surface->VKnot(surface->LastVKnotIndex());
784 surface->Segment(Ui1,Ui2,V0,V1);
785
0d969553 786 // return vertices
7fd59977 787 edge = TopoDS::Edge(shapes(i));
788 TopExp::Vertices(edge,v1f,v1l);
789 if (edge.Orientation() == TopAbs_REVERSED)
790 TopExp::Vertices(edge,v1l,v1f);
791 firstEdge = edge;
792
793 edge = TopoDS::Edge(shapes((nbSects-1)*nbEdges+i));
794 TopExp::Vertices(edge,v2f,v2l);
795 if (edge.Orientation() == TopAbs_REVERSED)
796 TopExp::Vertices(edge,v2l,v2f);
797
798 // make the face
799 B.MakeFace(face, surface, Precision::Confusion());
800
801 // make the wire
802 B.MakeWire(W);
e01907f1 803
7fd59977 804 // make the missing edges
805 Standard_Real f1, f2, l1, l2;
806 surface->Bounds(f1,l1,f2,l2);
e01907f1 807
7fd59977 808 // --- edge 1
809 if ( w1Point ) {
0d969553 810 // copy the degenerated edge
7fd59977 811 TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
812 edge1 = TopoDS::Edge(aLocalShape);
e01907f1 813 // edge1 = TopoDS::Edge(shapes(1).EmptyCopied());
7fd59977 814 edge1.Orientation(TopAbs_FORWARD);
815 }
816 else {
817 B.MakeEdge(edge1, surface->VIso(f2), Precision::Confusion());
818 }
819 v1f.Orientation(TopAbs_FORWARD);
820 B.Add(edge1, v1f);
821 v1l.Orientation(TopAbs_REVERSED);
822 B.Add(edge1, v1l);
823 B.Range(edge1, f1, l1);
0d969553
Y
824 // processing of looping sections
825 // store edges of the 1st section
7fd59977 826 if (vClosed)
827 vcouture(i) = edge1;
e01907f1 828
7fd59977 829
830 // --- edge 2
831 if (vClosed)
832 edge2 = TopoDS::Edge(vcouture(i));
833 else {
834 if ( w2Point ) {
e01907f1 835 // copy of the degenerated edge
836 TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
837 edge2 = TopoDS::Edge(aLocalShape);
838 // edge2 = TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
839 edge2.Orientation(TopAbs_FORWARD);
7fd59977 840 }
841 else {
e01907f1 842 B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
7fd59977 843 }
844 v2f.Orientation(TopAbs_FORWARD);
845 B.Add(edge2, v2f);
846 v2l.Orientation(TopAbs_REVERSED);
847 B.Add(edge2, v2l);
848 B.Range(edge2, f1, l1);
849 }
850 edge2.Reverse();
851
852
853 // --- edge 3
854 if (i==1) {
855 B.MakeEdge(edge3, surface->UIso(f1), Precision::Confusion());
856 v1f.Orientation(TopAbs_FORWARD);
857 B.Add(edge3, v1f);
858 v2f.Orientation(TopAbs_REVERSED);
859 B.Add(edge3, v2f);
860 B.Range(edge3, f2, l2);
861 if (uClosed) {
e01907f1 862 couture = edge3;
7fd59977 863 }
864 }
865 else {
866 edge3 = edge4;
867 }
868 edge3.Reverse();
869
870 // --- edge 4
871 if ( uClosed && i==nbEdges) {
872 edge4 = couture;
873 }
874 else {
875 B.MakeEdge(edge4, surface->UIso(l1), Precision::Confusion());
876 v1l.Orientation(TopAbs_FORWARD);
877 B.Add(edge4, v1l);
878 v2l.Orientation(TopAbs_REVERSED);
879 B.Add(edge4, v2l);
880 B.Range(edge4, f2, l2);
881 }
882
883 B.Add(W,edge1);
884 B.Add(W,edge4);
885 B.Add(W,edge2);
886 B.Add(W,edge3);
887
888 // set PCurve
889 if (vClosed) {
890 B.UpdateEdge(edge1,
e01907f1 891 new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
892 new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
893 Precision::Confusion());
7fd59977 894 B.Range(edge1,face,f1,l1);
895 }
896 else {
897 B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
e01907f1 898 Precision::Confusion());
7fd59977 899 B.Range(edge1,face,f1,l1);
900 B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
e01907f1 901 Precision::Confusion());
7fd59977 902 B.Range(edge2,face,f1,l1);
903 }
904
905 if ( uClosed && nbEdges ==1 ) {
906 B.UpdateEdge(edge3,
e01907f1 907 new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
908 new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
909 Precision::Confusion());
7fd59977 910 B.Range(edge3,face,f2,l2);
911
912 }
913 else {
914 B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
e01907f1 915 Precision::Confusion());
7fd59977 916 B.Range(edge3,face,f2,l2);
917 B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
e01907f1 918 Precision::Confusion());
7fd59977 919 B.Range(edge4,face,f2,l2);
920 }
921 B.Add(face,W);
922 B.Add(shell, face);
923
924 // complete newW1 newW2
925 TopoDS_Edge edge12 = edge1;
926 TopoDS_Edge edge22 = edge2;
927 edge12.Reverse();
928 edge22.Reverse();
929 BW1.Add(newW1, edge12);
930 BW2.Add(newW2, edge22);
931
932 // history
50258e77 933 myEdgeFace.Bind(firstEdge, face);
7fd59977 934 }
935
936 if (uClosed && w1Point && w2Point)
937 shell.Closed(Standard_True);
938
939 if (myIsSolid) {
940
941 if (vClosed) {
942
943 TopoDS_Solid solid;
7fd59977 944 B.MakeSolid(solid);
945 B.Add(solid, shell);
e01907f1 946
7fd59977 947 // verify the orientation the solid
948 BRepClass3d_SolidClassifier clas3d(solid);
949 clas3d.PerformInfinitePoint(Precision::Confusion());
950 if (clas3d.State() == TopAbs_IN) {
e01907f1 951 B.MakeSolid(solid);
952 TopoDS_Shape aLocalShape = shell.Reversed();
953 B.Add(solid, TopoDS::Shell(aLocalShape));
954 // B.Add(solid, TopoDS::Shell(shell.Reversed()));
7fd59977 955 }
956 myShape = solid;
957
958 }
959
960 else {
961 myShape = MakeSolid(shell, newW1, newW2, myPres3d, myFirst, myLast);
962 }
7fd59977 963 }
964
965 else {
966 myShape = shell;
7fd59977 967 }
3eb891ec 968 Done();
e01907f1 969
70737683 970 TopTools_DataMapOfShapeReal aVertexToleranceMap;
971 TopExp_Explorer aTopExplorer(myShape,TopAbs_EDGE);
972 while (aTopExplorer.More())
973 {
974 const TopoDS_Edge& aCurEdge = TopoDS::Edge(aTopExplorer.Current());
975 B.SameRange(aCurEdge, Standard_False);
976 B.SameParameter(aCurEdge, Standard_False);
977 Standard_Real aTolerance = BRep_Tool::Tolerance(aCurEdge);
978 if (myMutableInput)
979 {
980 BRepLib::SameParameter(aCurEdge,aTolerance);
981 }
982 else
983 {
984 //all edges from myShape can be safely updated/changed
985 //all vertices from myShape are the part of the original wires
986 Standard_Real aNewTolerance = -1;
987 BRepLib::SameParameter(aCurEdge, aTolerance, aNewTolerance, Standard_True);
988 if (aNewTolerance > 0)
989 {
990 TopoDS_Vertex aVertex1, aVertex2;
991 TopExp::Vertices(aCurEdge,aVertex1,aVertex2);
992 if (!aVertex1.IsNull())
993 {
994 const Standard_Real* anOldTolerance = aVertexToleranceMap.Seek(aVertex1);
995 if (!anOldTolerance || (anOldTolerance && *anOldTolerance < aNewTolerance))
996 {
997 aVertexToleranceMap.Bind(aVertex1,aNewTolerance);
998 }
999 }
1000 if (!aVertex2.IsNull())
1001 {
1002 const Standard_Real* anOldTolerance = aVertexToleranceMap.Seek(aVertex2);
1003 if (!anOldTolerance || (anOldTolerance && *anOldTolerance < aNewTolerance))
1004 {
1005 aVertexToleranceMap.Bind(aVertex2,aNewTolerance);
1006 }
1007 }
1008 }
1009 }
1010 aTopExplorer.Next();
1011 }
1012
1013 if (!myMutableInput)
1014 {
1015 BRepTools_ReShape aReshaper;
1016 TopTools_DataMapIteratorOfDataMapOfShapeReal aMapIterator(aVertexToleranceMap);
1017 for (;aMapIterator.More();aMapIterator.Next())
1018 {
1019 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aMapIterator.Key());
1020 Standard_Real aNewTolerance = aMapIterator.Value();
1021 if (BRep_Tool::Tolerance(aVertex) < aNewTolerance)
1022 {
1023 TopoDS_Vertex aNnewVertex = TopoDS::Vertex(aVertex.EmptyCopied());
1024 B.UpdateVertex(aNnewVertex, aNewTolerance);
1025 aReshaper.Replace(aVertex, aNnewVertex);
1026 }
1027 }
1028 myShape = aReshaper.Apply(myShape);
7fd59977 1029 }
1030}
1031
5e5b6f81 1032//=======================================================================
1033//function : EdgeToBSpline
1034//purpose : auxiliary -- get curve from edge and convert it to bspline
1035// parameterized from 0 to 1
1036//=======================================================================
1037
1038// NOTE: this code duplicates the same function in BRepFill_NSections.cxx
1039static Handle(Geom_BSplineCurve) EdgeToBSpline (const TopoDS_Edge& theEdge)
1040{
1041 Handle(Geom_BSplineCurve) aBSCurve;
1042 if (BRep_Tool::Degenerated(theEdge)) {
1043 // degenerated edge : construction of a point curve
1044 TColStd_Array1OfReal aKnots (1,2);
1045 aKnots(1) = 0.;
1046 aKnots(2) = 1.;
1047
1048 TColStd_Array1OfInteger aMults (1,2);
1049 aMults(1) = 2;
1050 aMults(2) = 2;
1051
1052 TColgp_Array1OfPnt aPoles(1,2);
1053 TopoDS_Vertex vf, vl;
1054 TopExp::Vertices(theEdge,vl,vf);
1055 aPoles(1) = BRep_Tool::Pnt(vf);
1056 aPoles(2) = BRep_Tool::Pnt(vl);
1057
1058 aBSCurve = new Geom_BSplineCurve (aPoles, aKnots, aMults, 1);
1059 }
1060 else
1061 {
1062 // get the curve of the edge
1063 TopLoc_Location aLoc;
1064 Standard_Real aFirst, aLast;
1065 Handle(Geom_Curve) aCurve = BRep_Tool::Curve (theEdge, aLoc, aFirst, aLast);
a4bb1420 1066 if (aCurve.IsNull())
3eb891ec 1067 {
1068 return nullptr;
1069 }
5e5b6f81 1070
1071 // convert its part used by edge to bspline; note that if edge curve is bspline,
1072 // conversion made via trimmed curve is still needed -- it will copy it, segment
1073 // as appropriate, and remove periodicity if it is periodic (deadly for approximator)
1074 Handle(Geom_TrimmedCurve) aTrimCurve = new Geom_TrimmedCurve (aCurve, aFirst, aLast);
1075
1076 // special treatment of conic curve
1077 if (aTrimCurve->BasisCurve()->IsKind(STANDARD_TYPE(Geom_Conic)))
1078 {
51740958 1079 const Handle(Geom_Curve)& aCurveTrimmed = aTrimCurve; // to avoid ambiguity
1080 GeomConvert_ApproxCurve anAppr (aCurveTrimmed, Precision::Confusion(), GeomAbs_C1, 16, 14);
5e5b6f81 1081 if (anAppr.HasResult())
1082 aBSCurve = anAppr.Curve();
1083 }
1084
1085 // general case
1086 if (aBSCurve.IsNull())
1087 aBSCurve = GeomConvert::CurveToBSplineCurve (aTrimCurve);
1088
1089 // apply transformation if needed
1090 if (! aLoc.IsIdentity())
1091 aBSCurve->Transform (aLoc.Transformation());
1092
1093 // reparameterize to [0,1]
1094 TColStd_Array1OfReal aKnots (1, aBSCurve->NbKnots());
1095 aBSCurve->Knots (aKnots);
1096 BSplCLib::Reparametrize (0., 1., aKnots);
1097 aBSCurve->SetKnots (aKnots);
1098 }
1099
1100 // reverse curve if edge is reversed
1101 if (theEdge.Orientation() == TopAbs_REVERSED)
1102 aBSCurve->Reverse();
1103
1104 return aBSCurve;
1105}
1106
7fd59977 1107//=======================================================================
1108//function : TotalSurf
1109//purpose :
1110//=======================================================================
1111
1112Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
e01907f1 1113 TotalSurf(const TopTools_Array1OfShape& shapes,
1114 const Standard_Integer NbSects,
1115 const Standard_Integer NbEdges,
1116 const Standard_Boolean w1Point,
1117 const Standard_Boolean w2Point,
1118 const Standard_Boolean vClosed) const
7fd59977 1119{
1120 Standard_Integer i,j,jdeb=1,jfin=NbSects;
7fd59977 1121 TopoDS_Vertex vf,vl;
1122
1123 GeomFill_SectionGenerator section;
1124 Handle(Geom_BSplineSurface) surface;
1125 Handle(Geom_BSplineCurve) BS, BS1;
1126 Handle(Geom_TrimmedCurve) curvTrim;
7fd59977 1127
1128 if (w1Point) {
1129 jdeb++;
e01907f1 1130 TopoDS_Edge edge = TopoDS::Edge(shapes(1));
7fd59977 1131 TopExp::Vertices(edge,vl,vf);
1132 TColgp_Array1OfPnt Extremities(1,2);
1133 Extremities(1) = BRep_Tool::Pnt(vf);
1134 Extremities(2) = BRep_Tool::Pnt(vl);
1135 TColStd_Array1OfReal Bounds(1,2);
1136 Bounds(1) = 0.;
1137 Bounds(2) = 1.;
7fd59977 1138 TColStd_Array1OfInteger Mult(1,2);
5e5b6f81 1139 Mult(1) = 2;
1140 Mult(2) = 2;
7fd59977 1141 Handle(Geom_BSplineCurve) BSPoint
5e5b6f81 1142 = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
7fd59977 1143 section.AddCurve(BSPoint);
1144 }
1145
1146 if (w2Point) {
1147 jfin--;
1148 }
1149
1150 for (j=jdeb; j<=jfin; j++) {
1151
0d969553 1152 // case of looping sections
7fd59977 1153 if (j==jfin && vClosed) {
1154 section.AddCurve(BS1);
1155 }
1156
1157 else {
1158 // read the first edge to initialise CompBS;
5e5b6f81 1159 TopoDS_Edge aPrevEdge = TopoDS::Edge (shapes((j-1)*NbEdges+1));
1160 Handle(Geom_BSplineCurve) curvBS = EdgeToBSpline (aPrevEdge);
3eb891ec 1161 if (curvBS.IsNull())
1162 {
1163 return nullptr;
1164 }
7fd59977 1165
0d969553 1166 // initialization
7fd59977 1167 GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
1168
1169 for (i=2; i<=NbEdges; i++) {
e01907f1 1170 // read the edge
5e5b6f81 1171 TopoDS_Edge aNextEdge = TopoDS::Edge (shapes((j-1)*NbEdges+i));
e01907f1 1172 Standard_Real aTolV = Precision::Confusion();
1173 TopExp::Vertices(aNextEdge,vf,vl);
1174 aTolV = Max(aTolV, BRep_Tool::Tolerance(vf));
1175 aTolV = Max(aTolV, BRep_Tool::Tolerance(vl));
1176 aTolV = Min(aTolV, 1.e-3);
5e5b6f81 1177 curvBS = EdgeToBSpline (aNextEdge);
3eb891ec 1178 if (curvBS.IsNull())
1179 {
1180 return nullptr;
1181 }
7fd59977 1182
e01907f1 1183 // concatenation
1184 CompBS.Add(curvBS, aTolV, Standard_True, Standard_False, 1);
7fd59977 1185 }
1186
0d969553 1187 // return the final section
7fd59977 1188 BS = CompBS.BSplineCurve();
1189 section.AddCurve(BS);
1190
0d969553 1191 // case of looping sections
7fd59977 1192 if (j==jdeb && vClosed) {
e01907f1 1193 BS1 = BS;
7fd59977 1194 }
1195
1196 }
1197 }
1198
1199 if (w2Point) {
e01907f1 1200 TopoDS_Edge edge = TopoDS::Edge(shapes(NbSects*NbEdges));
7fd59977 1201 TopExp::Vertices(edge,vl,vf);
1202 TColgp_Array1OfPnt Extremities(1,2);
1203 Extremities(1) = BRep_Tool::Pnt(vf);
1204 Extremities(2) = BRep_Tool::Pnt(vl);
1205 TColStd_Array1OfReal Bounds(1,2);
1206 Bounds(1) = 0.;
1207 Bounds(2) = 1.;
7fd59977 1208 TColStd_Array1OfInteger Mult(1,2);
5e5b6f81 1209 Mult(1) = 2;
1210 Mult(2) = 2;
7fd59977 1211 Handle(Geom_BSplineCurve) BSPoint
5e5b6f81 1212 = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
7fd59977 1213 section.AddCurve(BSPoint);
1214 }
1215
1216 section.Perform(Precision::PConfusion());
1217 Handle(GeomFill_Line) line = new GeomFill_Line(NbSects);
1218
1219 Standard_Integer nbIt = 3;
1220 if(myPres3d <= 1.e-3) nbIt = 0;
1221
1222 Standard_Integer degmin = 2, degmax = Max(myDegMax, degmin);
1223 Standard_Boolean SpApprox = Standard_True;
1224
1225 GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt);
1226 anApprox.SetContinuity(myContinuity);
1227
1228 if(myUseSmoothing) {
1229 anApprox.SetCriteriumWeight(myCritWeights[0], myCritWeights[1], myCritWeights[2]);
1230 anApprox.PerformSmoothing(line, section);
1231 }
1232 else {
1233 anApprox.SetParType(myParamType);
1234 anApprox.Perform(line, section, SpApprox);
1235 }
1236
1237 if(anApprox.IsDone()) {
1238 surface =
1239 new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
e01907f1 1240 anApprox.SurfUKnots(), anApprox.SurfVKnots(),
1241 anApprox.SurfUMults(), anApprox.SurfVMults(),
1242 anApprox.UDegree(), anApprox.VDegree());
7fd59977 1243 }
1244
1245 return surface;
e01907f1 1246
7fd59977 1247}
1248
1249//=======================================================================
1250//function : FirstShape
1251//purpose :
1252//=======================================================================
1253
1254const TopoDS_Shape& BRepOffsetAPI_ThruSections::FirstShape() const
1255{
1256 return myFirst;
1257}
1258
1259//=======================================================================
1260//function : LastShape
1261//purpose :
1262//=======================================================================
1263
1264const TopoDS_Shape& BRepOffsetAPI_ThruSections::LastShape() const
1265{
1266 return myLast;
1267}
1268
50258e77 1269//=======================================================================
1270//function : Generated
1271//purpose :
1272//=======================================================================
1273const TopTools_ListOfShape&
1274BRepOffsetAPI_ThruSections::Generated(const TopoDS_Shape& S)
1275{
1276 myGenerated.Clear();
1277
1278 TopTools_SequenceOfShape AllFaces;
1279 TopExp_Explorer Explo(myShape, TopAbs_FACE);
1280 for (; Explo.More(); Explo.Next())
1281 AllFaces.Append(Explo.Current());
1282
1283 if (S.ShapeType() == TopAbs_EDGE)
1284 {
1285 if (!myEdgeNewIndices.IsBound(S))
1286 return myGenerated;
1287
1288 const TColStd_ListOfInteger& Indices = myEdgeNewIndices(S);
1289 //Append the faces corresponding to <Indices>
1290 //These faces "grow" from the first section
1291 TColStd_ListIteratorOfListOfInteger itl(Indices);
1292 for (; itl.More(); itl.Next())
1293 {
1294 Standard_Integer IndOfFace = itl.Value();
0e97c80e 1295 if (AllFaces.Size() < IndOfFace)
1296 {
1297 continue;
1298 }
50258e77 1299 myGenerated.Append(AllFaces(IndOfFace));
1300 }
1301
1302 if (myIsRuled)
1303 //Append the next faces corresponding to <Indices>
1304 for (Standard_Integer i = 2; i < myWires.Length(); i++)
1305 for (itl.Initialize(Indices); itl.More(); itl.Next())
1306 {
1307 Standard_Integer IndOfFace = itl.Value();
1308 IndOfFace += (i-1)*myNbEdgesInSection;
0e97c80e 1309 if (AllFaces.Size() < IndOfFace)
1310 {
1311 continue;
1312 }
50258e77 1313 myGenerated.Append(AllFaces(IndOfFace));
1314 }
1315 }
1316 else if (S.ShapeType() == TopAbs_VERTEX)
1317 {
1318 if (!myVertexIndex.IsBound(S))
1319 return myGenerated;
1320
1321 TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1322
1323 Standard_Boolean IsDegen [2] = {Standard_False, Standard_False};
1324 if (myDegen1 || myDegen2)
1325 {
1326 TopoDS_Shape EndSections [2];
1327 EndSections[0] = myWires(1);
1328 EndSections[1] = myWires(myWires.Length());
1329 for (Standard_Integer i = 0; i < 2; i++)
1330 {
1331 if (i == 0 && !myDegen1)
1332 continue;
1333 if (i == 1 && !myDegen2)
1334 continue;
1335
1336 Explo.Init(EndSections[i], TopAbs_VERTEX);
1337 const TopoDS_Shape& aVertex = Explo.Current();
1338 if (S.IsSame(aVertex))
1339 {
1340 IsDegen[i] = Standard_True;
1341 break;
1342 }
1343 }
1344 }
1345 // Only one of <IsDegen> can be True:
1346 // in case of one vertex for start and end degenerated sections
1347 // IsDegen[0] is True;
1348 if (IsDegen[0] || IsDegen[1])
1349 {
1350 //For start or end degenerated section
1351 //we return the whole bunch of longitudinal edges
1352 TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1353 TopTools_IndexedMapOfShape Emap;
70737683 1354 TopoDS_Shape aNewShape = S;
1355 if ((myIsRuled || !myMutableInput) && !myBFGenerator.IsNull())
1356 {
1357 aNewShape = myBFGenerator->ResultShape(S);
1358 }
1359
1360 const TopTools_ListOfShape& anEdgeList = VEmap.FindFromKey(aNewShape);
1361 TopTools_ListIteratorOfListOfShape aListIterator(anEdgeList);
1362 for (; aListIterator.More(); aListIterator.Next())
50258e77 1363 {
70737683 1364 const TopoDS_Edge& anEdge = TopoDS::Edge(aListIterator.Value());
50258e77 1365 if (!BRep_Tool::Degenerated(anEdge))
1366 {
1367 TopoDS_Vertex VV [2];
1368 TopExp::Vertices(anEdge, VV[0], VV[1]);
1369 //Comprehensive check for possible case of
1370 //one vertex for start and end degenerated sections:
1371 //we must take only outgoing or only ingoing edges
70737683 1372 if ((IsDegen[0] && aNewShape.IsSame(VV[0])) ||
1373 (IsDegen[1] && aNewShape.IsSame(VV[1])))
1374 {
50258e77 1375 Emap.Add(anEdge);
70737683 1376 }
50258e77 1377 }
1378 }
1379 for (Standard_Integer j = 1; j <= Emap.Extent(); j++)
1380 {
1381 TopoDS_Edge anEdge = TopoDS::Edge(Emap(j));
1382 myGenerated.Append(anEdge);
1383 if (myIsRuled)
1384 {
1385 Standard_Integer i,k;
1386 for (i = 2,k = myWires.Length()-1; i < myWires.Length(); i++,k--)
1387 {
1388 Standard_Integer IndOfSec = (IsDegen[0])? i : k;
1389 TopoDS_Vertex aVertex = (IsDegen[0])?
1390 TopExp::LastVertex(anEdge) : TopExp::FirstVertex(anEdge);
1391 const TopTools_ListOfShape& EElist = VEmap.FindFromKey(aVertex);
1392 TopTools_IndexedMapOfShape EmapOfSection;
70737683 1393 TopoDS_Shape aWireSection = myWires(IndOfSec);
1394 if ((myIsRuled || !myMutableInput) && !myBFGenerator.IsNull())
1395 {
1396 aWireSection = myBFGenerator->ResultShape(aWireSection);
1397 }
1398 TopExp::MapShapes(aWireSection, TopAbs_EDGE, EmapOfSection);
50258e77 1399 TopoDS_Edge NextEdge;
70737683 1400 for (aListIterator.Initialize(EElist); aListIterator.More(); aListIterator.Next())
50258e77 1401 {
70737683 1402 NextEdge = TopoDS::Edge(aListIterator.Value());
50258e77 1403 if (!NextEdge.IsSame(anEdge) &&
1404 !EmapOfSection.Contains(NextEdge))
1405 break;
1406 }
1407 myGenerated.Append(NextEdge);
1408 anEdge = NextEdge;
1409 }
1410 }
1411 }
1412 return myGenerated;
1413 } //end of if (IsDegen[0] || IsDegen[1])
1414
1415 Standard_Integer Eindex = myVertexIndex(S);
1416 Standard_Integer Vindex = (Eindex > 0)? 0 : 1;
1417 Eindex = Abs(Eindex);
50258e77 1418
1419 //Find the first longitudinal edge
1420 TopoDS_Face FirstFace = TopoDS::Face(AllFaces(Eindex));
1421 FirstFace.Orientation(TopAbs_FORWARD);
1422 Explo.Init(FirstFace, TopAbs_EDGE);
1423 TopoDS_Edge anEdge;
1424 BRepAdaptor_Surface BAsurf(FirstFace, Standard_False);
1425 TopoDS_Vertex FirstVertex;
1426 TopExp::MapShapesAndAncestors(FirstFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1427 if (myDegen1 && BAsurf.GetType() == GeomAbs_Plane)
1428 {
1429 //There are only 3 edges in the face in this case:
1430 //we take 1-st or 3-rd edge
1431 if (Vindex == 0)
1432 {
1433 Explo.Next();
1434 Explo.Next();
1435 }
1436 anEdge = TopoDS::Edge(Explo.Current());
1437 }
1438 else
1439 {
70737683 1440 TopoDS_Edge FirstEdge;
1441 TopoDS_Vertex FirstVertexOfFirstEdge;
1442 const TopoDS_Wire& FirstSection = TopoDS::Wire(myWires(1));
1443 BRepTools_WireExplorer aWireExplorer(FirstSection);
1444 for (Standard_Integer i = 1; aWireExplorer.More(); aWireExplorer.Next(), i++)
1445 {
1446 FirstEdge = aWireExplorer.Current();
1447 if (i == Eindex)
1448 {
1449 if ((myIsRuled || !myMutableInput) && !myBFGenerator.IsNull())
1450 {
1451 FirstEdge = TopoDS::Edge(myBFGenerator->ResultShape(FirstEdge));
1452 }
1453 FirstVertexOfFirstEdge = aWireExplorer.CurrentVertex();
1454 break;
1455 }
1456 }
1457
50258e77 1458 TopoDS_Shape FirstEdgeInFace;
1459 FirstEdgeInFace = Explo.Current();
1460 TopoDS_Vertex VV [2];
1461 TopExp::Vertices(FirstEdge, VV[0], VV[1]);
bf97419a 1462 if (Vindex == 0)
1463 {
1464 if (VV[0].IsSame(FirstVertexOfFirstEdge))
1465 FirstVertex = VV[0];
1466 else
1467 FirstVertex = VV[1];
1468 }
1469 else //Vindex == 1
1470 {
1471 if (VV[0].IsSame(FirstVertexOfFirstEdge))
1472 FirstVertex = VV[1];
1473 else
1474 FirstVertex = VV[0];
1475 }
50258e77 1476 const TopTools_ListOfShape& Elist = VEmap.FindFromKey(FirstVertex);
1477 TopTools_ListIteratorOfListOfShape itl(Elist);
1478 TopAbs_Orientation anEdgeOr = (Vindex == 0)? TopAbs_REVERSED : TopAbs_FORWARD;
1479 for (; itl.More(); itl.Next())
1480 {
1481 anEdge = TopoDS::Edge(itl.Value());
1482 if (!anEdge.IsSame(FirstEdgeInFace) &&
1483 !BRep_Tool::Degenerated(anEdge) &&
1484 anEdge.Orientation() == anEdgeOr)
1485 break;
1486 }
1487 }
1488 myGenerated.Append(anEdge);
1489 if (myIsRuled)
1490 //Find the chain of longitudinal edges from first to last
1491 for (Standard_Integer i = 2; i < myWires.Length(); i++)
1492 {
1493 FirstVertex = TopExp::LastVertex(anEdge);
1494 const TopTools_ListOfShape& Elist1 = VEmap.FindFromKey(FirstVertex);
70737683 1495 TopoDS_Edge FirstEdge = (anEdge.IsSame(Elist1.First()))?
50258e77 1496 TopoDS::Edge(Elist1.Last()) : TopoDS::Edge(Elist1.First());
1497 Eindex += myNbEdgesInSection;
1498 FirstFace = TopoDS::Face(AllFaces(Eindex));
1499 FirstFace.Orientation(TopAbs_FORWARD);
1500 VEmap.Clear();
1501 TopExp::MapShapesAndAncestors(FirstFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1502 const TopTools_ListOfShape& Elist2 = VEmap.FindFromKey(FirstVertex);
1503 anEdge = (FirstEdge.IsSame(Elist2.First()))?
1504 TopoDS::Edge(Elist2.Last()) : TopoDS::Edge(Elist2.First());
1505 myGenerated.Append(anEdge);
1506 }
1507 }
1508
1509 return myGenerated;
1510}
1511
7fd59977 1512//=======================================================================
1513//function : GeneratedFace
1514//purpose :
1515//=======================================================================
1516
1517TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge) const
1518{
1519 TopoDS_Shape bid;
50258e77 1520 if (myEdgeFace.IsBound(edge)) {
1521 return myEdgeFace(edge);
7fd59977 1522 }
1523 else {
1524 return bid;
1525 }
1526}
1527
1528
1529//=======================================================================
1530//function : CriteriumWeight
0d969553 1531//purpose : returns the Weights associated to the criterium used in
7fd59977 1532// the optimization.
1533//=======================================================================
1534//
1535void BRepOffsetAPI_ThruSections::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const
1536{
1537 W1 = myCritWeights[0];
1538 W2 = myCritWeights[1];
1539 W3 = myCritWeights[2];
1540}
1541//=======================================================================
1542//function : SetCriteriumWeight
1543//purpose :
1544//=======================================================================
1545
1546void BRepOffsetAPI_ThruSections::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3)
1547{
3eb891ec 1548 if (W1 < 0 || W2 < 0 || W3 < 0)
1549 {
1550 myStatus = BRepFill_ThruSectionErrorStatus_Failed;
1551 return;
1552 }
7fd59977 1553 myCritWeights[0] = W1;
1554 myCritWeights[1] = W2;
1555 myCritWeights[2] = W3;
1556}
1557//=======================================================================
1558//function : SetContinuity
1559//purpose :
1560//=======================================================================
1561
1562void BRepOffsetAPI_ThruSections::SetContinuity (const GeomAbs_Shape TheCont)
1563{
1564 myContinuity = TheCont;
1565}
1566
1567//=======================================================================
1568//function : Continuity
1569//purpose :
1570//=======================================================================
1571
1572GeomAbs_Shape BRepOffsetAPI_ThruSections::Continuity () const
1573{
1574 return myContinuity;
1575}
1576
1577//=======================================================================
1578//function : SetParType
1579//purpose :
1580//=======================================================================
1581
1582void BRepOffsetAPI_ThruSections::SetParType (const Approx_ParametrizationType ParType)
1583{
1584 myParamType = ParType;
1585}
1586
1587//=======================================================================
1588//function : ParType
1589//purpose :
1590//=======================================================================
1591
1592Approx_ParametrizationType BRepOffsetAPI_ThruSections::ParType () const
1593{
1594 return myParamType;
1595}
1596
1597//=======================================================================
1598//function : SetMaxDegree
1599//purpose :
1600//=======================================================================
1601
1602void BRepOffsetAPI_ThruSections:: SetMaxDegree(const Standard_Integer MaxDeg)
1603{
1604 myDegMax = MaxDeg;
1605}
1606
1607//=======================================================================
1608//function : MaxDegree
1609//purpose :
1610//=======================================================================
1611
1612Standard_Integer BRepOffsetAPI_ThruSections::MaxDegree () const
1613{
1614 return myDegMax;
1615}
1616
1617//=======================================================================
1618//function : SetSmoothing
1619//purpose :
1620//=======================================================================
1621
1622void BRepOffsetAPI_ThruSections::SetSmoothing(const Standard_Boolean UseVar)
1623{
1624 myUseSmoothing = UseVar;
1625}
1626
1627//=======================================================================
1628//function : UseSmoothing
1629//purpose :
1630//=======================================================================
1631
1632Standard_Boolean BRepOffsetAPI_ThruSections::UseSmoothing () const
1633{
1634 return myUseSmoothing;
1635}
1636
70737683 1637//=======================================================================
1638//function : SetMutableInput
1639//purpose :
1640//=======================================================================
1641void BRepOffsetAPI_ThruSections::SetMutableInput(const Standard_Boolean theIsMutableInput)
1642{
1643 myMutableInput = theIsMutableInput;
1644}
7fd59977 1645
70737683 1646//=======================================================================
1647//function : IsMutableInput
1648//purpose :
1649//=======================================================================
1650Standard_Boolean BRepOffsetAPI_ThruSections::IsMutableInput() const
1651{
1652 return myMutableInput;
1653}
7fd59977 1654
1655
1656