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