0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / LocOpe / LocOpe_Generator.cxx
... / ...
CommitLineData
1// Created on: 1996-01-09
2// Created by: Jacques GOUSSARD
3// Copyright (c) 1996-1999 Matra Datavision
4// Copyright (c) 1999-2014 OPEN CASCADE SAS
5//
6// This file is part of Open CASCADE Technology software library.
7//
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.
13//
14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
16
17// Modifed: Portage NT 7-5-97 DPF (return NewParameter)
18
19#include <LocOpe_Generator.ixx>
20
21#include <TopTools_MapOfShape.hxx>
22#include <TopTools_DataMapOfShapeShape.hxx>
23#include <TopTools_DataMapOfShapeListOfShape.hxx>
24#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
25#include <TopTools_ListIteratorOfListOfShape.hxx>
26#include <TopTools_MapIteratorOfMapOfShape.hxx>
27#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
28#include <TopoDS_Iterator.hxx>
29#include <TopoDS_Solid.hxx>
30#include <TopoDS_Wire.hxx>
31#include <TopoDS_Edge.hxx>
32#include <TopoDS_Vertex.hxx>
33
34
35#include <TopExp_Explorer.hxx>
36
37#include <gp_Pln.hxx>
38#include <gp_Cylinder.hxx>
39
40#include <BRep_Builder.hxx>
41#include <BRep_Tool.hxx>
42#include <BRepAlgo_Loop.hxx>
43
44#include <Geom_Surface.hxx>
45#include <Geom_RectangularTrimmedSurface.hxx>
46#include <Geom_Plane.hxx>
47#include <Geom_CylindricalSurface.hxx>
48#include <Geom_Curve.hxx>
49#include <Geom_TrimmedCurve.hxx>
50#include <Geom_Line.hxx>
51#include <Geom_Circle.hxx>
52#include <Geom2d_Curve.hxx>
53
54#include <LocOpe_BuildShape.hxx>
55
56#include <TopoDS.hxx>
57#include <TopExp.hxx>
58#include <BRepTools.hxx>
59#include <GeomProjLib.hxx>
60#include <ElCLib.hxx>
61#include <Precision.hxx>
62
63static Standard_Boolean ToFuse(const TopoDS_Face& ,
64 const TopoDS_Face&);
65
66
67static Standard_Boolean ToFuse(const TopoDS_Edge& ,
68 const TopoDS_Edge&);
69
70
71static Standard_Boolean ToFuse(const TopoDS_Edge&,
72 const TopoDS_Face&,
73 const TopoDS_Vertex&,
74 const TopTools_MapOfShape&);
75
76static Standard_Real NewParameter(const TopoDS_Edge&,
77 const TopoDS_Vertex&,
78 const TopoDS_Edge&,
79 const TopoDS_Vertex&);
80
81
82//=======================================================================
83//function : Perform
84//purpose :
85//=======================================================================
86
87void LocOpe_Generator::Perform(const Handle(LocOpe_GeneratedShape)& G)
88{
89 if (myShape.IsNull()) {
90 Standard_NullObject::Raise();
91 }
92 myDone = Standard_False;
93 myRes.Nullify();
94// myDescFaces.Clear();
95 myModShapes.Clear();
96// myFFromE.Clear();
97
98 const TopTools_ListOfShape& ledges = G->GeneratingEdges();
99
100 // On genere une liste des faces a gauche du wire. Equivalent du LeftOf.
101 // Attention : il faudra bien propager pour ne pas oublier des faces
102 // a l`interieur
103
104 TopExp_Explorer exp, exp2, exp3;
105 TopTools_MapOfShape theLeft; // Faces a gauche
106
107 TopTools_MapOfShape GEdg,GVtx; // Edges et vertex generateurs
108
109 TopTools_ListIteratorOfListOfShape itl,itl2;
110
111
112 for (itl.Initialize(ledges); itl.More(); itl.Next()) {
113 const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
114
115 GEdg.Add(edg);
116 for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
117 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
118 if (!GVtx.Contains(vtx)) {
119 GVtx.Add(vtx);
120 }
121 }
122 for (exp2.Init(myShape, TopAbs_FACE); exp2.More(); exp2.Next()) {
123 const TopoDS_Face& fac = TopoDS::Face(exp2.Current());
124 for (exp3.Init(fac,TopAbs_EDGE); exp3.More(); exp3.Next()) {
125 if (exp3.Current().IsSame(edg) &&
126 exp3.Current().Orientation() == edg.Orientation()) {
127 theLeft.Add(fac);
128 TopTools_ListOfShape emptylist;
129 if(!myModShapes.IsBound(fac)) {
130 myModShapes.Bind(fac,emptylist);
131 }
132 break;
133 }
134 }
135 if (exp3.More()) {
136 break;
137 }
138 }
139 }
140
141 TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
142 TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,theEFMap);
143
144 TopTools_DataMapOfShapeListOfShape theEEMap;
145 TopTools_DataMapOfShapeListOfShape theFFMap;
146 TopTools_MapOfShape toRemove;
147 TopTools_MapIteratorOfMapOfShape itm;
148 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itf;
149
150 // recherche des fusions de faces
151 for (itm.Initialize(GEdg); itm.More(); itm.Next()) {
152 const TopoDS_Edge& edg = TopoDS::Edge(itm.Key());
153 if (!theEFMap.Contains(edg)) {
154 continue;
155 }
156 for (itl2.Initialize(theEFMap.FindFromKey(edg));itl2.More();itl2.Next()){
157 if (!theLeft.Contains(itl2.Value())) {
158 break;
159 }
160 }
161 if (!itl2.More()) { // edge "interne" au shell, ou bord libre
162 }
163 else {
164 const TopoDS_Face& fac = TopoDS::Face(itl2.Value());
165 TopoDS_Face facbis = G->Generated(edg);
166 if (ToFuse(fac,facbis)) {
167 // On recherche si une face a deja fusionne avec facbis
168 Standard_Boolean facbisfound = Standard_False;
169 for (itf.Initialize(theFFMap); itf.More(); itf.Next()) {
170 if (itf.Key().IsSame(fac)) {
171 continue;
172 }
173 for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
174 if (itl.Value().IsSame(facbis)) {
175 facbisfound = Standard_True;
176 break;
177 }
178 }
179 if (facbisfound) {
180 theFFMap(itf.Key()).Append(fac);
181 toRemove.Add(fac);
182 toRemove.Add(edg);
183 break;
184 }
185 }
186
187 if (!facbisfound) {
188 if (!theFFMap.IsBound(fac)) {
189 TopTools_ListOfShape thelist;
190 theFFMap.Bind(fac, thelist);
191 }
192 for (itl.Initialize(theFFMap(fac)); itl.More(); itl.Next()) {
193 if (itl.Value().IsSame(facbis)) {
194 break;
195 }
196 }
197 if (!itl.More()) {
198 theFFMap(fac).Append(facbis);
199 }
200 toRemove.Add(edg);
201 toRemove.Add(facbis);
202 }
203 }
204 else { // face generee par edg : on la marque.
205// myFFromE.Bind(edg,facbis);
206 }
207 }
208 }
209
210
211 // Il faut ici ajouter dans toRemove les edges de connexites entre faces
212 // a fusionner avec une meme face de base
213
214// TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itf(theFFMap);
215 itf.Initialize(theFFMap);
216 for (; itf.More(); itf.Next()) {
217 for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
218 for (exp.Init(itl.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
219 const TopoDS_Edge& ed = TopoDS::Edge(exp.Current());
220 if (toRemove.Contains(ed)) {
221 continue;
222 }
223 for (itl2.Initialize(itf.Value()); itl2.More(); itl2.Next()) {
224 if (!itl2.Value().IsSame(itl.Value())) {
225 for (exp2.Init(itl2.Value(),TopAbs_EDGE);exp2.More();exp2.Next()) {
226 if (ed.IsSame(exp2.Current())) {
227 toRemove.Add(ed);
228 break;
229 }
230 }
231 if (exp2.More()) {
232 break;
233 }
234 }
235 }
236 }
237 }
238 }
239
240 TopTools_ListOfShape RebuildFace;
241 TopTools_MapOfShape mapTreated;
242 TopTools_DataMapOfShapeShape DontFuse;
243 TopAbs_Orientation orient,orface;
244
245 for (itf.Reset(); itf.More(); itf.Next()) {
246 const TopoDS_Face& fac = TopoDS::Face(itf.Key());
247 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
248 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
249 if (mapTreated.Contains(edg)) {
250 continue; // on saute l`edge
251 }
252
253 mapTreated.Add(edg);
254 for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
255 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
256 if (GVtx.Contains(vtx)) {
257 TopoDS_Edge edgbis = G->Generated(vtx);
258
259 if ((edgbis.IsNull() || BRep_Tool::Degenerated(edgbis)) ||
260// toRemove.Contains(edgbis) ||
261 !ToFuse(edg,edgbis)) {
262 continue;
263 }
264// a voir
265 if (BRepTools::IsReallyClosed(edg,fac)) {
266 if (!theEEMap.IsBound(edg)) {
267 TopTools_ListOfShape thelist1;
268 theEEMap.Bind(edg, thelist1);
269 theEEMap(edg).Append(edgbis);
270 toRemove.Add(edgbis); // toujours vrai pour edge double
271 Standard_Boolean FuseEdge = Standard_True;
272 TopoDS_Vertex Vf,Vl;
273 TopExp::Vertices(edg,Vf,Vl);
274 Standard_Boolean ConnectLast = (Vl.IsSame(vtx));
275 for (exp3.Init(fac.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
276 exp3.More(); exp3.Next()) {
277 const TopoDS_Edge& eee = TopoDS::Edge(exp3.Current());
278 orient = eee.Orientation();
279 if (!eee.IsSame(edg)) {
280 TopExp::Vertices(eee,Vf,Vl);
281 if ((Vf.IsSame(vtx) || Vl.IsSame(vtx)) &&
282 !toRemove.Contains(eee)) {
283 FuseEdge = Standard_False;
284 // On recherche celui qu`il ne faut pas fusionner
285
286 if ((Vf.IsSame(vtx) && orient == TopAbs_FORWARD) ||
287 (Vl.IsSame(vtx) && orient == TopAbs_REVERSED)) {
288 if (ConnectLast) {
289 DontFuse.Bind(edg,fac.Oriented(TopAbs_FORWARD));
290 }
291 else {
292 DontFuse.Bind(edg,fac.Oriented(TopAbs_REVERSED));
293 }
294 }
295 else {
296 if (ConnectLast) {
297 DontFuse.Bind(edg,fac.Oriented(TopAbs_REVERSED));
298 }
299 else {
300 DontFuse.Bind(edg,fac.Oriented(TopAbs_FORWARD));
301 }
302 }
303 break;
304 }
305 }
306 }
307 if (FuseEdge) {
308 toRemove.Add(vtx);
309 }
310 }
311 }
312
313
314 else {
315/* A VOIR
316 if (!BRep_Tool::IsClosed(edg,fac)) {
317*/
318 if (!theEEMap.IsBound(edg)) {
319 TopTools_ListOfShape thelist2;
320 theEEMap.Bind(edg, thelist2);
321 }
322 theEEMap(edg).Append(edgbis);
323 const TopTools_ListOfShape& L = theEEMap(edg);
324 TopTools_ListIteratorOfListOfShape Lit(L);
325 Standard_Boolean OK = Standard_True;
326 for (; Lit.More(); Lit.Next()) {
327 if (Lit.Value().IsSame(edgbis)) {
328 OK = Standard_False;
329 break;
330 }
331 }
332 if (OK) theEEMap(edg).Append(edgbis);
333
334 itl.Initialize(theEFMap.FindFromKey(edg));
335 Standard_Boolean FuseEdge = ToFuse(edg,fac,vtx,toRemove);
336 if (!FuseEdge) {
337 DontFuse.Bind(edg,fac);
338 }
339 else {
340 for (; itl.More(); itl.Next()) {
341 if (!itl.Value().IsSame(fac)) {
342 if (theFFMap.IsBound(itl.Value())) {
343 FuseEdge = ToFuse(edg,TopoDS::Face(itl.Value()),
344 vtx,toRemove);
345 // edge a fusionner
346 if (FuseEdge) {
347 toRemove.Add(vtx);
348 }
349 else {
350 if (toRemove.Contains(vtx)) {
351 toRemove.Remove(vtx);
352 }
353 DontFuse.Bind(edg,itl.Value());
354 }
355 }
356 else { // on marque comme face a reconstruire
357 RebuildFace.Append(itl.Value());
358 if (toRemove.Contains(vtx)) {
359 toRemove.Remove(vtx);
360 }
361 DontFuse.Bind(edg,itl.Value());
362 }
363
364 break;
365 }
366 }
367 }
368 }
369 }
370 }
371 }
372 }
373
374
375
376 for (itl.Initialize(RebuildFace); itl.More(); itl.Next()) {
377 TopTools_ListOfShape thelist3;
378 theFFMap.Bind(itl.Value(), thelist3);
379 }
380
381 BRep_Builder B;
382 TopoDS_Face newface;
383 TopoDS_Wire outw,newwire;
384 TopoDS_Edge newedg;
385 TopoDS_Vertex newvtx;
386 TopLoc_Location loc;
387 Standard_Real tol,prm,f,l, Uminc = 0.,Umaxc = 0.;
388 gp_Pnt2d pf,pl;
389
390 Handle(Geom_Surface) S;
391 Handle(Geom_Plane) P;
392 Handle(Geom_Curve) C;
393
394 // Fusion des edges
395 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape ite(theEEMap);
396 for (; ite.More(); ite.Next()) {
397 Standard_Boolean KeepNewEdge = Standard_False;
398 const TopoDS_Edge& edg = TopoDS::Edge(ite.Key());
399 BRep_Tool::Range(edg,f,l);
400 TopoDS_Shape aLocalEdge = edg.EmptyCopied();
401 newedg = TopoDS::Edge(aLocalEdge);
402// newedg = TopoDS::Edge(edg.EmptyCopied());
403 newedg.Orientation(TopAbs_FORWARD);
404 for (exp.Init(edg.Oriented(TopAbs_FORWARD),TopAbs_VERTEX);
405 exp.More(); exp.Next()) {
406 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
407 prm = BRep_Tool::Parameter(vtx,edg);
408
409 newvtx.Nullify();
410 for (itl.Initialize(theEEMap(edg)); itl.More(); itl.Next()) {
411 const TopoDS_Edge& edgbis = TopoDS::Edge(itl.Value());
412 for (exp2.Init(edgbis,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
413 if (exp2.Current().IsSame(vtx)) {
414 break;
415 }
416 }
417 if (exp2.More()) {
418 for (exp2.ReInit(); exp2.More(); exp2.Next()) {
419 if (!exp2.Current().IsSame(vtx)) {
420 newvtx = TopoDS::Vertex(exp2.Current());
421 prm = NewParameter(edg,vtx,newedg,newvtx);
422 break;
423 }
424 }
425 break;
426 }
427 }
428
429 if (toRemove.Contains(vtx) ||
430 (prm <l && prm > f)) {
431 B.Add(newedg,newvtx.Oriented(vtx.Orientation()));
432 tol = BRep_Tool::Tolerance(newvtx);
433 B.UpdateVertex(newvtx,prm,newedg,tol);
434 toRemove.Add(itl.Value()); // i-e edgbis
435 KeepNewEdge = Standard_True;
436 }
437 else {
438 B.Add(newedg,vtx.Oriented(vtx.Orientation()));
439 tol = BRep_Tool::Tolerance(vtx);
440 B.UpdateVertex(vtx,prm,newedg,tol);
441 }
442 }
443 if (KeepNewEdge) {
444 TopTools_ListOfShape emptylist;
445 if(!myModShapes.IsBound(edg)) {
446 myModShapes.Bind(edg,emptylist);
447 }
448 myModShapes(edg).Append(newedg);
449 toRemove.Add(edg);
450 }
451 }
452
453 TopTools_MapOfShape EdgAdded;
454
455 // Fusion des faces, ou reconstruction
456 for (itf.Reset();itf.More(); itf.Next()) {
457 const TopoDS_Face& fac = TopoDS::Face(itf.Key());
458 Standard_Boolean ModFace = Standard_False;
459 TopTools_ListOfShape listofedg;
460
461 EdgAdded.Clear();
462
463 for(exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
464 if (exp.Current().IsSame(fac)) {
465 break;
466 }
467 }
468 orface = exp.Current().Orientation();
469 TopoDS_Shape aLocalFace = fac.EmptyCopied();
470 newface = TopoDS::Face(aLocalFace);
471// newface = TopoDS::Face(fac.EmptyCopied());
472 newface.Orientation(TopAbs_FORWARD);
473 S = BRep_Tool::Surface(fac);
474 if (S->DynamicType()== STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
475 S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
476 }
477 P = Handle(Geom_Plane)::DownCast(S);
478 TopoDS_Wire wir;
479 for (exp.Init(fac.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
480 exp.More(); exp.Next()) {
481 wir = TopoDS::Wire(exp.Current());
482 for (exp2.Init(wir,TopAbs_EDGE); exp2.More(); exp2.Next()) {
483 const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
484 if (toRemove.Contains(edg) || myModShapes.IsBound(edg) ) {
485 break;
486 }
487 }
488 if (!exp2.More()) { // wire non modifie
489// B.Add(newface,wir.Oriented(wir.Orientation()));
490 for (exp2.Init(wir,TopAbs_EDGE); exp2.More(); exp2.Next()) {
491 listofedg.Append(exp2.Current());
492 }
493 }
494 else {
495 if (!ModFace) {
496
497 // Petit truc crad pour les p-curves sur les cylindres...
498 if (P.IsNull()) {
499 Standard_Real Vminc,Vmaxc;
500 BRepTools::UVBounds(fac,Uminc,Umaxc,Vminc,Vmaxc);
501 }
502
503
504 // premier passage : on met les wires non touches des faces
505 // en vis a vis
506
507 for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
508 TopoDS_Face facbis = TopoDS::Face(itl.Value());
509 for (itl2.Initialize(G->OrientedFaces());itl2.More();itl2.Next()) {
510 if (itl2.Value().IsSame(facbis)) {
511 break;
512 }
513 }
514 if (itl2.More()) {
515 orient = itl2.Value().Orientation();
516 facbis.Orientation(orient);
517 }
518 else { // on fusionne avec une autre face du shape...
519 for (exp2.Init(myShape, TopAbs_FACE); exp2.More(); exp2.Next()) {
520 if (exp2.Current().IsSame(facbis)) {
521 facbis.Orientation(exp2.Current().Orientation());
522 break;
523 }
524 }
525 }
526
527 for (exp3.Init(facbis,TopAbs_WIRE); exp3.More(); exp3.Next()) {
528 for (exp2.Init(exp3.Current(),TopAbs_EDGE);
529 exp2.More(); exp2.Next()) {
530 if (toRemove.Contains(exp2.Current())) {
531 break;
532 }
533 }
534 if (!exp2.More()) {
535 TopoDS_Wire theNew;
536 B.MakeWire(theNew); // FORWARD
537 for (exp2.ReInit(); exp2.More(); exp2.Next()) {
538 const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
539
540 orient = TopAbs::Compose(orface,edg.Orientation());
541// B.Add(theNew,edg.Oriented(or));
542 listofedg.Append(edg.Oriented(orient));
543 EdgAdded.Add(edg);
544 if (P.IsNull()) {
545 // on met les courbes 2d si on n`est pas sur un plan
546 // on ne devrait pas avoir de pb d`edge de couture.
547 tol = BRep_Tool::Tolerance(edg);
548 C = BRep_Tool::Curve(edg,loc,f,l);
549 if (!loc.IsIdentity()) {
550 Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
551 C = Handle(Geom_Curve)::DownCast (GG);
552 }
553 if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
554 C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
555 }
556
557 Handle(Geom2d_Curve) C2d = GeomProjLib::Curve2d(C,f,l,S,tol);
558
559 // Tentative de recalage dans la facette
560 pf = C2d->Value(f);
561 pl = C2d->Value(l);
562 Standard_Real tttol = Precision::Angular();
563 while (Min(pf.X(),pl.X()) >= Umaxc-tttol) {
564 C2d->Translate(gp_Vec2d(-2.*M_PI,0));
565 pf = C2d->Value(f);
566 pl = C2d->Value(l);
567 }
568
569 while (Max(pf.X(),pl.X()) <= Uminc+tttol) {
570 C2d->Translate(gp_Vec2d(2.*M_PI,0));
571 pf = C2d->Value(f);
572 pl = C2d->Value(l);
573 }
574
575 if (!BRepTools::IsReallyClosed(edg,facbis)) {
576 B.UpdateEdge(edg,C2d,newface,tol);
577 }
578 // else {
579 // cout << "Edge double bizarre... " << endl;
580 // }
581 }
582 }
583// B.Add(newface,theNew);
584 }
585 }
586 }
587 ModFace = Standard_True;
588 }
589
590 // reconstruction du wire
591 //B.MakeWire(newwire);
592
593 Handle(Geom2d_Curve) C2d,C2d1;
594
595// for (exp2.Init(wir.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
596 for (exp2.Init(wir,TopAbs_EDGE); exp2.More(); exp2.Next()) {
597 const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
598 orient = edg.Orientation();
599 if (!toRemove.Contains(edg) && !theEEMap.IsBound(edg)) {
600// B.Add(newwire,edg.Oriented(or));
601// listofedg.Append(edg.Oriented(or));
602 listofedg.Append(edg);
603 }
604 else if (myModShapes.IsBound(edg) || theEEMap.IsBound(edg)) {
605 if (myModShapes.IsBound(edg)) {
606 newedg = TopoDS::Edge(myModShapes(edg).First());
607 }
608 else {
609 newedg = edg;
610 }
611// B.Add(newwire,newedg.Oriented(or));
612 listofedg.Append(newedg.Oriented(orient));
613 C = BRep_Tool::Curve(newedg,loc,f,l);
614 if (!loc.IsIdentity()) {
615 Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
616 C = Handle(Geom_Curve)::DownCast (GG);
617 }
618 if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
619 C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
620 }
621 if (P.IsNull()) { // on met les courbes 2d si on n`est pas
622 // sur un plan
623// TopAbs_Orientation oredonfafw = TopAbs::Compose(or,orsav);
624 TopAbs_Orientation oredonfafw = orient;
625 tol = BRep_Tool::Tolerance(newedg);
626 TopoDS_Shape aLocalEdge = edg.Oriented(oredonfafw);
627 TopoDS_Shape aLocalFace = fac.Oriented(TopAbs_FORWARD);
628 C2d = BRep_Tool::CurveOnSurface
629 (TopoDS::Edge(aLocalEdge),TopoDS::Face(aLocalFace),f,l);
630// C2d = BRep_Tool::CurveOnSurface
631// (TopoDS::Edge(edg.Oriented(oredonfafw)),
632// TopoDS::Face(fac.Oriented(TopAbs_FORWARD)),
633// f,l);
634
635 if (!BRepTools::IsReallyClosed(edg,fac)) {
636 B.UpdateEdge(newedg,C2d,newface,tol);
637 }
638 else if (C2d1.IsNull()){
639 C2d1 = C2d;
640 }
641 else {
642// if (TopAbs::Compose(orsav,or) == TopAbs_FORWARD) {
643 if (orient == TopAbs_FORWARD) {
644 B.UpdateEdge(newedg,C2d,C2d1,newface,tol);
645 }
646 else {
647 B.UpdateEdge(newedg,C2d1,C2d,newface,tol);
648 }
649 }
650 }
651 Standard_Boolean AddPart = Standard_False;
652 if (DontFuse.IsBound(edg)) {
653 if (!BRepTools::IsReallyClosed(edg,fac)) {
654 if (DontFuse(edg).IsSame(fac)) {
655 if (myModShapes.IsBound(edg)) {
656 AddPart = Standard_True;
657 }
658 }
659 else if (!toRemove.Contains(edg)) {
660 AddPart = Standard_True;
661 }
662
663 }
664 else {
665 if (myModShapes.IsBound(edg)) { // edg raccourci
666// if (TopAbs::Compose(orsav,or)==DontFuse(edg).Orientation()){
667 if (orient == DontFuse(edg).Orientation()){
668 AddPart = Standard_True;
669 }
670 }
671 else {
672// if (TopAbs::Compose(orsav,or) ==
673 if (orient ==
674 TopAbs::Reverse(DontFuse(edg).Orientation())) {
675 AddPart = Standard_True;
676 }
677 }
678 }
679 }
680 if (AddPart) {
681 itl2.Initialize(theEEMap(edg));
682 gp_Vec dir1,dir2;
683 for (; itl2.More(); itl2.Next()) {
684 if (EdgAdded.Contains(itl2.Value())) {
685 continue;
686 }
687 const TopoDS_Edge& edgbis = TopoDS::Edge(itl2.Value());
688 TopoDS_Iterator it1(newedg),it2;
689 for (; it1.More(); it1.Next()) {
690 for (it2.Initialize(edgbis); it2.More(); it2.Next()) {
691 if (it1.Value().IsSame(it2.Value())) {
692 break;
693 }
694 }
695 if (it2.More()) {
696 break;
697 }
698 }
699
700 if (it1.More()) {
701 gp_Pnt ptbid;
702 Standard_Real prmvt =
703 BRep_Tool::Parameter(TopoDS::Vertex(it1.Value()),newedg);
704 C->D1(prmvt,ptbid,dir1);
705
706
707 C = BRep_Tool::Curve(edgbis,loc,f,l);
708 if (!loc.IsIdentity()) {
709 Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
710 C = Handle(Geom_Curve)::DownCast (GG);
711 }
712 if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
713 C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
714 }
715 prmvt =
716 BRep_Tool::Parameter(TopoDS::Vertex(it1.Value()),edgbis);
717 C->D1(prmvt,ptbid,dir2);
718 }
719 else {
720 dir1 = dir2 = gp_Vec(1,0,0);
721 }
722 EdgAdded.Add(edgbis);
723 if (dir1.Dot(dir2) <0.) {
724// B.Add(newwire,edgbis.Oriented(TopAbs::Reverse(or)));
725 listofedg.Append(edgbis.Oriented(TopAbs::Reverse(orient)));
726 }
727 else {
728// B.Add(newwire,edgbis.Oriented(or));
729 listofedg.Append(edgbis.Oriented(orient));
730 }
731
732
733 if (P.IsNull()) {
734 // on met les courbes 2d si on n`est pas sur un plan
735 // C est la courbe de edgbis, f et l s`y rapportent
736 Handle(Geom2d_Curve) PTC = GeomProjLib::Curve2d(C,f,l,S,tol);
737 if (S->IsUPeriodic()) {
738 Standard_Real Uref;
739 if (DontFuse.IsBound(edg)) {
740 TopAbs_Orientation oredge = DontFuse(edg).Orientation();
741 if (myModShapes.IsBound(edg)) { // edge raccourci...
742 TopoDS_Shape aLocalShape = edg.Oriented(oredge);
743 TopoDS_Shape aLocalFace = fac.Oriented(TopAbs_FORWARD);
744 BRep_Tool::
745 UVPoints(TopoDS::Edge(aLocalShape),TopoDS::Face(aLocalFace),pf,pl);
746// BRep_Tool::
747// UVPoints(TopoDS::Edge(edg.Oriented(oredge)),
748// TopoDS::Face(fac.Oriented(TopAbs_FORWARD)),
749// pf,pl);
750 }
751 else {
752 TopoDS_Shape aLocalShape = edg.Oriented(TopAbs::Reverse(oredge));
753 TopoDS_Shape aLocalFace = fac.Oriented(TopAbs_FORWARD);
754 BRep_Tool::
755 UVPoints(TopoDS::Edge(aLocalShape),TopoDS::Face(aLocalFace),pf,pl);
756// BRep_Tool::
757// UVPoints(TopoDS::Edge(edg.Oriented(TopAbs::Reverse(oredge))),
758// TopoDS::Face(fac.Oriented(TopAbs_FORWARD)),
759// pf,pl);
760 }
761 Uref = pf.X();
762 }
763 else {
764 BRep_Tool::UVPoints(edg,fac,pf,pl);
765 Uref = pf.X();
766 }
767
768 Standard_Real NewU = (PTC->Value(f)).X();
769
770// if(abs(NewU - Uref) > Epsilon(S->UPeriod())) {
771 if(fabs(NewU - Uref) > Epsilon(S->UPeriod())) {
772 PTC -> Translate(gp_Vec2d((Uref - NewU), 0.));
773 }
774 }
775
776 B.UpdateEdge(edgbis,PTC,newface,tol);
777 }
778 }
779 }
780 }
781 }
782
783 // Recuperation des edges sur les faces a fusionner.
784
785// ICICICICI
786
787// orface = TopAbs::Compose(orsav,orface);
788
789 Standard_Boolean includeinw = Standard_False;
790 for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
791 TopoDS_Face facbis = TopoDS::Face(itl.Value());
792 Standard_Boolean genface = Standard_True;
793 for (itl2.Initialize(G->OrientedFaces()); itl2.More(); itl2.Next()) {
794 if (itl2.Value().IsSame(facbis)) {
795 break;
796 }
797 }
798 if (itl2.More()) {
799 orient = itl2.Value().Orientation();
800 facbis.Orientation(orient);
801 }
802 else { // on fusionne avec une autre face du shape...
803 genface = Standard_False;
804 for (exp2.Init(myShape, TopAbs_FACE); exp2.More(); exp2.Next()) {
805 if (exp2.Current().IsSame(facbis)) {
806 facbis.Orientation(exp2.Current().Orientation());
807 break;
808 }
809 }
810 }
811
812 for (exp3.Init(facbis,TopAbs_WIRE); exp3.More(); exp3.Next()) {
813 for (exp2.Init(exp3.Current(),TopAbs_EDGE);
814 exp2.More(); exp2.Next()) {
815 if (toRemove.Contains(exp2.Current())) {
816 break;
817 }
818 }
819 if (genface) {
820 includeinw = Standard_True;
821 }
822 else {
823 Standard_Boolean includeinw = Standard_False;
824 if (exp2.More()) {
825 for (exp2.ReInit(); exp2.More(); exp2.Next()) {
826 if (!toRemove.Contains(exp2.Current())) {
827 continue;
828 }
829 TopoDS_Vertex VF,VL;
830 TopExp::Vertices(TopoDS::Edge(exp2.Current()),VF,VL);
831 TopExp_Explorer exp4;
832 for (exp4.Init(wir,TopAbs_VERTEX);
833// for (TopExp_Explorer exp4(wir,TopAbs_VERTEX);
834 exp4.More(); exp4.Next()) {
835 if (exp4.Current().IsSame(VF) ||
836 exp4.Current().IsSame(VL)) {
837 includeinw = Standard_True;
838 break;
839 }
840 }
841 if (includeinw) {
842 break;
843 }
844 }
845 }
846 }
847
848 if (!includeinw) {
849 continue;
850 }
851
852 for (exp2.ReInit(); exp2.More(); exp2.Next()) {
853 const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
854 if (!toRemove.Contains(edg) && !EdgAdded.Contains(edg)) {
855
856 orient = TopAbs::Compose(orface,edg.Orientation());
857 // B.Add(newwire,edg.Oriented(or));
858 listofedg.Append(edg.Oriented(orient));
859 EdgAdded.Add(edg);
860 if (P.IsNull()) {
861 // on met les courbes 2d si on n`est pas sur un plan
862 // on ne devrait pas avoir de pb d`edge de couture.
863 tol = BRep_Tool::Tolerance(edg);
864 C = BRep_Tool::Curve(edg,loc,f,l);
865 if (!loc.IsIdentity()) {
866 Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
867 C = Handle(Geom_Curve)::DownCast (GG);
868 }
869 if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
870 C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
871 }
872
873 C2d = GeomProjLib::Curve2d(C,f,l,S,tol);
874
875 // Tentative de recalage dans la facette
876 pf = C2d->Value(f);
877 pl = C2d->Value(l);
878 Standard_Real tttol = Precision::Angular();
879 while (Min(pf.X(),pl.X()) >= Umaxc - tttol) {
880 C2d->Translate(gp_Vec2d(-2.*M_PI,0));
881 pf = C2d->Value(f);
882 pl = C2d->Value(l);
883 }
884
885 while (Max(pf.X(),pl.X()) <= Uminc + tttol) {
886 C2d->Translate(gp_Vec2d(2.*M_PI,0));
887 pf = C2d->Value(f);
888 pl = C2d->Value(l);
889 }
890
891 if (!BRepTools::IsReallyClosed(edg,facbis)) {
892 B.UpdateEdge(edg,C2d,newface,tol);
893 }
894 // else {
895 // cout << "Edge double bizarre... " << endl;
896 // }
897 }
898 }
899 }
900 }
901 }
902 }
903 }
904 if (!listofedg.IsEmpty()) {
905 BRepAlgo_Loop L;
906 L.Init(newface);
907 L.AddConstEdges(listofedg);
908 L.Perform();
909 L.WiresToFaces();
910 const TopTools_ListOfShape& listoffaces = L.NewFaces();
911 toRemove.Add(fac);
912 // if (!HasWire) {
913 // newface.Nullify();
914 // }
915 myModShapes.Bind(fac,listoffaces);
916 for (itl.Initialize(itf.Value()); itl.More(); itl.Next()) {
917 myModShapes.Bind(itl.Value(),listoffaces);
918 }
919 }
920 }
921
922/* JAG 16.09.96 : on utilise LocOpe_BuildShape
923 TopoDS_Shell theShell;
924 B.MakeShell(theShell);
925 for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
926 const TopoDS_Face& fac = TopoDS::Face(exp.Current());
927 if (!theLeft.Contains(fac)) {
928 if (!toRemove.Contains(exp.Current())) {
929 B.Add(theShell,fac);
930 myModShapes.Bind(fac,fac);
931 }
932 else if (!myModShapes(fac).IsNull()) {
933 B.Add(theShell, myModShapes(fac).Oriented(fac.Orientation()));
934 }
935 }
936 }
937
938
939 TopAbs_Orientation orsolid = myShape.Orientation();
940 for (itl.Initialize(G->OrientedFaces()); itl.More(); itl.Next()) {
941 const TopoDS_Face& fac = TopoDS::Face(itl.Value());
942 if (toRemove.Contains(fac)) {
943 continue;
944 }
945
946 if (orsolid == TopAbs_FORWARD) {
947 B.Add(theShell,fac);
948 }
949 else {
950 B.Add(theShell,fac.Reversed());
951 }
952 myModShapes.Bind(fac,fac);
953
954 }
955
956 B.MakeSolid(TopoDS::Solid(myRes));
957 B.Add(myRes,theShell);
958 myRes.Orientation(orsolid);
959
960*/
961
962 // 06.11.96
963 // Debug temporaire. Il faudra prevoir un syntaxe de BuildShape
964 // qui impose une ori de certaines faces.
965
966 TopoDS_Face FaceRefOri;
967
968 TopTools_ListOfShape lfres;
969 for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
970 const TopoDS_Face& fac = TopoDS::Face(exp.Current());
971 if (!theLeft.Contains(fac)) {
972 if (!toRemove.Contains(exp.Current())) {
973 lfres.Append(fac);
974 if(!myModShapes.IsBound(fac)) {
975 TopTools_ListOfShape emptylist;
976 myModShapes.Bind(fac, emptylist);
977 }
978 myModShapes(fac).Append(fac);
979 if (FaceRefOri.IsNull()) {
980 FaceRefOri = fac;
981 }
982 }
983 else if (myModShapes.IsBound(fac)) {
984 lfres.Append(myModShapes(fac).First().Oriented(fac.Orientation()));
985 }
986 }
987 }
988
989
990 TopAbs_Orientation orsolid = myShape.Orientation();
991 for (itl.Initialize(G->OrientedFaces()); itl.More(); itl.Next()) {
992 const TopoDS_Face& fac = TopoDS::Face(itl.Value());
993 if (toRemove.Contains(fac)) {
994 continue;
995 }
996
997 if (orsolid == TopAbs_FORWARD) {
998 lfres.Append(fac);
999 }
1000 else {
1001 lfres.Append(fac.Reversed());
1002 }
1003 if(!myModShapes.IsBound(fac)) {
1004 TopTools_ListOfShape emptylist;
1005 myModShapes.Bind(fac, emptylist);
1006 }
1007 myModShapes(fac).Append(fac);
1008 }
1009
1010 LocOpe_BuildShape BS(lfres);
1011 myRes = BS.Shape();
1012 // Suite debug du 06.11.96
1013 if (myRes.ShapeType() == TopAbs_SOLID) {
1014 for (exp.Init(myRes,TopAbs_FACE); exp.More(); exp.Next()) {
1015 if (exp.Current().IsSame(FaceRefOri)) {
1016 break;
1017 }
1018 }
1019 if (exp.More() &&
1020 exp.Current().Orientation() != FaceRefOri.Orientation()) {
1021 // ---C++: return const& ---C++: return const& ---C++: return const&Si un seul Shell , on change son orientation
1022 TopoDS_Solid NewSol;
1023 B.MakeSolid(NewSol);
1024 exp.Init(myRes,TopAbs_SHELL);
1025 B.Add(NewSol,exp.Current().Reversed());
1026 myRes.Nullify();
1027 myRes = NewSol;
1028 }
1029 }
1030
1031
1032 // recodage des regularites qui existaient sur le shape colle
1033
1034
1035
1036 myDone = Standard_True;
1037}
1038
1039//=======================================================================
1040//function : DescendantFace
1041//purpose :
1042//=======================================================================
1043
1044 const TopTools_ListOfShape& LocOpe_Generator::DescendantFace(const TopoDS_Face& F)
1045{
1046 // TopTools_ListOfShape list;
1047
1048 if (!myDone) {StdFail_NotDone::Raise();}
1049 return myModShapes(F);
1050}
1051
1052//=======================================================================
1053//function : ToFuse
1054//purpose :
1055//=======================================================================
1056
1057Standard_Boolean ToFuse(const TopoDS_Face& F1,
1058 const TopoDS_Face& F2)
1059{
1060 if (F1.IsNull() || F2.IsNull()) {
1061 return Standard_False;
1062 }
1063
1064 Handle(Geom_Surface) S1,S2;
1065 TopLoc_Location loc1, loc2;
1066 Handle(Standard_Type) typS1,typS2;
1067 const Standard_Real tollin = Precision::Confusion();
1068 const Standard_Real tolang = Precision::Angular();
1069
1070 S1 = BRep_Tool::Surface(F1,loc1);
1071 S2 = BRep_Tool::Surface(F2,loc2);
1072
1073 typS1 = S1->DynamicType();
1074 typS2 = S2->DynamicType();
1075
1076 if (typS1 == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1077 S1 = Handle(Geom_RectangularTrimmedSurface)::DownCast (S1)->BasisSurface();
1078 typS1 = S1->DynamicType();
1079 }
1080
1081 if (typS2 == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1082 S2 = Handle(Geom_RectangularTrimmedSurface)::DownCast (S2)->BasisSurface();
1083 typS2 = S2->DynamicType();
1084 }
1085
1086 if (typS1 != typS2) {
1087 return Standard_False;
1088 }
1089
1090
1091 Standard_Boolean ValRet = Standard_False;
1092 if (typS1 == STANDARD_TYPE(Geom_Plane)) {
1093
1094 gp_Pln pl1( Handle(Geom_Plane)::DownCast (S1)->Pln());
1095 gp_Pln pl2( Handle(Geom_Plane)::DownCast (S2)->Pln());
1096
1097 pl1.Transform(loc1.Transformation());
1098 pl2.Transform(loc2.Transformation());
1099
1100 if (pl1.Position().IsCoplanar(pl2.Position(),tollin,tolang)) {
1101 ValRet = Standard_True;
1102 }
1103 }
1104
1105 return ValRet;
1106}
1107
1108
1109//=======================================================================
1110//function : ToFuse
1111//purpose :
1112//=======================================================================
1113
1114Standard_Boolean ToFuse(const TopoDS_Edge& E1,
1115 const TopoDS_Edge& E2)
1116{
1117
1118 if (E1.IsNull() || E2.IsNull()) {
1119 return Standard_False;
1120 }
1121
1122 Handle(Geom_Curve) C1,C2;
1123 TopLoc_Location loc1, loc2;
1124 Handle(Standard_Type) typC1,typC2;
1125 const Standard_Real tollin = Precision::Confusion();
1126 const Standard_Real tolang = Precision::Angular();
1127 Standard_Real f,l;
1128
1129 C1 = BRep_Tool::Curve(E1,loc1,f,l);
1130 if (!loc1.IsIdentity()) {
1131 Handle(Geom_Geometry) CC1 = C1->Transformed(loc1.Transformation());
1132 C1 = Handle(Geom_Curve)::DownCast (CC1);
1133 }
1134
1135 C2 = BRep_Tool::Curve(E2,loc2,f,l);
1136 if (!loc2.IsIdentity()) {
1137 Handle(Geom_Geometry) CC2 = C2->Transformed(loc2.Transformation());
1138 C2 = Handle(Geom_Curve)::DownCast (CC2);
1139 }
1140
1141 typC1 = C1->DynamicType();
1142 typC2 = C2->DynamicType();
1143
1144 if (typC1 == STANDARD_TYPE(Geom_TrimmedCurve)) {
1145 C1 = Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
1146 typC1 = C1->DynamicType();
1147 }
1148 if (typC2 == STANDARD_TYPE(Geom_TrimmedCurve)) {
1149 C2 = Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
1150 typC2 = C2->DynamicType();
1151 }
1152
1153 if (typC1 != typC2) {
1154 return Standard_False;
1155 }
1156
1157 Standard_Boolean ValRet = Standard_False;
1158 if (typC1 == STANDARD_TYPE(Geom_Line)) {
1159 gp_Lin li1( Handle(Geom_Line)::DownCast (C1)->Lin());
1160 gp_Lin li2( Handle(Geom_Line)::DownCast (C2)->Lin());
1161
1162 if (li1.Position().IsCoaxial(li2.Position(),tolang,tollin)) {
1163 ValRet = Standard_True;
1164 }
1165 }
1166
1167 return ValRet;
1168}
1169
1170
1171//=======================================================================
1172//function : ToFuse
1173//purpose :
1174//=======================================================================
1175
1176Standard_Boolean ToFuse(const TopoDS_Edge& E,
1177 const TopoDS_Face& F,
1178 const TopoDS_Vertex& V,
1179 const TopTools_MapOfShape& toRemove)
1180{
1181 TopoDS_Vertex Vf,Vl;
1182 TopExp_Explorer exp;
1183 for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
1184// for (TopExp_Explorer exp(F,TopAbs_EDGE); exp.More(); exp.Next()) {
1185 const TopoDS_Edge& eee = TopoDS::Edge(exp.Current());
1186 if (!eee.IsSame(E)) {
1187 TopExp::Vertices(eee,Vf,Vl);
1188 if ((Vf.IsSame(V) || Vl.IsSame(V)) &&
1189 !toRemove.Contains(eee)) {
1190 return Standard_False;
1191 }
1192 }
1193 }
1194 return Standard_True;
1195}
1196
1197
1198//=======================================================================
1199//function : NewParameter
1200//purpose :
1201//=======================================================================
1202
1203Standard_Real NewParameter(const TopoDS_Edge& Edg,
1204 const TopoDS_Vertex& Vtx,
1205 const TopoDS_Edge& NewEdg,
1206 const TopoDS_Vertex& NewVtx)
1207{
1208
1209 Handle(Geom_Curve) C;
1210 TopLoc_Location loc;
1211 Handle(Standard_Type) typC;
1212 Standard_Real f,l;
1213
1214 gp_Pnt P = BRep_Tool::Pnt(NewVtx);
1215
1216 C = BRep_Tool::Curve(Edg,loc,f,l);
1217 if (!loc.IsIdentity()) {
1218 Handle(Geom_Geometry) GG = C->Transformed(loc.Transformation());
1219 C = Handle(Geom_Curve)::DownCast (GG);
1220 }
1221 typC = C->DynamicType();
1222 if (typC == STANDARD_TYPE(Geom_TrimmedCurve)) {
1223 C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
1224 typC = C->DynamicType();
1225 }
1226
1227 if (typC == STANDARD_TYPE(Geom_Line)) {
1228 return ElCLib::Parameter( Handle(Geom_Line)::DownCast (C)->Lin(),P);
1229 }
1230 else if (typC == STANDARD_TYPE(Geom_Circle)) {
1231 Standard_Real prm = ElCLib::Parameter
1232 ( Handle(Geom_Circle)::DownCast (C)->Circ(),P);
1233 // Vtx vient d`une exploration de Edg orientee FORWARD
1234
1235 TopAbs_Orientation orient = TopAbs::Reverse(Vtx.Orientation());
1236 if (orient == TopAbs_FORWARD || orient == TopAbs_REVERSED) {
1237// for (TopExp_Explorer exp(NewEdg.Oriented(TopAbs_FORWARD),TopAbs_VERTEX);
1238 TopExp_Explorer exp(NewEdg.Oriented(TopAbs_FORWARD),TopAbs_VERTEX) ;
1239 for ( ; exp.More(); exp.Next()) {
1240 if (exp.Current().Orientation() == orient) {
1241 break;
1242 }
1243 }
1244 if (exp.More()) {
1245 Standard_Real prmmax = BRep_Tool::Parameter
1246 (TopoDS::Vertex(exp.Current()),NewEdg);
1247 if (Abs(prmmax - prm) <= Epsilon(2.*M_PI)) {
1248 if (orient == TopAbs_REVERSED) {
1249 prm -= 2.*M_PI;
1250 }
1251 else {
1252 prm += 2.*M_PI;
1253 }
1254 }
1255 }
1256 }
1257 return prm;
1258 }
1259 return 0;
1260}