1 // Created on: 1994-08-25
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // IFV 04.06.99 - PRO18974 - processing of INTERNAL shapes.
19 #include <BRepTools_Modification.hxx>
20 #include <BRepTools_Modifier.hxx>
21 #include <Message_ProgressIndicator.hxx>
22 #include <Standard_NoSuchObject.hxx>
23 #include <Standard_NullObject.hxx>
24 #include <TColStd_ListIteratorOfListOfTransient.hxx>
25 #include <TColStd_ListOfTransient.hxx>
26 #include <TopExp_Explorer.hxx>
27 #include <TopoDS_Edge.hxx>
28 #include <TopoDS_Face.hxx>
29 #include <TopoDS_Iterator.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Vertex.hxx>
32 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
33 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
34 #include <TopTools_ListIteratorOfListOfShape.hxx>
35 #include <TopTools_ListOfShape.hxx>
38 #include <Poly_Triangulation.hxx>
39 #include <Poly_Polygon3D.hxx>
40 #include <BRepMesh_IncrementalMesh.hxx>
43 #include <Geom2d_Line.hxx>
44 #include <BRep_Builder.hxx>
45 #include <BRep_Tool.hxx>
47 #include <BRepTools.hxx>
54 #include <Standard_NullObject.hxx>
55 #include <gp_Trsf.hxx>
56 #include <BRepTools_TrsfModification.hxx>
57 #include <Message_ProgressSentry.hxx>
58 #include <Geom_Surface.hxx>
61 //=======================================================================
62 //function : BRepTools_Modifier
64 //=======================================================================
66 BRepTools_Modifier::BRepTools_Modifier ():myDone(Standard_False)
69 //=======================================================================
70 //function : BRepTools_Modifier
72 //=======================================================================
74 BRepTools_Modifier::BRepTools_Modifier (const TopoDS_Shape& S) :
75 myShape(S),myDone(Standard_False)
81 //=======================================================================
82 //function : BRepTools_Modifier
84 //=======================================================================
86 BRepTools_Modifier::BRepTools_Modifier
87 (const TopoDS_Shape& S,
88 const Handle(BRepTools_Modification)& M) : myShape(S),myDone(Standard_False)
96 //=======================================================================
99 //=======================================================================
101 void BRepTools_Modifier::Init(const TopoDS_Shape& S)
104 myDone = Standard_False;
110 //=======================================================================
113 //=======================================================================
115 void BRepTools_Modifier::Perform(const Handle(BRepTools_Modification)& M, const Handle(Message_ProgressIndicator) & aProgress)
117 if (myShape.IsNull()) {
118 Standard_NullObject::Raise();
120 TopTools_DataMapIteratorOfDataMapOfShapeShape theIter(myMap);
122 // Set to Null the value of shapes, in case when another modification is applied to the start shape.
124 if (!theIter.Value().IsNull()) {
125 while (theIter.More()) {
126 myMap(theIter.Value()).Nullify();
133 while (theIter.More()) {
134 Rebuild(theIter.Key(),M);
139 Message_ProgressSentry aPSentry(aProgress, "Converting Shape", 0, 2, 1);
141 Rebuild(myShape, M, aProgress);
143 if (!aPSentry.More())
145 // The processing was broken
151 if (myShape.ShapeType() == TopAbs_FACE) {
152 if (myShape.Orientation() == TopAbs_REVERSED) {
153 myMap(myShape).Reverse();
156 myMap(myShape).Orientation(myShape.Orientation());
160 myMap(myShape).Orientation(myShape.Orientation());
163 // Update the continuities
165 TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
166 TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,theEFMap);
170 Standard_Boolean RecomputeTriangles = Standard_False;
171 Standard_Real MaxDeflection = RealFirst();
172 Handle(Poly_Triangulation) Tr;
173 Handle(Poly_Polygon3D) Po;
177 while (theIter.More()) {
178 const TopoDS_Shape& S = theIter.Key();
180 if (S.ShapeType() == TopAbs_FACE && !S.IsSame(theIter.Value())) {
181 Tr = BRep_Tool::Triangulation(TopoDS::Face(S),Loc);
183 RecomputeTriangles = Standard_True;
184 MaxDeflection = Max(MaxDeflection,Tr->Deflection());
187 else */ if (S.ShapeType() == TopAbs_EDGE && !S.IsSame(theIter.Value())) {
188 const TopoDS_Edge& edg = TopoDS::Edge(S);
190 Po = BRep_Tool::Polygon3D(edg,Loc);
192 RecomputeTriangles = Standard_True;
193 MaxDeflection = Max(MaxDeflection,Po->Deflection());
196 TopTools_ListIteratorOfListOfShape it;
197 it.Initialize(theEFMap.FindFromKey(edg));
199 while (it.More() && F2.IsNull()) {
201 F1 = TopoDS::Face(it.Value());
204 F2 = TopoDS::Face(it.Value());
209 const TopoDS_Edge& newedg = TopoDS::Edge(myMap(edg));
210 const TopoDS_Face& newf1 = TopoDS::Face(myMap(F1));
211 const TopoDS_Face& newf2 = TopoDS::Face(myMap(F2));
212 GeomAbs_Shape Newcont = M->Continuity(edg,F1,F2,newedg,newf1,newf2);
213 if (Newcont > GeomAbs_C0) {
214 B.Continuity(newedg,newf1,newf2,Newcont);
221 if (RecomputeTriangles) {
222 BRepMesh_IncrementalMesh(myMap(myShape),MaxDeflection);
226 myDone = Standard_True;
230 //=======================================================================
233 //=======================================================================
235 void BRepTools_Modifier::Put(const TopoDS_Shape& S)
237 if (!myMap.IsBound(S)) {
238 myMap.Bind(S,TopoDS_Shape());
239 for(TopoDS_Iterator theIterator(S,Standard_False);theIterator.More();theIterator.Next()) {
241 Put(theIterator.Value());
246 //=======================================================================
249 //=======================================================================
251 Standard_Boolean BRepTools_Modifier::Rebuild
252 (const TopoDS_Shape& S,
253 const Handle(BRepTools_Modification)& M,
254 const Handle(Message_ProgressIndicator)& aProgress)
256 TopoDS_Shape& result = myMap(S);
257 // if (!result.IsNull()) return ! S.IsEqual(result);
258 if (!result.IsNull()) return ! S.IsSame(result);
259 Standard_Boolean rebuild = Standard_False, RevWires = Standard_False;
260 TopAbs_Orientation ResOr = TopAbs_FORWARD;
263 Standard_Boolean No3DCurve = Standard_False; // en fait, si on n`a pas de
264 //modif geometry 3d , it is necessary to test the existence of a curve 3d.
268 TopAbs_ShapeEnum ts = S.ShapeType();
272 Standard_Boolean RevFace;
273 Handle(Geom_Surface) surface;
274 TopLoc_Location location;
275 rebuild = M->NewSurface(TopoDS::Face(S),surface,location,tol,
278 B.MakeFace(TopoDS::Face(result),surface,
279 location.Predivided(S.Location()),tol);
280 result.Location(S.Location());
281 // result.Orientation(S.Orientation());
283 ResOr = TopAbs_REVERSED;
285 // set specifics flags of a Face
286 B.NaturalRestriction(TopoDS::Face(result),
287 BRep_Tool::NaturalRestriction(TopoDS::Face(S)));
290 // update triangulation on the copied face
291 Handle(Poly_Triangulation) aTriangulation;
292 if (M->NewTriangulation(TopoDS::Face(S), aTriangulation))
294 if (rebuild) // the copied face already exists => update it
295 B.UpdateFace(TopoDS::Face(result), aTriangulation);
297 { // create new face with bare triangulation
298 B.MakeFace(TopoDS::Face(result), aTriangulation);
299 result.Location(S.Location());
301 rebuild = Standard_True;
308 Handle(Geom_Curve) curve;
309 TopLoc_Location location;
310 rebuild = M->NewCurve(TopoDS::Edge(S),curve,location,tol);
312 if (curve.IsNull()) {
313 B.MakeEdge(TopoDS::Edge(result));
314 B.Degenerated(TopoDS::Edge(result),
315 BRep_Tool::Degenerated(TopoDS::Edge(S)));
316 B.UpdateEdge(TopoDS::Edge(result),tol); //OCC217
317 No3DCurve = Standard_True;
320 B.MakeEdge(TopoDS::Edge(result),curve,
321 location.Predivided(S.Location()),tol);
322 No3DCurve = Standard_False;
324 result.Location(S.Location());
325 // result.Orientation(S.Orientation());
327 // set specifics flags of an Edge
328 B.SameParameter(TopoDS::Edge(result),
329 BRep_Tool::SameParameter(TopoDS::Edge(S)));
330 B.SameRange(TopoDS::Edge(result),
331 BRep_Tool::SameRange(TopoDS::Edge(S)));
334 // update polygonal structure on the edge
335 Handle(Poly_Polygon3D) aPolygon;
336 if (M->NewPolygon(TopoDS::Edge(S), aPolygon))
338 if (rebuild) // the copied edge already exists => update it
339 B.UpdateEdge(TopoDS::Edge(result), aPolygon, S.Location());
341 { // create new edge with bare polygon
342 B.MakeEdge(TopoDS::Edge(result), aPolygon);
343 result.Location(S.Location());
345 rebuild = Standard_True;
353 rebuild = M->NewPoint(TopoDS::Vertex(S),vtx,tol);
355 B.MakeVertex(TopoDS::Vertex(result),vtx,tol);
365 // rebuild sub-shapes and test new sub-shape ?
367 Standard_Boolean newgeom = rebuild;
372 Standard_Integer aShapeCount = 0;
374 for (it.Initialize(S, Standard_False); it.More(); it.Next()) ++aShapeCount;
377 Message_ProgressSentry aPSentry(aProgress, "Converting SubShapes", 0, aShapeCount, 1);
379 for (it.Initialize(S, Standard_False); it.More() && aPSentry.More(); it.Next(), aPSentry.Next()) {
380 // always call Rebuild
381 Standard_Boolean subrebuilt = Rebuild(it.Value(), M, aProgress);
382 rebuild = subrebuilt || rebuild ;
384 if (!aPSentry.More())
386 // The processing was broken
387 return Standard_False;
391 // make an empty copy
392 if (rebuild && !newgeom) {
393 result = S.EmptyCopied();
394 result.Orientation(TopAbs_FORWARD);
397 // copy the sub-elements
400 TopAbs_Orientation orient;
401 for (it.Initialize(S,Standard_False); it.More(); it.Next()) {
402 orient = it.Value().Orientation();
403 if (RevWires || myMap(it.Value()).Orientation() == TopAbs_REVERSED) {
404 orient = TopAbs::Reverse(orient);
406 B.Add(result,myMap(it.Value()).Oriented(orient));
410 if (ts == TopAbs_FACE) {
412 Handle(Geom2d_Curve) curve2d; //,curve2d1;
413 TopoDS_Face face = TopoDS::Face(S);
414 TopAbs_Orientation fcor = face.Orientation();
415 if(fcor != TopAbs_REVERSED) fcor = TopAbs_FORWARD;
417 TopExp_Explorer ex(face.Oriented(fcor),TopAbs_EDGE);
418 for (;ex.More(); ex.Next())
420 const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
422 if (M->NewCurve2d(edge, face, TopoDS::Edge(myMap(ex.Current())), TopoDS::Face(result), curve2d, tol))
424 // rem dub 16/09/97 : Make constant topology or not make at all.
425 // Do not make if CopySurface = 1
426 // Atention, TRUE sewing edges (RealyClosed)
427 // stay even if CopySurface is true.
429 // check that edge contains two pcurves on this surface:
430 // either it is true seam on the current face, or belongs to two faces
431 // built on that same surface (see OCC21772)
432 // Note: this check could be made separate method in BRepTools
433 Standard_Boolean isClosed = Standard_False;
434 if(BRep_Tool::IsClosed(edge,face))
436 isClosed = ( ! newgeom || BRepTools::IsReallyClosed(edge,face) );
439 TopLoc_Location aLoc;
440 TopoDS_Shape resface = (myMap.IsBound(face) ? myMap(face) : face);
443 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(resface), aLoc);
444 // check other faces sharing the same surface
445 TopExp_Explorer aExpF(myShape,TopAbs_FACE);
446 for( ; aExpF.More() && !isClosed; aExpF.Next())
448 TopoDS_Face anOther = TopoDS::Face(aExpF.Current());
449 if(anOther.IsSame(face))
451 TopoDS_Shape resface2 = (myMap.IsBound(anOther) ? myMap(anOther) : anOther);
452 if(resface2.IsNull())
454 TopLoc_Location anOtherLoc;
455 Handle(Geom_Surface) anOtherSurf =
456 BRep_Tool::Surface(TopoDS::Face(resface2), anOtherLoc);
457 if ( aSurf == anOtherSurf && aLoc.IsEqual (anOtherLoc) )
459 TopExp_Explorer aExpE(anOther,TopAbs_EDGE);
460 for( ; aExpE.More() && !isClosed ; aExpE.Next())
461 isClosed = edge.IsSame(aExpE.Current());
468 TopoDS_Edge CurE = TopoDS::Edge(myMap(edge));
469 TopoDS_Shape aLocalResult = result;
470 aLocalResult.Orientation(TopAbs_FORWARD);
471 TopoDS_Face CurF = TopoDS::Face(aLocalResult);
472 Handle(Geom2d_Curve) curve2d1, currcurv;
474 if ((!RevWires && fcor != edge.Orientation()) ||
475 ( RevWires && fcor == edge.Orientation())) {
476 CurE.Orientation(TopAbs_FORWARD);
477 curve2d1 = BRep_Tool::CurveOnSurface(CurE,CurF,f,l);
478 if (curve2d1.IsNull()) curve2d1 = new Geom2d_Line(gp::OX2d());
479 B.UpdateEdge (CurE, curve2d1, curve2d, CurF, 0.);
482 CurE.Orientation(TopAbs_REVERSED);
483 curve2d1 = BRep_Tool::CurveOnSurface(CurE,CurF,f,l);
484 if (curve2d1.IsNull()) curve2d1 = new Geom2d_Line(gp::OX2d());
485 B.UpdateEdge (CurE, curve2d, curve2d1, CurF, 0.);
487 currcurv = BRep_Tool::CurveOnSurface(edge,face,f,l);
491 B.UpdateEdge(TopoDS::Edge(myMap(ex.Current())),
493 TopoDS::Face(result), 0.);
496 TopLoc_Location theLoc;
497 Standard_Real theF,theL;
498 Handle(Geom_Curve) C3D = BRep_Tool::Curve(TopoDS::Edge(myMap(ex.Current())), theLoc, theF, theL);
499 if (C3D.IsNull()) { // Update vertices
501 TopExp_Explorer ex2(edge,TopAbs_VERTEX);
503 const TopoDS_Vertex& vertex = TopoDS::Vertex(ex2.Current());
504 if (!M->NewParameter(vertex, edge, param, tol)) {
505 tol = BRep_Tool::Tolerance(vertex);
506 param = BRep_Tool::Parameter(vertex,edge);
509 TopAbs_Orientation vtxrelat = vertex.Orientation();
510 if (edge.Orientation() == TopAbs_REVERSED) {
511 // Update considere l'edge FORWARD, et le vertex en relatif
512 vtxrelat= TopAbs::Reverse(vtxrelat);
514 //if (myMap(edge).Orientation() == TopAbs_REVERSED) {
515 // vtxrelat= TopAbs::Reverse(vtxrelat);
518 TopoDS_Vertex aLocalVertex = TopoDS::Vertex(myMap(vertex));
519 aLocalVertex.Orientation(vtxrelat);
520 //B.UpdateVertex(TopoDS::Vertex
521 //(myMap(vertex).Oriented(vtxrelat)),
522 B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(myMap(edge)), tol);
528 // Copy polygon on triangulation
529 Handle(Poly_PolygonOnTriangulation) aPolyOnTria_1, aPolyOnTria_2;
530 Standard_Boolean aNewPonT = M->NewPolygonOnTriangulation(edge, face, aPolyOnTria_1);
531 if (BRepTools::IsReallyClosed(edge, face))
533 // Obtain triangulation on reversed edge
534 TopoDS_Edge anEdgeRev = edge;
536 aNewPonT = M->NewPolygonOnTriangulation(anEdgeRev, face, aPolyOnTria_2) || aNewPonT;
537 // It there is only one polygon on triangulation, store it to aPolyOnTria_1
538 if (aPolyOnTria_1.IsNull() && !aPolyOnTria_2.IsNull())
540 aPolyOnTria_1 = aPolyOnTria_2;
541 aPolyOnTria_2 = Handle(Poly_PolygonOnTriangulation)();
546 TopLoc_Location aLocation;
547 Handle(Poly_Triangulation) aNewFaceTria =
548 BRep_Tool::Triangulation(TopoDS::Face(myMap(face)), aLocation);
549 TopoDS_Edge aNewEdge = TopoDS::Edge(myMap(edge));
550 if (aPolyOnTria_2.IsNull())
551 B.UpdateEdge(aNewEdge, aPolyOnTria_1, aNewFaceTria, aLocation);
554 if (edge.Orientation() == TopAbs_FORWARD)
555 B.UpdateEdge(aNewEdge, aPolyOnTria_1, aPolyOnTria_2, aNewFaceTria, aLocation);
557 B.UpdateEdge(aNewEdge, aPolyOnTria_2, aPolyOnTria_1, aNewFaceTria, aLocation);
564 // else if (ts == TopAbs_EDGE) {
565 else if (ts == TopAbs_EDGE && !No3DCurve) {
568 const TopoDS_Edge& edge = TopoDS::Edge(S);
569 TopAbs_Orientation edor = edge.Orientation();
570 if(edor != TopAbs_REVERSED) edor = TopAbs_FORWARD;
571 TopExp_Explorer ex(edge.Oriented(edor), TopAbs_VERTEX);
573 const TopoDS_Vertex& vertex = TopoDS::Vertex(ex.Current());
575 if (!M->NewParameter(vertex, edge, param, tol)) {
576 tol = BRep_Tool::Tolerance(vertex);
577 param = BRep_Tool::Parameter(vertex,edge);
580 TopAbs_Orientation vtxrelat = vertex.Orientation();
581 if (edor == TopAbs_REVERSED) {
582 // Update considere l'edge FORWARD, et le vertex en relatif
583 vtxrelat= TopAbs::Reverse(vtxrelat);
586 //if (result.Orientation() == TopAbs_REVERSED) {
587 // vtxrelat= TopAbs::Reverse(vtxrelat);
589 TopoDS_Vertex aLocalVertex = TopoDS::Vertex(myMap(vertex));
590 aLocalVertex.Orientation(vtxrelat);
591 //B.UpdateVertex(TopoDS::Vertex(myMap(vertex).Oriented(vtxrelat)),
592 B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(result), tol);
601 result.Orientable(S.Orientable());
602 result.Closed(S.Closed());
603 result.Infinite(S.Infinite());
608 // Set flag of the shape.
609 result.Orientation(ResOr);
611 result.Modified (S.Modified());
612 result.Checked (S.Checked());
613 result.Orientable(S.Orientable());
614 result.Closed (S.Closed());
615 result.Infinite (S.Infinite());
616 result.Convex (S.Convex());