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
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.
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.
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.
22 #include <BRepFill_Pipe.ixx>
24 #include <Standard_ErrorHandler.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRepClass3d_SolidClassifier.hxx>
29 #include <BRepLib_MakeVertex.hxx>
30 #include <BRepTools_Substitution.hxx>
32 #include <GeomFill_CorrectedFrenet.hxx>
33 #include <GeomFill_Frenet.hxx>
34 #include <GeomFill_DiscreteTrihedron.hxx>
35 #include <GeomFill_CurveAndTrihedron.hxx>
37 #include <BRepFill_SectionPlacement.hxx>
38 #include <BRepFill_ShapeLaw.hxx>
39 #include <BRepFill_Edge3DLaw.hxx>
40 #include <BRepFill_Sweep.hxx>
42 #include <GeomAbs_Shape.hxx>
44 #include <TopAbs_ShapeEnum.hxx>
46 #include <TopoDS_Shell.hxx>
47 #include <TopoDS_Solid.hxx>
48 #include <TopoDS_Compound.hxx>
49 #include <TopoDS_Iterator.hxx>
50 #include <TopTools_DataMapOfShapeInteger.hxx>
51 #include <TColStd_DataMapOfIntegerInteger.hxx>
52 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
54 #include <Precision.hxx>
55 #include <Standard_NotImplemented.hxx>
57 #include <Geom_TrimmedCurve.hxx>
58 #include <Geom_OffsetCurve.hxx>
59 #include <Geom_BSplineCurve.hxx>
63 static Standard_Boolean Affich = 0;
66 //=======================================================================
67 //function : BRepFill_Pipe
69 //=======================================================================
71 BRepFill_Pipe::BRepFill_Pipe()
75 myMode = GeomFill_IsCorrectedFrenet;
76 myForceApproxC1 = Standard_False;
80 //=======================================================================
81 //function : BRepFill_Pipe
83 //=======================================================================
85 BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire& Spine,
86 const TopoDS_Shape& Profile,
87 const Standard_Boolean KPart)
91 myMode = GeomFill_IsCorrectedFrenet;
92 myForceApproxC1 = Standard_False;
93 Perform(Spine, Profile, KPart);
96 //=======================================================================
98 //purpose : Set the mode of sweeping
101 // - Corrected Frenet
102 // - Discrete Trihedron
103 //=======================================================================
105 void BRepFill_Pipe::SetMode(const GeomFill_Trihedron aMode)
107 if (aMode == GeomFill_IsFrenet ||
108 aMode == GeomFill_IsCorrectedFrenet ||
109 aMode == GeomFill_IsDiscreteTrihedron)
113 //=======================================================================
114 //function : SetForceApproxC1
115 //purpose : Set the flag that indicates attempt to approximate
116 // a C1-continuous surface if a swept surface proved
118 //=======================================================================
120 void BRepFill_Pipe::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
122 myForceApproxC1 = ForceApproxC1;
126 //=======================================================================
129 //=======================================================================
131 void BRepFill_Pipe::Perform(const TopoDS_Wire& Spine,
132 const TopoDS_Shape& Profile,
133 const Standard_Boolean KPart)
136 mySections.Nullify();
145 BRepTools_WireExplorer wexp;
146 TopoDS_Shape TheProf;
148 Handle(GeomFill_TrihedronLaw) TLaw;
151 case GeomFill_IsFrenet:
152 TLaw = new GeomFill_Frenet();
154 case GeomFill_IsCorrectedFrenet:
155 TLaw = new GeomFill_CorrectedFrenet();
157 case GeomFill_IsDiscreteTrihedron:
158 TLaw = new GeomFill_DiscreteTrihedron();
161 Handle(GeomFill_CurveAndTrihedron) Loc =
162 new (GeomFill_CurveAndTrihedron) (TLaw);
163 myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
164 if (myLoc->NbLaw() == 0) {
165 return; // Degenerated case
167 myLoc->TransformInG0Law(); // Set into continuity
169 BRepFill_SectionPlacement Place(myLoc, Profile);
170 myTrsf = Place.Transformation();
172 TopLoc_Location Loc2(myTrsf), Loc1;
173 Loc1 = Profile.Location();
176 TheProf.Location(Loc2.Multiplied(Loc1));
178 // Construct First && Last Shape
179 Handle(GeomFill_LocationLaw) law;
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(),
192 fila.Multiply(myTrsf);
193 TopLoc_Location LocFirst(fila);
195 if ( ! LocFirst.IsIdentity()) {
196 myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
199 myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
200 myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
201 // try { // Not good, but there are no other means to test SetValues
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(),
206 fila.Multiply(myTrsf);
207 TopLoc_Location LocLast(fila);
208 if (! myLoc->IsClosed() || LocFirst != LocLast) {
210 if ( ! LocLast.IsIdentity()) {
211 myLast.Location(LocLast.Multiplied(myProfile.Location()) );
219 DBRep::Set("theprof", TheProf);
220 DBRep::Set("thefirst", myFirst);
221 DBRep::Set("thelast" , myLast);
225 myShape = MakeShape(TheProf, myFirst, myLast);
229 //=======================================================================
232 //=======================================================================
234 const TopoDS_Shape& BRepFill_Pipe::Spine() const
239 //=======================================================================
242 //=======================================================================
244 const TopoDS_Shape& BRepFill_Pipe::Profile() const
249 //=======================================================================
252 //=======================================================================
254 const TopoDS_Shape& BRepFill_Pipe::Shape() const
260 //=======================================================================
261 //function : FirstShape
263 //=======================================================================
265 const TopoDS_Shape& BRepFill_Pipe::FirstShape() const
271 //=======================================================================
272 //function : LastShape
274 //=======================================================================
276 const TopoDS_Shape& BRepFill_Pipe::LastShape() const
282 //=======================================================================
285 //=======================================================================
287 TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
288 const TopoDS_Edge& EProfile)
292 if ( BRep_Tool::Degenerated(EProfile))
295 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
297 // *************************************************
298 // Search if EProfile is an edge of myProfile
299 // *************************************************
300 iprof = FindEdge(myProfile, EProfile, count);
302 if (!iprof) Standard_DomainError::Raise(
303 "BRepFill_Pipe::Face : Edge not in the Profile");
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;
313 if (!ispin) Standard_DomainError::Raise(
314 "BRepFill_Pipe::Edge : Edge not in the Spine");
316 theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
321 //=======================================================================
324 //=======================================================================
325 TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge& ESpine,
326 const TopoDS_Vertex& VProfile)
328 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;;
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");
338 // *************************************************
339 // Search if ESpine is an edge of mySpine and find
340 // the index of the corresponding Filler
341 // *************************************************
343 for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++)
344 if (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
346 if (!ispin) Standard_DomainError::Raise(
347 "BRepFill_Pipe::Edge : Edge not in the Spine");
350 // *************************************************
351 // Generate the corresponding Shape
352 // *************************************************
354 theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
361 //=======================================================================
364 //=======================================================================
366 TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const
368 TopoDS_Iterator it, itv;
370 Standard_Integer ii, ispin = 0;
372 TopoDS_Shape curSect = myProfile;
374 // *************************************************
375 // Search if ESpine is an edge of mySpine and find
376 // the index of the corresponding Filler
377 // *************************************************
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;
383 if (!ispin) Standard_DomainError::Raise(
384 "BRepFill_Pipe::Section : Vertex not in the Spine");
387 TopoDS_Compound Comp;
388 B.MakeCompound(Comp);
389 for (ii=1; ii<=mySections->ColLength(); ii++)
390 B.Add(Comp, mySections->Value(ii, ispin));
395 //=======================================================================
396 //function : PipeLine
397 //purpose : Construct a wire by sweeping of a point
398 //=======================================================================
400 TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
407 BRepLib_MakeVertex MkV(P);
408 Handle(BRepFill_ShapeLaw) Section =
409 new (BRepFill_ShapeLaw) (MkV.Vertex());
412 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
413 MkSw.SetForceApproxC1(myForceApproxC1);
414 MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
415 TopoDS_Shape aLocalShape = MkSw.Shape();
416 return TopoDS::Wire(aLocalShape);
417 // return TopoDS::Wire(MkSw.Shape());
420 //=======================================================================
421 //function : MakeShape
423 //=======================================================================
425 TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
426 const TopoDS_Shape& FirstShape,
427 const TopoDS_Shape& LastShape)
431 Standard_Boolean explode = Standard_False;
432 TopoDS_Shape TheS, TheFirst, TheLast;
433 Standard_Integer InitialLength = 0;
435 TheFirst = FirstShape;
437 if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
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
443 // explode is True in the second case
445 // create the result empty
447 switch (S.ShapeType()) {
451 B.MakeWire(TopoDS::Wire(result));
458 B.MakeShell(TopoDS::Shell(result));
461 W.Closed(S.Closed());
463 if (!FirstShape.IsNull()) {
465 B.Add(W, FirstShape);
466 W.Closed(FirstShape.Closed());
469 if (!LastShape.IsNull()) {
472 W.Closed(LastShape.Closed());
479 B.MakeShell(TopoDS::Shell(result));
484 B.MakeShell(TopoDS::Shell(result));
485 explode = Standard_True;
486 if ( !mySpine.Closed() && !TheFirst.IsNull()) {
487 B.Add(result, TheFirst.Reversed());
494 B.MakeCompSolid(TopoDS::CompSolid(result));
495 explode = Standard_True;
500 case TopAbs_COMPSOLID :
501 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
504 case TopAbs_COMPOUND :
506 B.MakeCompound(TopoDS::Compound(result));
507 explode = Standard_True;
516 TopoDS_Iterator itFirst, itLast;
517 TopoDS_Shape first, last;
518 if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
519 if (!TheLast.IsNull()) itLast.Initialize(TheLast);
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);
527 B.Add(result,MakeShape(it.Value(), first, last));
529 if (!TheFirst.IsNull()) itFirst.Next();
530 if (!TheLast.IsNull()) itLast.Next();
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);
539 MkSw.SetForceApproxC1(myForceApproxC1);
540 MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
541 result = MkSw.Shape();
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));
550 MkSw.SetForceApproxC1(myForceApproxC1);
551 MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax );
552 result = MkSw.Shape();
554 // Labeling of elements
555 if (mySections.IsNull()) {
556 myFaces = MkSw.SubShape();
557 mySections = MkSw.Sections();
558 myEdges = MkSw.InterFaces();
561 Handle(TopTools_HArray2OfShape) Aux, Somme;
562 Standard_Integer length;
563 Standard_Integer ii, jj, kk;
564 const Standard_Integer aNbFaces = myFaces->ColLength();
565 const Standard_Integer aNbEdges = myEdges->ColLength();
566 const Standard_Integer aNbSections = mySections->ColLength();
568 Aux = MkSw.SubShape();
569 length = Aux->ColLength() + myFaces->ColLength();
570 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
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));
576 for (kk=1, ii=myFaces->ColLength()+1;
577 kk <=Aux->ColLength(); kk++, ii++)
578 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
582 Aux = MkSw.Sections();
583 length = Aux->ColLength() + mySections->ColLength();
584 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
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));
590 for (kk=1, ii=mySections->ColLength()+1;
591 kk <=Aux->ColLength(); kk++, ii++)
592 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
596 Aux = MkSw.InterFaces();
597 length = Aux->ColLength() + myEdges->ColLength();
598 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
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));
604 for (kk=1, ii=myEdges->ColLength()+1;
605 kk <=Aux->ColLength(); kk++, ii++)
606 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
611 // Perform sharing faces
612 result = ShareFaces(result, aNbFaces, aNbEdges, aNbSections);
617 if ( TheS.ShapeType() == TopAbs_FACE ) {
618 Standard_Integer ii, jj;
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);
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));
637 result.Closed(Standard_True);
638 BS.Add(solid,TopoDS::Shell(result));
640 BRepClass3d_SolidClassifier SC(solid);
641 SC.PerformInfinitePoint(Precision::Confusion());
642 if ( SC.State() == TopAbs_IN) {
644 TopoDS_Shape aLocalShape = result.Reversed();
645 BS.Add(solid,TopoDS::Shell(aLocalShape));
646 // BS.Add(solid,TopoDS::Shell(result.Reversed()));
656 //============================================================================
657 //function : FindEdge
658 //purpose : Find the number of edge corresponding to the edge of the profile.
659 //============================================================================
661 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
662 const TopoDS_Edge& E,
663 Standard_Integer& InitialLength) const
665 Standard_Integer result = 0;
667 switch (S.ShapeType()) {
672 if (S.IsSame(E)) result = InitialLength;
678 Standard_Integer ii = InitialLength+1;
679 Handle(BRepFill_ShapeLaw) Section =
680 new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
681 InitialLength += Section->NbLaw();
683 for (; (ii<=InitialLength) && (!result); ii++) {
684 if (E.IsSame(Section->Edge(ii)) ) result = ii;
691 case TopAbs_COMPOUND :
693 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
694 result = FindEdge(it.Value(), E, InitialLength );
699 case TopAbs_COMPSOLID :
700 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
709 //=======================================================================
710 //function : FindVertex
711 //purpose : Find the number of edge corresponding to an edge of the profile.
712 //=======================================================================
714 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
715 const TopoDS_Vertex& V,
716 Standard_Integer& InitialLength) const
718 Standard_Integer result = 0;
720 switch (S.ShapeType()) {
724 if (S.IsSame(V)) result = InitialLength;
730 TopoDS_Vertex VF, VL;
731 TopExp::Vertices(TopoDS::Edge(S), VF, VL);
732 if (S.Orientation() == TopAbs_REVERSED) {
734 aux = VF; VF = VL; VL = aux;
736 if (VF.IsSame(V)) result = InitialLength+1;
737 else if (VL.IsSame(V)) result = InitialLength+2;
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;
749 for (; (ii<=InitialLength) && (!result); ii++) {
750 if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
757 case TopAbs_COMPOUND :
759 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
760 result = FindVertex(it.Value(), V, InitialLength);
765 case TopAbs_COMPSOLID :
766 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
775 //=======================================================================
776 //function : DefineRealSegmax
777 //purpose : Defines the real number of segments
778 // required in the case of bspline spine
779 //=======================================================================
781 void BRepFill_Pipe::DefineRealSegmax()
783 Standard_Integer RealSegmax = 0;
785 TopoDS_Iterator iter(mySpine);
786 for (; iter.More(); iter.Next())
788 TopoDS_Edge E = TopoDS::Edge(iter.Value());
789 Standard_Real first, last;
790 Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
793 while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
794 C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
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();
801 if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
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())
808 Standard_Integer I1, I2;
809 BC->LocateU( first, Precision::PConfusion(), I1, I2 );
812 if (last < BC->LastParameter())
814 Standard_Integer I1, I2;
815 BC->LocateU( last, Precision::PConfusion(), I1, I2 );
816 RealNbKnots -= NbKnots-I2;
818 RealSegmax += RealNbKnots-1;
822 if (mySegmax < RealSegmax)
823 mySegmax = RealSegmax;
826 //=======================================================================
827 //function : ShareFaces
829 //=======================================================================
831 TopoDS_Shape BRepFill_Pipe::ShareFaces
832 (const TopoDS_Shape &theShape,
833 const Standard_Integer theInitialFacesLen,
834 const Standard_Integer theInitialEdgesLen,
835 const Standard_Integer theInitialSectionsLen)
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;
847 BRep_Builder aBuilder;
849 // Check the first and last J index of myFaces.
850 for (i = 1; i <= 2; i++) {
851 // Compute jj index of faces.
855 jj = myFaces->RowLength();
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);
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());
871 // Add boundary edge.
872 aMapBndEdgeIndex.Bind(anExp.Current(), ii);
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);
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());
886 aMapNewOldFIndex.Bind(ii, anOldIndex);
888 // Find corresponding new and old edges indices.
890 TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV[0], aV[1]);
893 // Compute jj index of edges.
894 Standard_Integer je = (i == 1 ? 1 : myEdges->RowLength());
896 for (Standard_Integer j = 0; j < 2; j++) {
897 if (aMapUsedVtx.Contains(aV[j])) {
898 // This vertex is treated.
903 Standard_Integer iEOld = -1;
904 TopoDS_Vertex aVE[2];
906 for (ie = 1; ie <= theInitialEdgesLen; ie++) {
907 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
909 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
911 if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
919 for (ie = theInitialEdgesLen+1; ie <= myEdges->ColLength(); ie++) {
920 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
922 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
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]);
940 if (!aMapNewOldFIndex.IsEmpty()) {
941 TColStd_DataMapIteratorOfDataMapOfIntegerInteger anIter(aMapNewOldFIndex);
942 TopTools_ListOfShape aListShape;
943 BRepTools_Substitution aSubstitute;
945 for (; anIter.More(); anIter.Next()) {
946 const Standard_Integer aNewIndex = anIter.Key();
947 const Standard_Integer anOldIndex = anIter.Value();
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);
954 if (!aSubstitute.IsCopied(aNewFace)) {
955 aListShape.Append(anOldFace.Oriented(TopAbs_REVERSED));
956 aSubstitute.Substitute(aNewFace, aListShape);
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();
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);
971 if (!aSubstitute.IsCopied(aNewEdge)) {
972 aListShape.Append(anOldEdge.Oriented(TopAbs_FORWARD));
973 aSubstitute.Substitute(aNewEdge, aListShape);
976 // Change new vertices by old ones.
977 TopoDS_Iterator aNewIt(aNewEdge);
978 TopoDS_Iterator anOldIt(anOldEdge);
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);
994 // Perform substitution.
995 aSubstitute.Build(aResult);
997 if (aSubstitute.IsCopied(aResult)) {
999 const TopTools_ListOfShape& listSh = aSubstitute.Copy(aResult);
1001 aResult = listSh.First();
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
1008 if (aSubstitute.IsCopied(anOldFace)) {
1009 const TopTools_ListOfShape& aList = aSubstitute.Copy(anOldFace);
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);
1018 // Reverse the orientation for shared face.
1019 anOri = TopAbs::Reverse(anOri);
1022 myFaces->SetValue(ii, jj, aCopyFace.Oriented(anOri));
1024 // Check if it is necessary to update PCurves on this face.
1026 TopoDS_Face anOldF = TopoDS::Face(anOldFace);
1027 TopoDS_Face aCopyF = TopoDS::Face(aCopyFace);
1029 anOldF.Orientation(TopAbs_FORWARD);
1030 anExp.Init(anOldF, TopAbs_EDGE);
1032 for (; anExp.More(); anExp.Next()) {
1033 const TopoDS_Shape &anOldEdge = anExp.Current();
1035 if (aSubstitute.IsCopied(anOldEdge)) {
1036 const TopTools_ListOfShape& aListE =
1037 aSubstitute.Copy(anOldEdge);
1039 if(!aListE.IsEmpty()) {
1040 // This edge is copied. Check if there is a PCurve
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);
1048 if (aPCurve.IsNull()) {
1049 // There is no pcurve copy it from the old edge.
1050 TopoDS_Edge anOldE = TopoDS::Edge(anOldEdge);
1052 aPCurve = BRep_Tool::CurveOnSurface
1053 (anOldE, anOldF, aFirst, aLast);
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));
1060 aBuilder.UpdateEdge(aCopyE, aPCurve, aCopyF, aTol);
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);
1077 if (aSubstitute.IsCopied(aLocalShape)) {
1078 const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1080 if(!aList.IsEmpty()) {
1081 const TopAbs_Orientation anOri = TopAbs_FORWARD;
1083 myEdges->SetValue(ii, jj, aList.First().Oriented(anOri));
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);
1094 if (aSubstitute.IsCopied(aLocalShape)) {
1095 const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1097 if(!aList.IsEmpty()) {
1098 const TopAbs_Orientation anOri = TopAbs_FORWARD;
1100 mySections->SetValue(ii, jj, aList.First().Oriented(anOri));