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 myContinuity = GeomAbs_C2;
76 myMode = GeomFill_IsCorrectedFrenet;
77 myForceApproxC1 = Standard_False;
81 //=======================================================================
82 //function : BRepFill_Pipe
84 //=======================================================================
86 BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire& Spine,
87 const TopoDS_Shape& Profile,
88 const GeomFill_Trihedron aMode,
89 const Standard_Boolean ForceApproxC1,
90 const Standard_Boolean KPart)
96 myMode = GeomFill_IsCorrectedFrenet;
97 if (aMode == GeomFill_IsFrenet ||
98 aMode == GeomFill_IsCorrectedFrenet ||
99 aMode == GeomFill_IsDiscreteTrihedron)
102 myContinuity = GeomAbs_C2;
103 if (myMode == GeomFill_IsDiscreteTrihedron)
104 myContinuity = GeomAbs_C0;
106 myForceApproxC1 = ForceApproxC1;
107 Perform(Spine, Profile, KPart);
111 //=======================================================================
114 //=======================================================================
116 void BRepFill_Pipe::Perform(const TopoDS_Wire& Spine,
117 const TopoDS_Shape& Profile,
118 const Standard_Boolean /*KPart*/)
121 mySections.Nullify();
130 BRepTools_WireExplorer wexp;
131 TopoDS_Shape TheProf;
133 Handle(GeomFill_TrihedronLaw) TLaw;
136 case GeomFill_IsFrenet:
137 TLaw = new GeomFill_Frenet();
139 case GeomFill_IsCorrectedFrenet:
140 TLaw = new GeomFill_CorrectedFrenet();
142 case GeomFill_IsDiscreteTrihedron:
143 TLaw = new GeomFill_DiscreteTrihedron();
148 Handle(GeomFill_CurveAndTrihedron) Loc =
149 new (GeomFill_CurveAndTrihedron) (TLaw);
150 myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
151 if (myLoc->NbLaw() == 0) {
152 return; // Degenerated case
154 myLoc->TransformInG0Law(); // Set into continuity
156 BRepFill_SectionPlacement Place(myLoc, Profile);
157 myTrsf = Place.Transformation();
159 TopLoc_Location Loc2(myTrsf), Loc1;
160 Loc1 = Profile.Location();
163 TheProf.Location(Loc2.Multiplied(Loc1));
165 // Construct First && Last Shape
166 Handle(GeomFill_LocationLaw) law;
171 Standard_Real first, last;
172 myLoc->Law(1)->GetDomain(first, last);
173 myLoc->Law(1)->D0(first, M, V);
174 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
175 M(2,1), M(2,2), M(2,3), V.Y(),
176 M(3,1), M(3,2), M(3,3), V.Z(),
179 fila.Multiply(myTrsf);
180 TopLoc_Location LocFirst(fila);
182 if ( ! LocFirst.IsIdentity()) {
183 myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
186 myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
187 myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
188 // try { // Not good, but there are no other means to test SetValues
189 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
190 M(2,1), M(2,2), M(2,3), V.Y(),
191 M(3,1), M(3,2), M(3,3), V.Z(),
193 fila.Multiply(myTrsf);
194 TopLoc_Location LocLast(fila);
195 if (! myLoc->IsClosed() || LocFirst != LocLast) {
197 if ( ! LocLast.IsIdentity()) {
198 myLast.Location(LocLast.Multiplied(myProfile.Location()) );
206 DBRep::Set("theprof", TheProf);
207 DBRep::Set("thefirst", myFirst);
208 DBRep::Set("thelast" , myLast);
212 myShape = MakeShape(TheProf, myFirst, myLast);
216 //=======================================================================
219 //=======================================================================
221 const TopoDS_Shape& BRepFill_Pipe::Spine() const
226 //=======================================================================
229 //=======================================================================
231 const TopoDS_Shape& BRepFill_Pipe::Profile() const
236 //=======================================================================
239 //=======================================================================
241 const TopoDS_Shape& BRepFill_Pipe::Shape() const
247 //=======================================================================
248 //function : FirstShape
250 //=======================================================================
252 const TopoDS_Shape& BRepFill_Pipe::FirstShape() const
258 //=======================================================================
259 //function : LastShape
261 //=======================================================================
263 const TopoDS_Shape& BRepFill_Pipe::LastShape() const
269 //=======================================================================
272 //=======================================================================
274 TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
275 const TopoDS_Edge& EProfile)
279 if ( BRep_Tool::Degenerated(EProfile))
282 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
284 // *************************************************
285 // Search if EProfile is an edge of myProfile
286 // *************************************************
287 iprof = FindEdge(myProfile, EProfile, count);
289 if (!iprof) Standard_DomainError::Raise(
290 "BRepFill_Pipe::Face : Edge not in the Profile");
293 // *************************************************
294 // Search if ESpine is an edge of mySpine and find
295 // the index of the corresponding Filler
296 // *************************************************
297 for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++)
298 if (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
300 if (!ispin) Standard_DomainError::Raise(
301 "BRepFill_Pipe::Edge : Edge not in the Spine");
303 theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
308 //=======================================================================
311 //=======================================================================
312 TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge& ESpine,
313 const TopoDS_Vertex& VProfile)
315 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;;
317 // *************************************************
318 // Search if VProfile is a Vertex of myProfile
319 // *************************************************
320 iprof = FindVertex(myProfile, VProfile, count);
321 if (!iprof) Standard_DomainError::Raise(
322 "BRepFill_Pipe::Edge : Vertex not in the Profile");
325 // *************************************************
326 // Search if ESpine is an edge of mySpine and find
327 // the index of the corresponding Filler
328 // *************************************************
330 for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++)
331 if (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
333 if (!ispin) Standard_DomainError::Raise(
334 "BRepFill_Pipe::Edge : Edge not in the Spine");
337 // *************************************************
338 // Generate the corresponding Shape
339 // *************************************************
341 theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
348 //=======================================================================
351 //=======================================================================
353 TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const
355 TopoDS_Iterator it, itv;
357 Standard_Integer ii, ispin = 0;
359 TopoDS_Shape curSect = myProfile;
361 // *************************************************
362 // Search if ESpine is an edge of mySpine and find
363 // the index of the corresponding Filler
364 // *************************************************
366 // iterate on all the edges of mySpine
367 for (ii=1; ii<=myLoc->NbLaw()+1 && (!ispin); ii++)
368 if (VSpine.IsSame(myLoc->Vertex(ii))) ispin = ii;
370 if (!ispin) Standard_DomainError::Raise(
371 "BRepFill_Pipe::Section : Vertex not in the Spine");
374 TopoDS_Compound Comp;
375 B.MakeCompound(Comp);
376 for (ii=1; ii<=mySections->ColLength(); ii++)
377 B.Add(Comp, mySections->Value(ii, ispin));
382 //=======================================================================
383 //function : PipeLine
384 //purpose : Construct a wire by sweeping of a point
385 //=======================================================================
387 TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
394 BRepLib_MakeVertex MkV(P);
395 Handle(BRepFill_ShapeLaw) Section =
396 new (BRepFill_ShapeLaw) (MkV.Vertex());
399 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
400 MkSw.SetForceApproxC1(myForceApproxC1);
401 MkSw.Build( BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
402 TopoDS_Shape aLocalShape = MkSw.Shape();
403 return TopoDS::Wire(aLocalShape);
404 // return TopoDS::Wire(MkSw.Shape());
407 //=======================================================================
408 //function : MakeShape
410 //=======================================================================
412 TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
413 const TopoDS_Shape& FirstShape,
414 const TopoDS_Shape& LastShape)
418 Standard_Boolean explode = Standard_False;
419 TopoDS_Shape TheS, TheFirst, TheLast;
420 Standard_Integer InitialLength = 0;
422 TheFirst = FirstShape;
424 if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
426 // there are two kinds of generation
427 // 1. generate with S from each Filler (Vertex, Edge)
428 // 2. call MakeShape recursively on the subshapes of S
430 // explode is True in the second case
432 // create the result empty
434 switch (S.ShapeType()) {
438 B.MakeWire(TopoDS::Wire(result));
445 B.MakeShell(TopoDS::Shell(result));
448 W.Closed(S.Closed());
450 if (!FirstShape.IsNull()) {
452 B.Add(W, FirstShape);
453 W.Closed(FirstShape.Closed());
456 if (!LastShape.IsNull()) {
459 W.Closed(LastShape.Closed());
466 B.MakeShell(TopoDS::Shell(result));
471 B.MakeShell(TopoDS::Shell(result));
472 explode = Standard_True;
473 if ( !mySpine.Closed() && !TheFirst.IsNull()) {
474 B.Add(result, TheFirst.Reversed());
481 B.MakeCompSolid(TopoDS::CompSolid(result));
482 explode = Standard_True;
487 case TopAbs_COMPSOLID :
488 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
491 case TopAbs_COMPOUND :
493 B.MakeCompound(TopoDS::Compound(result));
494 explode = Standard_True;
503 TopoDS_Iterator itFirst, itLast;
504 TopoDS_Shape first, last;
505 if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
506 if (!TheLast.IsNull()) itLast.Initialize(TheLast);
508 for (TopoDS_Iterator it(S); it.More(); it.Next()) {
509 if (!TheFirst.IsNull()) first = itFirst.Value();
510 if (!TheLast.IsNull()) last = itLast.Value();
511 if (TheS.ShapeType() == TopAbs_FACE )
512 MakeShape(it.Value(), first, last);
514 B.Add(result,MakeShape(it.Value(), first, last));
516 if (!TheFirst.IsNull()) itFirst.Next();
517 if (!TheLast.IsNull()) itLast.Next();
522 if (TheS.ShapeType() == TopAbs_VERTEX ) {
523 Handle(BRepFill_ShapeLaw) Section =
524 new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
525 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
526 MkSw.SetForceApproxC1(myForceApproxC1);
527 MkSw.Build( BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
528 result = MkSw.Shape();
531 if (TheS.ShapeType() == TopAbs_WIRE ) {
532 Handle(BRepFill_ShapeLaw) Section =
533 new (BRepFill_ShapeLaw) (TopoDS::Wire(TheS));
534 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
535 MkSw.SetBounds(TopoDS::Wire(TheFirst),
536 TopoDS::Wire(TheLast));
537 MkSw.SetForceApproxC1(myForceApproxC1);
538 MkSw.Build( BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
539 result = MkSw.Shape();
541 // Labeling of elements
542 if (mySections.IsNull()) {
543 myFaces = MkSw.SubShape();
544 mySections = MkSw.Sections();
545 myEdges = MkSw.InterFaces();
548 Handle(TopTools_HArray2OfShape) Aux, Somme;
549 Standard_Integer length;
550 Standard_Integer ii, jj, kk;
551 const Standard_Integer aNbFaces = myFaces->ColLength();
552 const Standard_Integer aNbEdges = myEdges->ColLength();
553 const Standard_Integer aNbSections = mySections->ColLength();
555 Aux = MkSw.SubShape();
556 length = Aux->ColLength() + myFaces->ColLength();
557 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
559 for (jj=1; jj<=myFaces->RowLength(); jj++) {
560 for (ii=1; ii<=myFaces->ColLength(); ii++)
561 Somme->SetValue(ii, jj, myFaces->Value(ii, jj));
563 for (kk=1, ii=myFaces->ColLength()+1;
564 kk <=Aux->ColLength(); kk++, ii++)
565 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
569 Aux = MkSw.Sections();
570 length = Aux->ColLength() + mySections->ColLength();
571 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
573 for (jj=1; jj<=mySections->RowLength(); jj++) {
574 for (ii=1; ii<=mySections->ColLength(); ii++)
575 Somme->SetValue(ii, jj, mySections->Value(ii, jj));
577 for (kk=1, ii=mySections->ColLength()+1;
578 kk <=Aux->ColLength(); kk++, ii++)
579 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
583 Aux = MkSw.InterFaces();
584 length = Aux->ColLength() + myEdges->ColLength();
585 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
587 for (jj=1; jj<=myEdges->RowLength(); jj++) {
588 for (ii=1; ii<=myEdges->ColLength(); ii++)
589 Somme->SetValue(ii, jj, myEdges->Value(ii, jj));
591 for (kk=1, ii=myEdges->ColLength()+1;
592 kk <=Aux->ColLength(); kk++, ii++)
593 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
598 // Perform sharing faces
599 result = ShareFaces(result, aNbFaces, aNbEdges, aNbSections);
604 if ( TheS.ShapeType() == TopAbs_FACE ) {
605 Standard_Integer ii, jj;
607 for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
608 for (jj=1; jj<=myFaces->RowLength(); jj++) {
609 F = TopoDS::Face(myFaces->Value(ii, jj));
610 if (!F.IsNull()) B.Add(result, F);
614 if ( !mySpine.Closed()) {
615 // if Spine is not closed
616 // add the last face of the solid
617 B.Add(result, TopoDS::Face(TheLast));
624 result.Closed(Standard_True);
625 BS.Add(solid,TopoDS::Shell(result));
627 BRepClass3d_SolidClassifier SC(solid);
628 SC.PerformInfinitePoint(Precision::Confusion());
629 if ( SC.State() == TopAbs_IN) {
631 TopoDS_Shape aLocalShape = result.Reversed();
632 BS.Add(solid,TopoDS::Shell(aLocalShape));
633 // BS.Add(solid,TopoDS::Shell(result.Reversed()));
642 //============================================================================
643 //function : FindEdge
644 //purpose : Find the number of edge corresponding to the edge of the profile.
645 //============================================================================
647 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
648 const TopoDS_Edge& E,
649 Standard_Integer& InitialLength) const
651 Standard_Integer result = 0;
653 switch (S.ShapeType()) {
658 if (S.IsSame(E)) result = InitialLength;
664 Standard_Integer ii = InitialLength+1;
665 Handle(BRepFill_ShapeLaw) Section =
666 new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
667 InitialLength += Section->NbLaw();
669 for (; (ii<=InitialLength) && (!result); ii++) {
670 if (E.IsSame(Section->Edge(ii)) ) result = ii;
677 case TopAbs_COMPOUND :
679 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
680 result = FindEdge(it.Value(), E, InitialLength );
685 case TopAbs_COMPSOLID :
686 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
695 //=======================================================================
696 //function : FindVertex
697 //purpose : Find the number of edge corresponding to an edge of the profile.
698 //=======================================================================
700 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
701 const TopoDS_Vertex& V,
702 Standard_Integer& InitialLength) const
704 Standard_Integer result = 0;
706 switch (S.ShapeType()) {
710 if (S.IsSame(V)) result = InitialLength;
716 TopoDS_Vertex VF, VL;
717 TopExp::Vertices(TopoDS::Edge(S), VF, VL);
718 if (S.Orientation() == TopAbs_REVERSED) {
720 aux = VF; VF = VL; VL = aux;
722 if (VF.IsSame(V)) result = InitialLength+1;
723 else if (VL.IsSame(V)) result = InitialLength+2;
730 Standard_Integer ii = InitialLength+1;
731 Handle(BRepFill_ShapeLaw) Section =
732 new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
733 InitialLength += Section->NbLaw()+1;
735 for (; (ii<=InitialLength) && (!result); ii++) {
736 if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
743 case TopAbs_COMPOUND :
745 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
746 result = FindVertex(it.Value(), V, InitialLength);
751 case TopAbs_COMPSOLID :
752 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
761 //=======================================================================
762 //function : DefineRealSegmax
763 //purpose : Defines the real number of segments
764 // required in the case of bspline spine
765 //=======================================================================
767 void BRepFill_Pipe::DefineRealSegmax()
769 Standard_Integer RealSegmax = 0;
771 TopoDS_Iterator iter(mySpine);
772 for (; iter.More(); iter.Next())
774 TopoDS_Edge E = TopoDS::Edge(iter.Value());
775 Standard_Real first, last;
776 Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
779 while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
780 C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
782 if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
783 C = (*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve();
784 if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
785 C = (*((Handle(Geom_OffsetCurve)*)&C))->BasisCurve();
787 if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
789 const Handle(Geom_BSplineCurve)& BC = *((Handle(Geom_BSplineCurve)*)&C);
790 Standard_Integer NbKnots = BC->NbKnots();
791 Standard_Integer RealNbKnots = NbKnots;
792 if (first > BC->FirstParameter())
794 Standard_Integer I1, I2;
795 BC->LocateU( first, Precision::PConfusion(), I1, I2 );
798 if (last < BC->LastParameter())
800 Standard_Integer I1, I2;
801 BC->LocateU( last, Precision::PConfusion(), I1, I2 );
802 RealNbKnots -= NbKnots-I2;
804 RealSegmax += RealNbKnots-1;
808 if (mySegmax < RealSegmax)
809 mySegmax = RealSegmax;
812 //=======================================================================
813 //function : ShareFaces
815 //=======================================================================
817 TopoDS_Shape BRepFill_Pipe::ShareFaces
818 (const TopoDS_Shape &theShape,
819 const Standard_Integer theInitialFacesLen,
820 const Standard_Integer theInitialEdgesLen,
821 const Standard_Integer theInitialSectionsLen)
823 TopoDS_Shape aResult = theShape;
824 // Check if there are shapes to be shared.
825 TopTools_DataMapOfShapeInteger aMapBndEdgeIndex;
826 TColStd_DataMapOfIntegerInteger aMapNewOldFIndex;
827 TColStd_DataMapOfIntegerInteger aMapNewOldEIndex;
828 TopTools_MapOfShape aMapUsedVtx;
829 TopExp_Explorer anExp;
833 BRep_Builder aBuilder;
835 // Check the first and last J index of myFaces.
836 for (i = 1; i <= 2; i++) {
837 // Compute jj index of faces.
841 jj = myFaces->RowLength();
848 // Fill the map of boundary edges on initial faces.
849 for (ii = 1; ii <= theInitialFacesLen; ii++) {
850 anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE);
852 for (; anExp.More(); anExp.Next()) {
853 aMapBndEdgeIndex.Bind(anExp.Current(), ii);
857 // Check if edges of newly created faces are shared with old ones.
858 for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) {
859 anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE);
861 for (; anExp.More(); anExp.Next()) {
862 if (aMapBndEdgeIndex.IsBound(anExp.Current())) {
863 // This row should be replaced.
864 Standard_Integer anOldIndex = aMapBndEdgeIndex.Find(anExp.Current());
866 aMapNewOldFIndex.Bind(ii, anOldIndex);
868 // Find corresponding new and old edges indices.
870 TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV[0], aV[1]);
873 // Compute jj index of edges.
874 Standard_Integer je = (i == 1 ? 1 : myEdges->RowLength());
876 for (Standard_Integer j = 0; j < 2; j++) {
877 if (aMapUsedVtx.Contains(aV[j])) {
878 // This vertex is treated.
883 Standard_Integer iEOld = -1;
884 TopoDS_Vertex aVE[2];
886 for (ie = 1; ie <= theInitialEdgesLen; ie++) {
887 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
889 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
891 if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
899 for (ie = theInitialEdgesLen+1; ie <= myEdges->ColLength(); ie++) {
900 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
902 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
904 if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
905 // This row should be replaced.
906 aMapNewOldEIndex.Bind(ie, iEOld);
907 aMapUsedVtx.Add(aV[j]);
920 if (!aMapNewOldFIndex.IsEmpty()) {
921 TColStd_DataMapIteratorOfDataMapOfIntegerInteger anIter(aMapNewOldFIndex);
922 TopTools_ListOfShape aListShape;
923 BRepTools_Substitution aSubstitute;
925 for (; anIter.More(); anIter.Next()) {
926 const Standard_Integer aNewIndex = anIter.Key();
927 const Standard_Integer anOldIndex = anIter.Value();
929 // Change new faces by old ones.
930 for (jj = 1; jj <= myFaces->RowLength(); jj++) {
931 const TopoDS_Shape &aNewFace = myFaces->Value(aNewIndex, jj);
932 const TopoDS_Shape &anOldFace = myFaces->Value(anOldIndex, jj);
934 if (!aSubstitute.IsCopied(aNewFace)) {
935 aListShape.Append(anOldFace.Oriented(TopAbs_REVERSED));
936 aSubstitute.Substitute(aNewFace, aListShape);
942 // Change new edges by old ones.
943 for (anIter.Initialize(aMapNewOldEIndex); anIter.More(); anIter.Next()) {
944 const Standard_Integer aNewIndex = anIter.Key();
945 const Standard_Integer anOldIndex = anIter.Value();
947 for (jj = 1; jj <= myEdges->RowLength(); jj++) {
948 const TopoDS_Shape &aNewEdge = myEdges->Value(aNewIndex, jj);
949 const TopoDS_Shape &anOldEdge = myEdges->Value(anOldIndex, jj);
951 if (!aSubstitute.IsCopied(aNewEdge)) {
952 aListShape.Append(anOldEdge.Oriented(TopAbs_FORWARD));
953 aSubstitute.Substitute(aNewEdge, aListShape);
956 // Change new vertices by old ones.
957 TopoDS_Iterator aNewIt(aNewEdge);
958 TopoDS_Iterator anOldIt(anOldEdge);
960 for (; aNewIt.More() && anOldIt.More();
961 aNewIt.Next(), anOldIt.Next()) {
962 if (!aNewIt.Value().IsSame(anOldIt.Value())) {
963 if (!aSubstitute.IsCopied(aNewIt.Value())) {
964 aListShape.Append(anOldIt.Value().Oriented(TopAbs_FORWARD));
965 aSubstitute.Substitute(aNewIt.Value(), aListShape);
974 // Perform substitution.
975 aSubstitute.Build(aResult);
977 if (aSubstitute.IsCopied(aResult)) {
979 const TopTools_ListOfShape& listSh = aSubstitute.Copy(aResult);
981 aResult = listSh.First();
983 // Update original faces with copied ones.
984 for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) {
985 for (jj = 1; jj <= myFaces->RowLength(); jj++) {
986 TopoDS_Shape anOldFace = myFaces->Value(ii, jj); // Copy
988 if (aSubstitute.IsCopied(anOldFace)) {
989 const TopTools_ListOfShape& aList = aSubstitute.Copy(anOldFace);
991 if(!aList.IsEmpty()) {
992 // Store copied face.
993 const TopoDS_Shape &aCopyFace = aList.First();
994 TopAbs_Orientation anOri = anOldFace.Orientation();
995 const Standard_Boolean isShared = aMapNewOldFIndex.IsBound(ii);
998 // Reverse the orientation for shared face.
999 anOri = TopAbs::Reverse(anOri);
1002 myFaces->SetValue(ii, jj, aCopyFace.Oriented(anOri));
1004 // Check if it is necessary to update PCurves on this face.
1006 TopoDS_Face anOldF = TopoDS::Face(anOldFace);
1007 TopoDS_Face aCopyF = TopoDS::Face(aCopyFace);
1009 anOldF.Orientation(TopAbs_FORWARD);
1010 anExp.Init(anOldF, TopAbs_EDGE);
1012 for (; anExp.More(); anExp.Next()) {
1013 const TopoDS_Shape &anOldEdge = anExp.Current();
1015 if (aSubstitute.IsCopied(anOldEdge)) {
1016 const TopTools_ListOfShape& aListE =
1017 aSubstitute.Copy(anOldEdge);
1019 if(!aListE.IsEmpty()) {
1020 // This edge is copied. Check if there is a PCurve
1022 TopoDS_Edge aCopyE = TopoDS::Edge(aListE.First());
1023 Standard_Real aFirst;
1024 Standard_Real aLast;
1025 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface
1026 (aCopyE, aCopyF, aFirst, aLast);
1028 if (aPCurve.IsNull()) {
1029 // There is no pcurve copy it from the old edge.
1030 TopoDS_Edge anOldE = TopoDS::Edge(anOldEdge);
1032 aPCurve = BRep_Tool::CurveOnSurface
1033 (anOldE, anOldF, aFirst, aLast);
1035 if (aPCurve.IsNull() == Standard_False) {
1036 // Update the shared edge with PCurve from new Face.
1037 Standard_Real aTol = Max(BRep_Tool::Tolerance(anOldE),
1038 BRep_Tool::Tolerance(aCopyE));
1040 aBuilder.UpdateEdge(aCopyE, aPCurve, aCopyF, aTol);
1052 // Update new edges with shared ones.
1053 for (ii = theInitialEdgesLen + 1; ii <= myEdges->ColLength(); ii++) {
1054 for (jj = 1; jj <= myEdges->RowLength(); jj++) {
1055 const TopoDS_Shape &aLocalShape = myEdges->Value(ii, jj);
1057 if (aSubstitute.IsCopied(aLocalShape)) {
1058 const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1060 if(!aList.IsEmpty()) {
1061 const TopAbs_Orientation anOri = TopAbs_FORWARD;
1063 myEdges->SetValue(ii, jj, aList.First().Oriented(anOri));
1069 // Update new sections with shared ones.
1070 for (ii = theInitialSectionsLen+1; ii <= mySections->ColLength(); ii++) {
1071 for (jj = 1; jj <= mySections->RowLength(); jj++) {
1072 const TopoDS_Shape &aLocalShape = mySections->Value(ii, jj);
1074 if (aSubstitute.IsCopied(aLocalShape)) {
1075 const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1077 if(!aList.IsEmpty()) {
1078 const TopAbs_Orientation anOri = TopAbs_FORWARD;
1080 mySections->SetValue(ii, jj, aList.First().Oriented(anOri));