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 <NCollection_IndexedMap.hxx>
27 #include <Standard_Type.hxx>
28 #include <TopExp_Explorer.hxx>
29 #include <TopLoc_Location.hxx>
30 #include <TopoDS.hxx>
31 #include <TopoDS_Compound.hxx>
32 #include <TopoDS_Edge.hxx>
33 #include <TopoDS_Face.hxx>
34 #include <TopoDS_Iterator.hxx>
35 #include <TopoDS_Shape.hxx>
36 #include <TopoDS_Shell.hxx>
37 #include <TopoDS_Solid.hxx>
38 
39 IMPLEMENT_STANDARD_RTTIEXT(BRepTools_ReShape,Standard_Transient)
40 
41 namespace
42 {
43 
44 //! Adds the shape to the map.
45 //! If the shape is a wire, shell or solid then
46 //! adds the sub-shapes of the shape instead.
47 //! Returns 'true' if the sub-shapes were added.
48 template<typename TMap>
Add(TMap & theMap,const TopoDS_Shape & theShape)49 void Add(TMap& theMap, const TopoDS_Shape& theShape)
50 {
51   const TopAbs_ShapeEnum aType = theShape.ShapeType();
52   if (aType != TopAbs_WIRE && aType != TopAbs_SHELL &&
53     aType != TopAbs_COMPSOLID)
54   {
55     theMap.Add(theShape);
56     return;
57   }
58 
59   for (TopoDS_Iterator aIt(theShape); aIt.More(); aIt.Next())
60   {
61     theMap.Add(aIt.Value());
62   }
63 }
64 
65 }
66 
67 //include <ShapeExtend.hxx>
68 //#include <BRepTools_Edge.hxx>
CopyRanges(const TopoDS_Shape & toedge,const TopoDS_Shape & fromedge,const Standard_Real alpha,const Standard_Real beta)69 static void CopyRanges (const TopoDS_Shape& toedge, const TopoDS_Shape& fromedge,
70 			const Standard_Real alpha, const Standard_Real beta)
71 {
72   Handle(BRep_TEdge) aTEdgeFrom = Handle(BRep_TEdge)::DownCast(fromedge.TShape());
73   Handle(BRep_TEdge) aTEdgeTo   = Handle(BRep_TEdge)::DownCast(toedge.TShape());
74   BRep_ListOfCurveRepresentation& tolist = aTEdgeTo->ChangeCurves();
75   BRep_ListIteratorOfListOfCurveRepresentation fromitcr (aTEdgeFrom->ChangeCurves());
76   for (; fromitcr.More(); fromitcr.Next()) {
77     Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
78     if ( fromGC.IsNull() ) continue;
79     Standard_Boolean isC3d = fromGC->IsCurve3D();
80     if(isC3d) {
81       if(fromGC->Curve3D().IsNull()) continue; }
82     else {
83        if(fromGC->PCurve().IsNull()) continue; }
84 
85     if ( ! isC3d && ! fromGC->IsCurveOnSurface()) continue; // only 3d curves and pcurves are treated
86 
87     Handle(Geom_Surface) surface;
88     TopLoc_Location L;
89     if ( ! isC3d ) {
90       surface = fromGC->Surface();
91       L = fromGC->Location();
92     }
93 
94     Handle(BRep_GCurve) toGC;
95     for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More(); toitcr.Next()) {
96       toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
97       if ( toGC.IsNull() ) continue;
98       if ( isC3d ) {
99 	if ( ! toGC->IsCurve3D() ) continue;
100       }
101       else if ( ! toGC->IsCurveOnSurface() ||
102 	       surface != toGC->Surface() || L != toGC->Location() ) continue;
103       Standard_Real first = fromGC->First();
104       Standard_Real last = fromGC->Last();
105       Standard_Real len = last - first;
106       toGC->SetRange ( first+alpha*len, first+beta*len );
107       break;
108     }
109   }
110 }
111 
112 
113 //=======================================================================
114 //function : BRepTools_ReShape
115 //purpose  :
116 //=======================================================================
117 
BRepTools_ReShape()118 BRepTools_ReShape::BRepTools_ReShape()
119 : myStatus(-1)
120 {
121   myConsiderLocation = Standard_False;
122 }
123 
124 
125 //=======================================================================
126 //function : Clear
127 //purpose  :
128 //=======================================================================
129 
Clear()130 void BRepTools_ReShape::Clear()
131 {
132   myShapeToReplacement.Clear();
133   myNewShapes.Clear();
134 }
135 
136 
137 //=======================================================================
138 //function : Remove
139 //purpose  :
140 //=======================================================================
141 
Remove(const TopoDS_Shape & shape)142 void BRepTools_ReShape::Remove (const TopoDS_Shape& shape)
143 {
144   TopoDS_Shape nulshape;
145   replace(shape, nulshape, TReplacementKind_Remove);
146 }
147 
148 //=======================================================================
149 //function : replace
150 //purpose  :
151 //=======================================================================
152 
replace(const TopoDS_Shape & ashape,const TopoDS_Shape & anewshape,const TReplacementKind theKind)153 void BRepTools_ReShape::replace (const TopoDS_Shape& ashape,
154                                  const TopoDS_Shape& anewshape,
155                                  const TReplacementKind theKind)
156 {
157   TopoDS_Shape shape = ashape;
158   TopoDS_Shape newshape = anewshape;
159   if ( shape.IsNull() || shape == newshape ) return;
160 
161   if (shape.Orientation() == TopAbs_REVERSED)
162   {
163     shape.Reverse();
164     newshape.Reverse();
165   }
166   // protect against INTERNAL or EXTERNAL shape
167   else if (shape.Orientation() == TopAbs_INTERNAL
168     || shape.Orientation() == TopAbs_EXTERNAL)
169   {
170     newshape.Orientation((newshape.Orientation() == shape.Orientation()) ?
171       TopAbs_FORWARD : TopAbs_REVERSED);
172     shape.Orientation(TopAbs_FORWARD);
173   }
174 
175   if (myConsiderLocation) {
176     //sln 29.11.01 Bug22: Change location of 'newshape' in accordance with location of 'shape'
177     newshape.Location(newshape.Location().Multiplied(shape.Location().Inverted()), Standard_False);
178     TopLoc_Location nullLoc;
179     shape.Location ( nullLoc );
180   }
181 
182 #ifdef OCCT_DEBUG
183   if ( IsRecorded ( shape ) && ((myConsiderLocation && ! Value ( shape ).IsPartner ( newshape )) ||
184                                  (!myConsiderLocation && ! Value ( shape ).IsSame ( newshape ))))
185     std::cout << "Warning: BRepTools_ReShape::Replace: shape already recorded" << std::endl;
186 #endif
187 
188   myShapeToReplacement.Bind(shape, TReplacement(newshape, theKind));
189   myNewShapes.Add (newshape);
190 }
191 
192 //=======================================================================
193 //function : IsRecorded
194 //purpose  :
195 //=======================================================================
196 
IsRecorded(const TopoDS_Shape & ashape) const197 Standard_Boolean BRepTools_ReShape::IsRecorded (const TopoDS_Shape& ashape) const
198 {
199   TopoDS_Shape shape = ashape;
200   if (myConsiderLocation) {
201     TopLoc_Location nullLoc;
202     shape.Location ( nullLoc );
203   }
204   if (shape.IsNull()) return Standard_False;
205   return myShapeToReplacement.IsBound (shape);
206 }
207 
208 
209 //=======================================================================
210 //function : Value
211 //purpose  :
212 //=======================================================================
213 
Value(const TopoDS_Shape & ashape) const214 TopoDS_Shape BRepTools_ReShape::Value (const TopoDS_Shape& ashape) const
215 {
216   TopoDS_Shape res;
217   if (ashape.IsNull()) return res;
218   TopoDS_Shape shape = ashape;
219   if (myConsiderLocation) {
220     TopLoc_Location nullLoc;
221     shape.Location ( nullLoc );
222   }
223 
224   Standard_Boolean fromMap = Standard_False;
225   if (!myShapeToReplacement.IsBound(shape))
226   {
227     res = shape;
228   }
229   else
230   {
231     res = myShapeToReplacement(shape).Result();
232     if (shape.Orientation() == TopAbs_REVERSED)
233     {
234       res.Reverse();
235     }
236     fromMap = Standard_True;
237   }
238   // for INTERNAL/EXTERNAL, since they are not fully supported, keep orientation
239   if ( shape.Orientation() == TopAbs_INTERNAL ||
240        shape.Orientation() == TopAbs_EXTERNAL )
241     res.Orientation ( shape.Orientation() );
242 
243   if (myConsiderLocation) {
244     //sln 29.11.01 Bug22: Recalculate location of resulting shape in accordance with
245     //whether result is from map or not
246     if(fromMap) res.Location(ashape.Location()*res.Location(), Standard_False);
247     else res.Location(ashape.Location(), Standard_False);
248   }
249 
250   return res;
251 }
252 
253 
254 //=======================================================================
255 //function : Status
256 //purpose  :
257 //=======================================================================
258 
Status(const TopoDS_Shape & ashape,TopoDS_Shape & newsh,const Standard_Boolean last)259 Standard_Integer BRepTools_ReShape::Status(const TopoDS_Shape& ashape,
260 					    TopoDS_Shape& newsh,
261 					    const Standard_Boolean last)
262 {
263   Standard_Integer res = 0;
264   if (ashape.IsNull())  {  newsh.Nullify();  return res;  }
265 
266   TopoDS_Shape shape = ashape;
267   TopLoc_Location aLocSh = shape.Location();
268   if (myConsiderLocation) {
269     TopLoc_Location nullLoc;
270     shape.Location ( nullLoc );
271   }
272 
273   if (!myShapeToReplacement.IsBound(shape))
274   {
275     newsh = shape;
276     res = 0;
277   }
278   else
279   {
280     newsh = myShapeToReplacement(shape).Result();
281     res = 1;
282   }
283   if (res > 0) {
284     if (newsh.IsNull()) res = -1;
285     else if (newsh.IsEqual (shape)) res = 0;
286     else if ( last && ((myConsiderLocation && ! newsh.IsPartner (shape)) ||
287                        (!myConsiderLocation && ! newsh.IsSame (shape)))) {
288       //TopoDS_Shape newnewsh;
289       //Standard_Integer newres = Status (newsh, newnewsh, last);
290       //newsh = newnewsh;
291       //if (newres) res = newres;
292       // sln 29.11.01 Bug24: Correction iteration through maps. Way of iteration used early does not
293       // correspond to way of storing information in the maps.
294       newsh = Apply(shape, TopAbs_SHAPE);
295       if (newsh.IsNull()) res = -1;
296       if (newsh.IsEqual (shape)) res = 0;
297     }
298   }
299   if(myConsiderLocation && !newsh.IsNull())
300   {
301     TopLoc_Location aResLoc = (res >0 && !newsh.Location().IsIdentity() ?
302       aLocSh * newsh.Location() : aLocSh);
303     newsh.Location(aResLoc, Standard_False);
304   }
305   return res;
306 }
307 
308 //=======================================================================
309 //function : EncodeStatus
310 //purpose  : static
311 //=======================================================================
EncodeStatus(const Standard_Integer status)312 static Standard_Integer EncodeStatus (const Standard_Integer status)
313 {
314   switch ( status ) {
315   case 0   : return 0x0000; //ShapeExtend_OK
316   case 1: return 0x0001;    //ShapeExtend_DONE1
317   case 2: return 0x0002;    //....
318   case 3: return 0x0004;
319   case 4: return 0x0008;
320   case 5: return 0x0010;
321   case 6: return 0x0020;
322   case 7: return 0x0040;
323   case 8: return 0x0080;    //....
324   case 9 : return 0x00ff;   //ShapeExtend_DONE
325   case 10: return 0x0100;   //ShapeExtend_FAIL1
326   case 11: return 0x0200;   //...
327   case 12: return 0x0400;
328   case 13: return 0x0800;
329   case 14: return 0x1000;
330   case 15: return 0x2000;
331   case 16: return 0x4000;
332   case 17: return 0x8000;   //....
333   case 18 : return 0xff00;  //ShapeExtend_FAIL
334   }
335   return 0;
336 }
337 
338 
339 //=======================================================================
340 //function : Apply
341 //purpose  :
342 //=======================================================================
343 
Apply(const TopoDS_Shape & shape,const TopAbs_ShapeEnum until)344 TopoDS_Shape BRepTools_ReShape::Apply (const TopoDS_Shape& shape,
345                                        const TopAbs_ShapeEnum until)
346 {
347   myStatus = EncodeStatus(0); //ShapeExtend::EncodeStatus ( ShapeExtend_OK );
348   if ( shape.IsNull() ) return shape;
349 
350   // apply direct replacement
351   TopoDS_Shape newsh = Value ( shape );
352 
353   // if shape removed, return NULL
354   if ( newsh.IsNull() ) {
355     myStatus = EncodeStatus (2); //ShapeExtend_DONE2
356     return newsh;
357   }
358 
359   // if shape replaced, apply modifications to the result recursively
360   if ( (myConsiderLocation && ! newsh.IsPartner (shape)) ||
361       (!myConsiderLocation &&! newsh.IsSame ( shape )) ) {
362     TopoDS_Shape res = Apply ( newsh, until );
363     myStatus |= EncodeStatus(1); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
364     return res;
365   }
366 
367   TopAbs_ShapeEnum st = shape.ShapeType();
368   if (st > until || (st == until && until > TopAbs_COMPOUND)) return newsh; // stopping criteria
369   if(st == TopAbs_VERTEX || st == TopAbs_SHAPE)
370     return shape;
371   // define allowed types of components
372   //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
373   /*
374   switch ( st ) {
375   case TopAbs_COMPOUND:  subt = TopAbs_SHAPE;  break;
376   case TopAbs_COMPSOLID: subt = TopAbs_SOLID;  break;
377   case TopAbs_SOLID:     subt = TopAbs_SHELL;  break;
378   case TopAbs_SHELL:     subt = TopAbs_FACE;   break;
379   case TopAbs_FACE:      subt = TopAbs_WIRE;   break;
380   case TopAbs_WIRE:      subt = TopAbs_EDGE;   break;
381   case TopAbs_EDGE:      subt = TopAbs_VERTEX; break;
382   case TopAbs_VERTEX:
383   case TopAbs_SHAPE:
384   default:               return shape;
385   }
386   */
387   BRep_Builder B;
388 
389   TopoDS_Shape result = shape.EmptyCopied();
390   TopAbs_Orientation orien = shape.Orientation();
391   result.Orientation(TopAbs_FORWARD); // protect against INTERNAL or EXTERNAL shapes
392   Standard_Boolean modif = Standard_False;
393   Standard_Integer locStatus = myStatus;
394 
395   // apply recorded modifications to subshapes
396   Standard_Boolean isEmpty = Standard_True;
397   for ( TopoDS_Iterator it(shape,Standard_False); it.More(); it.Next() ) {
398     TopoDS_Shape sh = it.Value();
399     newsh = Apply ( sh, until );
400     if ( newsh != sh ) {
401       if ( myStatus & EncodeStatus(4)) //ShapeExtend::DecodeStatus ( myStatus, ShapeExtend_DONE4 ) )
402         locStatus |= EncodeStatus(4); //|= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
403       modif = 1;
404     }
405     if ( newsh.IsNull() ) {
406       locStatus |= EncodeStatus(4); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
407       continue;
408     }
409     if ( isEmpty )
410       isEmpty = Standard_False;
411     locStatus |= EncodeStatus(3);//ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
412     if ( st == TopAbs_COMPOUND || newsh.ShapeType() == sh.ShapeType()) { //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
413       B.Add ( result, newsh );
414       continue;
415     }
416     Standard_Integer nitems = 0;
417     for ( TopoDS_Iterator subit(newsh); subit.More(); subit.Next(), nitems++ ) {
418       TopoDS_Shape subsh = subit.Value();
419       if ( subsh.ShapeType() == sh.ShapeType() ) B.Add ( result, subsh );//fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
420       else locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
421     }
422     if ( ! nitems ) locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
423   }
424   if ( ! modif ) return shape;
425 
426   // For empty topological containers (any kind of shape except vertex, edge
427   // and face) we have to produce an empty result
428   if ( isEmpty && st != TopAbs_VERTEX && st != TopAbs_EDGE && st != TopAbs_FACE )
429   {
430     result = TopoDS_Shape();
431   }
432   else
433   {
434     // restore Range on edge broken by EmptyCopied()
435     if ( st == TopAbs_EDGE ) {
436       CopyRanges (result, shape, 0, 1);
437     }
438     else if (st == TopAbs_FACE)  {
439       TopoDS_Face face = TopoDS::Face ( shape );
440       if( BRep_Tool::NaturalRestriction( face ) ) {
441         BRep_Builder aB;
442         aB.NaturalRestriction( TopoDS::Face (  result ), Standard_True );
443       }
444     }
445     else if (st == TopAbs_WIRE || st == TopAbs_SHELL)
446       result.Closed (BRep_Tool::IsClosed (result));
447 
448     result.Orientation(orien);
449   }
450 
451   replace(shape, result,
452     result.IsNull() ? TReplacementKind_Remove : TReplacementKind_Modify);
453   myStatus = locStatus;
454 
455   return result;
456 }
457 
458 
459 //=======================================================================
460 //function : Status
461 //purpose  :
462 //=======================================================================
463 
464 /*Standard_Boolean BRepTools_ReShape::Status (const ShapeExtend_Status status) const
465 {
466   return ShapeExtend::DecodeStatus ( myStatus, status );
467 }*/
468 
469 //=======================================================================
470 //function : CopyVertex
471 //purpose  :
472 //=======================================================================
473 
CopyVertex(const TopoDS_Vertex & theV,const Standard_Real theTol)474 TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
475                                             const Standard_Real theTol)
476 {
477   return CopyVertex(theV, BRep_Tool::Pnt(theV), theTol);
478 }
479 
480 //=======================================================================
481 //function : CopyVertex
482 //purpose  :
483 //=======================================================================
484 
CopyVertex(const TopoDS_Vertex & theV,const gp_Pnt & theNewPos,const Standard_Real theTol)485 TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
486                                             const gp_Pnt& theNewPos,
487                                             const Standard_Real theTol)
488 {
489   TopoDS_Vertex aVertexCopy;
490   Standard_Boolean isRecorded = IsRecorded(theV);
491   aVertexCopy = isRecorded ? TopoDS::Vertex(Apply(theV)) : TopoDS::Vertex(theV.EmptyCopied());
492 
493   BRep_Builder B;
494   Standard_Real aNewTol = theTol > 0.0 ? theTol : BRep_Tool::Tolerance(theV);
495   B.UpdateVertex(aVertexCopy, theNewPos, aNewTol);
496 
497   if (!isRecorded)
498     Replace(theV, aVertexCopy);
499 
500   return aVertexCopy;
501 }
502 
IsNewShape(const TopoDS_Shape & theShape) const503 Standard_Boolean BRepTools_ReShape::IsNewShape(const TopoDS_Shape& theShape) const
504 {
505   return myNewShapes.Contains(theShape);
506 }
507 
508 //=======================================================================
509 //function : History
510 //purpose  :
511 //=======================================================================
512 
Handle(BRepTools_History)513 Handle(BRepTools_History) BRepTools_ReShape::History() const
514 {
515   Handle(BRepTools_History) aHistory = new BRepTools_History;
516 
517   // Fill the history.
518   for (TShapeToReplacement::Iterator aRIt(myShapeToReplacement);
519     aRIt.More(); aRIt.Next())
520   {
521     const TopoDS_Shape& aShape = aRIt.Key();
522     if (!BRepTools_History::IsSupportedType(aShape) ||
523       myNewShapes.Contains(aShape))
524     {
525       continue;
526     }
527 
528     NCollection_IndexedMap<TopoDS_Shape> aIntermediates;
529     NCollection_Map<TopoDS_Shape> aModified;
530     aIntermediates.Add(aShape);
531     for (Standard_Integer aI = 1; aI <= aIntermediates.Size(); ++aI)
532     {
533       const TopoDS_Shape& aIntermediate = aIntermediates(aI);
534       const TReplacement* aReplacement =
535         myShapeToReplacement.Seek(aIntermediate);
536       if (aReplacement == NULL)
537       {
538         Add(aModified, aIntermediate);
539       }
540       else if (aReplacement->RelationKind() !=
541         BRepTools_History::TRelationType_Removed)
542       {
543         const TopoDS_Shape aResult = aReplacement->RelationResult();
544         if (!aResult.IsNull())
545         {
546           Add(aIntermediates, aResult);
547         }
548       }
549     }
550 
551     if (aModified.IsEmpty())
552     {
553       aHistory->Remove(aShape);
554     }
555     else
556     {
557       for (NCollection_Map<TopoDS_Shape>::Iterator aIt(aModified);
558         aIt.More(); aIt.Next())
559       {
560         aHistory->AddModified(aShape, aIt.Value());
561       }
562     }
563   }
564 
565   return aHistory;
566 }
567