e92ec7b2ba7767ce3162006d48c6820415dc1f46
[occt.git] / src / BRepTools / BRepTools_Modifier.cxx
1 // Created on: 1994-08-25
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // IFV 04.06.99 - PRO18974 - processing of INTERNAL shapes.
18
19 #include <BRepTools_Modification.hxx>
20 #include <BRepTools_Modifier.hxx>
21 #include <Message_ProgressIndicator.hxx>
22 #include <Standard_NoSuchObject.hxx>
23 #include <Standard_NullObject.hxx>
24 #include <TColStd_ListIteratorOfListOfTransient.hxx>
25 #include <TColStd_ListOfTransient.hxx>
26 #include <TopExp_Explorer.hxx>
27 #include <TopoDS_Edge.hxx>
28 #include <TopoDS_Face.hxx>
29 #include <TopoDS_Iterator.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Vertex.hxx>
32 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
33 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
34 #include <TopTools_ListIteratorOfListOfShape.hxx>
35 #include <TopTools_ListOfShape.hxx>
36
37 #if 0
38 #include <Poly_Triangulation.hxx>
39 #include <Poly_Polygon3D.hxx>
40 #include <BRepMesh_IncrementalMesh.hxx>
41 #endif
42
43 #include <Geom2d_Line.hxx>
44 #include <BRep_Builder.hxx>
45 #include <BRep_Tool.hxx>
46 #include <TopoDS.hxx>
47 #include <BRepTools.hxx>
48 #include <TopAbs.hxx>
49 #include <TopExp.hxx>
50 #include <gp_Pnt.hxx>
51
52 #include <gp.hxx>
53
54 #include <Standard_NullObject.hxx>
55 #include <gp_Trsf.hxx>
56 #include <BRepTools_TrsfModification.hxx>
57 #include <Message_ProgressSentry.hxx>
58 #include <Geom_Surface.hxx>
59
60
61 //=======================================================================
62 //function : BRepTools_Modifier
63 //purpose  : 
64 //=======================================================================
65
66 BRepTools_Modifier::BRepTools_Modifier ():myDone(Standard_False)
67 {}
68
69 //=======================================================================
70 //function : BRepTools_Modifier
71 //purpose  : 
72 //=======================================================================
73
74 BRepTools_Modifier::BRepTools_Modifier (const TopoDS_Shape& S) :
75   myShape(S),myDone(Standard_False)
76 {
77   myMap.Clear();
78   Put(S);
79 }
80
81 //=======================================================================
82 //function : BRepTools_Modifier
83 //purpose  : 
84 //=======================================================================
85
86 BRepTools_Modifier::BRepTools_Modifier
87   (const TopoDS_Shape& S,
88    const Handle(BRepTools_Modification)& M) : myShape(S),myDone(Standard_False)
89 {
90   myMap.Clear();
91   Put(S);
92   Perform(M);
93 }
94
95
96 //=======================================================================
97 //function : Init
98 //purpose  : 
99 //=======================================================================
100
101 void BRepTools_Modifier::Init(const TopoDS_Shape& S)
102 {
103   myShape = S;
104   myDone = Standard_False;
105   myMap.Clear();
106   Put(S);
107 }
108
109
110 //=======================================================================
111 //function : Perform
112 //purpose  : 
113 //=======================================================================
114
115 void BRepTools_Modifier::Perform(const Handle(BRepTools_Modification)& M, const Handle(Message_ProgressIndicator) & aProgress)
116 {
117   if (myShape.IsNull()) {
118     Standard_NullObject::Raise();
119   }
120   TopTools_DataMapIteratorOfDataMapOfShapeShape theIter(myMap);
121
122   // Set to Null the value of shapes, in case when another modification is applied to the start shape.
123
124   if (!theIter.Value().IsNull()) {
125     while (theIter.More()) {
126       myMap(theIter.Value()).Nullify();
127       theIter.Next();
128     }
129     theIter.Reset();
130   }
131
132   /*
133   while (theIter.More()) {
134     Rebuild(theIter.Key(),M);
135     theIter.Next();
136   }
137   */
138
139   Message_ProgressSentry aPSentry(aProgress, "Converting Shape", 0, 2, 1);
140
141   Rebuild(myShape, M, aProgress);
142
143   if (!aPSentry.More())
144   {
145     // The processing was broken
146     return;
147   }
148
149   aPSentry.Next();
150
151   if (myShape.ShapeType() == TopAbs_FACE) {
152     if (myShape.Orientation() == TopAbs_REVERSED) {
153       myMap(myShape).Reverse();
154     }
155     else{
156       myMap(myShape).Orientation(myShape.Orientation());
157     } 
158   }
159   else {
160     myMap(myShape).Orientation(myShape.Orientation());
161   }
162
163   // Update the continuities
164
165   TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
166   TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,theEFMap);
167   BRep_Builder B;
168
169 /*
170   Standard_Boolean RecomputeTriangles = Standard_False;
171   Standard_Real MaxDeflection = RealFirst();
172   Handle(Poly_Triangulation) Tr;
173   Handle(Poly_Polygon3D) Po;
174   TopLoc_Location Loc;
175 */
176
177   while (theIter.More()) {
178     const TopoDS_Shape& S = theIter.Key();
179 /*
180     if (S.ShapeType() == TopAbs_FACE && !S.IsSame(theIter.Value())) {
181       Tr = BRep_Tool::Triangulation(TopoDS::Face(S),Loc);
182       if (!Tr.IsNull()) {
183         RecomputeTriangles = Standard_True;
184         MaxDeflection = Max(MaxDeflection,Tr->Deflection());
185       }
186     }
187     else */ if (S.ShapeType() == TopAbs_EDGE && !S.IsSame(theIter.Value())) {
188       const TopoDS_Edge& edg = TopoDS::Edge(S);
189 /*
190       Po = BRep_Tool::Polygon3D(edg,Loc);
191       if (!Po.IsNull()) {
192         RecomputeTriangles = Standard_True;
193         MaxDeflection = Max(MaxDeflection,Po->Deflection());
194       }
195 */
196       TopTools_ListIteratorOfListOfShape it;
197       it.Initialize(theEFMap.FindFromKey(edg));
198       TopoDS_Face F1,F2;
199       while (it.More() && F2.IsNull()) {
200         if (F1.IsNull()) {
201           F1 = TopoDS::Face(it.Value());
202         }
203         else {
204           F2 = TopoDS::Face(it.Value());
205         }
206         it.Next();
207       }
208       if (!F2.IsNull()) {
209         const TopoDS_Edge& newedg = TopoDS::Edge(myMap(edg));
210         const TopoDS_Face& newf1  = TopoDS::Face(myMap(F1));
211         const TopoDS_Face& newf2  = TopoDS::Face(myMap(F2));
212         GeomAbs_Shape Newcont = M->Continuity(edg,F1,F2,newedg,newf1,newf2);
213         if (Newcont > GeomAbs_C0) {
214           B.Continuity(newedg,newf1,newf2,Newcont);
215         }
216       }
217     }
218     theIter.Next();
219   }
220 /*
221   if (RecomputeTriangles) {
222     BRepMesh_IncrementalMesh(myMap(myShape),MaxDeflection);
223   }
224 */
225
226   myDone = Standard_True;
227
228 }
229
230 //=======================================================================
231 //function : Put
232 //purpose  : 
233 //=======================================================================
234
235 void BRepTools_Modifier::Put(const TopoDS_Shape& S)
236 {
237   if (!myMap.IsBound(S)) {
238     myMap.Bind(S,TopoDS_Shape());
239     for(TopoDS_Iterator theIterator(S,Standard_False);theIterator.More();theIterator.Next()) {
240
241       Put(theIterator.Value());
242     }
243   }
244 }
245
246 //=======================================================================
247 //function : Rebuild
248 //purpose  : 
249 //=======================================================================
250
251 Standard_Boolean BRepTools_Modifier::Rebuild
252   (const TopoDS_Shape& S,
253    const Handle(BRepTools_Modification)& M,
254    const Handle(Message_ProgressIndicator)& aProgress)
255 {
256   TopoDS_Shape& result = myMap(S);
257 //  if (!result.IsNull()) return ! S.IsEqual(result);
258   if (!result.IsNull()) return ! S.IsSame(result);
259   Standard_Boolean rebuild = Standard_False, RevWires = Standard_False;
260   TopAbs_Orientation ResOr = TopAbs_FORWARD;
261   BRep_Builder B;
262   Standard_Real tol;
263   Standard_Boolean No3DCurve = Standard_False; // en fait, si on n`a pas de 
264   //modif geometry 3d , it is necessary to test the existence of a curve 3d.
265
266   // new geometry ?
267
268   TopAbs_ShapeEnum ts = S.ShapeType();
269   switch (ts) {
270   case TopAbs_FACE:
271     {
272       Standard_Boolean RevFace;
273       Handle(Geom_Surface) surface;
274       TopLoc_Location location;
275       rebuild = M->NewSurface(TopoDS::Face(S),surface,location,tol,
276                               RevWires,RevFace);
277       if (rebuild) {
278         B.MakeFace(TopoDS::Face(result),surface,
279                    location.Predivided(S.Location()),tol);
280         result.Location(S.Location());
281 //      result.Orientation(S.Orientation());
282         if (RevFace) {
283           ResOr = TopAbs_REVERSED;
284         }
285         // set specifics flags of a Face
286         B.NaturalRestriction(TopoDS::Face(result),
287                              BRep_Tool::NaturalRestriction(TopoDS::Face(S)));
288       }
289
290       // update triangulation on the copied face
291       Handle(Poly_Triangulation) aTriangulation;
292       if (M->NewTriangulation(TopoDS::Face(S), aTriangulation))
293       {
294         if (rebuild) // the copied face already exists => update it
295           B.UpdateFace(TopoDS::Face(result), aTriangulation);
296         else
297         { // create new face with bare triangulation
298           B.MakeFace(TopoDS::Face(result), aTriangulation);
299           result.Location(S.Location());
300         }
301         rebuild = Standard_True;
302       }
303     }
304     break;
305
306   case TopAbs_EDGE:
307     {
308       Handle(Geom_Curve) curve;
309       TopLoc_Location location;
310       rebuild = M->NewCurve(TopoDS::Edge(S),curve,location,tol);
311       if (rebuild) {
312         if (curve.IsNull()) {
313           B.MakeEdge(TopoDS::Edge(result));
314           B.Degenerated(TopoDS::Edge(result),
315                         BRep_Tool::Degenerated(TopoDS::Edge(S)));
316           B.UpdateEdge(TopoDS::Edge(result),tol);  //OCC217
317           No3DCurve = Standard_True;
318         }
319         else {
320           B.MakeEdge(TopoDS::Edge(result),curve,
321                      location.Predivided(S.Location()),tol);
322           No3DCurve = Standard_False;
323         }
324         result.Location(S.Location());
325 //      result.Orientation(S.Orientation());
326
327         // set specifics flags of an Edge
328         B.SameParameter(TopoDS::Edge(result),
329                         BRep_Tool::SameParameter(TopoDS::Edge(S)));
330         B.SameRange(TopoDS::Edge(result),
331                     BRep_Tool::SameRange(TopoDS::Edge(S)));
332       }
333
334       // update polygonal structure on the edge
335       Handle(Poly_Polygon3D) aPolygon;
336       if (M->NewPolygon(TopoDS::Edge(S), aPolygon))
337       {
338         if (rebuild) // the copied edge already exists => update it
339           B.UpdateEdge(TopoDS::Edge(result), aPolygon, S.Location());
340         else
341         { // create new edge with bare polygon
342           B.MakeEdge(TopoDS::Edge(result), aPolygon);
343           result.Location(S.Location());
344         }
345         rebuild = Standard_True;
346       }
347     }
348     break;
349
350   case TopAbs_VERTEX:
351     {
352       gp_Pnt vtx;
353       rebuild = M->NewPoint(TopoDS::Vertex(S),vtx,tol);
354       if (rebuild) {
355         B.MakeVertex(TopoDS::Vertex(result),vtx,tol);
356       }
357     }
358     break;
359
360   default:
361     {
362     }
363   }
364
365   // rebuild sub-shapes and test new sub-shape ?
366
367   Standard_Boolean newgeom = rebuild;
368
369   TopoDS_Iterator it;
370
371   {
372     Standard_Integer aShapeCount = 0;
373     {
374       for (it.Initialize(S, Standard_False); it.More(); it.Next()) ++aShapeCount;
375     }
376     
377     Message_ProgressSentry aPSentry(aProgress, "Converting SubShapes", 0, aShapeCount, 1);
378     //
379     for (it.Initialize(S, Standard_False); it.More() && aPSentry.More(); it.Next(), aPSentry.Next()) {
380       // always call Rebuild
381       Standard_Boolean subrebuilt = Rebuild(it.Value(), M, aProgress);
382       rebuild =  subrebuilt || rebuild ;
383     }
384     if (!aPSentry.More())
385     {
386       // The processing was broken
387       return Standard_False;
388     }
389   }
390
391   // make an empty copy
392   if (rebuild && !newgeom) {
393     result = S.EmptyCopied();
394     result.Orientation(TopAbs_FORWARD);
395   }
396
397   // copy the sub-elements 
398   
399   if (rebuild) {
400     TopAbs_Orientation orient;
401     for (it.Initialize(S,Standard_False); it.More(); it.Next()) {
402       orient = it.Value().Orientation();
403       if (RevWires || myMap(it.Value()).Orientation() == TopAbs_REVERSED) {
404         orient = TopAbs::Reverse(orient);
405       }
406       B.Add(result,myMap(it.Value()).Oriented(orient));
407     }
408
409
410     if (ts == TopAbs_FACE) {
411       // pcurves
412       Handle(Geom2d_Curve) curve2d; //,curve2d1;
413       TopoDS_Face face = TopoDS::Face(S);
414       TopAbs_Orientation fcor = face.Orientation();
415       if(fcor != TopAbs_REVERSED) fcor = TopAbs_FORWARD;
416
417       TopExp_Explorer ex(face.Oriented(fcor),TopAbs_EDGE);
418       for (;ex.More(); ex.Next()) 
419       {
420         const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
421
422         if (M->NewCurve2d(edge, face, TopoDS::Edge(myMap(ex.Current())), TopoDS::Face(result), curve2d, tol))
423         {
424           // rem dub 16/09/97 : Make constant topology or not make at all.
425           // Do not make if CopySurface = 1
426           // Atention, TRUE sewing edges (RealyClosed)  
427           // stay even if  CopySurface is true.
428     
429           // check that edge contains two pcurves on this surface:
430           // either it is true seam on the current face, or belongs to two faces
431           // built on that same surface (see OCC21772)
432           // Note: this check could be made separate method in BRepTools
433           Standard_Boolean isClosed = Standard_False;
434           if(BRep_Tool::IsClosed(edge,face))
435           {
436             isClosed = ( ! newgeom || BRepTools::IsReallyClosed(edge,face) );
437             if ( ! isClosed )
438             {
439               TopLoc_Location aLoc;
440               TopoDS_Shape resface = (myMap.IsBound(face) ? myMap(face) : face);
441               if(resface.IsNull())
442                 resface = face;
443               Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(resface), aLoc);
444               // check other faces sharing the same surface
445               TopExp_Explorer aExpF(myShape,TopAbs_FACE);
446               for( ; aExpF.More() && !isClosed; aExpF.Next())
447               {
448                 TopoDS_Face anOther = TopoDS::Face(aExpF.Current());
449                 if(anOther.IsSame(face))
450                   continue;
451                 TopoDS_Shape resface2 = (myMap.IsBound(anOther) ? myMap(anOther) : anOther);
452                 if(resface2.IsNull())
453                   resface2 = anOther;
454                 TopLoc_Location anOtherLoc;
455                 Handle(Geom_Surface) anOtherSurf = 
456                   BRep_Tool::Surface(TopoDS::Face(resface2), anOtherLoc);
457                 if ( aSurf == anOtherSurf && aLoc.IsEqual (anOtherLoc) )
458                 {
459                   TopExp_Explorer aExpE(anOther,TopAbs_EDGE);
460                   for( ; aExpE.More() && !isClosed ; aExpE.Next())
461                     isClosed = edge.IsSame(aExpE.Current());
462                 }
463               }
464             }
465           }
466           if (isClosed) 
467           {
468             TopoDS_Edge CurE = TopoDS::Edge(myMap(edge));
469             TopoDS_Shape aLocalResult = result;
470             aLocalResult.Orientation(TopAbs_FORWARD);
471             TopoDS_Face CurF = TopoDS::Face(aLocalResult);
472             Handle(Geom2d_Curve) curve2d1, currcurv;
473             Standard_Real f,l;
474             if ((!RevWires && fcor != edge.Orientation()) ||
475               ( RevWires && fcor == edge.Orientation())) {
476                 CurE.Orientation(TopAbs_FORWARD);
477                 curve2d1 = BRep_Tool::CurveOnSurface(CurE,CurF,f,l);
478                 if (curve2d1.IsNull()) curve2d1 = new Geom2d_Line(gp::OX2d());
479                 B.UpdateEdge (CurE, curve2d1, curve2d, CurF, 0.);
480             }
481             else {
482               CurE.Orientation(TopAbs_REVERSED);
483               curve2d1 = BRep_Tool::CurveOnSurface(CurE,CurF,f,l);
484               if (curve2d1.IsNull()) curve2d1 = new Geom2d_Line(gp::OX2d());
485               B.UpdateEdge (CurE, curve2d, curve2d1, CurF, 0.);
486             }
487             currcurv = BRep_Tool::CurveOnSurface(edge,face,f,l);
488             B.Range(edge,f,l);
489           }
490           else {
491             B.UpdateEdge(TopoDS::Edge(myMap(ex.Current())),
492               curve2d,
493               TopoDS::Face(result), 0.);
494           }
495
496           TopLoc_Location theLoc;
497           Standard_Real theF,theL;
498           Handle(Geom_Curve) C3D = BRep_Tool::Curve(TopoDS::Edge(myMap(ex.Current())), theLoc, theF, theL);
499           if (C3D.IsNull()) { // Update vertices
500             Standard_Real param;
501             TopExp_Explorer ex2(edge,TopAbs_VERTEX);
502             while (ex2.More()) {
503               const TopoDS_Vertex& vertex = TopoDS::Vertex(ex2.Current());
504               if (!M->NewParameter(vertex, edge, param, tol)) {
505                 tol = BRep_Tool::Tolerance(vertex);
506                 param = BRep_Tool::Parameter(vertex,edge);
507               }
508
509               TopAbs_Orientation vtxrelat = vertex.Orientation();
510               if (edge.Orientation() == TopAbs_REVERSED) {
511                 // Update considere l'edge FORWARD, et le vertex en relatif
512                 vtxrelat= TopAbs::Reverse(vtxrelat);
513               }
514               //if (myMap(edge).Orientation() == TopAbs_REVERSED) {
515               //  vtxrelat= TopAbs::Reverse(vtxrelat);
516               //}
517
518               TopoDS_Vertex aLocalVertex = TopoDS::Vertex(myMap(vertex));
519               aLocalVertex.Orientation(vtxrelat);
520               //B.UpdateVertex(TopoDS::Vertex
521               //(myMap(vertex).Oriented(vtxrelat)),
522               B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(myMap(edge)), tol);
523               ex2.Next();
524             }
525           }
526         }
527
528         // Copy polygon on triangulation
529         Handle(Poly_PolygonOnTriangulation) aPolyOnTria_1, aPolyOnTria_2;
530         Standard_Boolean aNewPonT = M->NewPolygonOnTriangulation(edge, face, aPolyOnTria_1);
531         if (BRepTools::IsReallyClosed(edge, face))
532         {
533           // Obtain triangulation on reversed edge
534           TopoDS_Edge anEdgeRev = edge;
535           anEdgeRev.Reverse();
536           aNewPonT = M->NewPolygonOnTriangulation(anEdgeRev, face, aPolyOnTria_2) || aNewPonT;
537           // It there is only one polygon on triangulation, store it to aPolyOnTria_1
538           if (aPolyOnTria_1.IsNull() && !aPolyOnTria_2.IsNull())
539           {
540             aPolyOnTria_1 = aPolyOnTria_2;
541             aPolyOnTria_2 = Handle(Poly_PolygonOnTriangulation)();
542           }
543         }
544         if (aNewPonT)
545         {
546           TopLoc_Location aLocation;
547           Handle(Poly_Triangulation) aNewFaceTria =
548               BRep_Tool::Triangulation(TopoDS::Face(myMap(face)), aLocation);
549           TopoDS_Edge aNewEdge = TopoDS::Edge(myMap(edge));
550           if (aPolyOnTria_2.IsNull())
551             B.UpdateEdge(aNewEdge, aPolyOnTria_1, aNewFaceTria, aLocation);
552           else
553           {
554             if (edge.Orientation() == TopAbs_FORWARD)
555               B.UpdateEdge(aNewEdge, aPolyOnTria_1, aPolyOnTria_2, aNewFaceTria, aLocation);
556             else
557               B.UpdateEdge(aNewEdge, aPolyOnTria_2, aPolyOnTria_1, aNewFaceTria, aLocation);
558           }
559         }
560       }
561
562     }
563
564 //    else if (ts == TopAbs_EDGE) {
565     else if (ts == TopAbs_EDGE && !No3DCurve) {
566       // Vertices
567       Standard_Real param;
568       const TopoDS_Edge& edge = TopoDS::Edge(S);
569       TopAbs_Orientation edor = edge.Orientation();
570       if(edor != TopAbs_REVERSED) edor = TopAbs_FORWARD;
571       TopExp_Explorer ex(edge.Oriented(edor), TopAbs_VERTEX);
572       while (ex.More()) {
573         const TopoDS_Vertex& vertex = TopoDS::Vertex(ex.Current());
574
575         if (!M->NewParameter(vertex, edge, param, tol)) {
576           tol = BRep_Tool::Tolerance(vertex);
577           param = BRep_Tool::Parameter(vertex,edge);
578         }
579
580         TopAbs_Orientation vtxrelat = vertex.Orientation();
581         if (edor == TopAbs_REVERSED) {
582           // Update considere l'edge FORWARD, et le vertex en relatif
583           vtxrelat= TopAbs::Reverse(vtxrelat);
584         }
585
586         //if (result.Orientation() == TopAbs_REVERSED) {
587         //  vtxrelat= TopAbs::Reverse(vtxrelat);
588         //}
589         TopoDS_Vertex aLocalVertex = TopoDS::Vertex(myMap(vertex));
590         aLocalVertex.Orientation(vtxrelat);
591         //B.UpdateVertex(TopoDS::Vertex(myMap(vertex).Oriented(vtxrelat)),
592         B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(result), tol);
593
594         ex.Next();
595       }
596
597     }
598
599     // update flags
600
601     result.Orientable(S.Orientable());
602     result.Closed(S.Closed());
603     result.Infinite(S.Infinite());
604   }
605   else
606     result = S;
607
608   // Set flag of the shape.
609   result.Orientation(ResOr);
610
611   result.Modified  (S.Modified());
612   result.Checked   (S.Checked());
613   result.Orientable(S.Orientable());
614   result.Closed    (S.Closed());
615   result.Infinite  (S.Infinite());
616   result.Convex    (S.Convex());
617
618   return rebuild;
619 }
620
621