1 // Created on: 1996-01-30
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-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.
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepExtrema_ExtPF.hxx>
21 #include <Extrema_ExtPS.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom_Surface.hxx>
24 #include <GeomAdaptor_Surface.hxx>
25 #include <gp_Pnt2d.hxx>
28 #include <LocOpe_Generator.hxx>
29 #include <LocOpe_GluedShape.hxx>
30 #include <LocOpe_Gluer.hxx>
31 #include <LocOpe_Spliter.hxx>
32 #include <LocOpe_WiresOnShape.hxx>
33 #include <Precision.hxx>
34 #include <Standard_ConstructionError.hxx>
35 #include <Standard_NoSuchObject.hxx>
36 #include <StdFail_NotDone.hxx>
38 #include <TopExp_Explorer.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
45 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
46 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_IndexedMapOfShape.hxx>
48 #include <TopTools_ListIteratorOfListOfShape.hxx>
50 static TopAbs_Orientation GetOrientation(const TopoDS_Face&,
54 static Standard_Boolean Contains(const TopTools_ListOfShape&,
58 //=======================================================================
61 //=======================================================================
63 void LocOpe_Gluer::Init(const TopoDS_Shape& Sbase,
64 const TopoDS_Shape& Snew)
71 myDone = Standard_False;
72 myOri = TopAbs_INTERNAL;
73 myOpe = LocOpe_INVALID;
77 //=======================================================================
80 //=======================================================================
82 void LocOpe_Gluer::Bind(const TopoDS_Face& Fnew,
83 const TopoDS_Face& Fbase)
85 TopExp_Explorer exp(mySn,TopAbs_FACE);
87 for (; exp.More(); exp.Next()) {
88 if (exp.Current().IsSame(Fnew)) {
93 throw Standard_ConstructionError();
96 TopoDS_Shape aLocalFace = Fnew.Oriented(exp.Current().Orientation());
97 TopoDS_Face Fnor = TopoDS::Face(aLocalFace);
98 // TopoDS_Face Fnor = TopoDS::Face(Fnew.Oriented(exp.Current().Orientation()));
100 for (exp.Init(mySb,TopAbs_FACE); exp.More(); exp.Next()) {
101 if (exp.Current().IsSame(Fbase)) {
106 throw Standard_ConstructionError();
109 aLocalFace = Fbase.Oriented(exp.Current().Orientation());
110 TopoDS_Face Fbor = TopoDS::Face(aLocalFace);
111 // TopoDS_Face Fbor = TopoDS::Face(Fbase.Oriented(exp.Current().Orientation()));
112 TopAbs_Orientation Ori = GetOrientation(Fnor,Fbor);
114 if (myOri == TopAbs_INTERNAL) {
116 if (myOri == TopAbs_REVERSED) {
124 else if (Ori != TopAbs_FORWARD) {
125 myOpe = LocOpe_INVALID;
128 for (exp.Init(Fnor, TopAbs_EDGE); exp.More(); exp.Next()) {
129 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
130 // if (!myMapEF.IsBound(edg)) {
131 // myMapEF.Bind(edg,Fbor);
132 if (!myMapEF.Contains(edg)) {
133 myMapEF.Add(edg,Fbor);
135 // else if (!myMapEF(edg).IsSame(Fbor)) {
136 else if (!myMapEF.FindFromKey(edg).IsSame(Fbor)) {
137 // myMapEF.UnBind(edg); // edg sur 2 face. a binder avec l`edge commun
138 myMapEF.ChangeFromKey(edg).Nullify();
139 // edg sur 2 face. a binder avec l`edge commun
142 // myMapEF.Bind(Fnor,Fbor);
143 myMapEF.Add(Fnor,Fbor);
147 //=======================================================================
150 //=======================================================================
152 void LocOpe_Gluer::Bind(const TopoDS_Edge& Enew,
153 const TopoDS_Edge& Ebase)
155 if (myMapEE.IsBound(Enew) && !myMapEE(Enew).IsSame(Ebase)) {
156 throw Standard_ConstructionError();
158 myMapEE.Bind(Enew,Ebase);
162 //=======================================================================
165 //=======================================================================
167 void LocOpe_Gluer::Perform()
169 Standard_Integer ind ;
173 if (mySb.IsNull() || mySn.IsNull() ||
174 myMapEF.IsEmpty() || myOpe ==LocOpe_INVALID) {
175 throw Standard_ConstructionError();
178 Handle(LocOpe_WiresOnShape) theWOnS = new LocOpe_WiresOnShape(mySb);
179 Handle(LocOpe_GluedShape) theGS = new LocOpe_GluedShape(mySn);
181 Standard_Integer lmap = myMapEF.Extent();
183 for ( ind = 1; ind <= lmap; ind++) {
184 TopoDS_Shape S = myMapEF.FindKey(ind);
185 if (S.ShapeType() == TopAbs_EDGE) {
186 TopoDS_Shape S2 = myMapEF(ind);
188 theWOnS->Bind(TopoDS::Edge(S), TopoDS::Face(S2));
191 else { // TopAbs_FACE
192 theGS->GlueOnFace(TopoDS::Face(S));
196 TopTools_DataMapIteratorOfDataMapOfShapeShape itm(myMapEE);
197 for (; itm.More(); itm.Next()) {
198 theWOnS->Bind(TopoDS::Edge(itm.Key()), TopoDS::Edge(itm.Value()));
203 if (!theWOnS->IsDone()) {
207 LocOpe_Spliter theSplit(mySb);
208 theSplit.Perform(theWOnS);
209 if (!theSplit.IsDone()) {
212 // Mise a jour des descendants
213 // for (TopExp_Explorer exp(mySb,TopAbs_FACE); exp.More(); exp.Next()) {
214 TopExp_Explorer exp(mySb,TopAbs_FACE) ;
215 for ( ; exp.More(); exp.Next()) {
216 myDescF.Bind(exp.Current(),theSplit.DescendantShapes(exp.Current()));
219 for (exp.Init(mySn,TopAbs_FACE); exp.More(); exp.Next()) {
220 TopTools_ListOfShape thelist;
221 myDescF.Bind(exp.Current(), thelist);
222 if (Contains(theGS->OrientedFaces(),exp.Current())) {
223 myDescF(exp.Current()).Append(exp.Current());
227 LocOpe_Generator theGen(theSplit.ResultingShape());
228 theGen.Perform(theGS);
230 myDone = theGen.IsDone();
232 myRes = theGen.ResultingShape();
236 // Mise a jour des descendants
237 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itd;
238 for (itd.Initialize(myDescF);
241 TopTools_ListOfShape newDesc;
242 TopTools_ListIteratorOfListOfShape itl;
243 for (itl.Initialize(itd.Value());
246 TopTools_ListIteratorOfListOfShape itl2
247 (theGen.DescendantFace(TopoDS::Face(itl.Value())));
248 for (; itl2.More(); itl2.Next()) {
249 const TopoDS_Face& descface =TopoDS::Face(itl2.Value());
250 if (!descface.IsNull()) { // sinon la face a disparu
251 newDesc.Append(descface);
255 myDescF(itd.Key()) = newDesc;
259 // recodage des regularites
260 TopTools_IndexedDataMapOfShapeListOfShape theMapEF1, theMapEF2;
261 TopExp::MapShapesAndAncestors(mySn,TopAbs_EDGE,TopAbs_FACE,theMapEF1);
262 TopExp::MapShapesAndAncestors(myRes,TopAbs_EDGE,TopAbs_FACE,theMapEF2);
264 for (ind = 1; ind <= theMapEF1.Extent(); ind++) {
265 const TopoDS_Edge& edg = TopoDS::Edge(theMapEF1.FindKey(ind));
266 const TopTools_ListOfShape& LL = theMapEF1(ind);
267 if (LL.Extent() == 2) {
268 const TopoDS_Face& fac1 = TopoDS::Face(LL.First());
269 const TopoDS_Face& fac2 = TopoDS::Face(LL.Last());
270 GeomAbs_Shape thecont = BRep_Tool::Continuity(edg,fac1,fac2);
271 if (thecont >= GeomAbs_G1) {
272 // on essaie de recoder
273 Standard_Integer ind2 = theMapEF2.FindIndex(edg);
275 const TopTools_ListOfShape& LL2 = theMapEF2(ind2);
276 if (LL2.Extent() == 2) {
277 const TopoDS_Face& ff1 = TopoDS::Face(LL2.First());
278 const TopoDS_Face& ff2 = TopoDS::Face(LL2.Last());
279 if ((ff1.IsSame(fac1) && ff2.IsSame(fac2)) ||
280 (ff1.IsSame(fac2) && ff2.IsSame(fac1))) {
285 B.Continuity(edg, ff1,ff2,thecont);
292 //creation de la liste d`edge
293 theWOnS->InitEdgeIterator();
294 while(theWOnS->MoreEdge()) {
295 TopoDS_Edge edg = theWOnS->Edge();
296 for (ind = 1; ind <= theMapEF2.Extent(); ind++) {
297 const TopoDS_Edge& edg1 = TopoDS::Edge(theMapEF2.FindKey(ind));
298 if(edg1.IsSame(edg)) {
300 // recodage eventuel des regularites sur cet edge
301 const TopTools_ListOfShape& L = theMapEF2(ind);
302 if (L.Extent() == 2) {
303 const TopoDS_Face& fac1 = TopoDS::Face(L.First());
304 const TopoDS_Face& fac2 = TopoDS::Face(L.Last());
305 if(LocOpe::TgtFaces(edg, fac1, fac2)) {
306 myTgtEdges.Append(edg);
307 GeomAbs_Shape thecont = BRep_Tool::Continuity(edg,fac1,fac2);
308 if (thecont < GeomAbs_G1) {
310 B.Continuity(edg, fac1,fac2,GeomAbs_G1);
319 // recodage eventuel des regularites sur cet edge
325 //=======================================================================
326 //function : DescendantFaces
328 //=======================================================================
330 const TopTools_ListOfShape& LocOpe_Gluer::DescendantFaces
331 (const TopoDS_Face& F) const
333 if (!myDone) {throw StdFail_NotDone();}
334 if (myDescF.IsBound(F))
336 static TopTools_ListOfShape nullList;
342 //=======================================================================
343 //function : GetOrientation
345 //=======================================================================
347 static TopAbs_Orientation GetOrientation(const TopoDS_Face& Fn,
348 const TopoDS_Face& Fb)
351 Handle(Geom_Surface) Sn,Sb;
352 Sn = BRep_Tool::Surface(Fn);
353 Sb = BRep_Tool::Surface(Fb);
356 // Find a point on Sb
361 gp_Vec d1u,d1v, n1,n2;
364 for (exp.Init(Fn,TopAbs_EDGE); exp.More(); exp.Next()) {
365 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
366 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,Fn,f,l);
367 if (Precision::IsNegativeInfinite(f) &&
368 Precision::IsPositiveInfinite(l)) {
372 else if (Precision::IsNegativeInfinite(f)) {
375 else if (Precision::IsPositiveInfinite(l)) {
378 Standard_Real deltau = (l-f)/20.;
379 for (Standard_Integer i=1; i<=21; i++) {
380 C2d->D0(f+(i-1)*deltau,ptvtx);
381 Sn->D1(ptvtx.X(),ptvtx.Y(),pvt,d1u,d1v);
382 n1 = d1u.Crossed(d1v);
383 if (n1.Magnitude() > Precision::Confusion() ) {
385 if (Fn.Orientation() == TopAbs_REVERSED) {
390 GeomAdaptor_Surface GAS(Sb);
391 Standard_Real TolU = GAS.UResolution(Precision::Confusion());
392 Standard_Real TolV = GAS.VResolution(Precision::Confusion());
393 Extrema_ExtPS dist(pvt,GAS,TolU,TolV);
395 Standard_Real dist2min = RealLast();
396 Standard_Integer jmin = 0;
397 for (Standard_Integer j=1; j<=dist.NbExt(); j++) {
398 if (dist.SquareDistance(j)<dist2min) {
400 dist2min = dist.SquareDistance(j);
405 dist.Point(jmin).Parameter(uu,vv);
406 Sb->D1(uu,vv,pvt,d1u,d1v);
407 n2 = d1u.Crossed(d1v);
408 if (n2.Magnitude() > Precision::Confusion()) {
410 if (Fb.Orientation() == TopAbs_REVERSED) {
413 if (n1.Dot(n2) > 0.) {
414 return TopAbs_REVERSED;
416 return TopAbs_FORWARD;
423 return TopAbs_INTERNAL;
427 //=======================================================================
428 //function : GetOrientation
430 //=======================================================================
432 static Standard_Boolean Contains(const TopTools_ListOfShape& L,
433 const TopoDS_Shape& S)
435 TopTools_ListIteratorOfListOfShape it;
436 for (it.Initialize(L);
439 if (it.Value().IsSame(S)) {
440 return Standard_True;
443 return Standard_False;
450 //=======================================================================
451 //function : AddEdges
453 //=======================================================================
455 void LocOpe_Gluer::AddEdges()
457 TopExp_Explorer exp, expsb;
458 exp.Init(mySn, TopAbs_EDGE);
461 // Standard_Real l, f;
462 TopTools_IndexedMapOfShape MapV, MapFPrism, MapE;
463 TopExp_Explorer vexp;
464 Standard_Integer flag, i;
466 TopExp::MapShapes(mySn, TopAbs_FACE, MapFPrism);
468 for (expsb.Init(myRes, TopAbs_FACE); expsb.More(); expsb.Next()) {
469 if (!MapFPrism.Contains(expsb.Current())) {
471 TopExp::MapShapes(expsb.Current(), TopAbs_VERTEX, MapV);
472 TopExp::MapShapes(expsb.Current(), TopAbs_EDGE, MapE);
473 for(exp.Init(mySn, TopAbs_EDGE); exp.More(); exp.Next()) {
474 TopoDS_Edge e = TopoDS::Edge(exp.Current());
475 if (MapE.Contains(e)) continue;
477 vexp.Init(e, TopAbs_VERTEX);
478 for(; vexp.More(); vexp.Next()) {
479 TopoDS_Vertex v = TopoDS::Vertex(vexp.Current());
480 if (MapV.Contains(v)) {
486 vexp.Init(e, TopAbs_VERTEX);
487 BRepExtrema_ExtPF ext;
488 ext.Initialize(TopoDS::Face(expsb.Current()));
490 for(; vexp.More(); vexp.Next()) {
491 TopoDS_Vertex v = TopoDS::Vertex(vexp.Current());
492 if (!MapV.Contains(v)) {
493 ext.Perform(v, TopoDS::Face(expsb.Current()));
494 if (!ext.IsDone() || ext.NbExt() == 0) { flag = 0; break;}
496 Standard_Real dist2min = ext.SquareDistance(1);
497 for (i = 2; i <= ext.NbExt(); i++) {
498 dist2min = Min(dist2min, ext.SquareDistance(i));
500 if (dist2min >= BRep_Tool::Tolerance(v) * BRep_Tool::Tolerance(v)) {