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