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