summaryrefslogtreecommitdiff
path: root/src/TopOpeBRepTool/TopOpeBRepTool_PURGE.cxx
blob: 87c5864e9a29cdceca80c34cfd788328e9052d9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
// File:	TopOpeBRepTool_PURGE.cxx
// Created:	Thu Nov 13 13:45:48 1997
// Author:	Xuan PHAM PHU
//		<xpu@poulopox.paris1.matra-dtv.fr>

#include <TopOpeBRepTool.hxx>
#include <TopOpeBRepTool_TOOL.hxx>
#include <TopOpeBRepTool_CORRISO.hxx>
#include <TopOpeBRepTool_C2DF.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec2d.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom_Surface.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_Array1OfShape.hxx>

#include <BRep_Tool.hxx>
#include <Precision.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <BRep_Builder.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <TopOpeBRepTool_define.hxx>
#include <TopOpeBRepTool_EXPORT.hxx>
#include <TopOpeBRepTool_2d.hxx>
#include <Standard_Failure.hxx>
#include <TopOpeBRepTool_PURGE.hxx>

#ifdef DEB
//Standard_EXPORT Standard_Integer STATIC_PURGE_iwi = 0;
//Standard_EXPORT TopTools_IndexedMapOfShape STATIC_PURGE_mapw, STATIC_PURGE_mapv;
//Standard_EXPORT TopTools_IndexedMapOfOrientedShape STATIC_PURGE_mapeds, STATIC_CORR_mapeds;

Standard_EXPORT void debcorrUV(){};
Standard_EXPORT Standard_Boolean TopOpeBRepTool_GettracePURGE();
Standard_EXPORT Standard_Boolean TopOpeBRepTool_GettraceCORRISO();
#endif
// DEB

// Unused :
#ifdef DEB
static void FUN_RaiseError()
{
#ifdef DEB
  Standard_Boolean trc = TopOpeBRepTool_GettracePURGE();
  //  Standard_Failure::Raise("TopOpeBRepTool::PurgeClosingEdges");
  FUN_REINIT(); 
  if (trc) cout <<"*********failure in TopOpeBRepTool::PurgeClosingEdges***********\n";
#endif
}
static void FUN_Raise()
{
#ifdef DEB
  //  cout <<"*********failure in TopOpeBRepTool::CorrectONUVISO***********\n";
  //  Standard_Failure::Raise("TopOpeBRepTool::CorrectONUVISO");
#endif
}
#endif

#define SPLITEDGE (0)
#define INCREASE  (1)
#define DECREASE (-1)

#define M_FORWARD(sta)  (sta == TopAbs_FORWARD)
#define M_REVERSED(sta) (sta == TopAbs_REVERSED)
#define M_INTERNAL(sta) (sta == TopAbs_INTERNAL)
#define M_EXTERNAL(sta) (sta == TopAbs_EXTERNAL)

static void FUN_addtomap(TopTools_DataMapOfShapeListOfShape& map, const TopoDS_Shape& key, const TopoDS_Shape& item)
{
  if (map.IsBound(key))               map.ChangeFind(key).Append(item);
  else {TopTools_ListOfShape los; los.Append(item); map.Bind(key,los);}
}

static Standard_Boolean FUN_getv(const TopAbs_Orientation& orivine, const TopoDS_Shape& e, TopoDS_Shape& v)
{
  v.Nullify();
  // gets <v> oriented <orivine> in <e>
  TopAbs_Orientation oe = e.Orientation();
  Standard_Boolean isnonO = M_INTERNAL(oe) || M_EXTERNAL(oe);
  TopoDS_Shape eO;
  if (isnonO) {
    eO = e.Oriented(TopAbs_FORWARD);
  }
  else {
    eO = e;
  }
  TopExp_Explorer exv(eO, TopAbs_VERTEX);
  for (; exv.More(); exv.Next()) {	
    const TopoDS_Shape& vcur = exv.Current();
    if (vcur.Orientation() == orivine) {v = vcur; return Standard_True;}    
  } // exv
  return Standard_False;
}

Standard_EXPORT Standard_Boolean FUN_tool_ClosedW(const TopoDS_Wire& W)
{
  // !! an edge oriented INTERNAL/EXTERNAL has all its vertices
  // oriented INTERNAL/EXTERNAL.

  // <mapvedsO> = {(v,loe)} / e is oriented :
  // <mapvedsO> = {(v,loe)} / e is not oriented (INTERNAL/EXTERNAL) :
  TopTools_DataMapOfShapeListOfShape mapvFine,mapvRine, mapvIine;

  TopExp_Explorer exe(W, TopAbs_EDGE);
  for (; exe.More(); exe.Next()){
    const TopoDS_Shape& e = exe.Current();
    TopAbs_Orientation oe = e.Orientation();
    Standard_Boolean isnonO = M_INTERNAL(oe) || M_EXTERNAL(oe);
    TopoDS_Shape eO;
    if (isnonO) {
      eO = e.Oriented(TopAbs_FORWARD);
    }
    else {
      eO = e;
    }

    TopExp_Explorer exv(eO, TopAbs_VERTEX); 
    for (; exv.More(); exv.Next()) {	
      const TopoDS_Shape& v = exv.Current();
      TopAbs_Orientation oriv = v.Orientation();
      if (M_FORWARD(oriv))  FUN_addtomap(mapvFine,v,e);
      if (M_REVERSED(oriv)) FUN_addtomap(mapvRine,v,e);
      if (M_INTERNAL(oriv)) FUN_addtomap(mapvIine,v,e);
    }      
  }

  if (mapvFine.Extent() == 0) return Standard_False;   // empty wire  

  TopTools_MapOfShape mapvok;    
  // a vertex is found valid if is - an internal vertex
  //                               - found FORWARD and REVERSED. 
  TopTools_MapOfShape mapvonlyFine; // {(v,e)} v F in e, v belongs to only one e
  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itvFine(mapvFine);
  for (; itvFine.More(); itvFine.Next()){
    const TopoDS_Shape& vFine = itvFine.Key();
    Standard_Boolean vIine = mapvIine.IsBound(vFine);
    if (vIine) {mapvok.Add(vFine); continue;}
    Standard_Boolean vRine = mapvRine.IsBound(vFine);
    if (vRine) {mapvok.Add(vFine); continue;}
    mapvonlyFine.Add(vFine);
  }  
  // <mapvRinonee> = {(v,e)} v R in e, v belongs to only one e
  TopTools_MapOfShape mapvonlyRine; 
  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itvRine(mapvRine);
  for (; itvRine.More(); itvRine.Next()){
    const TopoDS_Shape& vRine = itvRine.Key();
    Standard_Boolean vok = mapvok.Contains(vRine);
    if (vok) continue;
    Standard_Boolean vIine = mapvIine.IsBound(vRine);
    if (vIine) {mapvok.Add(vRine); continue;}    
    mapvonlyRine.Add(vRine);
  }
  
  // checking vertices <mapvonlyFine> and <mapvonlyRine>
  TopTools_MapIteratorOfMapOfShape itvonlyFRine;
  Standard_Integer nmap = 0;
  while (nmap <= 2) {
    nmap++;
    Standard_Boolean vFine = (nmap == 1);
    if (vFine) itvonlyFRine.Initialize(mapvonlyFine);
    else       itvonlyFRine.Initialize(mapvonlyRine);

    for (; itvonlyFRine.More(); itvonlyFRine.Next()){
      const TopoDS_Shape& vtocheck = itvonlyFRine.Key();
      TopTools_ListOfShape edsvFRine;
      if (vFine) edsvFRine = mapvFine.Find(vtocheck);
      else       edsvFRine = mapvRine.Find(vtocheck);
       
      if (edsvFRine.Extent() > 1) return Standard_False; // faulty wire
      const TopoDS_Shape& e = edsvFRine.First();

      TopAbs_Orientation ovori = vFine? TopAbs_REVERSED: TopAbs_FORWARD;
      TopoDS_Shape ov; Standard_Boolean ovfound = FUN_getv(ovori,e,ov);
      if (!ovfound) return Standard_False; // faulty edge

      // <vtocheck> is on only one edge <e>,
      // <vtocheck> is FORWARD/REVERSED in <e>,
      // <ovfound> is REVERSED/FORWARD in <e>.
      // <vtocheck> is ok if : - <ovfound> is INTERNAL in another edge
      //                       - <ovfound> is FORWARD and REVERSED in 
      //                         one or two other edges.
      //                      and e is not oriented
      TopAbs_Orientation oe = e.Orientation();
      if (M_FORWARD(oe) || M_REVERSED(oe)) return Standard_False;
      if (!mapvok.Contains(ov)) return Standard_False;

      Standard_Boolean ovIine = mapvIine.IsBound(ov); if (ovIine)  continue;
      Standard_Boolean ovFine = mapvRine.IsBound(ov); if (!ovFine) return Standard_False;
      Standard_Boolean ovRine = mapvRine.IsBound(ov); if (!ovRine) return Standard_False;
    
      const TopTools_ListOfShape& edsovFine = mapvFine.Find(ov);
      const TopTools_ListOfShape& edsovRine = mapvRine.Find(ov);
      if (edsovFine.Extent() > 1) continue;
      if (edsovRine.Extent() > 1) continue;
      if (edsovFine.First().IsEqual(e)) return Standard_False;
      if (edsovRine.First().IsEqual(e)) return Standard_False;
    }
  } // nmap
  return Standard_True; 
}

//=======================================================================
//function : PurgeClosingEdges
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRepTool::PurgeClosingEdges(const TopoDS_Face& Fin, const TopoDS_Face& FF, 
//				      const TopTools_DataMapOfShapeInteger& MWisOld,
				      const TopTools_DataMapOfShapeInteger& ,
				      TopTools_IndexedMapOfOrientedShape& MshNOK)
{
  // Fin is the original face
  // FF  is the splitted face

  // prequesitory : splitted edges, of edge ancestor a closing edge
  //                keep in memory the geometry of the ancestor edge,
  //                they answer True to BRep_Tool::IsClosed.
  // elsewhere : we have to get this information using geometric 
  //             criteriums (TopOpeBRepTool_TOOL::IsonCLO)

#ifdef DEB
  Standard_Boolean trc =  TopOpeBRepTool_GettracePURGE();
  if (trc) cout<<"\n* PurgeClosingEdges:\n\n";
#endif
  TopOpeBRepTool_CORRISO CORRISO(Fin);  
  Standard_Real tolF = BRep_Tool::Tolerance(Fin);
  Standard_Real uperiod; Standard_Boolean uclosed = CORRISO.Refclosed(1,uperiod);
  Standard_Real vperiod; Standard_Boolean vclosed = CORRISO.Refclosed(2,vperiod);
  if (!uclosed && !vclosed) return Standard_False;
  Standard_Boolean inU = uclosed ? Standard_True : Standard_False;  
  Standard_Real xmin = inU ? (CORRISO.GASref().FirstUParameter()) :
                             (CORRISO.GASref().FirstVParameter());
  Standard_Real xper = inU ? uperiod : vperiod;
  Standard_Real tolx = inU ? (CORRISO.Tol(1,tolF)) : (CORRISO.Tol(2,tolF));

  TopExp_Explorer exw(FF, TopAbs_WIRE);
  for (; exw.More(); exw.Next()){
    const TopoDS_Shape& W = exw.Current();

    CORRISO.Init(W);
    Standard_Boolean ok = CORRISO.UVClosed();
    if (ok) continue;

    TopTools_ListOfShape cEds; 
    TopTools_ListIteratorOfListOfShape ite(CORRISO.Eds());
    for (; ite.More(); ite.Next()){
      const TopoDS_Edge& E = TopoDS::Edge(ite.Value());
      Standard_Boolean closing = BRep_Tool::IsClosed(E,Fin); 
      if (!closing) {// xpu231198 : pcurve modified, the information is lost
	TopOpeBRepTool_C2DF C2DF; Standard_Boolean isb = CORRISO.UVRep(E,C2DF);
	if (!isb) return Standard_False;//NYIRAISE
	Standard_Boolean onclo = TopOpeBRepTool_TOOL::IsonCLO(C2DF,inU,xmin,xper,tolx);
	if (onclo) closing=Standard_True;
      }
      if (closing) cEds.Append(E);
    }          
    Standard_Integer ncE = cEds.Extent();
    Standard_Boolean nopurge = (ncE <= 1);
    if (nopurge) return Standard_True;
    
    // Checking <W>
    TopTools_ListOfShape fyEds; Standard_Boolean topurge = CORRISO.PurgeFyClosingE(cEds,fyEds);
    if (topurge) {
      TopTools_ListIteratorOfListOfShape it(fyEds);
      for (; it.More(); it.Next()) MshNOK.Add(it.Value()); 
      MshNOK.Add(W); 
      MshNOK.Add(FF);
    }
    
#ifdef DEB
    if (trc && topurge) cout<<"found FAULTY edge = ed"<<endl;
#endif
  } // exw
  return Standard_True;
}

//=======================================================================
//function : PurgeClosingEdges
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRepTool::PurgeClosingEdges(const TopoDS_Face& Fin, const TopTools_ListOfShape& LOF, 
				      const TopTools_DataMapOfShapeInteger& MWisOld,
				      TopTools_IndexedMapOfOrientedShape& MshNOK)
{  
  Standard_Boolean uvclosed = FUN_tool_closedS(Fin);
  if (!uvclosed) return Standard_True;
  
  TopTools_ListIteratorOfListOfShape it(LOF);
  for (; it.More(); it.Next()){
    const TopoDS_Face& FF = TopoDS::Face(it.Value());
    Standard_Boolean ok = TopOpeBRepTool::PurgeClosingEdges(Fin,FF,MWisOld,MshNOK);
    if (!ok) return Standard_False;    
  }
  return Standard_True;
}

/*static Standard_Boolean FUN_correctClosingE(TopoDS_Edge& newfE, TopoDS_Face& Fsp)
{    
  Standard_Real f,l,tol; Handle(Geom2d_Curve) PC = FUNTOOLC2D_CurveOnSurface(newfE,Fsp,f,l,tol);
  gp_Dir2d d2d; gp_Pnt2d O2d; Standard_Boolean isuiso,isviso; 
  Standard_Boolean uviso = FUN_tool_IsUViso(PC,isuiso,isviso,d2d,O2d);
  if (!uviso) return Standard_False;

  Standard_Real period = 2*PI;
  Standard_Real piso = isuiso? O2d.X(): O2d.Y();
  Standard_Real tol2d = 1.e-6;
  Standard_Boolean is0   = Abs(piso) < tol2d;
  Standard_Boolean is2PI = Abs(period-piso) < tol2d;
  // --------------------------------------------------
  //  prequesitory :  Closed Surfaces have period 2PI
  if (!is0 && !is2PI) return Standard_False;
  // -------------------------------------------------- 
  Standard_Real factor = is0? period: -period;
  gp_Vec2d transl(1.,0.); if (isviso) transl = gp_Vec2d(0.,1.);
  transl.Multiply(factor);
  
  Standard_Integer ok = FUN_tool_translate(transl,Fsp,newfE);
  return Standard_True;   
}

static Standard_Boolean FUN_correctDegeneratedE
(const TopTools_IndexedDataMapOfShapeListOfShape& mve,TopoDS_Edge& Ein,TopoDS_Face& Fsp)
{
  TopoDS_Vertex v1,v2; TopExp::Vertices(Ein,v1,v2);
  TopAbs_Orientation ov1 = v1.Orientation();
  TopAbs_Orientation ov2 = v2.Orientation();
  Standard_Boolean ok1 = mve.Contains(v1); if (!ok1) return Standard_False;
  Standard_Boolean ok2 = mve.Contains(v2); if (!ok2) return Standard_False;

  const TopTools_ListOfShape& le= mve.FindFromKey(v1);

  TopoDS_Edge e1,e2; Standard_Boolean fe1 = Standard_False; Standard_Boolean fe2 = Standard_False;
  TopoDS_Vertex vfe1,vfe2;
  Standard_Boolean fEin = Standard_False;
  for(TopTools_ListIteratorOfListOfShape itle(le);itle.More();itle.Next()) {
    const TopoDS_Shape& ecx = TopoDS::Edge(itle.Value());
    if (ecx.IsEqual(Ein)) {
      fEin = Standard_True;
    }
    else {
      TopExp_Explorer exv;
      for (exv.Init(ecx,TopAbs_VERTEX);exv.More();exv.Next()) {
//      for (TopExp_Explorer exv(ecx,TopAbs_VERTEX);exv.More();exv.Next()) {
	const TopoDS_Vertex& vecx = TopoDS::Vertex(exv.Current());
	Standard_Boolean issam = vecx.IsSame(v1);
	if (issam) { 
	  Standard_Boolean iseq1 = vecx.IsEqual(v1);
	  Standard_Boolean iseq2 = vecx.IsEqual(v2);
	  if (!iseq1) {
	    e1 = TopoDS::Edge(ecx);
	    vfe1 = TopoDS::Vertex(vecx); 
	    fe1 = Standard_True;
	  }
	  if (!iseq2) {
	    e2 = TopoDS::Edge(ecx);
	    vfe2 = TopoDS::Vertex(vecx); 
	    fe2 = Standard_True;
	  }
	}
	if (fe1 && fe2) break;
      }
      if (fe1 && fe2) break;
    }
    if (fEin && fe1 && fe2) break;
  } // itle.More()

  Standard_Boolean ok = (fEin && fe1 && fe2);
  if (!ok) return Standard_False;
  
#ifdef DEB
  debcorrUV(); // call Draw_Call("av2d;dy fyf;fit;ppcu fyf")
#endif

  Standard_Real f,l,tol; Handle(Geom2d_Curve) PC = FUNTOOLC2D_CurveOnSurface(Ein,Fsp,f,l,tol);
  gp_Dir2d d2d; gp_Pnt2d O2d; Standard_Boolean isuiso = 0,isviso = 0; 
  Standard_Boolean uviso = FUN_tool_IsUViso(PC,isuiso,isviso,d2d,O2d);
  if (!uviso) return Standard_False;

  Standard_Real pfEin,plEin,tolEin; Handle(Geom2d_Curve) PCEin = FUNTOOLC2D_CurveOnSurface(Ein,Fsp,pfEin,plEin,tolEin); 
  if (PCEin.IsNull()) Standard_Failure::Raise(" FUN_correctDegeneratedE : no 2d curve Ein");
  Standard_Real pf1,pl1,tol1; Handle(Geom2d_Curve) PC1 = FUNTOOLC2D_CurveOnSurface(e1,Fsp,pf1,pl1,tol1); 
  if (PC1.IsNull()) Standard_Failure::Raise(" FUN_correctDegeneratedE : no 2d curve e1");
  Standard_Real pf2,pl2,tol2; Handle(Geom2d_Curve) PC2 = FUNTOOLC2D_CurveOnSurface(e2,Fsp,pf2,pl2,tol2); 
  if (PC2.IsNull()) Standard_Failure::Raise(" FUN_correctDegeneratedE : no 2d curve e2");
  
  Standard_Real parv1 = BRep_Tool::Parameter(v1,Ein,Fsp);
  Standard_Real parv2 = BRep_Tool::Parameter(v2,Ein,Fsp);
  gp_Pnt2d  pv1; PCEin->D0(parv1,pv1);
  gp_Pnt2d  pv2; PCEin->D0(parv2,pv2);

  Standard_Real par1 = BRep_Tool::Parameter(vfe1,e1,Fsp);
  Standard_Real par2 = BRep_Tool::Parameter(vfe2,e2,Fsp);
  gp_Pnt2d  p1; PC1->D0(par1,p1);
  gp_Pnt2d  p2; PC2->D0(par2,p2);

  Standard_Real cv1 = (isuiso) ? pv1.Y() : pv1.X();
  Standard_Real cv2 = (isuiso) ? pv2.Y() : pv2.X();
  Standard_Real c1 = (isuiso) ? p1.Y() : p1.X();
  Standard_Real c2 = (isuiso) ? p2.Y() : p2.X();

  Standard_Real d1 = (c1 - cv1);
  Standard_Real d2 = (c2 - cv2);
  Standard_Real adc = Abs(c1 - c2);
  Standard_Real adcv = Abs(cv1 - cv2);

  Standard_Real tol2d = 1.e-6;
  Standard_Boolean mmd = (Abs(adc-adcv) < tol2d);
  if (mmd) { // correction de CTS20973
    gp_Vec2d transl(0.,1.); if (isviso) transl = gp_Vec2d(1.,0.);
    transl.Multiply(d1); // ou d2
    ok = FUN_tool_translate(transl,Fsp,Ein);
  }
  else {
    // redefinition des parametres de v1,v2 de Ein tels que des parametres de 
#ifdef DEB
    if (TopOpeBRepTool_GettraceCORRISO()) {
      cout<<"FUN_correctDegeneratedE : !mmd NYI"<<endl;
    }
#endif
    ok = Standard_False;
  }
  
  return ok;   
} //FUN_correctDegeneratedE*/

/*static Standard_Boolean FUN_tool_reguUV(const TopoDS_Face& FF, TopoDS_Face& fF)
{  

  const TopoDS_Face& F = TopoDS::Face(FF);
  Standard_Boolean uclosed,vclosed; Standard_Real uperiod,vperiod;
  Standard_Boolean closed = FUN_tool_closedS(F,uclosed,uperiod,vclosed,vperiod);
  if (!closed) return Standard_False;    
  Standard_Real tolu,tolv; FUN_tool_tolUV(TopoDS::Face(fF),tolu,tolv);

  TopTools_ListOfShape leko;
  // --------
  TopTools_IndexedMapOfOrientedShape mape;
  TopExp_Explorer ex(fF, TopAbs_EDGE);
  for (; ex.More(); ex.Next()){
    const TopoDS_Edge& ee = TopoDS::Edge(ex.Current());
    TopAbs_Orientation oee = ee.Orientation();
    TopAbs_Orientation oe = TopAbs::Complement(oee);
    TopoDS_Edge e = TopoDS::Edge(ee.Oriented(oe));
    Standard_Boolean hasoppo = mape.Contains(e); // e with complement ori was added to mape
    if (hasoppo) {
      // ee :
      Standard_Real ff,ll; Handle(Geom2d_Curve) PCee = BRep_Tool::CurveOnSurface(ee,F,ff,ll);
      Standard_Boolean uisoee,visoee; gp_Dir2d d2dee; gp_Pnt2d O2dee; 
      Standard_Boolean uvisoee = FUN_tool_IsUViso(PCee,uisoee,visoee,d2dee,O2dee);
      // e :
      Standard_Real f,l; Handle(Geom2d_Curve) PCe = BRep_Tool::CurveOnSurface(e,F,f,l);
      Standard_Boolean uisoe,visoe; gp_Dir2d d2de; gp_Pnt2d O2de; 
      Standard_Boolean uvisoe = FUN_tool_IsUViso(PCe,uisoe,visoe,d2de,O2de);

      // isfaulty :
      Standard_Boolean isfaulty = Standard_False;
      Standard_Real dd = O2dee.Distance(O2de);
      if (uisoee && uisoe) isfaulty = (dd < tolu);
      if (visoee && visoe) isfaulty = (dd < tolv);

      if (isfaulty) leko.Append(ee);
    }
    else mape.Add(ee);
  }
  
  Standard_Integer nko = leko.Extent();
  if (nko != 1) return Standard_False;

  // eko = edge with faulty pcurve :
  const TopoDS_Shape& eko = leko.First();
  TopAbs_Orientation oeko = eko.Orientation();
  TopTools_ListOfShape edges; ex.Init(fF, TopAbs_EDGE);
  for (; ex.More(); ex.Next()){
    const TopoDS_Shape& ee = ex.Current();
    if (!ee.IsSame(eko)) edges.Append(ee);
  }    
  // fe = edge with vfe = vertex(ivfe) not uv-connexed :
  TopoDS_Shape fe; Standard_Integer ivfe=0; 
  Standard_Boolean det = ::FUN_DetectEdgewithfaultyUV(FF,fF,edges,Standard_False,fe,ivfe);
  if (!det) return Standard_False;

  TopTools_Array1OfShape Vfe(1,2); FUN_Vertices(TopoDS::Edge(fe),Vfe); 
  TopAbs_Orientation ofe = fe.Orientation(); 
  const TopoDS_Vertex& vfe = TopoDS::Vertex(Vfe(ivfe));
  Standard_Real parfe = BRep_Tool::Parameter(vfe,TopoDS::Edge(fe));
  gp_Pnt2d uvfe; Standard_Boolean ok = FUN_tool_paronEF(TopoDS::Edge(fe),parfe,F,uvfe);
  if (!ok) return Standard_False;
  // ivconnex :
  Standard_Integer ivconnex = (ivfe == 1) ? 2 : 1;
//  if (ofe == TopAbs_REVERSED) ivconnex = (ivconnex == 1) ? 2 : 1;
  
  // vertex(ivconnex) of eko FORWARD
  TopoDS_Edge ekoFOR = TopoDS::Edge(eko.Oriented(TopAbs_FORWARD));
  TopTools_Array1OfShape Veko(1,2); FUN_Vertices(TopoDS::Edge(ekoFOR),Veko);  
  const TopoDS_Vertex& veko1 = TopoDS::Vertex(Veko(1));
  const TopoDS_Vertex& veko2 = TopoDS::Vertex(Veko(2));
  Standard_Integer iveko = 0;
  if (veko1.IsSame(vfe)) iveko = 1;
  if (veko2.IsSame(vfe)) iveko = 2;
  if (iveko == 0) return Standard_False;

  // ett : edge same eko with pcurve to translate
  // isekoFOR=true : vfe should be connexed to vertex(ivconnex) of ekoFOR
  Standard_Boolean isekoFOR = (iveko == ivconnex); 
  TopAbs_Orientation oett = isekoFOR ? TopAbs_FORWARD : TopAbs_REVERSED; 
  TopoDS_Edge ett = TopoDS::Edge(eko.Oriented(oett));
  const TopoDS_Vertex& vtt = TopoDS::Vertex(Veko(iveko));

  Standard_Real parett = BRep_Tool::Parameter(vtt,ett);
  gp_Pnt2d uvtt; ok = FUN_tool_paronEF(ett,parett,F,uvtt);
  if (!ok) return Standard_False;
  
  Standard_Real du = uvfe.X()-uvtt.X(); 
  Standard_Real dv = uvfe.Y()-uvtt.Y(); 
  Standard_Boolean tru=Standard_False, trv=Standard_False;
  if (uclosed) tru = (Abs(Abs(du)-uperiod) < tolu);
  if (vclosed) trv = (Abs(Abs(dv)-vperiod) < tolv);
  if (!tru && !trv) return Standard_False;

  gp_Vec2d tt;
  if (tru) tt = gp_Vec2d(du,0.);
  if (trv) tt = gp_Vec2d(0.,dv);
  Standard_Real f,l; Handle(Geom2d_Curve) PC1 = BRep_Tool::CurveOnSurface(ett,F,f,l);
  Standard_Boolean uisoett,visoett; gp_Dir2d d2dett; gp_Pnt2d o2dett; 
  Standard_Boolean uvisoett = FUN_tool_IsUViso(PC1,uisoett,visoett,d2dett,o2dett);o2dett.Translate(tt);
  Handle(Geom2d_Line) L2d = new Geom2d_Line(o2dett,d2dett);
  Handle(Geom2d_TrimmedCurve) PC2 = new Geom2d_TrimmedCurve(L2d,f,l);

  BRep_Builder BB;
  Standard_Real toltt = BRep_Tool::Tolerance(ett);
//  BB.UpdateEdge(TopoDS::Edge(ett),PC2,PC1,fF,toltt);
  // xpu220998 : cto cylcong A1
  Handle(Geom2d_Curve) nullc2d;
  BB.UpdateEdge(TopoDS::Edge(ekoFOR),nullc2d,nullc2d,fF,toltt); // clear
  if (isekoFOR) BB.UpdateEdge(TopoDS::Edge(ekoFOR),PC2,PC1,fF,toltt);
  else          BB.UpdateEdge(TopoDS::Edge(ekoFOR),PC1,PC2,fF,toltt);

  return Standard_True;
}*/

static Standard_Boolean FUN_connexX(const Standard_Boolean onU, TopOpeBRepTool_CORRISO& CORRISO, 
		       const TopTools_ListOfShape& EdstoCheck, TopTools_DataMapOfOrientedShapeInteger& fyEds)
// purpose : Fref is x-periodic, 
//           <fyEds>={(fye,recadre)}, recadre = INCREASE,DECREASE
//                                    fye has its 2 bounds faulty
{
  fyEds.Clear();
  Standard_Real tolF = BRep_Tool::Tolerance(CORRISO.Fref());
  Standard_Integer Index = onU ? 1 : 2;
  Standard_Real xperiod; Standard_Boolean xclosed = CORRISO.Refclosed(Index,xperiod);
  if (!xclosed) return Standard_False;
  Standard_Real xtol = CORRISO.Tol(Index,tolF);
  
  // fy has its 2 uvbounds non-connexed       
  //nyixpu300998 : iterative (while ko) + map of "static" edges
  TopoDS_Shape fy; Standard_Integer Ify=0; Standard_Boolean hasfy = CORRISO.EdgeWithFaultyUV(EdstoCheck,2,fy,Ify); 
  if (!hasfy) return Standard_False;
  TopOpeBRepTool_C2DF C2DF; Standard_Boolean isb = CORRISO.UVRep(TopoDS::Edge(fy),C2DF);
  if (!isb) return Standard_False; // NYIRAISE

  TopTools_Array1OfShape vfy(1,2); TopOpeBRepTool_TOOL::Vertices(TopoDS::Edge(fy),vfy);
  for (Standard_Integer ii = 1; ii <=2; ii++) {
    // vff = vertex[ii] of fy
    const TopoDS_Vertex& vff = TopoDS::Vertex(vfy(ii));
    Standard_Real parvff = TopOpeBRepTool_TOOL::ParE(ii,TopoDS::Edge(fy));gp_Pnt2d uvff = TopOpeBRepTool_TOOL::UVF(parvff,C2DF);
    // loe list of edges connexed to faultE
    TopTools_ListOfShape loe; isb = CORRISO.Connexity(vff,loe);
    if (!isb) return Standard_False; // FUNRAISE

    TopTools_ListIteratorOfListOfShape ite(loe); // iteration on connex edges of vff
    for (; ite.More(); ite.Next()){
      const TopoDS_Edge& ee = TopoDS::Edge(ite.Value());
      TopTools_Array1OfShape vee(1,2); TopOpeBRepTool_TOOL::Vertices(ee,vee);
      for (Standard_Integer ive = 1; ive <=2; ive++) {	  
	// ve = vertex[ive] of ee
	const TopoDS_Vertex& ve = TopoDS::Vertex(vee(ive));	  
	Standard_Boolean samev = ve.IsSame(vff);
	if (!samev) continue;	
	if (ive == ii) continue;
	TopOpeBRepTool_C2DF C2DFe; isb = CORRISO.UVRep(ee,C2DFe);
	if (!isb) return Standard_False; // FUNRAISE
	Standard_Real paree = TopOpeBRepTool_TOOL::ParE(ive,ee); gp_Pnt2d uve = TopOpeBRepTool_TOOL::UVF(paree,C2DFe);	
	
	// xxtrsl :
	Standard_Real dxx = onU ? uve.X()-uvff.X() : uve.Y()-uvff.Y();
	Standard_Boolean isper =( Abs(xperiod-Abs(dxx)) < xtol);
	if (!isper) continue;
	
	Standard_Integer recadre = (dxx > 0) ? INCREASE : DECREASE; 
	fyEds.Bind(fy,recadre);
      } //ive=1..2
    }//ite(loe)
  }//ii=1..2    
  return !fyEds.IsEmpty();
} // FUN_connexX
 
//=======================================================================
//function : CorrectONUVISO
//purpose  :  
//=======================================================================

Standard_Boolean TopOpeBRepTool::CorrectONUVISO(const TopoDS_Face& Fin, TopoDS_Face& Fsp)
// <Fref> is x-periodic 
{
#ifdef DEB
  Standard_Boolean trc = TopOpeBRepTool_GettraceCORRISO();
  if (trc) cout<<"\n####    CorrectONUVISO    ####\n\n";
  debcorrUV();
#endif

  Standard_Real tolF = BRep_Tool::Tolerance(Fin);

  TopOpeBRepTool_CORRISO CORRISO(Fin);
  Standard_Real uperiod,vperiod;
  Standard_Boolean uclosed = CORRISO.Refclosed(1,uperiod);
  Standard_Boolean vclosed = CORRISO.Refclosed(2,vperiod);
  if (!uclosed && !vclosed) return Standard_False;
  
  CORRISO.Init(Fsp);
  Standard_Boolean ok = CORRISO.UVClosed();
  if (ok) return Standard_True; // Fsp is valid

  // 1. We check connexity among all edges of <Fsp>
  // if we find on edge with 2 faulty UVbounds, we try to UVconnect it.
//  for (Standard_Integer i=1; i<=2; i++) {
  Standard_Integer i ;
  for ( i=1; i<=2; i++) {
    Standard_Boolean onU = (i==1) ? Standard_True : Standard_False; 
    const TopTools_ListOfShape& Tocheck = CORRISO.Eds();
    TopTools_DataMapOfOrientedShapeInteger fyEds; ok =::FUN_connexX(onU,CORRISO,Tocheck,fyEds);
    if (!ok) continue;
    ok = CORRISO.TrslUV(onU,fyEds);
    if (!ok) continue;
    ok = CORRISO.UVClosed();
    if (!ok) continue;
    ok = CORRISO.GetnewS(Fsp);
    if (!ok) return Standard_False; //NYIRAISE
    return Standard_True;
  }

  // 2. x-2drep(edges) are in [xfirst,xfirst+xperiod]
  for (i = 1; i <=2; i++) {
    Standard_Boolean onU = (i==1);     
    Standard_Real xper=0.; Standard_Boolean xclosed = CORRISO.Refclosed(i,xper);
    if (!xclosed) continue;
    Standard_Real tolx = CORRISO.Tol(i,tolF);
    tolx *= 1.e2; // BUC60380
    TopTools_DataMapOfOrientedShapeInteger FyEds; Standard_Boolean hasfy = CORRISO.EdgesOUTofBoundsUV(CORRISO.Eds(),onU,tolx,FyEds);
    if (!hasfy) continue;
    ok = CORRISO.TrslUV(onU,FyEds);
    if (!ok) return Standard_False;
    ok = CORRISO.UVClosed();
    if (!ok) continue;
    ok = CORRISO.GetnewS(Fsp);
    if (!ok) return Standard_False; //NYIRAISE
    return Standard_True;
  }
  return Standard_False;

  /*// xpu310898 : eC closing ff, ff sdm F(reference face), proj(eC,F) gives ee with
  //             !closing(ee,Fsp) -> 2drep(Fsp) is not closed.
  //             purpose : translate pceCFOR or pceCREV
  //   cto902B7 (ff=f7,eC=e9,F=f14)
  ok = ::FUN_tool_reguUV(Fin,Fsp);*/

  /*// JYL 980909 : reecriture complete
  // 1/ traitement de TOUTES les aretes
  //    isou et isov fautives (et non la premiere trouvee);
  // 2/ traitement des aretes degenerees fautives : CTS20973

  TopTools_ListOfShape lisoe,ldege;
  TopExp_Explorer exe(Fsp, TopAbs_EDGE);
  for (; exe.More(); exe.Next()){
    const TopoDS_Edge& E = TopoDS::Edge(exe.Current());
    Standard_Boolean degen = BRep_Tool::Degenerated(E);
    if ( degen ) {
      ldege.Append(E);
    }
    else {
      Standard_Real f,l; Handle(Geom2d_Curve) PC = BRep_Tool::CurveOnSurface(E,Fin,f,l);
      Standard_Boolean uiso,viso; gp_Dir2d d2d; gp_Pnt2d O2d; 
      Standard_Boolean uviso = FUN_tool_IsUViso(PC,uiso,viso,d2d,O2d);
      Standard_Boolean onclosing = (uiso && uclosed) || (viso && vclosed);
      if      ( onclosing) {
	lisoe.Append(E);
      }
    }
  }
  
  Standard_Integer nisoe = lisoe.Extent();
  Standard_Integer ndege = ldege.Extent();
  if (nisoe ==0 && ndege == 0) return Standard_False;

  Standard_Integer tmpisoe;
  Standard_Integer tmpdege;

  TopTools_ListOfShape lfyisoe; Standard_Boolean tocorrectisoe = Standard_False;
  tocorrectisoe = FUN_DetectEdgeswithfaultyUV(Fsp,Fsp,lisoe,Standard_True,lfyisoe,tmpisoe);

  TopTools_ListOfShape lfydege; Standard_Boolean tocorrectdege = Standard_False;
  tocorrectdege = FUN_DetectEdgeswithfaultyUV(Fsp,Fsp,ldege,Standard_True,lfydege,tmpdege);

  tocorrect = (tocorrectisoe || tocorrectdege);
  if (!tocorrect) {
    return Standard_True;
  }
  
#ifdef DEB
  if (trc) {
    cout<<"CorrectONUVISO ";
    cout<<"iso faulty "<<tocorrectisoe<<" deg faulty "<<tocorrectdege<<endl;;
  }
  debcorrUV();
#endif
  
  if (tocorrectisoe) {
    for (TopTools_ListIteratorOfListOfShape itiso(lfyisoe);itiso.More();itiso.Next()) {
      TopoDS_Edge& fyisoe = TopoDS::Edge(itiso.Value());
      
      // !! if the faulty edge ON closing appears twice in <Eds>, NOTHING is done!
      // -> see processing ::PurgeClosingEdges later called in WESMakeFaces    
      Standard_Integer nfoundisoe = 0;
      for (exe.Init(Fsp, TopAbs_EDGE); exe.More(); exe.Next()) {
	if (exe.Current().IsSame(fyisoe)) {
	  nfoundisoe++; 
	}
      }
      if (nfoundisoe > 1) {
	continue;
      }
      
#ifdef DRAW
      if (trc) { 
	cout<<"TopOpeBRepTool correctONUVISO : faulty iso edge"<<endl;
	FUN_tool_draw("fyf",Fsp);FUN_tool_draw("fyisoe",fyisoe);
      }
#endif
      
      Standard_Boolean ok = ::FUN_correctClosingE(fyisoe,Fsp);
      if (!ok) {
	FUN_Raise();
	continue;
      }
    }
    
    Standard_Integer tmpisoe;
    TopTools_ListOfShape lffyisoe; tocorrectisoe = FUN_DetectEdgeswithfaultyUV(Fsp,Fsp,lfyisoe,Standard_False,lffyisoe,tmpisoe);
  } // end lffyisoe process
  
  if (tocorrectdege) {
    TopTools_IndexedDataMapOfShapeListOfShape mve;
    TopExp::MapShapesAndAncestors(Fsp,TopAbs_VERTEX,TopAbs_EDGE,mve);
    
    for (TopTools_ListIteratorOfListOfShape itdeg(lfydege);itdeg.More();itdeg.Next()) {
      TopoDS_Edge& fydege = TopoDS::Edge(itdeg.Value());
      
#ifdef DRAW
      if (trc) { 
	cout<<"TopOpeBRepTool correctONUVISO : faulty deg edge"<<endl;
	FUN_tool_draw("fyf",Fsp);FUN_tool_draw("fydege",fydege);
      }
#endif
      
      Standard_Boolean ok = ::FUN_correctDegeneratedE(mve,fydege,Fsp);
      if (!ok) {
	FUN_Raise();
	continue;
      }
    } // itdeg
    
    TopTools_ListOfShape lffydege; tocorrectdege = FUN_DetectEdgeswithfaultyUV(Fsp,Fsp,lfydege,Standard_False,lffydege,tmpdege);
  } // end lfydege process

  TopTools_ListOfShape eFsp; FUN_tool_shapes(Fsp,TopAbs_EDGE,eFsp);
  TopTools_ListOfShape lffydege; tocorrect = FUN_DetectEdgeswithfaultyUV(Fsp,Fsp,eFsp,Standard_False,lffydege,tmpdege);
  Standard_Boolean done = !tocorrect;
  return done;*/

} // correctONUVISO

//=======================================================================
//function : MakeFaces
//purpose  : 
//=======================================================================

Standard_Boolean TopOpeBRepTool::MakeFaces(const TopoDS_Face& Fin, const TopTools_ListOfShape& LOF, 
			      const TopTools_IndexedMapOfOrientedShape& MshNOK,
			      TopTools_ListOfShape& LOFF)
{
//  TopOpeBRepDS_BuildTool BT;
  BRep_Builder BB;
  LOFF.Clear();
  TopTools_ListIteratorOfListOfShape it(LOF);
  for (; it.More(); it.Next()){
    const TopoDS_Face& FF = TopoDS::Face(it.Value());
    Standard_Boolean valid = !MshNOK.Contains(FF);
    if (valid) {LOFF.Append(FF); continue;}
    
    TopoDS_Shape aLocalShape = Fin.EmptyCopied();
    TopoDS_Face newFace = TopoDS::Face(aLocalShape);// BT.CopyFace(Fin,newFace);
//    TopoDS_Face newFace = TopoDS::Face(Fin.EmptyCopied());// BT.CopyFace(Fin,newFace);
    TopExp_Explorer exw(FF, TopAbs_WIRE);
    
    for (; exw.More(); exw.Next()){
      const TopoDS_Wire& W = TopoDS::Wire(exw.Current());
      valid = !MshNOK.Contains(W);
      //      if (valid) {BT.AddFaceWire(newFace,W); continue;}
      if (valid) {BB.Add(newFace,W); continue;}

      TopoDS_Wire newWire; //BT.MakeWire(newWire);
      BB.MakeWire(newWire);
      TopExp_Explorer exe(W, TopAbs_EDGE);
      Standard_Integer ne = 0;
      for (; exe.More(); exe.Next()){
	const TopoDS_Edge& E = TopoDS::Edge(exe.Current());
	valid = !MshNOK.Contains(E);
	if (!valid) continue;
	//	BT.AddWireEdge(newWire,E);
	BB.Add(newWire,E);
	ne++;
      } // exe
      if (ne == 0) continue;
      Standard_Boolean closed = FUN_tool_ClosedW(newWire);
      //      BT.Closed(newWire,closed); 
      //      BT.AddFaceWire(newFace,newWire);
      newWire.Closed(closed);
      BB.Add(newFace,newWire);
    } // exw
    LOFF.Append(newFace);
  }
  return Standard_True;
}

/*static Handle(Geom2d_TrimmedCurve) FUN_translate(const gp_Vec2d& tvector, const TopoDS_Face& fF, TopoDS_Edge& fyE)
{
  Standard_Real f,l,tol; Handle(Geom2d_Curve) PC = FUNTOOLC2D_CurveOnSurface(fyE,fF,f,l,tol);
  Standard_Boolean isou,isov; gp_Pnt2d o2d; gp_Dir2d d2d;
  Standard_Boolean isouv = FUN_tool_IsUViso(PC,isou,isov,d2d,o2d); o2d.Translate(tvector);
  Handle(Geom2d_Line) L2d = new Geom2d_Line(o2d,d2d);
  Handle(Geom2d_TrimmedCurve) C2d = new Geom2d_TrimmedCurve(L2d,f,l);
  return C2d;
}
Standard_EXPORT void FUN_tool_ttranslate(const gp_Vec2d& tvector, const TopoDS_Face& fF, TopoDS_Edge& fyE)
{  
  Handle(Geom2d_TrimmedCurve) C2d = ::FUN_translate(tvector,fF,fyE);
  Standard_Real tole = BRep_Tool::Tolerance(fyE);
  BRep_Builder BB;
//  Handle(Geom2d_Curve) toclear; BB.UpdateEdge(fyE,toclear,fF,tole);
  BB.UpdateEdge(fyE,C2d,fF,tole);
}

static Standard_Boolean FUN_tool_translate(const gp_Vec2d& tvector, TopoDS_Face& fF, TopoDS_Edge& fyE)
     // prequesitory : <fF> is on periodic surface, translates edge 
     //  <fyE>'s uorviso to have its uorvpar bounded in [0.,2PI].
{
  Handle(Geom2d_TrimmedCurve) C2d = ::FUN_translate(tvector,fF,fyE);
  Standard_Real tole = BRep_Tool::Tolerance(fyE);
  
  //xpu040598 : CTS20280 f37 modified when its split is modified!
  TopoDS_Face newf; Standard_Boolean ok = FUN_tool_pcurveonF(fF,fyE,C2d,newf);
  if (ok) fF = newf;
  return ok;
  //xpu040598
}
*/