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