0026936: Drawbacks of inlining in new type system in OCCT 7.0 -- automatic
[occt.git] / src / BRepTools / BRepTools_ReShape.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 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
973c2be1 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.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 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
7fd59977 18#include <BRep_Builder.hxx>
42cf5bc1 19#include <BRep_GCurve.hxx>
7fd59977 20#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
42cf5bc1 21#include <BRep_ListOfCurveRepresentation.hxx>
7fd59977 22#include <BRep_TEdge.hxx>
42cf5bc1 23#include <BRep_Tool.hxx>
24#include <BRepTools_ReShape.hxx>
7fd59977 25#include <Geom_Surface.hxx>
42cf5bc1 26#include <Standard_Type.hxx>
27#include <TopExp_Explorer.hxx>
7fd59977 28#include <TopLoc_Location.hxx>
42cf5bc1 29#include <TopoDS.hxx>
30#include <TopoDS_Compound.hxx>
7fd59977 31#include <TopoDS_Edge.hxx>
42cf5bc1 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>
7fd59977 37
92efcf78 38IMPLEMENT_STANDARD_RTTIEXT(BRepTools_ReShape,MMgt_TShared)
39
42cf5bc1 40//include <ShapeExtend.hxx>
41//#include <BRepTools_Edge.hxx>
b7c077b9 42static void CopyRanges (const TopoDS_Shape& toedge, const TopoDS_Shape& fromedge,
43 const Standard_Real alpha, const Standard_Real beta)
7fd59977 44{
b7c077b9 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()) {
7fd59977 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
7fd59977 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
91BRepTools_ReShape::BRepTools_ReShape()
92{
93 myConsiderLocation = Standard_False;
94 myConsiderOrientation = Standard_False;
95}
96
97
98//=======================================================================
99//function : Clear
100//purpose :
101//=======================================================================
102
103void BRepTools_ReShape::Clear()
104{
105 myNMap.Clear();
106 myRMap.Clear();
107}
108
109
110//=======================================================================
111//function : Remove
112//purpose :
113//=======================================================================
114
115void BRepTools_ReShape::Remove (const TopoDS_Shape& shape,
116 const Standard_Boolean oriented)
117{
118 TopoDS_Shape nulshape;
119 Replace (shape,nulshape,oriented);
120}
121
122//=======================================================================
123//function : Replace
124//purpose :
125//=======================================================================
126
127void BRepTools_ReShape::Replace (const TopoDS_Shape& ashape,
128 const TopoDS_Shape& anewshape,
129 const Standard_Boolean oriented)
130{
131 TopoDS_Shape shape = ashape;
132 TopoDS_Shape newshape = anewshape;
133 if ( shape.IsNull() || shape == newshape ) return;
134 if (myConsiderLocation) {
135 //sln 29.11.01 Bug22: Change location of 'newshape' in accordance with location of 'shape'
136 newshape.Location(newshape.Location().Multiplied(shape.Location().Inverted()));
137 TopLoc_Location nullLoc;
138 shape.Location ( nullLoc );
139 }
140
0797d9d3 141#ifdef OCCT_DEBUG
7fd59977 142 if ( IsRecorded ( shape ) && ((myConsiderLocation && ! Value ( shape ).IsPartner ( newshape )) ||
143 (!myConsiderLocation && ! Value ( shape ).IsSame ( newshape ))))
144 cout << "Warning: BRepTools_ReShape::Replace: shape already recorded" << endl;
145#endif
146
147 if (oriented) {
148 if( shape.Orientation()==TopAbs_REVERSED ) {
149 if( myConsiderOrientation )
150 myRMap.Bind (shape,newshape);
151 else {
152 myNMap.Bind (shape.Reversed(),newshape.Reversed());
153 }
154 }
155 else
156 myNMap.Bind (shape,newshape);
157 }
158 else {
159 // protect against INTERNAL or EXTERNAL shape
160 if ( shape.Orientation() == TopAbs_INTERNAL ||
161 shape.Orientation() == TopAbs_EXTERNAL ) {
162 Replace ( shape.Oriented ( TopAbs_FORWARD ),
163 newshape.Oriented ( newshape.Orientation() == shape.Orientation() ?
164 TopAbs_FORWARD : TopAbs_REVERSED ), oriented );
165 return;
166 }
167
168 Replace (shape,newshape,Standard_True);
169 if(myConsiderOrientation)
170 Replace (shape.Reversed(),newshape.Reversed(),Standard_True);
171 }
172}
173
174
175//=======================================================================
176//function : IsRecorded
177//purpose :
178//=======================================================================
179
180Standard_Boolean BRepTools_ReShape::IsRecorded (const TopoDS_Shape& ashape) const
181{
182 TopoDS_Shape shape = ashape;
183 if (myConsiderLocation) {
184 TopLoc_Location nullLoc;
185 shape.Location ( nullLoc );
186 }
187 if (shape.IsNull()) return Standard_False;
188 if ( myConsiderOrientation && shape.Orientation()==TopAbs_REVERSED )
189 return myRMap.IsBound (shape);
190 else
191 return myNMap.IsBound (shape);
192}
193
194
195//=======================================================================
196//function : Value
197//purpose :
198//=======================================================================
199
200TopoDS_Shape BRepTools_ReShape::Value (const TopoDS_Shape& ashape) const
201{
202 TopoDS_Shape res;
203 if (ashape.IsNull()) return res;
204 TopoDS_Shape shape = ashape;
205 if (myConsiderLocation) {
206 TopLoc_Location nullLoc;
207 shape.Location ( nullLoc );
208 }
209
210 Standard_Boolean fromMap = Standard_False;
211 if ( shape.Orientation()==TopAbs_REVERSED ) {
212 if( myConsiderOrientation ) {
213 if (!myRMap.IsBound (shape)) res = shape;
214 else {
215 res = myRMap.Find (shape);
216 fromMap = Standard_True;
217 }
218 }
219 else {
220 if (!myNMap.IsBound (shape)) res = shape;
221 else {
222 res = myNMap.Find (shape).Reversed();
223 fromMap = Standard_True;
224 }
225 }
226 }
227 else {
228 if (!myNMap.IsBound (shape)) res = shape;
229 else {
230 res = myNMap.Find (shape);
231 fromMap = Standard_True;
232 }
233 }
234 // for INTERNAL/EXTERNAL, since they are not fully supported, keep orientation
235 if ( shape.Orientation() == TopAbs_INTERNAL ||
236 shape.Orientation() == TopAbs_EXTERNAL )
237 res.Orientation ( shape.Orientation() );
238
239 if (myConsiderLocation) {
240 //sln 29.11.01 Bug22: Recalculate location of resulting shape in accordance with
241 //whether result is from map or not
242 if(fromMap) res.Location(ashape.Location()*res.Location());
243 else res.Location(ashape.Location());
244 }
245
246 return res;
247}
248
249
250//=======================================================================
251//function : Status
252//purpose :
253//=======================================================================
254
255Standard_Integer BRepTools_ReShape::Status(const TopoDS_Shape& ashape,
256 TopoDS_Shape& newsh,
257 const Standard_Boolean last)
258{
259 Standard_Integer res = 0;
260 if (ashape.IsNull()) { newsh.Nullify(); return res; }
261
262 TopoDS_Shape shape = ashape;
263 TopLoc_Location aLocSh = shape.Location();
264 if (myConsiderLocation) {
265 TopLoc_Location nullLoc;
266 shape.Location ( nullLoc );
267 }
268
269 if ( myConsiderOrientation && shape.Orientation()==TopAbs_REVERSED ) {
270 if (!myRMap.IsBound (shape)) { newsh = shape; res = 0; }
271 else { newsh = myRMap.Find (shape); res = 1; }
272 }
273 else {
274 if (!myNMap.IsBound (shape)) { newsh = shape; res = 0; }
275 else { newsh = myNMap.Find (shape); res = 1; }
276 }
277 if (res > 0) {
278 if (newsh.IsNull()) res = -1;
279 else if (newsh.IsEqual (shape)) res = 0;
280 else if ( last && ((myConsiderLocation && ! newsh.IsPartner (shape)) ||
281 (!myConsiderLocation && ! newsh.IsSame (shape)))) {
282 //TopoDS_Shape newnewsh;
283 //Standard_Integer newres = Status (newsh, newnewsh, last);
284 //newsh = newnewsh;
285 //if (newres) res = newres;
286 // sln 29.11.01 Bug24: Correction iteration through maps. Way of iteration used early does not
287 // correspond to way of storing information in the maps.
288 newsh = Apply(shape, TopAbs_SHAPE);
289 if (newsh.IsNull()) res = -1;
290 if (newsh.IsEqual (shape)) res = 0;
291 }
292 }
293 if(myConsiderLocation && !newsh.IsNull())
294 {
295 TopLoc_Location aResLoc = (res >0 && !newsh.Location().IsIdentity() ?
296 aLocSh * newsh.Location() : aLocSh);
297 newsh.Location(aResLoc);
298 }
299 return res;
300}
301
302
303//=======================================================================
304//function : Apply
305//purpose :
306//=======================================================================
307
308TopoDS_Shape BRepTools_ReShape::Apply (const TopoDS_Shape& shape,
309 const TopAbs_ShapeEnum until,
310 const Standard_Integer buildmode)
311{
312 if (shape.IsNull()) return shape;
313 TopoDS_Shape newsh;
314 if (Status (shape,newsh,Standard_False) != 0) return newsh;
315
316 TopAbs_ShapeEnum st = shape.ShapeType();
317 if (st == until) return newsh; // critere d arret
318
319 Standard_Integer modif = 0;
320 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID) {
321 BRep_Builder B;
322 TopoDS_Compound C;
323 B.MakeCompound (C);
324 for (TopoDS_Iterator it (shape); it.More(); it.Next()) {
325 TopoDS_Shape sh = it.Value();
326 Standard_Integer stat = Status (sh,newsh,Standard_False);
327 if (stat != 0) modif = 1;
328 if (stat >= 0) B.Add (C,newsh);
329 }
330 if (modif == 0) return shape;
331 return C;
332 }
333
334 if (st == TopAbs_SOLID) {
335 BRep_Builder B;
336 TopoDS_Compound C;
337 B.MakeCompound (C);
338 TopoDS_Solid S;
339 B.MakeSolid (S);
340 for (TopoDS_Iterator it (shape); it.More(); it.Next()) {
341 TopoDS_Shape sh = it.Value();
342 newsh = Apply (sh,until,buildmode);
343 if (newsh.IsNull()) {
344 modif = -1;
345 }
346 else if (newsh.ShapeType() != TopAbs_SHELL) {
347 Standard_Integer nbsub = 0;
348 for (TopExp_Explorer exh(newsh,TopAbs_SHELL); exh.More(); exh.Next()) {
349 TopoDS_Shape onesh = exh.Current ();
350 B.Add (S,onesh);
351 nbsub ++;
352 }
353 if (nbsub == 0) modif = -1;
354 B.Add (C,newsh); // c est tout
355 }
356 else {
357 if (modif == 0 && !sh.IsEqual(newsh)) modif = 1;
358 B.Add (C,newsh);
359 B.Add (S,newsh);
360 }
361 }
ab860031 362
7fd59977 363 if ( (modif < 0 && buildmode < 2) || (modif == 0 && buildmode < 1) )
364 return C;
ab860031 365 else
ab860031 366 return S;
7fd59977 367 }
368
369 if (st == TopAbs_SHELL) {
370 BRep_Builder B;
371 TopoDS_Compound C;
372 B.MakeCompound (C);
373 TopoDS_Shell S;
374 B.MakeShell (S);
375 for (TopoDS_Iterator it (shape); it.More(); it.Next()) {
376 TopoDS_Shape sh = it.Value();
377 newsh = Apply (sh,until,buildmode);
378 if (newsh.IsNull()) {
379 modif = -1;
380 }
381 else if (newsh.ShapeType() != TopAbs_FACE) {
382 Standard_Integer nbsub = 0;
383 for (TopExp_Explorer exf(newsh,TopAbs_FACE); exf.More(); exf.Next()) {
384 TopoDS_Shape onesh = exf.Current ();
385 B.Add (S,onesh);
386 nbsub ++;
387 }
388 if (nbsub == 0) modif = -1;
389 B.Add (C,newsh); // c est tout
390 }
391 else {
392 if (modif == 0 && !sh.IsEqual(newsh)) modif = 1;
393 B.Add (C,newsh);
394 B.Add (S,newsh);
395 }
396 }
397 if ( (modif < 0 && buildmode < 2) || (modif == 0 && buildmode < 1) )
398 return C;
ab860031 399 else
400 {
401 S.Closed (BRep_Tool::IsClosed (S));
402 return S;
403 }
7fd59977 404 }
405 cout<<"BRepTools_ReShape::Apply NOT YET IMPLEMENTED"<<endl;
406 return shape;
407}
408
409
410//=======================================================================
411//function : EncodeStatus
412//purpose : static
413//=======================================================================
414static Standard_Integer EncodeStatus (const Standard_Integer status)
415{
416 switch ( status ) {
417 case 0 : return 0x0000; //ShapeExtend_OK
418 case 1: return 0x0001; //ShapeExtend_DONE1
419 case 2: return 0x0002; //....
420 case 3: return 0x0004;
421 case 4: return 0x0008;
422 case 5: return 0x0010;
423 case 6: return 0x0020;
424 case 7: return 0x0040;
425 case 8: return 0x0080; //....
426 case 9 : return 0x00ff; //ShapeExtend_DONE
427 case 10: return 0x0100; //ShapeExtend_FAIL1
428 case 11: return 0x0200; //...
429 case 12: return 0x0400;
430 case 13: return 0x0800;
431 case 14: return 0x1000;
432 case 15: return 0x2000;
433 case 16: return 0x4000;
434 case 17: return 0x8000; //....
435 case 18 : return 0xff00; //ShapeExtend_FAIL
436 }
437 return 0;
438}
439
440
441//=======================================================================
442//function : Apply
443//purpose :
444//=======================================================================
445
446TopoDS_Shape BRepTools_ReShape::Apply (const TopoDS_Shape& shape,
447 const TopAbs_ShapeEnum until)
448{
449 myStatus = EncodeStatus(0); //ShapeExtend::EncodeStatus ( ShapeExtend_OK );
450 if ( shape.IsNull() ) return shape;
451
452 // apply direct replacement
453 TopoDS_Shape newsh = Value ( shape );
454
455 // if shape removed, return NULL
456 if ( newsh.IsNull() ) {
457 myStatus = EncodeStatus (2); //ShapeExtend_DONE2
458 return newsh;
459 }
460
461 // if shape replaced, apply modifications to the result recursively
462 if ( (myConsiderLocation && ! newsh.IsPartner (shape)) ||
463 (!myConsiderLocation &&! newsh.IsSame ( shape )) ) {
464 TopoDS_Shape res = Apply ( newsh, until );
465 myStatus |= EncodeStatus(1); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
466 return res;
467 }
468
469 TopAbs_ShapeEnum st = shape.ShapeType(); //, subt;
470 if ( st >= until ) return newsh; // critere d arret
471 if(st == TopAbs_VERTEX || st == TopAbs_SHAPE)
472 return shape;
473 // define allowed types of components
474 //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
475 /*
476 switch ( st ) {
477 case TopAbs_COMPOUND: subt = TopAbs_SHAPE; break;
478 case TopAbs_COMPSOLID: subt = TopAbs_SOLID; break;
479 case TopAbs_SOLID: subt = TopAbs_SHELL; break;
480 case TopAbs_SHELL: subt = TopAbs_FACE; break;
481 case TopAbs_FACE: subt = TopAbs_WIRE; break;
482 case TopAbs_WIRE: subt = TopAbs_EDGE; break;
483 case TopAbs_EDGE: subt = TopAbs_VERTEX; break;
484 case TopAbs_VERTEX:
485 case TopAbs_SHAPE:
486 default: return shape;
487 }
488 */
489 BRep_Builder B;
490
491 TopoDS_Shape result = shape.EmptyCopied();
492 TopAbs_Orientation orien = shape.Orientation();
493 result.Orientation(TopAbs_FORWARD); // protect against INTERNAL or EXTERNAL shapes
494 Standard_Boolean modif = Standard_False;
495 Standard_Integer locStatus = myStatus;
496
497 // apply recorded modifications to subshapes
498 for ( TopoDS_Iterator it(shape,Standard_False); it.More(); it.Next() ) {
499 TopoDS_Shape sh = it.Value();
500 newsh = Apply ( sh, until );
501 if ( newsh != sh ) {
502 if ( myStatus & EncodeStatus(4)) //ShapeExtend::DecodeStatus ( myStatus, ShapeExtend_DONE4 ) )
503 locStatus |= EncodeStatus(4); //|= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
504 modif = 1;
505 }
506 if ( newsh.IsNull() ) {
507 locStatus |= EncodeStatus(4); //ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
508 continue;
509 }
510 locStatus |= EncodeStatus(3);//ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
511 if ( st == TopAbs_COMPOUND || newsh.ShapeType() == sh.ShapeType()) { //fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
512 B.Add ( result, newsh );
513 continue;
514 }
515 Standard_Integer nitems = 0;
516 for ( TopoDS_Iterator subit(newsh); subit.More(); subit.Next(), nitems++ ) {
517 TopoDS_Shape subsh = subit.Value();
518 if ( subsh.ShapeType() == sh.ShapeType() ) B.Add ( result, subsh );//fix for SAMTECH bug OCC322 about abcense internal vertices after sewing.
519 else locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
520 }
521 if ( ! nitems ) locStatus |= EncodeStatus(10);//ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
522 }
523 if ( ! modif ) return shape;
524
525 // restore Range on edge broken by EmptyCopied()
526 if ( st == TopAbs_EDGE ) {
b7c077b9 527 CopyRanges (result, shape, 0, 1);
7fd59977 528 }
da72a17c 529 else if (st == TopAbs_FACE) {
7fd59977 530 TopoDS_Face face = TopoDS::Face ( shape );
531 if( BRep_Tool::NaturalRestriction( face ) ) {
532 BRep_Builder aB;
533 aB.NaturalRestriction( TopoDS::Face ( result ), Standard_True );
534 }
535 }
da72a17c 536 else if (st == TopAbs_WIRE || st == TopAbs_SHELL)
537 result.Closed (BRep_Tool::IsClosed (result));
7fd59977 538
539 result.Orientation(orien);
540 myStatus = locStatus;
541 Replace ( shape, result );
ab860031 542
7fd59977 543 return result;
544}
545
546
547//=======================================================================
548//function : Status
549//purpose :
550//=======================================================================
551
552/*Standard_Boolean BRepTools_ReShape::Status (const ShapeExtend_Status status) const
553{
554 return ShapeExtend::DecodeStatus ( myStatus, status );
555}*/
556
557
558//=======================================================================
559//function : ModeConsiderLocation
560//purpose :
561//=======================================================================
562
563Standard_Boolean& BRepTools_ReShape::ModeConsiderLocation()
564{
565 return myConsiderLocation;
566}
567
568
569//=======================================================================
570//function : ModeConsiderOrientation
571//purpose :
572//=======================================================================
573
574Standard_Boolean& BRepTools_ReShape::ModeConsiderOrientation()
575{
576 return myConsiderOrientation;
577}
ed5ca017 578
579//=======================================================================
580//function : CopyVertex
581//purpose :
582//=======================================================================
583
584TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
585 const Standard_Real theTol)
586{
587 return CopyVertex(theV, BRep_Tool::Pnt(theV), theTol);
588}
589
590//=======================================================================
591//function : CopyVertex
592//purpose :
593//=======================================================================
594
595TopoDS_Vertex BRepTools_ReShape::CopyVertex(const TopoDS_Vertex& theV,
596 const gp_Pnt& theNewPos,
597 const Standard_Real theTol)
598{
599 TopoDS_Vertex aVertexCopy;
600 Standard_Boolean isRecorded = IsRecorded(theV);
601 aVertexCopy = isRecorded ? TopoDS::Vertex(Apply(theV)) : TopoDS::Vertex(theV.EmptyCopied());
602
603 BRep_Builder B;
604 Standard_Real aNewTol = theTol > 0.0 ? theTol : BRep_Tool::Tolerance(theV);
605 B.UpdateVertex(aVertexCopy, theNewPos, aNewTol);
606
607 if (!isRecorded)
608 Replace(theV, aVertexCopy);
609
610 return aVertexCopy;
611}