1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
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
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>
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>
38 IMPLEMENT_STANDARD_RTTIEXT(BRepTools_ReShape,MMgt_TShared)
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)
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();
54 if(fromGC->Curve3D().IsNull()) continue; }
56 if(fromGC->PCurve().IsNull()) continue; }
58 if ( ! isC3d && ! fromGC->IsCurveOnSurface()) continue; // only 3d curves and pcurves are treated
60 Handle(Geom_Surface) surface;
63 surface = fromGC->Surface();
64 L = fromGC->Location();
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;
72 if ( ! toGC->IsCurve3D() ) continue;
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 );
86 //=======================================================================
87 //function : BRepTools_ReShape
89 //=======================================================================
91 BRepTools_ReShape::BRepTools_ReShape()
93 myConsiderLocation = Standard_False;
94 myConsiderOrientation = Standard_False;
98 //=======================================================================
101 //=======================================================================
103 void BRepTools_ReShape::Clear()
111 //=======================================================================
114 //=======================================================================
116 void BRepTools_ReShape::Remove (const TopoDS_Shape& shape,
117 const Standard_Boolean oriented)
119 TopoDS_Shape nulshape;
120 Replace (shape,nulshape,oriented);
123 //=======================================================================
126 //=======================================================================
128 void BRepTools_ReShape::Replace (const TopoDS_Shape& ashape,
129 const TopoDS_Shape& anewshape,
130 const Standard_Boolean oriented)
132 TopoDS_Shape shape = ashape;
133 TopoDS_Shape newshape = anewshape;
134 if ( shape.IsNull() || shape == newshape ) return;
135 if (myConsiderLocation) {
136 //sln 29.11.01 Bug22: Change location of 'newshape' in accordance with location of 'shape'
137 newshape.Location(newshape.Location().Multiplied(shape.Location().Inverted()));
138 TopLoc_Location nullLoc;
139 shape.Location ( nullLoc );
143 if ( IsRecorded ( shape ) && ((myConsiderLocation && ! Value ( shape ).IsPartner ( newshape )) ||
144 (!myConsiderLocation && ! Value ( shape ).IsSame ( newshape ))))
145 cout << "Warning: BRepTools_ReShape::Replace: shape already recorded" << endl;
149 if( shape.Orientation()==TopAbs_REVERSED ) {
150 if( myConsiderOrientation )
151 myRMap.Bind (shape,newshape);
153 myNMap.Bind (shape.Reversed(),newshape.Reversed());
157 myNMap.Bind (shape,newshape);
158 myNewShapes.Add (newshape);
161 // protect against INTERNAL or EXTERNAL shape
162 if ( shape.Orientation() == TopAbs_INTERNAL ||
163 shape.Orientation() == TopAbs_EXTERNAL ) {
164 Replace ( shape.Oriented ( TopAbs_FORWARD ),
165 newshape.Oriented ( newshape.Orientation() == shape.Orientation() ?
166 TopAbs_FORWARD : TopAbs_REVERSED ), oriented );
170 Replace (shape,newshape,Standard_True);
171 if(myConsiderOrientation)
172 Replace (shape.Reversed(),newshape.Reversed(),Standard_True);
177 //=======================================================================
178 //function : IsRecorded
180 //=======================================================================
182 Standard_Boolean BRepTools_ReShape::IsRecorded (const TopoDS_Shape& ashape) const
184 TopoDS_Shape shape = ashape;
185 if (myConsiderLocation) {
186 TopLoc_Location nullLoc;
187 shape.Location ( nullLoc );
189 if (shape.IsNull()) return Standard_False;
190 if ( myConsiderOrientation && shape.Orientation()==TopAbs_REVERSED )
191 return myRMap.IsBound (shape);
193 return myNMap.IsBound (shape);
197 //=======================================================================
200 //=======================================================================
202 TopoDS_Shape BRepTools_ReShape::Value (const TopoDS_Shape& ashape) const
205 if (ashape.IsNull()) return res;
206 TopoDS_Shape shape = ashape;
207 if (myConsiderLocation) {
208 TopLoc_Location nullLoc;
209 shape.Location ( nullLoc );
212 Standard_Boolean fromMap = Standard_False;
213 if ( shape.Orientation()==TopAbs_REVERSED ) {
214 if( myConsiderOrientation ) {
215 if (!myRMap.IsBound (shape)) res = shape;
217 res = myRMap.Find (shape);
218 fromMap = Standard_True;
222 if (!myNMap.IsBound (shape)) res = shape;
224 res = myNMap.Find (shape).Reversed();
225 fromMap = Standard_True;
230 if (!myNMap.IsBound (shape)) res = shape;
232 res = myNMap.Find (shape);
233 fromMap = Standard_True;
236 // for INTERNAL/EXTERNAL, since they are not fully supported, keep orientation
237 if ( shape.Orientation() == TopAbs_INTERNAL ||
238 shape.Orientation() == TopAbs_EXTERNAL )
239 res.Orientation ( shape.Orientation() );
241 if (myConsiderLocation) {
242 //sln 29.11.01 Bug22: Recalculate location of resulting shape in accordance with
243 //whether result is from map or not
244 if(fromMap) res.Location(ashape.Location()*res.Location());
245 else res.Location(ashape.Location());
252 //=======================================================================
255 //=======================================================================
257 Standard_Integer BRepTools_ReShape::Status(const TopoDS_Shape& ashape,
259 const Standard_Boolean last)
261 Standard_Integer res = 0;
262 if (ashape.IsNull()) { newsh.Nullify(); return res; }
264 TopoDS_Shape shape = ashape;
265 TopLoc_Location aLocSh = shape.Location();
266 if (myConsiderLocation) {
267 TopLoc_Location nullLoc;
268 shape.Location ( nullLoc );
271 if ( myConsiderOrientation && shape.Orientation()==TopAbs_REVERSED ) {
272 if (!myRMap.IsBound (shape)) { newsh = shape; res = 0; }
273 else { newsh = myRMap.Find (shape); res = 1; }
276 if (!myNMap.IsBound (shape)) { newsh = shape; res = 0; }
277 else { newsh = myNMap.Find (shape); res = 1; }
280 if (newsh.IsNull()) res = -1;
281 else if (newsh.IsEqual (shape)) res = 0;
282 else if ( last && ((myConsiderLocation && ! newsh.IsPartner (shape)) ||
283 (!myConsiderLocation && ! newsh.IsSame (shape)))) {
284 //TopoDS_Shape newnewsh;
285 //Standard_Integer newres = Status (newsh, newnewsh, last);
287 //if (newres) res = newres;
288 // sln 29.11.01 Bug24: Correction iteration through maps. Way of iteration used early does not
289 // correspond to way of storing information in the maps.
290 newsh = Apply(shape, TopAbs_SHAPE);
291 if (newsh.IsNull()) res = -1;
292 if (newsh.IsEqual (shape)) res = 0;
295 if(myConsiderLocation && !newsh.IsNull())
297 TopLoc_Location aResLoc = (res >0 && !newsh.Location().IsIdentity() ?
298 aLocSh * newsh.Location() : aLocSh);
299 newsh.Location(aResLoc);
305 //=======================================================================
308 //=======================================================================
310 TopoDS_Shape BRepTools_ReShape::Apply (const TopoDS_Shape& shape,
311 const TopAbs_ShapeEnum until,
312 const Standard_Integer buildmode)
314 if (shape.IsNull()) return shape;
316 if (Status (shape,newsh,Standard_False) != 0) return newsh;
318 TopAbs_ShapeEnum st = shape.ShapeType();
319 if (st == until) return newsh; // critere d arret
321 Standard_Integer modif = 0;
322 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID) {
326 for (TopoDS_Iterator it (shape); it.More(); it.Next()) {
327 TopoDS_Shape sh = it.Value();
328 Standard_Integer stat = Status (sh,newsh,Standard_False);
329 if (stat != 0) modif = 1;
330 if (stat >= 0) B.Add (C,newsh);
332 if (modif == 0) return shape;
336 if (st == TopAbs_SOLID) {
342 for (TopoDS_Iterator it (shape); it.More(); it.Next()) {
343 TopoDS_Shape sh = it.Value();
344 newsh = Apply (sh,until,buildmode);
345 if (newsh.IsNull()) {
348 else if (newsh.ShapeType() != TopAbs_SHELL) {
349 Standard_Integer nbsub = 0;
350 for (TopExp_Explorer exh(newsh,TopAbs_SHELL); exh.More(); exh.Next()) {
351 TopoDS_Shape onesh = exh.Current ();
355 if (nbsub == 0) modif = -1;
356 B.Add (C,newsh); // c est tout
359 if (modif == 0 && !sh.IsEqual(newsh)) modif = 1;
365 if ( (modif < 0 && buildmode < 2) || (modif == 0 && buildmode < 1) )
371 if (st == TopAbs_SHELL) {
377 for (TopoDS_Iterator it (shape); it.More(); it.Next()) {
378 TopoDS_Shape sh = it.Value();
379 newsh = Apply (sh,until,buildmode);
380 if (newsh.IsNull()) {
383 else if (newsh.ShapeType() != TopAbs_FACE) {
384 Standard_Integer nbsub = 0;
385 for (TopExp_Explorer exf(newsh,TopAbs_FACE); exf.More(); exf.Next()) {
386 TopoDS_Shape onesh = exf.Current ();
390 if (nbsub == 0) modif = -1;
391 B.Add (C,newsh); // c est tout
394 if (modif == 0 && !sh.IsEqual(newsh)) modif = 1;
399 if ( (modif < 0 && buildmode < 2) || (modif == 0 && buildmode < 1) )
403 S.Closed (BRep_Tool::IsClosed (S));
407 cout<<"BRepTools_ReShape::Apply NOT YET IMPLEMENTED"<<endl;
412 //=======================================================================
413 //function : EncodeStatus
415 //=======================================================================
416 static Standard_Integer EncodeStatus (const Standard_Integer status)
419 case 0 : return 0x0000; //ShapeExtend_OK
420 case 1: return 0x0001; //ShapeExtend_DONE1
421 case 2: return 0x0002; //....
422 case 3: return 0x0004;
423 case 4: return 0x0008;
424 case 5: return 0x0010;
425 case 6: return 0x0020;
426 case 7: return 0x0040;
427 case 8: return 0x0080; //....
428 case 9 : return 0x00ff; //ShapeExtend_DONE
429 case 10: return 0x0100; //ShapeExtend_FAIL1
430 case 11: return 0x0200; //...
431 case 12: return 0x0400;
432 case 13: return 0x0800;
433 case 14: return 0x1000;
434 case 15: return 0x2000;
435 case 16: return 0x4000;
436 case 17: return 0x8000; //....
437 case 18 : return 0xff00; //ShapeExtend_FAIL
443 //=======================================================================
446 //=======================================================================
448 TopoDS_Shape BRepTools_ReShape::Apply (const TopoDS_Shape& shape,
449 const TopAbs_ShapeEnum until)
451 myStatus = EncodeStatus(0); //ShapeExtend::EncodeStatus ( ShapeExtend_OK );
452 if ( shape.IsNull() ) return shape;
454 // apply direct replacement
455 TopoDS_Shape newsh = Value ( shape );
457 // if shape removed, return NULL
458 if ( newsh.IsNull() ) {
459 myStatus = EncodeStatus (2); //ShapeExtend_DONE2
463 // if shape replaced, apply modifications to the result recursively
464 if ( (myConsiderLocation && ! newsh.IsPartner (shape)) ||
465 (!myConsiderLocation &&! newsh.IsSame ( shape )) ) {
466 TopoDS_Shape res = Apply ( newsh, until );
467 myStatus |= EncodeStatus(1); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
471 TopAbs_ShapeEnum st = shape.ShapeType(); //, subt;
472 if ( st >= until ) return newsh; // critere d arret
473 if(st == TopAbs_VERTEX || st == TopAbs_SHAPE)
475 // define allowed types of components
476 //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
479 case TopAbs_COMPOUND: subt = TopAbs_SHAPE; break;
480 case TopAbs_COMPSOLID: subt = TopAbs_SOLID; break;
481 case TopAbs_SOLID: subt = TopAbs_SHELL; break;
482 case TopAbs_SHELL: subt = TopAbs_FACE; break;
483 case TopAbs_FACE: subt = TopAbs_WIRE; break;
484 case TopAbs_WIRE: subt = TopAbs_EDGE; break;
485 case TopAbs_EDGE: subt = TopAbs_VERTEX; break;
488 default: return shape;
493 TopoDS_Shape result = shape.EmptyCopied();
494 TopAbs_Orientation orien = shape.Orientation();
495 result.Orientation(TopAbs_FORWARD); // protect against INTERNAL or EXTERNAL shapes
496 Standard_Boolean modif = Standard_False;
497 Standard_Integer locStatus = myStatus;
499 // apply recorded modifications to subshapes
500 Standard_Boolean isEmpty = Standard_True;
501 for ( TopoDS_Iterator it(shape,Standard_False); it.More(); it.Next() ) {
502 TopoDS_Shape sh = it.Value();
503 newsh = Apply ( sh, until );
505 if ( myStatus & EncodeStatus(4)) //ShapeExtend::DecodeStatus ( myStatus, ShapeExtend_DONE4 ) )
506 locStatus |= EncodeStatus(4); //|= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
509 if ( newsh.IsNull() ) {
510 locStatus |= EncodeStatus(4); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
514 isEmpty = Standard_False;
515 locStatus |= EncodeStatus(3);//ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
516 if ( st == TopAbs_COMPOUND || newsh.ShapeType() == sh.ShapeType()) { //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
517 B.Add ( result, newsh );
520 Standard_Integer nitems = 0;
521 for ( TopoDS_Iterator subit(newsh); subit.More(); subit.Next(), nitems++ ) {
522 TopoDS_Shape subsh = subit.Value();
523 if ( subsh.ShapeType() == sh.ShapeType() ) B.Add ( result, subsh );//fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
524 else locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
526 if ( ! nitems ) locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
528 if ( ! modif ) return shape;
530 // For empty topological containers (any kind of shape except vertex, edge
531 // and face) we have to produce an empty result
532 if ( isEmpty && st != TopAbs_VERTEX && st != TopAbs_EDGE && st != TopAbs_FACE )
534 result = TopoDS_Shape();
538 // restore Range on edge broken by EmptyCopied()
539 if ( st == TopAbs_EDGE ) {
540 CopyRanges (result, shape, 0, 1);
542 else if (st == TopAbs_FACE) {
543 TopoDS_Face face = TopoDS::Face ( shape );
544 if( BRep_Tool::NaturalRestriction( face ) ) {
546 aB.NaturalRestriction( TopoDS::Face ( result ), Standard_True );
549 else if (st == TopAbs_WIRE || st == TopAbs_SHELL)
550 result.Closed (BRep_Tool::IsClosed (result));
552 result.Orientation(orien);
555 Replace ( shape, result );
556 myStatus = locStatus;
562 //=======================================================================
565 //=======================================================================
567 /*Standard_Boolean BRepTools_ReShape::Status (const ShapeExtend_Status status) const
569 return ShapeExtend::DecodeStatus ( myStatus, status );
573 //=======================================================================
574 //function : ModeConsiderLocation
576 //=======================================================================
578 Standard_Boolean& BRepTools_ReShape::ModeConsiderLocation()
580 return myConsiderLocation;
584 //=======================================================================
585 //function : ModeConsiderOrientation
587 //=======================================================================
589 Standard_Boolean& BRepTools_ReShape::ModeConsiderOrientation()
591 return myConsiderOrientation;
594 //=======================================================================
595 //function : CopyVertex
597 //=======================================================================
599 TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
600 const Standard_Real theTol)
602 return CopyVertex(theV, BRep_Tool::Pnt(theV), theTol);
605 //=======================================================================
606 //function : CopyVertex
608 //=======================================================================
610 TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
611 const gp_Pnt& theNewPos,
612 const Standard_Real theTol)
614 TopoDS_Vertex aVertexCopy;
615 Standard_Boolean isRecorded = IsRecorded(theV);
616 aVertexCopy = isRecorded ? TopoDS::Vertex(Apply(theV)) : TopoDS::Vertex(theV.EmptyCopied());
619 Standard_Real aNewTol = theTol > 0.0 ? theTol : BRep_Tool::Tolerance(theV);
620 B.UpdateVertex(aVertexCopy, theNewPos, aNewTol);
623 Replace(theV, aVertexCopy);
628 Standard_Boolean BRepTools_ReShape::IsNewShape(const TopoDS_Shape& theShape) const
630 return myNewShapes.Contains(theShape);