0023282: Wrong triangulation on cone
[occt.git] / src / BRepFill / BRepFill_Pipe.cxx
CommitLineData
b311480e 1// Created on: 1994-06-07
2// Created by: Bruno DUMORTIER
3// Copyright (c) 1994-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21
22#include <BRepFill_Pipe.ixx>
23
24#include <Standard_ErrorHandler.hxx>
25
26#include <BRep_Tool.hxx>
27#include <BRep_Builder.hxx>
28#include <BRepClass3d_SolidClassifier.hxx>
29#include <BRepLib_MakeVertex.hxx>
46e68e02 30#include <BRepTools_Substitution.hxx>
7fd59977 31
32#include <GeomFill_CorrectedFrenet.hxx>
a31abc03 33#include <GeomFill_Frenet.hxx>
34#include <GeomFill_DiscreteTrihedron.hxx>
7fd59977 35#include <GeomFill_CurveAndTrihedron.hxx>
36
37#include <BRepFill_SectionPlacement.hxx>
38#include <BRepFill_ShapeLaw.hxx>
39#include <BRepFill_Edge3DLaw.hxx>
40#include <BRepFill_Sweep.hxx>
41
42#include <GeomAbs_Shape.hxx>
43#include <TopExp.hxx>
44#include <TopAbs_ShapeEnum.hxx>
45#include <TopoDS.hxx>
46#include <TopoDS_Shell.hxx>
47#include <TopoDS_Solid.hxx>
48#include <TopoDS_Compound.hxx>
49#include <TopoDS_Iterator.hxx>
46e68e02 50#include <TopTools_DataMapOfShapeInteger.hxx>
51#include <TColStd_DataMapOfIntegerInteger.hxx>
52#include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
7fd59977 53
54#include <Precision.hxx>
55#include <Standard_NotImplemented.hxx>
56
57#include <Geom_TrimmedCurve.hxx>
58#include <Geom_OffsetCurve.hxx>
59#include <Geom_BSplineCurve.hxx>
60
61#ifdef DRAW
62#include <DBRep.hxx>
63static Standard_Boolean Affich = 0;
64#endif
65
66//=======================================================================
67//function : BRepFill_Pipe
68//purpose :
69//=======================================================================
70
71BRepFill_Pipe::BRepFill_Pipe()
72{
73 myDegmax = 10;
74 mySegmax = 100;
a31abc03 75 myMode = GeomFill_IsCorrectedFrenet;
76 myForceApproxC1 = Standard_False;
7fd59977 77}
78
79
80//=======================================================================
81//function : BRepFill_Pipe
82//purpose :
83//=======================================================================
84
85BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire& Spine,
86 const TopoDS_Shape& Profile,
87 const Standard_Boolean KPart)
88{
89 myDegmax = 10;
90 mySegmax = 100;
a31abc03 91 myMode = GeomFill_IsCorrectedFrenet;
92 myForceApproxC1 = Standard_False;
7fd59977 93 Perform(Spine, Profile, KPart);
94}
95
a31abc03 96//=======================================================================
97//function : SetMode
98//purpose : Set the mode of sweeping
99// It can be:
100// - Frenet
101// - Corrected Frenet
102// - Discrete Trihedron
103//=======================================================================
104
105void BRepFill_Pipe::SetMode(const GeomFill_Trihedron aMode)
106{
107 if (aMode == GeomFill_IsFrenet ||
108 aMode == GeomFill_IsCorrectedFrenet ||
109 aMode == GeomFill_IsDiscreteTrihedron)
110 myMode = aMode;
111}
112
113//=======================================================================
114//function : SetForceApproxC1
115//purpose : Set the flag that indicates attempt to approximate
116// a C1-continuous surface if a swept surface proved
117// to be C0.
118//=======================================================================
119
120void BRepFill_Pipe::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
121{
122 myForceApproxC1 = ForceApproxC1;
123}
7fd59977 124
125
126//=======================================================================
127//function : Perform
128//purpose :
129//=======================================================================
130
131void BRepFill_Pipe::Perform(const TopoDS_Wire& Spine,
132 const TopoDS_Shape& Profile,
133 const Standard_Boolean KPart)
134
135{
136 mySections.Nullify();
137 myFaces.Nullify();
138 myEdges.Nullify();
139
140 mySpine = Spine;
141 myProfile = Profile;
142
143 DefineRealSegmax();
144
145 BRepTools_WireExplorer wexp;
146 TopoDS_Shape TheProf;
147
a31abc03 148 Handle(GeomFill_TrihedronLaw) TLaw;
149 switch (myMode)
150 {
151 case GeomFill_IsFrenet:
152 TLaw = new GeomFill_Frenet();
153 break;
154 case GeomFill_IsCorrectedFrenet:
155 TLaw = new GeomFill_CorrectedFrenet();
156 break;
157 case GeomFill_IsDiscreteTrihedron:
158 TLaw = new GeomFill_DiscreteTrihedron();
159 break;
160 }
7fd59977 161 Handle(GeomFill_CurveAndTrihedron) Loc =
162 new (GeomFill_CurveAndTrihedron) (TLaw);
163 myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
164 if (myLoc->NbLaw() == 0) {
0d969553 165 return; // Degenerated case
7fd59977 166 }
0d969553 167 myLoc->TransformInG0Law(); // Set into continuity
7fd59977 168
169 BRepFill_SectionPlacement Place(myLoc, Profile);
170 myTrsf = Place.Transformation();
171
172 TopLoc_Location Loc2(myTrsf), Loc1;
173 Loc1 = Profile.Location();
174 TopoDS_Shape aux;
175 TheProf = myProfile;
176 TheProf.Location(Loc2.Multiplied(Loc1));
177
0d969553 178 // Construct First && Last Shape
7fd59977 179 Handle(GeomFill_LocationLaw) law;
180
181 gp_Mat M;
182 gp_Vec V;
183 gp_Trsf fila;
184 Standard_Real first, last;
185 myLoc->Law(1)->GetDomain(first, last);
186 myLoc->Law(1)->D0(first, M, V);
187 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
188 M(2,1), M(2,2), M(2,3), V.Y(),
189 M(3,1), M(3,2), M(3,3), V.Z(),
190 1.e-12, 1.e-14);
191
192 fila.Multiply(myTrsf);
193 TopLoc_Location LocFirst(fila);
194 myFirst = myProfile;
195 if ( ! LocFirst.IsIdentity()) {
196 myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
197 }
198
199 myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
200 myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
0d969553 201// try { // Not good, but there are no other means to test SetValues
7fd59977 202 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
203 M(2,1), M(2,2), M(2,3), V.Y(),
204 M(3,1), M(3,2), M(3,3), V.Z(),
205 1.e-12, 1.e-14);
206 fila.Multiply(myTrsf);
207 TopLoc_Location LocLast(fila);
208 if (! myLoc->IsClosed() || LocFirst != LocLast) {
209 myLast = myProfile;
210 if ( ! LocLast.IsIdentity()) {
211 myLast.Location(LocLast.Multiplied(myProfile.Location()) );
212 }
213 }
214 else {
215 myLast = myFirst;
216 }
217#if DRAW
218 if (Affich) {
219 DBRep::Set("theprof", TheProf);
220 DBRep::Set("thefirst", myFirst);
221 DBRep::Set("thelast" , myLast);
222 }
223#endif
224
225 myShape = MakeShape(TheProf, myFirst, myLast);
226}
227
228
229//=======================================================================
230//function : Spine
231//purpose :
232//=======================================================================
233
234const TopoDS_Shape& BRepFill_Pipe::Spine() const
235{
236 return mySpine;
237}
238
239//=======================================================================
240//function : Profile
241//purpose :
242//=======================================================================
243
244const TopoDS_Shape& BRepFill_Pipe::Profile() const
245{
246 return myProfile;
247}
248
249//=======================================================================
250//function : Shape
251//purpose :
252//=======================================================================
253
254const TopoDS_Shape& BRepFill_Pipe::Shape() const
255{
256 return myShape;
257}
258
259
260//=======================================================================
261//function : FirstShape
262//purpose :
263//=======================================================================
264
265const TopoDS_Shape& BRepFill_Pipe::FirstShape() const
266{
267 return myFirst;
268}
269
270
271//=======================================================================
272//function : LastShape
273//purpose :
274//=======================================================================
275
276const TopoDS_Shape& BRepFill_Pipe::LastShape() const
277{
278 return myLast;
279}
280
281
282//=======================================================================
283//function : Face
284//purpose :
285//=======================================================================
286
287TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
288 const TopoDS_Edge& EProfile)
289{
290 TopoDS_Face theFace;
291
292 if ( BRep_Tool::Degenerated(EProfile))
293 return theFace;
294
295 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
296
297 // *************************************************
298 // Search if EProfile is an edge of myProfile
299 // *************************************************
300 iprof = FindEdge(myProfile, EProfile, count);
301
302 if (!iprof) Standard_DomainError::Raise(
303 "BRepFill_Pipe::Face : Edge not in the Profile");
304
305
306 // *************************************************
307 // Search if ESpine is an edge of mySpine and find
308 // the index of the corresponding Filler
309 // *************************************************
310 for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++)
311 if (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
312
313 if (!ispin) Standard_DomainError::Raise(
314 "BRepFill_Pipe::Edge : Edge not in the Spine");
315
316 theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
317 return theFace;
318
319}
320
321//=======================================================================
322//function : Edge
323//purpose :
324//=======================================================================
325TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge& ESpine,
326 const TopoDS_Vertex& VProfile)
327{
328 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;;
329
330 // *************************************************
331 // Search if VProfile is a Vertex of myProfile
332 // *************************************************
333 iprof = FindVertex(myProfile, VProfile, count);
334 if (!iprof) Standard_DomainError::Raise(
335 "BRepFill_Pipe::Edge : Vertex not in the Profile");
336
337
338 // *************************************************
339 // Search if ESpine is an edge of mySpine and find
340 // the index of the corresponding Filler
341 // *************************************************
342
343 for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++)
344 if (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
345
346 if (!ispin) Standard_DomainError::Raise(
347 "BRepFill_Pipe::Edge : Edge not in the Spine");
348
349
350 // *************************************************
351 // Generate the corresponding Shape
352 // *************************************************
353 TopoDS_Edge theEdge;
354 theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
355
356 return theEdge;
357
358}
359
360
361//=======================================================================
362//function : Section
363//purpose :
364//=======================================================================
365
366TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const
367{
368 TopoDS_Iterator it, itv;
369
370 Standard_Integer ii, ispin = 0;
371
372 TopoDS_Shape curSect = myProfile;
373
374 // *************************************************
375 // Search if ESpine is an edge of mySpine and find
376 // the index of the corresponding Filler
377 // *************************************************
378
379 // iterate on all the edges of mySpine
380 for (ii=1; ii<=myLoc->NbLaw()+1 && (!ispin); ii++)
381 if (VSpine.IsSame(myLoc->Vertex(ii))) ispin = ii;
382
383 if (!ispin) Standard_DomainError::Raise(
384 "BRepFill_Pipe::Section : Vertex not in the Spine");
385
386 BRep_Builder B;
387 TopoDS_Compound Comp;
388 B.MakeCompound(Comp);
389 for (ii=1; ii<=mySections->ColLength(); ii++)
390 B.Add(Comp, mySections->Value(ii, ispin));
391
392 return Comp;
393}
394
395//=======================================================================
396//function : PipeLine
0d969553 397//purpose : Construct a wire by sweeping of a point
7fd59977 398//=======================================================================
399
400TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
401{
0d969553 402 // Postioning
7fd59977 403 gp_Pnt P;
404 P = Point;
405 P.Transform(myTrsf);
406
407 BRepLib_MakeVertex MkV(P);
408 Handle(BRepFill_ShapeLaw) Section =
409 new (BRepFill_ShapeLaw) (MkV.Vertex());
410
0d969553 411 // Sweeping
7fd59977 412 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
a31abc03 413 MkSw.SetForceApproxC1(myForceApproxC1);
414 MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
7fd59977 415 TopoDS_Shape aLocalShape = MkSw.Shape();
416 return TopoDS::Wire(aLocalShape);
417// return TopoDS::Wire(MkSw.Shape());
418}
419
420//=======================================================================
421//function : MakeShape
422//purpose :
423//=======================================================================
424
425TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
426 const TopoDS_Shape& FirstShape,
427 const TopoDS_Shape& LastShape)
428{
429 TopoDS_Shape result;
430 BRep_Builder B;
431 Standard_Boolean explode = Standard_False;
432 TopoDS_Shape TheS, TheFirst, TheLast;
433 Standard_Integer InitialLength = 0;
434 TheS = S;
435 TheFirst = FirstShape;
436 TheLast = LastShape;
437 if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
438
439 // there are two kinds of generation
440 // 1. generate with S from each Filler (Vertex, Edge)
441 // 2. call MakeShape recursively on the subshapes of S
442 //
443 // explode is True in the second case
444
445 // create the result empty
446
447 switch (S.ShapeType()) {
448
449 case TopAbs_VERTEX :
450 {
451 B.MakeWire(TopoDS::Wire(result));
452 break;
453 }
454
455 case TopAbs_EDGE :
456 {
457 TopoDS_Wire W;
458 B.MakeShell(TopoDS::Shell(result));
459 B.MakeWire(W);
460 B.Add(W, S);
461 W.Closed(S.Closed());
462 TheS = W;
463 if (!FirstShape.IsNull()) {
464 B.MakeWire(W);
465 B.Add(W, FirstShape);
466 W.Closed(FirstShape.Closed());
467 TheFirst = W;
468 }
469 if (!LastShape.IsNull()) {
470 B.MakeWire(W);
471 B.Add(W, LastShape);
472 W.Closed(LastShape.Closed());
473 TheLast = W;
474 }
475 break;
476 }
477
478 case TopAbs_WIRE :
479 B.MakeShell(TopoDS::Shell(result));
480 break;
481
482 case TopAbs_FACE :
483 {
484 B.MakeShell(TopoDS::Shell(result));
485 explode = Standard_True;
486 if ( !mySpine.Closed() && !TheFirst.IsNull()) {
487 B.Add(result, TheFirst.Reversed());
488 }
489 break;
490 }
491
492 case TopAbs_SHELL :
493 {
494 B.MakeCompSolid(TopoDS::CompSolid(result));
495 explode = Standard_True;
496 break;
497 }
498
499 case TopAbs_SOLID :
500 case TopAbs_COMPSOLID :
501 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
502 break;
503
504 case TopAbs_COMPOUND :
505 {
506 B.MakeCompound(TopoDS::Compound(result));
507 explode = Standard_True;
508 break;
509 }
7fd59977 510 default:
511 break;
7fd59977 512 }
513
514 if (explode) {
515 // add the subshapes
516 TopoDS_Iterator itFirst, itLast;
517 TopoDS_Shape first, last;
518 if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
519 if (!TheLast.IsNull()) itLast.Initialize(TheLast);
520
521 for (TopoDS_Iterator it(S); it.More(); it.Next()) {
522 if (!TheFirst.IsNull()) first = itFirst.Value();
523 if (!TheLast.IsNull()) last = itLast.Value();
524 if (TheS.ShapeType() == TopAbs_FACE )
525 MakeShape(it.Value(), first, last);
526 else
527 B.Add(result,MakeShape(it.Value(), first, last));
528
529 if (!TheFirst.IsNull()) itFirst.Next();
530 if (!TheLast.IsNull()) itLast.Next();
531 }
532 }
533
534 else {
535 if (TheS.ShapeType() == TopAbs_VERTEX ) {
536 Handle(BRepFill_ShapeLaw) Section =
537 new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
538 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
a31abc03 539 MkSw.SetForceApproxC1(myForceApproxC1);
540 MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
7fd59977 541 result = MkSw.Shape();
542 }
543
544 if (TheS.ShapeType() == TopAbs_WIRE ) {
545 Handle(BRepFill_ShapeLaw) Section =
546 new (BRepFill_ShapeLaw) (TopoDS::Wire(TheS));
547 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
548 MkSw.SetBounds(TopoDS::Wire(TheFirst),
549 TopoDS::Wire(TheLast));
a31abc03 550 MkSw.SetForceApproxC1(myForceApproxC1);
551 MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
7fd59977 552 result = MkSw.Shape();
553
0d969553 554 // Labeling of elements
7fd59977 555 if (mySections.IsNull()) {
556 myFaces = MkSw.SubShape();
557 mySections = MkSw.Sections();
558 myEdges = MkSw.InterFaces();
559 }
560 else {
561 Handle(TopTools_HArray2OfShape) Aux, Somme;
562 Standard_Integer length;
563 Standard_Integer ii, jj, kk;
46e68e02 564 const Standard_Integer aNbFaces = myFaces->ColLength();
565 const Standard_Integer aNbEdges = myEdges->ColLength();
566 const Standard_Integer aNbSections = mySections->ColLength();
7fd59977 567
568 Aux = MkSw.SubShape();
569 length = Aux->ColLength() + myFaces->ColLength();
570 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
571 Aux->RowLength());
572 for (jj=1; jj<=myFaces->RowLength(); jj++) {
573 for (ii=1; ii<=myFaces->ColLength(); ii++)
574 Somme->SetValue(ii, jj, myFaces->Value(ii, jj));
575
576 for (kk=1, ii=myFaces->ColLength()+1;
577 kk <=Aux->ColLength(); kk++, ii++)
578 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
579 }
580 myFaces = Somme;
7fd59977 581
582 Aux = MkSw.Sections();
583 length = Aux->ColLength() + mySections->ColLength();
584 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
585 Aux->RowLength());
586 for (jj=1; jj<=mySections->RowLength(); jj++) {
587 for (ii=1; ii<=mySections->ColLength(); ii++)
588 Somme->SetValue(ii, jj, mySections->Value(ii, jj));
589
590 for (kk=1, ii=mySections->ColLength()+1;
591 kk <=Aux->ColLength(); kk++, ii++)
592 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
593 }
594 mySections = Somme;
595
596 Aux = MkSw.InterFaces();
597 length = Aux->ColLength() + myEdges->ColLength();
598 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
599 Aux->RowLength());
600 for (jj=1; jj<=myEdges->RowLength(); jj++) {
601 for (ii=1; ii<=myEdges->ColLength(); ii++)
602 Somme->SetValue(ii, jj, myEdges->Value(ii, jj));
603
604 for (kk=1, ii=myEdges->ColLength()+1;
605 kk <=Aux->ColLength(); kk++, ii++)
606 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
607 }
46e68e02 608
609 myEdges = Somme;
610
611 // Perform sharing faces
612 result = ShareFaces(result, aNbFaces, aNbEdges, aNbSections);
7fd59977 613 }
614 }
615 }
616
617 if ( TheS.ShapeType() == TopAbs_FACE ) {
618 Standard_Integer ii, jj;
619 TopoDS_Face F;
620 for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
621 for (jj=1; jj<=myFaces->RowLength(); jj++) {
622 F = TopoDS::Face(myFaces->Value(ii, jj));
623 if (!F.IsNull()) B.Add(result, F);
624 }
625 }
626
627 if ( !mySpine.Closed()) {
628 // if Spine is not closed
629 // add the last face of the solid
630 B.Add(result, TopoDS::Face(TheLast));
631 }
632
633 TopoDS_Solid solid;
634 BRep_Builder BS;
635 BS.MakeSolid(solid);
636
637 result.Closed(Standard_True);
638 BS.Add(solid,TopoDS::Shell(result));
639
640 BRepClass3d_SolidClassifier SC(solid);
641 SC.PerformInfinitePoint(Precision::Confusion());
642 if ( SC.State() == TopAbs_IN) {
643 BS.MakeSolid(solid);
644 TopoDS_Shape aLocalShape = result.Reversed();
645 BS.Add(solid,TopoDS::Shell(aLocalShape));
646// BS.Add(solid,TopoDS::Shell(result.Reversed()));
647 }
648 return solid;
649 }
650 else {
651 return result;
652 }
653 return result;
654}
655
0d969553 656//============================================================================
7fd59977 657//function : FindEdge
0d969553
Y
658//purpose : Find the number of edge corresponding to the edge of the profile.
659//============================================================================
7fd59977 660
661Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
662 const TopoDS_Edge& E,
663 Standard_Integer& InitialLength) const
664{
665 Standard_Integer result = 0;
666
667 switch (S.ShapeType()) {
668
669 case TopAbs_EDGE :
670 {
671 InitialLength++;
672 if (S.IsSame(E)) result = InitialLength;
673 break;
674 }
675
676 case TopAbs_WIRE :
677 {
678 Standard_Integer ii = InitialLength+1;
679 Handle(BRepFill_ShapeLaw) Section =
680 new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
681 InitialLength += Section->NbLaw();
682
683 for (; (ii<=InitialLength) && (!result); ii++) {
684 if (E.IsSame(Section->Edge(ii)) ) result = ii;
685 }
686 break;
687 }
688
689 case TopAbs_FACE :
690 case TopAbs_SHELL :
691 case TopAbs_COMPOUND :
692 {
693 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
694 result = FindEdge(it.Value(), E, InitialLength );
695 break;
696 }
697
698 case TopAbs_SOLID :
699 case TopAbs_COMPSOLID :
700 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
701 break;
7fd59977 702 default:
703 break;
7fd59977 704 }
705
706 return result;
707}
708
709//=======================================================================
710//function : FindVertex
0d969553 711//purpose : Find the number of edge corresponding to an edge of the profile.
7fd59977 712//=======================================================================
713
714Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
715 const TopoDS_Vertex& V,
716 Standard_Integer& InitialLength) const
717{
718 Standard_Integer result = 0;
719
720 switch (S.ShapeType()) {
721 case TopAbs_VERTEX :
722 {
723 InitialLength++;
724 if (S.IsSame(V)) result = InitialLength;
725 break;
726 }
727
728 case TopAbs_EDGE :
729 {
730 TopoDS_Vertex VF, VL;
731 TopExp::Vertices(TopoDS::Edge(S), VF, VL);
732 if (S.Orientation() == TopAbs_REVERSED) {
733 TopoDS_Vertex aux;
734 aux = VF; VF = VL; VL = aux;
735 }
736 if (VF.IsSame(V)) result = InitialLength+1;
737 else if (VL.IsSame(V)) result = InitialLength+2;
738 InitialLength += 2;
739 break;
740 }
741
742 case TopAbs_WIRE :
743 {
744 Standard_Integer ii = InitialLength+1;
745 Handle(BRepFill_ShapeLaw) Section =
746 new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
747 InitialLength += Section->NbLaw()+1;
748
749 for (; (ii<=InitialLength) && (!result); ii++) {
750 if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
751 }
752 break;
753 }
754
755 case TopAbs_FACE :
756 case TopAbs_SHELL :
757 case TopAbs_COMPOUND :
758 {
759 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
760 result = FindVertex(it.Value(), V, InitialLength);
761 break;
762 }
763
764 case TopAbs_SOLID :
765 case TopAbs_COMPSOLID :
766 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
767 break;
7fd59977 768 default:
769 break;
7fd59977 770 }
771
772 return result;
773}
774
775//=======================================================================
776//function : DefineRealSegmax
777//purpose : Defines the real number of segments
778// required in the case of bspline spine
779//=======================================================================
780
781void BRepFill_Pipe::DefineRealSegmax()
782{
783 Standard_Integer RealSegmax = 0;
784
785 TopoDS_Iterator iter(mySpine);
786 for (; iter.More(); iter.Next())
787 {
788 TopoDS_Edge E = TopoDS::Edge(iter.Value());
789 Standard_Real first, last;
790 Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
791 if (C.IsNull())
792 continue;
793 while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
794 C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
795 {
796 if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
797 C = (*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve();
798 if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
799 C = (*((Handle(Geom_OffsetCurve)*)&C))->BasisCurve();
800 }
801 if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
802 {
803 const Handle(Geom_BSplineCurve)& BC = *((Handle(Geom_BSplineCurve)*)&C);
804 Standard_Integer NbKnots = BC->NbKnots();
805 Standard_Integer RealNbKnots = NbKnots;
806 if (first > BC->FirstParameter())
807 {
808 Standard_Integer I1, I2;
809 BC->LocateU( first, Precision::PConfusion(), I1, I2 );
810 RealNbKnots -= I1-1;
811 }
812 if (last < BC->LastParameter())
813 {
814 Standard_Integer I1, I2;
815 BC->LocateU( last, Precision::PConfusion(), I1, I2 );
816 RealNbKnots -= NbKnots-I2;
817 }
818 RealSegmax += RealNbKnots-1;
819 }
820 }
821
822 if (mySegmax < RealSegmax)
823 mySegmax = RealSegmax;
824}
46e68e02 825
826//=======================================================================
827//function : ShareFaces
828//purpose :
829//=======================================================================
830
831TopoDS_Shape BRepFill_Pipe::ShareFaces
832 (const TopoDS_Shape &theShape,
833 const Standard_Integer theInitialFacesLen,
834 const Standard_Integer theInitialEdgesLen,
835 const Standard_Integer theInitialSectionsLen)
836{
837 TopoDS_Shape aResult = theShape;
838 // Check if there are shapes to be shared.
839 TopTools_DataMapOfShapeInteger aMapBndEdgeIndex;
840 TColStd_DataMapOfIntegerInteger aMapNewOldFIndex;
841 TColStd_DataMapOfIntegerInteger aMapNewOldEIndex;
842 TopTools_MapOfShape aMapUsedVtx;
843 TopExp_Explorer anExp;
844 Standard_Integer i;
845 Standard_Integer ii;
846 Standard_Integer jj;
847 BRep_Builder aBuilder;
848
849 // Check the first and last J index of myFaces.
850 for (i = 1; i <= 2; i++) {
851 // Compute jj index of faces.
852 if (i == 1) {
853 jj = 1;
854 } else {
7566ccf3 855 jj = myFaces->RowLength();
46e68e02 856
857 if (jj == 1) {
858 break;
859 }
860 }
861
862 // Fill the map of boundary edges on initial faces.
863 for (ii = 1; ii <= theInitialFacesLen; ii++) {
864 anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE);
865
866 for (; anExp.More(); anExp.Next()) {
867 if (aMapBndEdgeIndex.IsBound(anExp.Current())) {
868 // This is not boundary edge. Remove it.
869 aMapBndEdgeIndex.UnBind(anExp.Current());
870 } else {
871 // Add boundary edge.
872 aMapBndEdgeIndex.Bind(anExp.Current(), ii);
873 }
874 }
875 }
876
877 // Check if edges of newly created faces are shared with old ones.
878 for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) {
879 anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE);
880
881 for (; anExp.More(); anExp.Next()) {
882 if (aMapBndEdgeIndex.IsBound(anExp.Current())) {
883 // This row should be replaced.
884 Standard_Integer anOldIndex = aMapBndEdgeIndex.Find(anExp.Current());
885
886 aMapNewOldFIndex.Bind(ii, anOldIndex);
887
888 // Find corresponding new and old edges indices.
889 TopoDS_Vertex aV[2];
890 TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV[0], aV[1]);
891 Standard_Integer ie;
46e68e02 892
893 // Compute jj index of edges.
7566ccf3 894 Standard_Integer je = (i == 1 ? 1 : myEdges->RowLength());
46e68e02 895
7566ccf3 896 for (Standard_Integer j = 0; j < 2; j++) {
46e68e02 897 if (aMapUsedVtx.Contains(aV[j])) {
898 // This vertex is treated.
899 continue;
900 }
901
902 // Find old index.
903 Standard_Integer iEOld = -1;
904 TopoDS_Vertex aVE[2];
905
906 for (ie = 1; ie <= theInitialEdgesLen; ie++) {
907 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
908
909 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
910
911 if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
912 iEOld = ie;
913 break;
914 }
915 }
916
917 if (iEOld > 0) {
918 // Find new index.
919 for (ie = theInitialEdgesLen+1; ie <= myEdges->ColLength(); ie++) {
920 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
921
922 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
923
924 if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
925 // This row should be replaced.
926 aMapNewOldEIndex.Bind(ie, iEOld);
927 aMapUsedVtx.Add(aV[j]);
928 break;
929 }
930 }
931 }
932 }
933
934 break;
935 }
936 }
937 }
938 }
939
940 if (!aMapNewOldFIndex.IsEmpty()) {
941 TColStd_DataMapIteratorOfDataMapOfIntegerInteger anIter(aMapNewOldFIndex);
942 TopTools_ListOfShape aListShape;
943 BRepTools_Substitution aSubstitute;
944
945 for (; anIter.More(); anIter.Next()) {
946 const Standard_Integer aNewIndex = anIter.Key();
947 const Standard_Integer anOldIndex = anIter.Value();
948
949 // Change new faces by old ones.
950 for (jj = 1; jj <= myFaces->RowLength(); jj++) {
951 const TopoDS_Shape &aNewFace = myFaces->Value(aNewIndex, jj);
952 const TopoDS_Shape &anOldFace = myFaces->Value(anOldIndex, jj);
953
954 if (!aSubstitute.IsCopied(aNewFace)) {
955 aListShape.Append(anOldFace.Oriented(TopAbs_REVERSED));
956 aSubstitute.Substitute(aNewFace, aListShape);
957 aListShape.Clear();
958 }
959 }
960 }
961
962 // Change new edges by old ones.
963 for (anIter.Initialize(aMapNewOldEIndex); anIter.More(); anIter.Next()) {
964 const Standard_Integer aNewIndex = anIter.Key();
965 const Standard_Integer anOldIndex = anIter.Value();
966
967 for (jj = 1; jj <= myEdges->RowLength(); jj++) {
968 const TopoDS_Shape &aNewEdge = myEdges->Value(aNewIndex, jj);
969 const TopoDS_Shape &anOldEdge = myEdges->Value(anOldIndex, jj);
970
971 if (!aSubstitute.IsCopied(aNewEdge)) {
972 aListShape.Append(anOldEdge.Oriented(TopAbs_FORWARD));
973 aSubstitute.Substitute(aNewEdge, aListShape);
974 aListShape.Clear();
975
976 // Change new vertices by old ones.
977 TopoDS_Iterator aNewIt(aNewEdge);
978 TopoDS_Iterator anOldIt(anOldEdge);
979
980 for (; aNewIt.More() && anOldIt.More();
981 aNewIt.Next(), anOldIt.Next()) {
982 if (!aNewIt.Value().IsSame(anOldIt.Value())) {
983 if (!aSubstitute.IsCopied(aNewIt.Value())) {
984 aListShape.Append(anOldIt.Value().Oriented(TopAbs_FORWARD));
985 aSubstitute.Substitute(aNewIt.Value(), aListShape);
986 aListShape.Clear();
987 }
988 }
989 }
990 }
991 }
992 }
993
994 // Perform substitution.
995 aSubstitute.Build(aResult);
996
997 if (aSubstitute.IsCopied(aResult)) {
998 // Get copied shape.
999 const TopTools_ListOfShape& listSh = aSubstitute.Copy(aResult);
1000
1001 aResult = listSh.First();
1002
1003 // Update original faces with copied ones.
1004 for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) {
1005 for (jj = 1; jj <= myFaces->RowLength(); jj++) {
1006 TopoDS_Shape anOldFace = myFaces->Value(ii, jj); // Copy
1007
1008 if (aSubstitute.IsCopied(anOldFace)) {
1009 const TopTools_ListOfShape& aList = aSubstitute.Copy(anOldFace);
1010
1011 if(!aList.IsEmpty()) {
1012 // Store copied face.
1013 const TopoDS_Shape &aCopyFace = aList.First();
1014 TopAbs_Orientation anOri = anOldFace.Orientation();
1015 const Standard_Boolean isShared = aMapNewOldFIndex.IsBound(ii);
1016
1017 if (isShared) {
1018 // Reverse the orientation for shared face.
1019 anOri = TopAbs::Reverse(anOri);
1020 }
1021
1022 myFaces->SetValue(ii, jj, aCopyFace.Oriented(anOri));
1023
1024 // Check if it is necessary to update PCurves on this face.
1025 if (!isShared) {
1026 TopoDS_Face anOldF = TopoDS::Face(anOldFace);
1027 TopoDS_Face aCopyF = TopoDS::Face(aCopyFace);
1028
1029 anOldF.Orientation(TopAbs_FORWARD);
1030 anExp.Init(anOldF, TopAbs_EDGE);
1031
1032 for (; anExp.More(); anExp.Next()) {
1033 const TopoDS_Shape &anOldEdge = anExp.Current();
1034
1035 if (aSubstitute.IsCopied(anOldEdge)) {
1036 const TopTools_ListOfShape& aListE =
1037 aSubstitute.Copy(anOldEdge);
1038
1039 if(!aListE.IsEmpty()) {
1040 // This edge is copied. Check if there is a PCurve
1041 // on the face.
1042 TopoDS_Edge aCopyE = TopoDS::Edge(aListE.First());
1043 Standard_Real aFirst;
1044 Standard_Real aLast;
1045 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface
1046 (aCopyE, aCopyF, aFirst, aLast);
1047
1048 if (aPCurve.IsNull()) {
1049 // There is no pcurve copy it from the old edge.
1050 TopoDS_Edge anOldE = TopoDS::Edge(anOldEdge);
1051
1052 aPCurve = BRep_Tool::CurveOnSurface
1053 (anOldE, anOldF, aFirst, aLast);
1054
1055 if (aPCurve.IsNull() == Standard_False) {
1056 // Update the shared edge with PCurve from new Face.
1057 Standard_Real aTol = Max(BRep_Tool::Tolerance(anOldE),
1058 BRep_Tool::Tolerance(aCopyE));
1059
1060 aBuilder.UpdateEdge(aCopyE, aPCurve, aCopyF, aTol);
1061 }
1062 }
1063 }
1064 }
1065 }
1066 }
1067 }
1068 }
1069 }
1070 }
1071
1072 // Update new edges with shared ones.
1073 for (ii = theInitialEdgesLen + 1; ii <= myEdges->ColLength(); ii++) {
1074 for (jj = 1; jj <= myEdges->RowLength(); jj++) {
1075 const TopoDS_Shape &aLocalShape = myEdges->Value(ii, jj);
1076
1077 if (aSubstitute.IsCopied(aLocalShape)) {
1078 const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1079
1080 if(!aList.IsEmpty()) {
1081 const TopAbs_Orientation anOri = TopAbs_FORWARD;
1082
1083 myEdges->SetValue(ii, jj, aList.First().Oriented(anOri));
1084 }
1085 }
1086 }
1087 }
1088
1089 // Update new sections with shared ones.
1090 for (ii = theInitialSectionsLen+1; ii <= mySections->ColLength(); ii++) {
1091 for (jj = 1; jj <= mySections->RowLength(); jj++) {
1092 const TopoDS_Shape &aLocalShape = mySections->Value(ii, jj);
1093
1094 if (aSubstitute.IsCopied(aLocalShape)) {
1095 const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1096
1097 if(!aList.IsEmpty()) {
1098 const TopAbs_Orientation anOri = TopAbs_FORWARD;
1099
1100 mySections->SetValue(ii, jj, aList.First().Oriented(anOri));
1101 }
1102 }
1103 }
1104 }
1105 }
1106 }
1107
1108 return aResult;
1109}