0024023: Revamp the OCCT Handle -- general
[occt.git] / src / BRepTools / BRepTools_Modifier.cxx
CommitLineData
b311480e 1// Created on: 1994-08-25
2// Created by: Jacques GOUSSARD
3// Copyright (c) 1994-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
0d969553 17// IFV 04.06.99 - PRO18974 - processing of INTERNAL shapes.
7fd59977 18
19#include <BRepTools_Modifier.ixx>
20
21#include <TopoDS_Iterator.hxx>
22#include <TopoDS_Vertex.hxx>
23#include <TopoDS_Edge.hxx>
24#include <TopoDS_Face.hxx>
25#include <TopoDS_Shape.hxx>
26#include <TopExp_Explorer.hxx>
27#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
28#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
29#include <TopTools_ListOfShape.hxx>
30#include <TopTools_ListIteratorOfListOfShape.hxx>
31#include <TColStd_ListOfTransient.hxx>
32#include <TColStd_ListIteratorOfListOfTransient.hxx>
33
34#if 0
35#include <Poly_Triangulation.hxx>
36#include <Poly_Polygon3D.hxx>
37#include <BRepMesh_IncrementalMesh.hxx>
38#endif
39
40#include <Geom2d_Line.hxx>
41#include <BRep_Builder.hxx>
42#include <BRep_Tool.hxx>
43#include <TopoDS.hxx>
44#include <BRepTools.hxx>
45#include <TopAbs.hxx>
46#include <TopExp.hxx>
47#include <gp_Pnt.hxx>
48
49#include <gp.hxx>
50
51#include <Standard_NullObject.hxx>
52#include <gp_Trsf.hxx>
53#include <BRepTools_TrsfModification.hxx>
b350f6ee 54#include <Message_ProgressSentry.hxx>
c04c30b3 55#include <Geom_Surface.hxx>
7fd59977 56
57
58//=======================================================================
59//function : BRepTools_Modifier
60//purpose :
61//=======================================================================
62
63BRepTools_Modifier::BRepTools_Modifier ():myDone(Standard_False)
64{}
65
66//=======================================================================
67//function : BRepTools_Modifier
68//purpose :
69//=======================================================================
70
71BRepTools_Modifier::BRepTools_Modifier (const TopoDS_Shape& S) :
72 myShape(S),myDone(Standard_False)
73{
74 myMap.Clear();
75 Put(S);
76}
77
78//=======================================================================
79//function : BRepTools_Modifier
80//purpose :
81//=======================================================================
82
83BRepTools_Modifier::BRepTools_Modifier
84 (const TopoDS_Shape& S,
85 const Handle(BRepTools_Modification)& M) : myShape(S),myDone(Standard_False)
86{
87 myMap.Clear();
88 Put(S);
89 Perform(M);
90}
91
92
93//=======================================================================
94//function : Init
95//purpose :
96//=======================================================================
97
98void BRepTools_Modifier::Init(const TopoDS_Shape& S)
99{
100 myShape = S;
101 myDone = Standard_False;
102 myMap.Clear();
103 Put(S);
104}
105
106
107//=======================================================================
108//function : Perform
109//purpose :
110//=======================================================================
111
b350f6ee 112void BRepTools_Modifier::Perform(const Handle(BRepTools_Modification)& M, const Handle(Message_ProgressIndicator) & aProgress)
7fd59977 113{
114 if (myShape.IsNull()) {
115 Standard_NullObject::Raise();
116 }
117 TopTools_DataMapIteratorOfDataMapOfShapeShape theIter(myMap);
118
0d969553 119 // Set to Null the value of shapes, in case when another modification is applied to the start shape.
7fd59977 120
121 if (!theIter.Value().IsNull()) {
122 while (theIter.More()) {
123 myMap(theIter.Value()).Nullify();
124 theIter.Next();
125 }
126 theIter.Reset();
127 }
128
129 /*
130 while (theIter.More()) {
131 Rebuild(theIter.Key(),M);
132 theIter.Next();
133 }
134 */
135
b350f6ee 136 Message_ProgressSentry aPSentry(aProgress, "Converting Shape", 0, 2, 1);
137
138 Rebuild(myShape, M, aProgress);
139
140 if (!aPSentry.More())
141 {
142 // The processing was broken
143 return;
144 }
145
146 aPSentry.Next();
7fd59977 147
148 if (myShape.ShapeType() == TopAbs_FACE) {
149 if (myShape.Orientation() == TopAbs_REVERSED) {
150 myMap(myShape).Reverse();
151 }
152 else{
153 myMap(myShape).Orientation(myShape.Orientation());
154 }
155 }
156 else {
157 myMap(myShape).Orientation(myShape.Orientation());
158 }
159
0d969553 160 // Update the continuities
7fd59977 161
162 TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
163 TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,theEFMap);
164 BRep_Builder B;
165
166/*
167 Standard_Boolean RecomputeTriangles = Standard_False;
168 Standard_Real MaxDeflection = RealFirst();
169 Handle(Poly_Triangulation) Tr;
170 Handle(Poly_Polygon3D) Po;
171 TopLoc_Location Loc;
172*/
173
174 while (theIter.More()) {
175 const TopoDS_Shape& S = theIter.Key();
176/*
177 if (S.ShapeType() == TopAbs_FACE && !S.IsSame(theIter.Value())) {
178 Tr = BRep_Tool::Triangulation(TopoDS::Face(S),Loc);
179 if (!Tr.IsNull()) {
b350f6ee 180 RecomputeTriangles = Standard_True;
181 MaxDeflection = Max(MaxDeflection,Tr->Deflection());
7fd59977 182 }
183 }
184 else */ if (S.ShapeType() == TopAbs_EDGE && !S.IsSame(theIter.Value())) {
185 const TopoDS_Edge& edg = TopoDS::Edge(S);
186/*
187 Po = BRep_Tool::Polygon3D(edg,Loc);
188 if (!Po.IsNull()) {
189 RecomputeTriangles = Standard_True;
190 MaxDeflection = Max(MaxDeflection,Po->Deflection());
191 }
192*/
193 TopTools_ListIteratorOfListOfShape it;
194 it.Initialize(theEFMap.FindFromKey(edg));
195 TopoDS_Face F1,F2;
196 while (it.More() && F2.IsNull()) {
b350f6ee 197 if (F1.IsNull()) {
198 F1 = TopoDS::Face(it.Value());
199 }
200 else {
201 F2 = TopoDS::Face(it.Value());
202 }
203 it.Next();
7fd59977 204 }
205 if (!F2.IsNull()) {
b350f6ee 206 const TopoDS_Edge& newedg = TopoDS::Edge(myMap(edg));
207 const TopoDS_Face& newf1 = TopoDS::Face(myMap(F1));
208 const TopoDS_Face& newf2 = TopoDS::Face(myMap(F2));
209 GeomAbs_Shape Newcont = M->Continuity(edg,F1,F2,newedg,newf1,newf2);
210 if (Newcont > GeomAbs_C0) {
211 B.Continuity(newedg,newf1,newf2,Newcont);
212 }
7fd59977 213 }
214 }
215 theIter.Next();
216 }
217/*
218 if (RecomputeTriangles) {
219 BRepMesh_IncrementalMesh(myMap(myShape),MaxDeflection);
220 }
221*/
222
223 myDone = Standard_True;
224
225}
226
227//=======================================================================
228//function : Put
229//purpose :
230//=======================================================================
231
232void BRepTools_Modifier::Put(const TopoDS_Shape& S)
233{
234 if (!myMap.IsBound(S)) {
235 myMap.Bind(S,TopoDS_Shape());
236 for(TopoDS_Iterator theIterator(S,Standard_False);theIterator.More();theIterator.Next()) {
237
238 Put(theIterator.Value());
239 }
240 }
241}
242
243//=======================================================================
244//function : Rebuild
245//purpose :
246//=======================================================================
247
248Standard_Boolean BRepTools_Modifier::Rebuild
249 (const TopoDS_Shape& S,
b350f6ee 250 const Handle(BRepTools_Modification)& M,
251 const Handle(Message_ProgressIndicator)& aProgress)
7fd59977 252{
253 TopoDS_Shape& result = myMap(S);
254// if (!result.IsNull()) return ! S.IsEqual(result);
255 if (!result.IsNull()) return ! S.IsSame(result);
256 Standard_Boolean rebuild = Standard_False, RevWires = Standard_False;
257 TopAbs_Orientation ResOr = TopAbs_FORWARD;
258 BRep_Builder B;
259 Standard_Real tol;
260 Standard_Boolean No3DCurve = Standard_False; // en fait, si on n`a pas de
0d969553 261 //modif geometry 3d , it is necessary to test the existence of a curve 3d.
7fd59977 262
263 // new geometry ?
264
265 TopAbs_ShapeEnum ts = S.ShapeType();
266 switch (ts) {
267 case TopAbs_FACE:
268 {
269 Standard_Boolean RevFace;
270 Handle(Geom_Surface) surface;
271 TopLoc_Location location;
272 rebuild = M->NewSurface(TopoDS::Face(S),surface,location,tol,
273 RevWires,RevFace);
274 if (rebuild) {
275 B.MakeFace(TopoDS::Face(result),surface,
276 location.Predivided(S.Location()),tol);
277 result.Location(S.Location());
278// result.Orientation(S.Orientation());
279 if (RevFace) {
280 ResOr = TopAbs_REVERSED;
281 }
282 // set specifics flags of a Face
283 B.NaturalRestriction(TopoDS::Face(result),
284 BRep_Tool::NaturalRestriction(TopoDS::Face(S)));
285 }
286 }
287 break;
288
289 case TopAbs_EDGE:
290 {
291 Handle(Geom_Curve) curve;
292 TopLoc_Location location;
293 rebuild = M->NewCurve(TopoDS::Edge(S),curve,location,tol);
294 if (rebuild) {
295 if (curve.IsNull()) {
296 B.MakeEdge(TopoDS::Edge(result));
297 B.Degenerated(TopoDS::Edge(result),
298 BRep_Tool::Degenerated(TopoDS::Edge(S)));
299 B.UpdateEdge(TopoDS::Edge(result),tol); //OCC217
300 No3DCurve = Standard_True;
301 }
302 else {
303 B.MakeEdge(TopoDS::Edge(result),curve,
304 location.Predivided(S.Location()),tol);
305 No3DCurve = Standard_False;
306 }
307 result.Location(S.Location());
308// result.Orientation(S.Orientation());
309
310 // set specifics flags of an Edge
311 B.SameParameter(TopoDS::Edge(result),
312 BRep_Tool::SameParameter(TopoDS::Edge(S)));
313 B.SameRange(TopoDS::Edge(result),
314 BRep_Tool::SameRange(TopoDS::Edge(S)));
315 }
316 }
317 break;
318
319 case TopAbs_VERTEX:
320 {
321 gp_Pnt vtx;
322 rebuild = M->NewPoint(TopoDS::Vertex(S),vtx,tol);
323 if (rebuild) {
324 B.MakeVertex(TopoDS::Vertex(result),vtx,tol);
325 }
326 }
327 break;
328
329 default:
330 {
331 }
332 }
333
334 // rebuild sub-shapes and test new sub-shape ?
335
336 Standard_Boolean newgeom = rebuild;
337
338 TopoDS_Iterator it;
339
b350f6ee 340 {
341 Standard_Integer aShapeCount = 0;
342 {
343 for (it.Initialize(S, Standard_False); it.More(); it.Next()) ++aShapeCount;
344 }
345
346 Message_ProgressSentry aPSentry(aProgress, "Converting SubShapes", 0, aShapeCount, 1);
347 //
348 for (it.Initialize(S, Standard_False); it.More() && aPSentry.More(); it.Next(), aPSentry.Next()) {
349 // always call Rebuild
350 Standard_Boolean subrebuilt = Rebuild(it.Value(), M, aProgress);
351 rebuild = subrebuilt || rebuild ;
352 }
353 if (!aPSentry.More())
354 {
355 // The processing was broken
356 return Standard_False;
357 }
7fd59977 358 }
359
360 // make an empty copy
361 if (rebuild && !newgeom) {
362 result = S.EmptyCopied();
363 result.Orientation(TopAbs_FORWARD);
364 }
365
366 // copy the sub-elements
367
368 if (rebuild) {
369 TopAbs_Orientation orient;
370 for (it.Initialize(S,Standard_False); it.More(); it.Next()) {
371 orient = it.Value().Orientation();
372 if (RevWires || myMap(it.Value()).Orientation() == TopAbs_REVERSED) {
373 orient = TopAbs::Reverse(orient);
374 }
375 B.Add(result,myMap(it.Value()).Oriented(orient));
376 }
377
378
379 if (ts == TopAbs_FACE) {
380 // pcurves
381 Handle(Geom2d_Curve) curve2d; //,curve2d1;
382 TopoDS_Face face = TopoDS::Face(S);
383 TopAbs_Orientation fcor = face.Orientation();
384 if(fcor != TopAbs_REVERSED) fcor = TopAbs_FORWARD;
385
386 TopExp_Explorer ex(face.Oriented(fcor),TopAbs_EDGE);
387 for (;ex.More(); ex.Next())
388 {
b350f6ee 389 const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
7fd59977 390
b350f6ee 391 if (M->NewCurve2d(edge, face, TopoDS::Edge(myMap(ex.Current())), TopoDS::Face(result), curve2d, tol))
7fd59977 392 {
b350f6ee 393 // rem dub 16/09/97 : Make constant topology or not make at all.
394 // Do not make if CopySurface = 1
395 // Atention, TRUE sewing edges (RealyClosed)
396 // stay even if CopySurface is true.
7fd59977 397
398 // check that edge contains two pcurves on this surface:
399 // either it is true seam on the current face, or belongs to two faces
400 // built on that same surface (see OCC21772)
401 // Note: this check could be made separate method in BRepTools
402 Standard_Boolean isClosed = Standard_False;
403 if(BRep_Tool::IsClosed(edge,face))
404 {
405 isClosed = ( ! newgeom || BRepTools::IsReallyClosed(edge,face) );
406 if ( ! isClosed )
407 {
408 TopLoc_Location aLoc;
409 TopoDS_Shape resface = (myMap.IsBound(face) ? myMap(face) : face);
410 if(resface.IsNull())
411 resface = face;
412 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(resface), aLoc);
413 // check other faces sharing the same surface
414 TopExp_Explorer aExpF(myShape,TopAbs_FACE);
415 for( ; aExpF.More() && !isClosed; aExpF.Next())
416 {
417 TopoDS_Face anOther = TopoDS::Face(aExpF.Current());
418 if(anOther.IsSame(face))
419 continue;
420 TopoDS_Shape resface2 = (myMap.IsBound(anOther) ? myMap(anOther) : anOther);
421 if(resface2.IsNull())
422 resface2 = anOther;
423 TopLoc_Location anOtherLoc;
424 Handle(Geom_Surface) anOtherSurf =
425 BRep_Tool::Surface(TopoDS::Face(resface2), anOtherLoc);
426 if ( aSurf == anOtherSurf && aLoc.IsEqual (anOtherLoc) )
427 {
428 TopExp_Explorer aExpE(anOther,TopAbs_EDGE);
429 for( ; aExpE.More() && !isClosed ; aExpE.Next())
430 isClosed = edge.IsSame(aExpE.Current());
431 }
432 }
433 }
434 }
b350f6ee 435 if (isClosed)
436 {
437 TopoDS_Edge CurE = TopoDS::Edge(myMap(edge));
438 TopoDS_Shape aLocalResult = result;
439 aLocalResult.Orientation(TopAbs_FORWARD);
440 TopoDS_Face CurF = TopoDS::Face(aLocalResult);
441 Handle(Geom2d_Curve) curve2d1, currcurv;
442 Standard_Real f,l;
443 if ((!RevWires && fcor != edge.Orientation()) ||
444 ( RevWires && fcor == edge.Orientation())) {
445 CurE.Orientation(TopAbs_FORWARD);
446 curve2d1 = BRep_Tool::CurveOnSurface(CurE,CurF,f,l);
447 if (curve2d1.IsNull()) curve2d1 = new Geom2d_Line(gp::OX2d());
448 B.UpdateEdge (CurE, curve2d1, curve2d, CurF, 0.);
449 }
450 else {
451 CurE.Orientation(TopAbs_REVERSED);
452 curve2d1 = BRep_Tool::CurveOnSurface(CurE,CurF,f,l);
453 if (curve2d1.IsNull()) curve2d1 = new Geom2d_Line(gp::OX2d());
454 B.UpdateEdge (CurE, curve2d, curve2d1, CurF, 0.);
455 }
456 currcurv = BRep_Tool::CurveOnSurface(edge,face,f,l);
457 B.Range(edge,f,l);
458 }
459 else {
460 B.UpdateEdge(TopoDS::Edge(myMap(ex.Current())),
461 curve2d,
462 TopoDS::Face(result), 0.);
463 }
7fd59977 464
b350f6ee 465 TopLoc_Location theLoc;
466 Standard_Real theF,theL;
467 Handle(Geom_Curve) C3D = BRep_Tool::Curve(TopoDS::Edge(myMap(ex.Current())), theLoc, theF, theL);
468 if (C3D.IsNull()) { // Update vertices
469 Standard_Real param;
470 TopExp_Explorer ex2(edge,TopAbs_VERTEX);
471 while (ex2.More()) {
472 const TopoDS_Vertex& vertex = TopoDS::Vertex(ex2.Current());
473 if (!M->NewParameter(vertex, edge, param, tol)) {
474 tol = BRep_Tool::Tolerance(vertex);
475 param = BRep_Tool::Parameter(vertex,edge);
476 }
477
478 TopAbs_Orientation vtxrelat = vertex.Orientation();
479 if (edge.Orientation() == TopAbs_REVERSED) {
480 // Update considere l'edge FORWARD, et le vertex en relatif
481 vtxrelat= TopAbs::Reverse(vtxrelat);
482 }
483 //if (myMap(edge).Orientation() == TopAbs_REVERSED) {
484 // vtxrelat= TopAbs::Reverse(vtxrelat);
485 //}
486
487 TopoDS_Vertex aLocalVertex = TopoDS::Vertex(myMap(vertex));
488 aLocalVertex.Orientation(vtxrelat);
489 //B.UpdateVertex(TopoDS::Vertex
490 //(myMap(vertex).Oriented(vtxrelat)),
491 B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(myMap(edge)), tol);
492 ex2.Next();
493 }
494 }
495 }
7fd59977 496 }
497
498 }
499
500// else if (ts == TopAbs_EDGE) {
501 else if (ts == TopAbs_EDGE && !No3DCurve) {
502 // Vertices
503 Standard_Real param;
504 const TopoDS_Edge& edge = TopoDS::Edge(S);
505 TopAbs_Orientation edor = edge.Orientation();
506 if(edor != TopAbs_REVERSED) edor = TopAbs_FORWARD;
507 TopExp_Explorer ex(edge.Oriented(edor), TopAbs_VERTEX);
508 while (ex.More()) {
b350f6ee 509 const TopoDS_Vertex& vertex = TopoDS::Vertex(ex.Current());
510
511 if (!M->NewParameter(vertex, edge, param, tol)) {
512 tol = BRep_Tool::Tolerance(vertex);
513 param = BRep_Tool::Parameter(vertex,edge);
514 }
515
516 TopAbs_Orientation vtxrelat = vertex.Orientation();
517 if (edor == TopAbs_REVERSED) {
518 // Update considere l'edge FORWARD, et le vertex en relatif
519 vtxrelat= TopAbs::Reverse(vtxrelat);
520 }
521
522 //if (result.Orientation() == TopAbs_REVERSED) {
523 // vtxrelat= TopAbs::Reverse(vtxrelat);
524 //}
525 TopoDS_Vertex aLocalVertex = TopoDS::Vertex(myMap(vertex));
526 aLocalVertex.Orientation(vtxrelat);
527 //B.UpdateVertex(TopoDS::Vertex(myMap(vertex).Oriented(vtxrelat)),
528 B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(result), tol);
529
530 ex.Next();
7fd59977 531 }
532
533 }
534
535 // update flags
536
537 result.Orientable(S.Orientable());
538 result.Closed(S.Closed());
539 result.Infinite(S.Infinite());
540 }
541 else
542 result = S;
543
544 // Set flag of the shape.
545 result.Orientation(ResOr);
546
7fd59977 547 result.Modified (S.Modified());
548 result.Checked (S.Checked());
549 result.Orientable(S.Orientable());
550 result.Closed (S.Closed());
551 result.Infinite (S.Infinite());
552 result.Convex (S.Convex());
553
554 return rebuild;
555}
556
557