77216b759151973ae103564db826fe20514604ed
[occt.git] / src / BRepTools / BRepTools_ReShape.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 //    abv 28.04.99 S4137: ading method Apply for work on all types of shapes
15 //    sln 29.11.01 Bug24: correction iteration through map in method 'Status'
16 //    sln 29.11.01 Bug22: correction of methods Replace and Value for case when mode myConsiderLocation is on
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_GCurve.hxx>
20 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
21 #include <BRep_ListOfCurveRepresentation.hxx>
22 #include <BRep_TEdge.hxx>
23 #include <BRep_Tool.hxx>
24 #include <BRepTools_ReShape.hxx>
25 #include <Geom_Surface.hxx>
26 #include <Standard_Type.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopLoc_Location.hxx>
29 #include <TopoDS.hxx>
30 #include <TopoDS_Compound.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TopoDS_Iterator.hxx>
34 #include <TopoDS_Shape.hxx>
35 #include <TopoDS_Shell.hxx>
36 #include <TopoDS_Solid.hxx>
37
38 IMPLEMENT_STANDARD_RTTIEXT(BRepTools_ReShape,MMgt_TShared)
39
40 //include <ShapeExtend.hxx>
41 //#include <BRepTools_Edge.hxx>
42 static void CopyRanges (const TopoDS_Shape& toedge, const TopoDS_Shape& fromedge,
43                         const Standard_Real alpha, const Standard_Real beta) 
44 {
45   Handle(BRep_TEdge) aTEdgeFrom = Handle(BRep_TEdge)::DownCast(fromedge.TShape());
46   Handle(BRep_TEdge) aTEdgeTo   = Handle(BRep_TEdge)::DownCast(toedge.TShape());
47   BRep_ListOfCurveRepresentation& tolist = aTEdgeTo->ChangeCurves();
48   BRep_ListIteratorOfListOfCurveRepresentation fromitcr (aTEdgeFrom->ChangeCurves());
49   for (; fromitcr.More(); fromitcr.Next()) {
50     Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
51     if ( fromGC.IsNull() ) continue;
52     Standard_Boolean isC3d = fromGC->IsCurve3D();
53     if(isC3d) {
54       if(fromGC->Curve3D().IsNull()) continue; }
55     else {
56        if(fromGC->PCurve().IsNull()) continue; }
57       
58     if ( ! isC3d && ! fromGC->IsCurveOnSurface()) continue; // only 3d curves and pcurves are treated
59
60     Handle(Geom_Surface) surface;
61     TopLoc_Location L;
62     if ( ! isC3d ) {
63       surface = fromGC->Surface();
64       L = fromGC->Location();
65     } 
66
67     Handle(BRep_GCurve) toGC;
68     for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More(); toitcr.Next()) {
69       toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
70       if ( toGC.IsNull() ) continue;
71       if ( isC3d ) {
72         if ( ! toGC->IsCurve3D() ) continue;
73       }
74       else if ( ! toGC->IsCurveOnSurface() || 
75                surface != toGC->Surface() || L != toGC->Location() ) continue;
76       Standard_Real first = fromGC->First();
77       Standard_Real last = fromGC->Last();
78       Standard_Real len = last - first;
79       toGC->SetRange ( first+alpha*len, first+beta*len );
80       break;
81     }
82   }
83 }
84
85
86 //=======================================================================
87 //function : BRepTools_ReShape
88 //purpose  : 
89 //=======================================================================
90
91 BRepTools_ReShape::BRepTools_ReShape()
92 {
93   myConsiderLocation = Standard_False;
94 }
95
96
97 //=======================================================================
98 //function : Clear
99 //purpose  : 
100 //=======================================================================
101
102 void BRepTools_ReShape::Clear() 
103 {
104   myNMap.Clear();
105   myNewShapes.Clear();
106 }
107
108
109 //=======================================================================
110 //function : Remove
111 //purpose  : 
112 //=======================================================================
113
114 void BRepTools_ReShape::Remove (const TopoDS_Shape& shape)
115 {
116   TopoDS_Shape nulshape;
117   Replace (shape,nulshape);
118 }
119
120 //=======================================================================
121 //function : replace
122 //purpose  : 
123 //=======================================================================
124
125 void BRepTools_ReShape::replace (const TopoDS_Shape& ashape,
126                                  const TopoDS_Shape& anewshape)
127 {
128   TopoDS_Shape shape = ashape;
129   TopoDS_Shape newshape = anewshape;
130   if ( shape.IsNull() || shape == newshape ) return;
131
132   if (shape.Orientation() == TopAbs_REVERSED)
133   {
134     shape.Reverse();
135     newshape.Reverse();
136   }
137   // protect against INTERNAL or EXTERNAL shape
138   else if (shape.Orientation() == TopAbs_INTERNAL
139     || shape.Orientation() == TopAbs_EXTERNAL)
140   {
141     newshape.Orientation((newshape.Orientation() == shape.Orientation()) ?
142       TopAbs_FORWARD : TopAbs_REVERSED);
143     shape.Orientation(TopAbs_FORWARD);
144   }
145
146   if (myConsiderLocation) {
147     //sln 29.11.01 Bug22: Change location of 'newshape' in accordance with location of 'shape'
148     newshape.Location(newshape.Location().Multiplied(shape.Location().Inverted()));
149     TopLoc_Location nullLoc; 
150     shape.Location ( nullLoc );
151   }
152
153 #ifdef OCCT_DEBUG
154   if ( IsRecorded ( shape ) && ((myConsiderLocation && ! Value ( shape ).IsPartner ( newshape )) ||
155                                  (!myConsiderLocation && ! Value ( shape ).IsSame ( newshape )))) 
156     cout << "Warning: BRepTools_ReShape::Replace: shape already recorded" << endl;
157 #endif
158
159   myNMap.Bind (shape, newshape);
160   myNewShapes.Add (newshape);
161 }
162
163
164 //=======================================================================
165 //function : IsRecorded
166 //purpose  : 
167 //=======================================================================
168
169 Standard_Boolean BRepTools_ReShape::IsRecorded (const TopoDS_Shape& ashape) const
170 {
171   TopoDS_Shape shape = ashape;
172   if (myConsiderLocation) {
173     TopLoc_Location nullLoc;
174     shape.Location ( nullLoc );
175   }
176   if (shape.IsNull()) return Standard_False;
177   return myNMap.IsBound (shape);
178 }
179
180
181 //=======================================================================
182 //function : Value
183 //purpose  : 
184 //=======================================================================
185
186 TopoDS_Shape BRepTools_ReShape::Value (const TopoDS_Shape& ashape) const
187 {
188   TopoDS_Shape res;
189   if (ashape.IsNull()) return res;
190   TopoDS_Shape shape = ashape;
191   if (myConsiderLocation) {
192     TopLoc_Location nullLoc;
193     shape.Location ( nullLoc );
194   }
195   
196   Standard_Boolean fromMap = Standard_False;
197   if ( shape.Orientation()==TopAbs_REVERSED ) {
198     if (!myNMap.IsBound (shape)) res = shape;
199     else { 
200       res = myNMap.Find (shape).Reversed();
201       fromMap = Standard_True;
202     }
203   }
204   else {
205     if (!myNMap.IsBound (shape)) res = shape;
206     else {
207       res = myNMap.Find (shape);
208       fromMap = Standard_True;
209     }
210   }
211   // for INTERNAL/EXTERNAL, since they are not fully supported, keep orientation
212   if ( shape.Orientation() == TopAbs_INTERNAL ||
213        shape.Orientation() == TopAbs_EXTERNAL ) 
214     res.Orientation ( shape.Orientation() );
215
216   if (myConsiderLocation) {
217     //sln 29.11.01 Bug22: Recalculate location of resulting shape in accordance with
218     //whether result is from map or not
219     if(fromMap) res.Location(ashape.Location()*res.Location());
220     else res.Location(ashape.Location());
221   }
222
223   return res;
224 }
225
226
227 //=======================================================================
228 //function : Status
229 //purpose  : 
230 //=======================================================================
231
232 Standard_Integer BRepTools_ReShape::Status(const TopoDS_Shape& ashape,
233                                             TopoDS_Shape& newsh,
234                                             const Standard_Boolean last) 
235 {
236   Standard_Integer res = 0;
237   if (ashape.IsNull())  {  newsh.Nullify();  return res;  }
238
239   TopoDS_Shape shape = ashape;
240   TopLoc_Location aLocSh = shape.Location();
241   if (myConsiderLocation) {
242     TopLoc_Location nullLoc;
243     shape.Location ( nullLoc );
244   }
245
246   if (!myNMap.IsBound (shape))  {  newsh = shape;  res = 0; }
247   else {  newsh = myNMap.Find (shape);  res = 1;  }
248   if (res > 0) {
249     if (newsh.IsNull()) res = -1;
250     else if (newsh.IsEqual (shape)) res = 0;
251     else if ( last && ((myConsiderLocation && ! newsh.IsPartner (shape)) ||
252                        (!myConsiderLocation && ! newsh.IsSame (shape)))) {
253       //TopoDS_Shape newnewsh;
254       //Standard_Integer newres = Status (newsh, newnewsh, last);
255       //newsh = newnewsh;
256       //if (newres) res = newres;
257       // sln 29.11.01 Bug24: Correction iteration through maps. Way of iteration used early does not
258       // correspond to way of storing information in the maps.
259       newsh = Apply(shape, TopAbs_SHAPE);
260       if (newsh.IsNull()) res = -1; 
261       if (newsh.IsEqual (shape)) res = 0;
262     }
263   }
264   if(myConsiderLocation && !newsh.IsNull()) 
265   {
266     TopLoc_Location aResLoc = (res >0 && !newsh.Location().IsIdentity() ? 
267       aLocSh * newsh.Location() : aLocSh);
268     newsh.Location(aResLoc);
269   }
270   return res;
271 }
272
273 //=======================================================================
274 //function : EncodeStatus
275 //purpose  : static
276 //=======================================================================
277 static Standard_Integer EncodeStatus (const Standard_Integer status)
278 {
279   switch ( status ) {
280   case 0   : return 0x0000; //ShapeExtend_OK
281   case 1: return 0x0001;    //ShapeExtend_DONE1
282   case 2: return 0x0002;    //....
283   case 3: return 0x0004;
284   case 4: return 0x0008;
285   case 5: return 0x0010;
286   case 6: return 0x0020;
287   case 7: return 0x0040;
288   case 8: return 0x0080;    //....
289   case 9 : return 0x00ff;   //ShapeExtend_DONE
290   case 10: return 0x0100;   //ShapeExtend_FAIL1
291   case 11: return 0x0200;   //...
292   case 12: return 0x0400;
293   case 13: return 0x0800;
294   case 14: return 0x1000;
295   case 15: return 0x2000;
296   case 16: return 0x4000;
297   case 17: return 0x8000;   //....
298   case 18 : return 0xff00;  //ShapeExtend_FAIL
299   }
300   return 0;
301 }
302
303
304 //=======================================================================
305 //function : Apply
306 //purpose  : 
307 //=======================================================================
308
309 TopoDS_Shape BRepTools_ReShape::Apply (const TopoDS_Shape& shape,
310                                        const TopAbs_ShapeEnum until) 
311 {
312   myStatus = EncodeStatus(0); //ShapeExtend::EncodeStatus ( ShapeExtend_OK );
313   if ( shape.IsNull() ) return shape;
314
315   // apply direct replacement
316   TopoDS_Shape newsh = Value ( shape );
317   
318   // if shape removed, return NULL
319   if ( newsh.IsNull() ) {
320     myStatus = EncodeStatus (2); //ShapeExtend_DONE2
321     return newsh;
322   }
323   
324   // if shape replaced, apply modifications to the result recursively 
325   if ( (myConsiderLocation && ! newsh.IsPartner (shape)) || 
326       (!myConsiderLocation &&! newsh.IsSame ( shape )) ) {
327     TopoDS_Shape res = Apply ( newsh, until );
328     myStatus |= EncodeStatus(1); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
329     return res;
330   }
331
332   TopAbs_ShapeEnum st = shape.ShapeType(); //, subt;
333   if ( st >= until ) return newsh;    // critere d arret
334   if(st == TopAbs_VERTEX || st == TopAbs_SHAPE)
335     return shape;
336   // define allowed types of components
337   //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing. 
338   /*
339   switch ( st ) {
340   case TopAbs_COMPOUND:  subt = TopAbs_SHAPE;  break;
341   case TopAbs_COMPSOLID: subt = TopAbs_SOLID;  break;
342   case TopAbs_SOLID:     subt = TopAbs_SHELL;  break;
343   case TopAbs_SHELL:     subt = TopAbs_FACE;   break;
344   case TopAbs_FACE:      subt = TopAbs_WIRE;   break;
345   case TopAbs_WIRE:      subt = TopAbs_EDGE;   break;
346   case TopAbs_EDGE:      subt = TopAbs_VERTEX; break;
347   case TopAbs_VERTEX:
348   case TopAbs_SHAPE:
349   default:               return shape;
350   }
351   */
352   BRep_Builder B;
353   
354   TopoDS_Shape result = shape.EmptyCopied();
355   TopAbs_Orientation orien = shape.Orientation();
356   result.Orientation(TopAbs_FORWARD); // protect against INTERNAL or EXTERNAL shapes
357   Standard_Boolean modif = Standard_False;
358   Standard_Integer locStatus = myStatus;
359   
360   // apply recorded modifications to subshapes
361   Standard_Boolean isEmpty = Standard_True;
362   for ( TopoDS_Iterator it(shape,Standard_False); it.More(); it.Next() ) {
363     TopoDS_Shape sh = it.Value();
364     newsh = Apply ( sh, until );
365     if ( newsh != sh ) {
366       if ( myStatus & EncodeStatus(4)) //ShapeExtend::DecodeStatus ( myStatus, ShapeExtend_DONE4 ) )
367         locStatus |= EncodeStatus(4); //|= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
368       modif = 1;
369     }
370     if ( newsh.IsNull() ) {
371       locStatus |= EncodeStatus(4); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
372       continue;
373     }
374     if ( isEmpty )
375       isEmpty = Standard_False;
376     locStatus |= EncodeStatus(3);//ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
377     if ( st == TopAbs_COMPOUND || newsh.ShapeType() == sh.ShapeType()) { //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
378       B.Add ( result, newsh );
379       continue;
380     }
381     Standard_Integer nitems = 0;
382     for ( TopoDS_Iterator subit(newsh); subit.More(); subit.Next(), nitems++ ) {
383       TopoDS_Shape subsh = subit.Value();
384       if ( subsh.ShapeType() == sh.ShapeType() ) B.Add ( result, subsh );//fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
385       else locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
386     }
387     if ( ! nitems ) locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
388   }
389   if ( ! modif ) return shape;
390
391   // For empty topological containers (any kind of shape except vertex, edge
392   // and face) we have to produce an empty result
393   if ( isEmpty && st != TopAbs_VERTEX && st != TopAbs_EDGE && st != TopAbs_FACE )
394   {
395     result = TopoDS_Shape();
396   }
397   else
398   {
399     // restore Range on edge broken by EmptyCopied()
400     if ( st == TopAbs_EDGE ) {
401       CopyRanges (result, shape, 0, 1);
402     }
403     else if (st == TopAbs_FACE)  {
404       TopoDS_Face face = TopoDS::Face ( shape );
405       if( BRep_Tool::NaturalRestriction( face ) ) {
406         BRep_Builder aB;
407         aB.NaturalRestriction( TopoDS::Face (  result ), Standard_True );
408       }
409     }
410     else if (st == TopAbs_WIRE || st == TopAbs_SHELL)
411       result.Closed (BRep_Tool::IsClosed (result));
412
413     result.Orientation(orien);
414   }
415
416   Replace ( shape, result );
417   myStatus = locStatus;
418
419   return result;
420 }
421
422
423 //=======================================================================
424 //function : Status
425 //purpose  : 
426 //=======================================================================
427
428 /*Standard_Boolean BRepTools_ReShape::Status (const ShapeExtend_Status status) const
429 {
430   return ShapeExtend::DecodeStatus ( myStatus, status );
431 }*/
432
433 //=======================================================================
434 //function : CopyVertex
435 //purpose  : 
436 //=======================================================================
437
438 TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
439                                             const Standard_Real theTol)
440 {
441   return CopyVertex(theV, BRep_Tool::Pnt(theV), theTol);
442 }
443
444 //=======================================================================
445 //function : CopyVertex
446 //purpose  : 
447 //=======================================================================
448
449 TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
450                                             const gp_Pnt& theNewPos,
451                                             const Standard_Real theTol)
452 {
453   TopoDS_Vertex aVertexCopy;
454   Standard_Boolean isRecorded = IsRecorded(theV);
455   aVertexCopy = isRecorded ? TopoDS::Vertex(Apply(theV)) : TopoDS::Vertex(theV.EmptyCopied());
456
457   BRep_Builder B;
458   Standard_Real aNewTol = theTol > 0.0 ? theTol : BRep_Tool::Tolerance(theV);
459   B.UpdateVertex(aVertexCopy, theNewPos, aNewTol);
460
461   if (!isRecorded)
462     Replace(theV, aVertexCopy);
463
464   return aVertexCopy;
465 }
466
467 Standard_Boolean BRepTools_ReShape::IsNewShape(const TopoDS_Shape& theShape) const
468 {
469   return myNewShapes.Contains(theShape);
470 }