0022972: Eliminate macro definitions that has compiler-provided analogs (WNT and...
[occt.git] / src / TopOpeBRep / TopOpeBRep_FacesIntersector.cxx
1 // Created on: 1993-11-18
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1993-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
18 #include <Bnd_Box.hxx>
19 #include <BRepAdaptor_HSurface.hxx>
20 #include <BRepTopAdaptor_TopolTool.hxx>
21 #include <TopoDS_Shape.hxx>
22 #include <TopOpeBRep_FacesIntersector.hxx>
23 #include <TopOpeBRep_LineInter.hxx>
24
25 #ifdef DRAW
26 #include <TopOpeBRep_DRAW.hxx>
27 #endif
28
29 #include <IntPatch_LineConstructor.hxx>
30 #include <TopOpeBRep_TypeLineCurve.hxx>
31 #include <TopoDS.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <BRep_Tool.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopOpeBRepTool_ShapeTool.hxx>
37 #include <Precision.hxx>
38 #include <Geom_Curve.hxx>
39 #include <Standard_ProgramError.hxx>
40 #include <TCollection_AsciiString.hxx>
41 #include <Standard_CString.hxx>
42 #include <BRepTools.hxx>
43 #include <TopOpeBRepTool_tol.hxx>
44
45 Standard_EXPORT Standard_Real GLOBAL_tolFF = 1.e-7;
46
47 #ifdef OCCT_DEBUG
48 #include <TopAbs.hxx>
49 extern Standard_Boolean TopOpeBRep_GettraceFI();
50 extern Standard_Boolean TopOpeBRep_GettraceFITOL();
51 extern Standard_Boolean TopOpeBRep_GettraceSAVFF();
52
53 Standard_Integer SAVFFi1 = 0;
54 Standard_Integer SAVFFi2 = 0;
55 static void SAVFF(const TopoDS_Face& F1,const TopoDS_Face& F2)
56 {
57   TCollection_AsciiString an1("SAVA");if (SAVFFi1) an1=an1+SAVFFi1;
58   TCollection_AsciiString an2("SAVB");if (SAVFFi2) an2=an2+SAVFFi2;
59   Standard_CString n1=an1.ToCString();Standard_CString n2=an2.ToCString();
60 #ifdef DRAW
61   cout<<"FaceIntersector :   set "<<n1<<","<<n2<<endl;DBRep::Set(n1,F1);DBRep::Set(n2,F2);
62 #endif
63   cout<<"FaceIntersector : write "<<n1<<","<<n2<<endl;BRepTools::Write(F1,n1);BRepTools::Write(F2,n2); 
64 }
65
66 extern Standard_Boolean TopOpeBRepTool_GettraceKRO();
67 #include <TopOpeBRepTool_KRO.hxx>
68 Standard_EXPORT TOPKRO KRO_DSFILLER_INTFF("intersection face/face");
69
70 #endif
71
72 // NYI
73 // NYI : IntPatch_Intersection : TolArc,TolTang exact definition
74 // NYI
75
76
77 // modified by NIZHNY-MKK  Mon Apr  2 12:14:32 2001.BEGIN
78 #include <IntPatch_WLine.hxx>
79 #include <IntPatch_RLine.hxx>
80 #include <IntPatch_Point.hxx>
81 #include <Adaptor3d_HSurface.hxx>
82 #include <Adaptor3d_TopolTool.hxx>
83 #include <Adaptor3d_HVertex.hxx>
84 #include <Adaptor2d_HCurve2d.hxx>
85 #include <Geom2dInt_TheProjPCurOfGInter.hxx>
86
87 static Standard_Boolean TestWLineAlongRestriction(const Handle(IntPatch_WLine)& theWLine,
88                                                   const Standard_Integer                         theRank,
89                                                   const Handle(Adaptor3d_HSurface)&              theSurface,
90                                                   const Handle(Adaptor3d_TopolTool)&             theDomain,
91                                                   const Standard_Real                            theTolArc);
92
93 static 
94 Handle(IntPatch_RLine) BuildRLineBasedOnWLine(const Handle(IntPatch_WLine)& theWLine,
95                                                                const Handle(Adaptor2d_HCurve2d)&              theArc,
96                                                                const Standard_Integer                         theRank);
97
98 static
99 Handle(IntPatch_RLine) BuildRLine(const IntPatch_SequenceOfLine&     theSeqOfWLine,
100                                                    const Standard_Integer             theRank,
101                                                    const Handle(Adaptor3d_HSurface)&  theSurface,
102                                                    const Handle(Adaptor3d_TopolTool)& theDomain,
103                                                    const Standard_Real                theTolArc);
104
105 static void TestWLinesToAnArc(IntPatch_SequenceOfLine&           slin,
106                               const Handle(Adaptor3d_HSurface)&  theSurface1,
107                               const Handle(Adaptor3d_TopolTool)& theDomain1,
108                               const Handle(Adaptor3d_HSurface)&  theSurface2,
109                               const Handle(Adaptor3d_TopolTool)& theDomain2,
110                               const Standard_Real                theTolArc);
111 // modified by NIZHNY-MKK  Mon Apr  2 12:14:38 2001.END
112
113 // modified by NIZHNY-OFV  Fri Mar 29 12:37:21 2002.BEGIN
114 #include <TColgp_SequenceOfPnt.hxx>
115 #include <TopExp.hxx>
116 #include <TColStd_SequenceOfReal.hxx>
117 #include <Extrema_ExtPS.hxx>
118 #include <Extrema_ExtPC.hxx>
119 #include <Extrema_POnSurf.hxx>
120 #include <GeomAdaptor_Curve.hxx>
121 static void MergeWLinesIfAllSegmentsAlongRestriction(IntPatch_SequenceOfLine&           theSlin,
122                                                      const Handle(Adaptor3d_HSurface)&  theSurface1,
123                                                      const Handle(Adaptor3d_TopolTool)& theDomain1,
124                                                      const Handle(Adaptor3d_HSurface)&  theSurface2,
125                                                      const Handle(Adaptor3d_TopolTool)& theDomain2,
126                                                      const Standard_Real                theTolArc);
127 //------------------------------------------------------------------------------------------------
128 static Standard_Integer GetArc(IntPatch_SequenceOfLine&           theSlin,
129                                const Standard_Integer&            theRankS,
130                                const Handle(Adaptor3d_HSurface)&  theSurfaceObj,
131                                const Handle(Adaptor3d_TopolTool)& theDomainObj,
132                                const Handle(Adaptor3d_HSurface)&  theSurfaceTool,
133                                const gp_Pnt&                      theTestPoint,
134                                Standard_Real&                     theVrtxTol,
135                                Handle(IntSurf_LineOn2S)&          theLineOn2S,
136                                Standard_Real&                     theFirst,
137                                Standard_Real&                     theLast);
138 //------------------------------------------------------------------------------------------------
139 static Standard_Boolean IsPointOK(const gp_Pnt&            theTestPnt,
140                                   const Adaptor3d_Surface& theTestSurface,
141                                   const Standard_Real&     theTol);
142 //-------------------------------------------------------------------------------------------------
143 static Standard_Boolean GetPointOn2S(const gp_Pnt&            theTestPnt,
144                                      const Adaptor3d_Surface& theTestSurface,
145                                      const Standard_Real&     theTol,
146                                      Extrema_POnSurf&         theResultPoint);
147 //-------------------------------------------------------------------------------------------------------------------------
148 static Handle(IntPatch_WLine) GetMergedWLineOnRestriction(IntPatch_SequenceOfLine&           theSlin,
149                                                                            const Standard_Real&               theVrtxTol,
150                                                                            const Handle(IntSurf_LineOn2S)&    theLineOn2S);
151 //---------------------------------------------------------------------------------------------------------------------------
152 // modified by NIZHNY-OFV  Fri Mar 29 12:41:02 2002.END
153
154 //=======================================================================
155 //function : TopOpeBRep_FacesIntersector
156 //purpose  : 
157 //=======================================================================
158 TopOpeBRep_FacesIntersector::TopOpeBRep_FacesIntersector ()
159 {
160   ResetIntersection();
161   myTol1 = myTol2 = Precision::Confusion();
162   myForceTolerances = Standard_False;
163   mySurface1 = new BRepAdaptor_HSurface();
164   mySurface2 = new BRepAdaptor_HSurface();
165   myDomain1 = new BRepTopAdaptor_TopolTool();
166   myDomain2 = new BRepTopAdaptor_TopolTool();
167 }
168
169 //=======================================================================
170 //function : Perform
171 //purpose  : 
172 //=======================================================================
173 void TopOpeBRep_FacesIntersector::Perform(const TopoDS_Shape& F1,const TopoDS_Shape& F2,
174                                           const Bnd_Box& B1,const Bnd_Box& B2)
175 {
176 #ifdef OCCT_DEBUG
177   if (TopOpeBRep_GettraceSAVFF()) SAVFF(TopoDS::Face(F1),TopoDS::Face(F2));
178 #endif
179   
180   ResetIntersection();
181   if (!myForceTolerances) ShapeTolerances(F1,F2);
182   
183   myFace1 = TopoDS::Face(F1); myFace1.Orientation(TopAbs_FORWARD);
184   myFace2 = TopoDS::Face(F2); myFace2.Orientation(TopAbs_FORWARD);
185   BRepAdaptor_Surface& S1 = mySurface1->ChangeSurface(); S1.Initialize(myFace1);
186   BRepAdaptor_Surface& S2 = mySurface2->ChangeSurface(); S2.Initialize(myFace2);
187   mySurfaceType1 = S1.GetType();
188   mySurfaceType2 = S2.GetType();
189   const Handle(Adaptor3d_HSurface)& aSurf1 = mySurface1; // to avoid ambiguity
190   myDomain1->Initialize(aSurf1);
191   const Handle(Adaptor3d_HSurface)& aSurf2 = mySurface2; // to avoid ambiguity
192   myDomain2->Initialize(aSurf2);
193
194 #ifdef OCCT_DEBUG
195   if (TopOpeBRepTool_GettraceKRO()) KRO_DSFILLER_INTFF.Start();
196 #endif
197
198   Standard_Real Deflection=0.01,MaxUV=0.01;
199   if (!myForceTolerances) {
200     FTOL_FaceTolerances3d(B1,B2,myFace1,myFace2,S1,S2,
201                                 myTol1,myTol2,Deflection,MaxUV);  
202     myTol1 = (myTol1 > 1.e-4)? 1.e-4: myTol1;
203     myTol2 = (myTol2 > 1.e-4)? 1.e-4: myTol2;
204   }
205   
206   Standard_Real tol1 = myTol1;
207   Standard_Real tol2 = myTol2;
208   GLOBAL_tolFF = Max(tol1,tol2);
209
210 #ifdef OCCT_DEBUG
211   if (TopOpeBRep_GettraceFITOL()) {
212     cout<<"FacesIntersector : Perform tol1 = "<<tol1<<endl;
213     cout<<"                           tol2 = "<<tol2<<endl;
214     cout<<"                           defl = "<<Deflection<<"  MaxUV = "<<MaxUV<<endl;
215   }
216 #endif
217
218   myIntersector.SetTolerances(myTol1,myTol2,MaxUV,Deflection); 
219   myIntersector.Perform(mySurface1,myDomain1,mySurface2,myDomain2,
220                         myTol1,myTol2,Standard_True,Standard_True);
221
222 #ifdef OCCT_DEBUG
223   if (TopOpeBRepTool_GettraceKRO()) KRO_DSFILLER_INTFF.Stop();
224 #endif
225
226   //xpu180998 : cto900Q1
227   Standard_Boolean done = myIntersector.IsDone();
228   if (!done) return;
229
230   PrepareLines();
231   myIntersectionDone = Standard_True;
232
233   // mySurfacesSameOriented : a mettre dans IntPatch NYI
234   if ( SameDomain() ) {
235     mySurfacesSameOriented = TopOpeBRepTool_ShapeTool::SurfacesSameOriented(S1,S2);
236   }
237
238   // build the map of edges found as RESTRICTION
239   for (InitLine(); MoreLine(); NextLine()) {
240     TopOpeBRep_LineInter& L = CurrentLine();
241     if (L.TypeLineCurve() == TopOpeBRep_RESTRICTION) {
242       const TopoDS_Shape& E = L.Arc();
243       myEdgeRestrictionMap.Add(E);
244     }
245   }
246   
247 #ifdef OCCT_DEBUG
248   if (TopOpeBRep_GettraceFI()) cout<<"Perform : isempty "<<IsEmpty()<<endl;
249 #endif
250 }
251
252 //=======================================================================
253 //function : Perform
254 //purpose  : 
255 //=======================================================================
256
257 void TopOpeBRep_FacesIntersector::Perform(const TopoDS_Shape& F1,const TopoDS_Shape& F2)
258 {
259   Bnd_Box B1,B2;
260   Perform(F1,F2,B1,B2);
261 }
262
263
264 //=======================================================================
265 //function : IsEmpty
266 //purpose  : 
267 //=======================================================================
268
269 Standard_Boolean TopOpeBRep_FacesIntersector::IsEmpty () 
270 {
271   if ( ! myIntersectionDone ) return Standard_False;
272   Standard_Boolean done  = myIntersector.IsDone();
273   Standard_Boolean empty = myIntersector.IsEmpty();
274   if ( !done || empty ) return Standard_True;
275   else {
276     // ElemIntersector is done and is not empty
277     // returns True if at least one VPoint is found
278     empty = Standard_True;
279     for ( InitLine(); MoreLine(); NextLine() ) {
280       empty = (CurrentLine().NbVPoint() == 0);
281       if ( ! empty ) break;
282     }
283     return empty;
284   }
285 }
286
287 //=======================================================================
288 //function : IsDone
289 //purpose  : 
290 //=======================================================================
291
292 Standard_Boolean TopOpeBRep_FacesIntersector::IsDone () const
293 {
294   return myIntersectionDone;
295 }
296
297 //=======================================================================
298 //function : SameDomain
299 //purpose  : 
300 //=======================================================================
301
302 Standard_Boolean TopOpeBRep_FacesIntersector::SameDomain () const 
303 {
304   if (!myIntersectionDone) 
305     Standard_ProgramError::Raise("FacesIntersector : bad SameDomain");
306
307   Standard_Boolean sd = myIntersector.TangentFaces();
308
309   //Standard_Boolean plpl = (mySurfaceType1 == GeomAbs_Plane) && (mySurfaceType2 == GeomAbs_Plane);
310
311 //  if (!plpl) return Standard_False;
312   return sd;
313 }
314
315
316 //=======================================================================
317 //function : Face
318 //purpose  : 
319 //=======================================================================
320
321 const TopoDS_Shape& TopOpeBRep_FacesIntersector::Face
322 (const Standard_Integer Index) const 
323 {
324   if      ( Index == 1 ) return myFace1;
325   else if ( Index == 2 ) return myFace2;
326   else Standard_ProgramError::Raise("TopOpeBRep_FacesIntersector::Face");
327
328   return myNullShape;
329 }
330
331
332 //=======================================================================
333 //function : SurfacesSameOriented
334 //purpose  : 
335 //=======================================================================
336
337 Standard_Boolean TopOpeBRep_FacesIntersector::SurfacesSameOriented () const
338 {
339   if ( SameDomain() ) {
340     return mySurfacesSameOriented;
341   }
342   Standard_ProgramError::Raise("FacesIntersector : bad SurfacesSameOriented");
343   return Standard_False;
344 }
345
346 //=======================================================================
347 //function : IsRestriction
348 //purpose  : 
349 //=======================================================================
350
351 Standard_Boolean TopOpeBRep_FacesIntersector::IsRestriction
352    (const TopoDS_Shape& E) const
353 {
354   Standard_Boolean isrest = myEdgeRestrictionMap.Contains(E);
355   return isrest;
356 }
357
358 //=======================================================================
359 //function : Restrictions
360 //purpose  : 
361 //=======================================================================
362
363 const TopTools_IndexedMapOfShape& TopOpeBRep_FacesIntersector::Restrictions 
364    () const 
365 {
366   return myEdgeRestrictionMap;
367 }
368
369 //=======================================================================
370 //function : PrepareLines
371 //purpose  : 
372 //=======================================================================
373
374 void  TopOpeBRep_FacesIntersector::PrepareLines()
375 {
376   myLineNb = 0;
377   Standard_Integer n = myIntersector.NbLines();
378   myHAL = new TopOpeBRep_HArray1OfLineInter(0,n); 
379   BRepAdaptor_Surface& S1 = *((BRepAdaptor_Surface*)&(mySurface1->Surface()));
380   BRepAdaptor_Surface& S2 = *((BRepAdaptor_Surface*)&(mySurface2->Surface()));
381
382   // modified by NIZHNY-MKK  Mon Apr  2 12:14:58 2001.BEGIN
383   if(n==0)
384     return;
385   // modified by NIZHNY-MKK  Mon Apr  2 12:15:09 2001.END
386
387   Standard_Boolean newV = Standard_True;
388
389   if (!newV) {
390   /*for (  Standard_Integer i=1; i<=n; i++) {
391     TopOpeBRep_LineInter& LI = myHAL->ChangeValue(i);
392     const Handle(IntPatch_Line)& L = myIntersector.Line(i);
393     LI.SetLine(L,S1,S2);
394     LI.Index(i);
395     myLineNb++;;
396   }*/}
397
398   if (newV) {
399     //-- lbr
400
401     // modified by NIZHNY-MKK  Mon Apr  2 12:16:04 2001
402     IntPatch_SequenceOfLine aSeqOfLines, aSeqOfResultLines;
403
404     Standard_Integer i ;
405 //    Standard_Integer nbl=0;
406     IntPatch_LineConstructor **Ptr = 
407       (IntPatch_LineConstructor **)malloc(n*sizeof(IntPatch_LineConstructor *));
408     for( i=1;i<=n;i++) { 
409       Ptr[i-1]=new IntPatch_LineConstructor(2);
410       Ptr[i-1]->Perform(myIntersector.SequenceOfLine(),
411                         myIntersector.Line(i),
412                         mySurface1,myDomain1,
413                         mySurface2,myDomain2,
414                         myTol1);
415       // modified by NIZHNY-MKK  Mon Apr  2 12:16:26 2001.BEGIN
416       aSeqOfLines.Clear();
417       for(Standard_Integer k=1; k<=Ptr[i-1]->NbLines(); k++) {
418         aSeqOfLines.Append(Ptr[i-1]->Line(k));
419       }
420
421       TestWLinesToAnArc(aSeqOfLines, mySurface1, myDomain1, mySurface2, myDomain2, myTol1);
422
423       for(Standard_Integer j=1; j<=aSeqOfLines.Length(); j++) {
424         aSeqOfResultLines.Append(aSeqOfLines.Value(j));
425       }
426       delete Ptr[i-1];      
427       //       nbl+=Ptr[i-1]->NbLines();
428       // modified by NIZHNY-MKK  Mon Apr  2 12:16:31 2001.END
429     }
430
431     // modified by NIZHNY-MKK  Mon Apr  2 12:17:22 2001.BEGIN
432     //     myHAL = new TopOpeBRep_HArray1OfLineInter(0,nbl); 
433     myLineNb = aSeqOfResultLines.Length();
434  
435     //Fun_ConvertWLinesToRLine(aSeqOfResultLines,mySurface1, myDomain1, mySurface2, myDomain2, myTol1);
436     MergeWLinesIfAllSegmentsAlongRestriction(aSeqOfResultLines,mySurface1, myDomain1, mySurface2, myDomain2, myTol1);
437     myLineNb = aSeqOfResultLines.Length();
438
439
440     if(myLineNb > 0) {
441       myHAL = new TopOpeBRep_HArray1OfLineInter(1, myLineNb); 
442       for(Standard_Integer index = 1; index <= myLineNb; index++) {
443         TopOpeBRep_LineInter& LI = myHAL->ChangeValue(index);
444         const Handle(IntPatch_Line)& L = aSeqOfResultLines.Value(index);
445         LI.SetLine(L,S1,S2);
446         LI.Index(index);
447       }
448     }
449     
450     //     nbl=1;
451     //     for(i=1;i<=n;i++) { 
452     //       for(Standard_Integer k=1;k<=Ptr[i-1]->NbLines();k++) {
453     //  TopOpeBRep_LineInter& LI = myHAL->ChangeValue(nbl);
454     //  const Handle(IntPatch_Line)& L = Ptr[i-1]->Line(k);
455     //  LI.SetLine(L,S1,S2);
456     //  LI.Index(nbl);
457     //  myLineNb++;
458     //  nbl++;
459     //       }
460     //       delete Ptr[i-1];
461     //     }
462     // modified by NIZHNY-MKK  Mon Apr  2 12:17:57 2001.END
463     free(Ptr);
464   }
465 }
466
467 //=======================================================================
468 //function : Lines
469 //purpose  : 
470 //=======================================================================
471
472 Handle(TopOpeBRep_HArray1OfLineInter) TopOpeBRep_FacesIntersector::Lines()
473 {
474   return myHAL;
475 }
476
477 //=======================================================================
478 //function : NbLines
479 //purpose  : 
480 //=======================================================================
481
482 Standard_Integer TopOpeBRep_FacesIntersector::NbLines()const
483 {
484   return myLineNb;
485 }
486
487 //=======================================================================
488 //function : InitLine
489 //purpose  : 
490 //=======================================================================
491
492 void  TopOpeBRep_FacesIntersector::InitLine()
493 {
494   myLineIndex = 1;
495   FindLine();
496 }
497
498 //=======================================================================
499 //function : FindLine
500 //purpose  : 
501 //=======================================================================
502
503 void  TopOpeBRep_FacesIntersector::FindLine()
504 {
505   myLineFound = Standard_False;
506   if ( ! myIntersectionDone ) return;
507
508   while (myLineIndex <= myLineNb) {
509     const TopOpeBRep_LineInter& L = myHAL->Value(myLineIndex);
510     myLineFound = L.OK();
511     if (myLineFound) break;
512     else myLineIndex++;
513   }
514 }
515
516 //=======================================================================
517 //function : MoreLine
518 //purpose  : 
519 //=======================================================================
520
521 Standard_Boolean  TopOpeBRep_FacesIntersector::MoreLine()const 
522 {
523   return myLineFound;
524 }
525
526
527 //=======================================================================
528 //function : NextLine
529 //purpose  : 
530 //=======================================================================
531
532 void  TopOpeBRep_FacesIntersector::NextLine()
533 {
534   myLineIndex++;
535   FindLine();
536 }
537
538 //=======================================================================
539 //function : CurrentLine
540 //purpose  : 
541 //=======================================================================
542
543 TopOpeBRep_LineInter& TopOpeBRep_FacesIntersector::CurrentLine()
544 {
545   TopOpeBRep_LineInter& TLI = myHAL->ChangeValue(myLineIndex);
546   return TLI;
547 }
548
549
550 //=======================================================================
551 //function : CurrentLineIndex
552 //purpose  : 
553 //=======================================================================
554
555 Standard_Integer TopOpeBRep_FacesIntersector::CurrentLineIndex()const
556 {
557   return myLineIndex;
558 }
559
560 //=======================================================================
561 //function : Line
562 //purpose  : 
563 //=======================================================================
564
565 TopOpeBRep_LineInter& TopOpeBRep_FacesIntersector::ChangeLine(const Standard_Integer IL)
566 {
567   TopOpeBRep_LineInter& TLI = myHAL->ChangeValue(IL);
568   return TLI;
569 }
570
571 //=======================================================================
572 //function : ResetIntersection
573 //purpose  : 
574 //=======================================================================
575
576 void TopOpeBRep_FacesIntersector::ResetIntersection() 
577 {
578   myIntersectionDone = Standard_False;
579   myLineIndex = 1;
580   myLineNb = 0;
581   myEdgeRestrictionMap.Clear();
582   myLineFound = Standard_False;
583 }
584
585
586 //=======================================================================
587 //function : ForceTolerances
588 //purpose  : 
589 //=======================================================================
590
591 void TopOpeBRep_FacesIntersector::ForceTolerances(const Standard_Real Tol1,
592                                                   const Standard_Real Tol2)
593 {
594   myTol1 = Tol1;
595   myTol2 = Tol2;  
596   myForceTolerances = Standard_True;
597 #ifdef OCCT_DEBUG
598   if (TopOpeBRep_GettraceFITOL())
599     cout<<"ForceTolerances : myTol1,myTol2 = "<<myTol1<<","<<myTol2<<endl;
600 #endif
601 }
602
603 //=======================================================================
604 //function : GetTolerances
605 //purpose  : 
606 //=======================================================================
607
608 void TopOpeBRep_FacesIntersector::GetTolerances(Standard_Real& Tol1,
609                                                 Standard_Real& Tol2) const
610 {
611   Tol1 = myTol1;
612   Tol2 = myTol2;
613 }
614
615 //=======================================================================
616 //function : ShapeTolerances
617 //purpose  : (private)
618 //=======================================================================
619
620 #ifdef OCCT_DEBUG
621 void TopOpeBRep_FacesIntersector::ShapeTolerances(const TopoDS_Shape& S1,
622                                                   const TopoDS_Shape& S2)
623 #else
624 void TopOpeBRep_FacesIntersector::ShapeTolerances(const TopoDS_Shape& ,
625                                                   const TopoDS_Shape& )
626 #endif
627 {
628 //  myTol1 = Max(ToleranceMax(S1,TopAbs_EDGE),ToleranceMax(S2,TopAbs_EDGE));
629   myTol1 = Precision::Confusion();
630   myTol2 = myTol1;  
631   myForceTolerances = Standard_False;
632 #ifdef OCCT_DEBUG
633   if (TopOpeBRep_GettraceFITOL()) {
634     cout<<"ShapeTolerances on S1 = ";TopAbs::Print(S1.ShapeType(),cout);
635     cout<<" S2 = ";TopAbs::Print(S2.ShapeType(),cout);
636     cout<<" : myTol1,myTol2 = "<<myTol1<<","<<myTol2<<endl;
637   }
638 #endif
639 }
640
641 //=======================================================================
642 //function : ToleranceMax
643 //purpose  : (private)
644 //=======================================================================
645
646 Standard_Real TopOpeBRep_FacesIntersector::ToleranceMax
647 (const TopoDS_Shape& S,const TopAbs_ShapeEnum T) const
648 {
649   TopExp_Explorer e(S,T);
650   if ( ! e.More() ) return Precision::Intersection();
651   else {
652     Standard_Real tol = RealFirst();
653     for (; e.More(); e.Next())
654       tol = Max(tol,TopOpeBRepTool_ShapeTool::Tolerance(e.Current()));
655     return tol;
656   }
657 }
658
659
660 // modified by NIZHNY-MKK  Mon Apr  2 12:18:30 2001.BEGIN
661 // ================================================================================================
662 // static function: TestWLineAlongRestriction
663 // purpose:
664 // ================================================================================================
665 static Standard_Boolean TestWLineAlongRestriction(const Handle(IntPatch_WLine)& theWLine,
666                                                   const Standard_Integer                         theRank,
667                                                   const Handle(Adaptor3d_HSurface)&              theSurface,
668                                                   const Handle(Adaptor3d_TopolTool)&             theDomain,
669                                                   const Standard_Real                            theTolArc) {
670
671   Standard_Boolean result = Standard_False; 
672   Standard_Integer NbPnts = theWLine->NbPnts();  
673   Standard_Integer along = 0;
674
675   for(Standard_Integer i=1; i<=NbPnts; i++) {
676     const IntSurf_PntOn2S& Pmid = theWLine->Point(i);
677     Standard_Real u=0., v=0.;
678     if(theRank==1) Pmid.ParametersOnS1(u, v);
679     else Pmid.ParametersOnS2(u, v);
680     //------------------------------------------
681     gp_Pnt ap;
682     gp_Vec ad1u, ad1v;
683     //Standard_Real nad1u, nad1v, tolu, tolv;
684     
685     theSurface->D1(u, v, ap, ad1u, ad1v);
686     //nad1u=ad1u.Magnitude();
687     //nad1v=ad1v.Magnitude();
688     //if(nad1u>1e-12) tolu=theTolArc/nad1u; else tolu=0.1;
689     //if(nad1v>1e-12) tolv=theTolArc/nad1v; else tolv=0.1;
690     //if(tolu>tolv)  tolu=tolv;
691     //------------------------------------------
692     
693     //if(theDomain->IsThePointOn(gp_Pnt2d(u, v),tolu)) {
694     //  along++;
695     //}
696
697     if(theDomain->IsThePointOn(gp_Pnt2d(u, v),theTolArc)) along++;
698     //if(along!=i) break;
699   }
700   if(along==NbPnts) result = Standard_True;
701   return result;
702 }
703
704
705 // ================================================================================================
706 // static function: BuildRLineBasedOnWLine
707 // purpose: 
708 // ================================================================================================
709 static 
710 Handle(IntPatch_RLine) BuildRLineBasedOnWLine(const Handle(IntPatch_WLine)& theWLine,
711                                                                const Handle(Adaptor2d_HCurve2d)&              theArc,
712                                                                const Standard_Integer                         theRank) {
713   Handle(IntPatch_RLine) anRLine;
714
715   if((theRank != 1) && (theRank != 2))
716     return anRLine;
717
718   gp_Pnt2d aPOnLine;
719   Standard_Real u=0., v=0.;
720   Standard_Integer nbvtx = theWLine->NbVertex();
721   const IntPatch_Point& Vtx1 = theWLine->Vertex(1);
722   const IntPatch_Point& Vtx2 = theWLine->Vertex(nbvtx);
723   
724   if(theRank == 1) {
725     Vtx1.ParametersOnS1(u, v);
726   }
727   else {
728     Vtx1.ParametersOnS2(u, v);
729   }
730   
731   aPOnLine = gp_Pnt2d(u, v);
732   Standard_Real par1 = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), aPOnLine, 1.e-7);
733   
734   if(theRank == 1) {
735     Vtx2.ParametersOnS1(u, v);
736   }
737   else {
738     Vtx2.ParametersOnS2(u, v);
739   }
740   aPOnLine = gp_Pnt2d(u, v);
741   Standard_Real par2 = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), aPOnLine, 1.e-7);
742
743   Standard_Real tol = (Vtx1.Tolerance() > Vtx2.Tolerance()) ? Vtx1.Tolerance() : Vtx2.Tolerance();
744
745   if(Abs(par1 - par2) < theArc->Resolution(tol))
746     return anRLine;
747
748   Standard_Boolean IsOnFirst = (theRank == 1);
749
750   Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
751   const Handle(IntSurf_LineOn2S)& Lori = theWLine->Curve();
752   IntSurf_Transition TransitionUndecided;
753   
754   anRLine = new IntPatch_RLine(Standard_False, theWLine->TransitionOnS1(), theWLine->TransitionOnS2());
755
756   if(IsOnFirst) {
757     anRLine->SetArcOnS1(theArc);
758   }
759   else {
760     anRLine->SetArcOnS2(theArc);
761   }
762   
763   Standard_Integer k = 0;
764   if(par1 < par2) {
765
766     for(k = 1; k <= Lori->NbPoints(); k++) { 
767       aLineOn2S->Add(Lori->Value(k));
768     }
769     anRLine->Add(aLineOn2S);
770     IntPatch_Point VtxFirst = Vtx1;
771     
772     VtxFirst.SetArc(IsOnFirst, //-- On First
773                     theArc,
774                     par1,
775                     TransitionUndecided,
776                     TransitionUndecided);
777     VtxFirst.SetParameter(par1);
778     anRLine->AddVertex(VtxFirst);
779     
780     for(k = 2; k < nbvtx; k++) { 
781       IntPatch_Point Vtx = theWLine->Vertex(k);
782       if(theRank == 1) {
783         Vtx.ParametersOnS1(u, v);
784       }
785       else {
786         Vtx.ParametersOnS2(u, v);
787       }
788       gp_Pnt2d atmpPoint(u, v);
789       Standard_Real apar = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), atmpPoint, 1.e-7);
790       Vtx.SetParameter(apar);
791       anRLine->AddVertex(Vtx);
792     }
793     
794     IntPatch_Point VtxLast = Vtx2;
795     VtxLast.SetArc(IsOnFirst, //-- On First
796                    theArc,
797                    par2,
798                    TransitionUndecided,
799                    TransitionUndecided);
800     VtxLast.SetParameter(par2);
801     anRLine->AddVertex(VtxLast);
802     anRLine->SetFirstPoint(1);
803     anRLine->SetLastPoint(nbvtx);
804     anRLine->ComputeVertexParameters(Precision::Confusion());
805   }
806   else {
807
808     for(k = Lori->NbPoints(); k >= 1; k--) { 
809       aLineOn2S->Add(Lori->Value(k));
810     }
811     anRLine->Add(aLineOn2S);
812
813     IntPatch_Point VtxFirst = Vtx2;
814     VtxFirst.SetArc(IsOnFirst, //-- On First
815                     theArc,
816                     par2,
817                     TransitionUndecided,
818                     TransitionUndecided);
819     VtxFirst.SetParameter(par2);
820     anRLine->AddVertex(VtxFirst);
821
822     for(k = nbvtx - 1; k >= 2; k--) { 
823       IntPatch_Point Vtx = theWLine->Vertex(k);
824       Vtx.ReverseTransition();
825       if(theRank == 1) {
826         Vtx.ParametersOnS1(u, v);
827       }
828       else {
829         Vtx.ParametersOnS2(u, v);
830       }
831       gp_Pnt2d atmpPoint(u, v);
832       Standard_Real apar = Geom2dInt_TheProjPCurOfGInter::FindParameter(theArc->Curve2d(), atmpPoint, 1.e-7);
833       Vtx.SetParameter(apar);
834       anRLine->AddVertex(Vtx);
835     }
836     IntPatch_Point VtxLast = Vtx1;
837     VtxLast.SetArc(IsOnFirst, //-- On First
838                    theArc,
839                    par1,
840                    TransitionUndecided,
841                    TransitionUndecided);
842     VtxLast.SetParameter(par1);
843     anRLine->AddVertex(VtxLast);
844     anRLine->SetFirstPoint(1);
845     anRLine->SetLastPoint(nbvtx);
846     anRLine->ComputeVertexParameters(Precision::Confusion());
847   }
848
849   return anRLine;
850 }
851
852 // ================================================================================================
853 // static function: BuildRLine
854 // purpose: build rline based on group of wlines
855 //          return null handle if it is not possible to build rline
856 // ================================================================================================
857 static
858 Handle(IntPatch_RLine) BuildRLine(const IntPatch_SequenceOfLine&     theSeqOfWLine, 
859                                                    const Standard_Integer             theRank,
860                                                    const Handle(Adaptor3d_HSurface)&  theSurface,
861                                                    const Handle(Adaptor3d_TopolTool)& theDomain,
862                                                    const Standard_Real                theTolArc) {
863   Handle(IntPatch_RLine) anRLine;
864   const Handle(IntPatch_WLine)& aWLine1 = *((Handle(IntPatch_WLine) *)& (theSeqOfWLine.Value(1)));
865   const Handle(IntPatch_WLine)& aWLine2 = *((Handle(IntPatch_WLine) *)& (theSeqOfWLine.Value(theSeqOfWLine.Length())));
866   const IntPatch_Point& P1 = aWLine1->Vertex(1);
867   const IntPatch_Point& P2 = aWLine2->Vertex(aWLine2->NbVertex());
868   const Handle(Adaptor3d_HVertex)& aV1 = (theRank==1) ? P1.VertexOnS1() : P1.VertexOnS2();
869   const Handle(Adaptor3d_HVertex)& aV2 = (theRank==1) ? P2.VertexOnS1() : P2.VertexOnS2();
870
871   // avoid closed and degenerated edges
872   if(aV1->IsSame(aV2))
873     return anRLine;
874
875   for(theDomain->Init(); theDomain->More(); theDomain->Next()) {
876     theDomain->Initialize(theDomain->Value());
877     Standard_Boolean foundVertex1 = Standard_False;
878     Standard_Boolean foundVertex2 = Standard_False;
879
880     for(theDomain->InitVertexIterator(); (!foundVertex1 || !foundVertex2) && theDomain->MoreVertex(); theDomain->NextVertex()) {
881
882       if(!foundVertex1 && aV1->IsSame(theDomain->Vertex()))
883         foundVertex1 = Standard_True;
884       if(!foundVertex2 && aV2->IsSame(theDomain->Vertex()))
885           foundVertex2 = Standard_True;
886     }
887
888     if(foundVertex1 && foundVertex2) {
889       Standard_Boolean buildrline = (theSeqOfWLine.Length() > 0);
890
891       for(Standard_Integer i = 1; buildrline && i<=theSeqOfWLine.Length(); i++) {
892         const Handle(IntPatch_WLine)& aWLine = 
893           *((Handle(IntPatch_WLine) *)& (theSeqOfWLine.Value(i)));
894
895         Standard_Integer indexpnt = aWLine->NbPnts()/2;
896         if(indexpnt < 1)
897           buildrline = Standard_False;
898         else {    
899           Standard_Real u = RealLast(), v = RealLast();
900           const IntSurf_PntOn2S& POn2S = aWLine->Point(indexpnt);
901           if(theRank==1) {
902             POn2S.ParametersOnS1(u, v);
903           }
904           else {
905             POn2S.ParametersOnS2(u, v);
906           }
907           gp_Pnt2d aPOnArc, aPOnLine(u, v);
908           Standard_Real par = Geom2dInt_TheProjPCurOfGInter::FindParameter(theDomain->Value()->Curve2d(), aPOnLine, 1e-7);
909           aPOnArc = theDomain->Value()->Value(par);
910           gp_Pnt ap;
911           gp_Vec ad1u, ad1v;
912           Standard_Real nad1u, nad1v, tolu, tolv;         
913
914           theSurface->D1(u, v, ap, ad1u, ad1v);
915           nad1u=ad1u.Magnitude();
916           nad1v=ad1v.Magnitude();
917           if(nad1u>1e-12) tolu=theTolArc/nad1u; else tolu=0.1;
918           if(nad1v>1e-12) tolv=theTolArc/nad1v; else tolv=0.1;
919           Standard_Real aTolerance  = (tolu > tolv) ? tolv : tolu;
920           
921           if(aPOnArc.Distance(aPOnLine) > aTolerance) {
922             buildrline = Standard_False;
923           }
924         }
925       } //end for
926       
927       if(buildrline) {
928         IntSurf_TypeTrans trans1 = IntSurf_Undecided, trans2 = IntSurf_Undecided;
929
930         Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
931
932         for(Standard_Integer j = 1; j<=theSeqOfWLine.Length(); j++) {
933           const Handle(IntPatch_WLine)& atmpWLine = 
934             *((Handle(IntPatch_WLine) *)& (theSeqOfWLine.Value(j)));
935
936           const Handle(IntSurf_LineOn2S)& Lori = atmpWLine->Curve();
937           
938           if(atmpWLine->TransitionOnS1()!=IntSurf_Undecided && atmpWLine->TransitionOnS1()!=IntSurf_Touch) {
939             trans1 = atmpWLine->TransitionOnS1();
940           }
941           if(atmpWLine->TransitionOnS2()!=IntSurf_Undecided && atmpWLine->TransitionOnS2()!=IntSurf_Touch) {
942             trans2 = atmpWLine->TransitionOnS2();
943           }
944
945           Standard_Integer ParamMinOnLine = (Standard_Integer) atmpWLine->Vertex(1).ParameterOnLine();
946           Standard_Integer ParamMaxOnLine = (Standard_Integer) atmpWLine->Vertex(atmpWLine->NbVertex()).ParameterOnLine();
947
948           for(Standard_Integer k = ParamMinOnLine; k <= ParamMaxOnLine; k++) { 
949             aLineOn2S->Add(Lori->Value(k));
950           }
951         }
952
953         Handle(IntPatch_WLine) emulatedWLine = 
954           new IntPatch_WLine(aLineOn2S, Standard_False, trans1, trans2);
955
956         IntPatch_Point aFirstVertex = P1;
957         IntPatch_Point aLastVertex  = P2;
958         aFirstVertex.SetParameter(1);
959         aLastVertex.SetParameter(aLineOn2S->NbPoints());
960
961         emulatedWLine->AddVertex(aFirstVertex);
962         Standard_Integer apointindex = 0;
963
964         for(apointindex = 2; apointindex <= aWLine1->NbVertex(); apointindex++) {
965           IntPatch_Point aPoint = aWLine1->Vertex(apointindex);
966           Standard_Real aTolerance = (aPoint.Tolerance() > P1.Tolerance()) ? aPoint.Tolerance() : P1.Tolerance();
967           if(aPoint.Value().IsEqual(P1.Value(), aTolerance)) {
968             aPoint.SetParameter(1);
969             emulatedWLine->AddVertex(aPoint);
970           }
971         }
972         
973         for(apointindex = 1; apointindex < aWLine2->NbVertex(); apointindex++) {
974           IntPatch_Point aPoint = aWLine2->Vertex(apointindex);
975           Standard_Real aTolerance = (aPoint.Tolerance() > P2.Tolerance()) ? aPoint.Tolerance() : P2.Tolerance();
976           if(aPoint.Value().IsEqual(P2.Value(), aTolerance)) {
977             aPoint.SetParameter(aLineOn2S->NbPoints());
978             emulatedWLine->AddVertex(aPoint);
979           }
980         }
981
982         emulatedWLine->AddVertex(aLastVertex);
983
984         anRLine = BuildRLineBasedOnWLine(emulatedWLine, theDomain->Value(), theRank);
985         
986         break;
987       }
988     }
989   } //end for
990   
991   return anRLine;
992 }
993
994 // ================================================================================================
995 // static function: TestWLinesToAnArc
996 // purpose: test if possible to replace group of wlines by rline and replace in the sequence slin
997 // ================================================================================================
998 static void TestWLinesToAnArc(IntPatch_SequenceOfLine&           slin,
999                               const Handle(Adaptor3d_HSurface)&  theSurface1,
1000                               const Handle(Adaptor3d_TopolTool)& theDomain1,
1001                               const Handle(Adaptor3d_HSurface)&  theSurface2,
1002                               const Handle(Adaptor3d_TopolTool)& theDomain2,
1003                               const Standard_Real                theTolArc) { 
1004
1005   IntPatch_SequenceOfLine aSeqOfWLine;
1006   IntPatch_SequenceOfLine aSeqOfRLine;
1007   for(Standard_Integer rank = 1; rank <= 2; rank++) {
1008     for(Standard_Integer i=1; i<=slin.Length(); i++) {
1009       if(slin.Value(i)->ArcType()!=IntPatch_Walking)
1010         continue;
1011       const Handle(IntPatch_WLine)& aWLine = *((Handle(IntPatch_WLine) *)& (slin.Value(i)));
1012       Standard_Integer nbvtx = aWLine->NbVertex();
1013       const IntPatch_Point& Vtx1 = aWLine->Vertex(1);
1014       const IntPatch_Point& Vtx2 = aWLine->Vertex(nbvtx);
1015       Standard_Boolean isvertex = Standard_False, wlineWasAppended = Standard_False;
1016
1017
1018       if(rank==1)
1019         isvertex = Vtx1.IsVertexOnS1();
1020       else
1021         isvertex = Vtx1.IsVertexOnS2();
1022
1023       if(isvertex) {
1024         Standard_Boolean appendwline = Standard_True;
1025         if(rank==1) {
1026           if(!aWLine->HasArcOnS1() && !TestWLineAlongRestriction(aWLine, rank, theSurface1, theDomain1, theTolArc)) {       
1027             appendwline = Standard_False;
1028           }
1029         }
1030         if(rank==2) {
1031           if(!aWLine->HasArcOnS2() && !TestWLineAlongRestriction(aWLine, rank, theSurface2, theDomain2, theTolArc)) {
1032             appendwline = Standard_False;
1033           }
1034         }
1035         wlineWasAppended = appendwline;
1036         if(appendwline)
1037           aSeqOfWLine.Append(aWLine);
1038       }
1039       else {
1040         if(aSeqOfWLine.Length()==0)
1041           continue;
1042         const Handle(IntPatch_WLine)& aLastWLine = 
1043           *((Handle(IntPatch_WLine) *)& (aSeqOfWLine.Value(aSeqOfWLine.Length())));
1044         const IntPatch_Point& aLastPoint = aLastWLine->Vertex(aLastWLine->NbVertex());
1045         Standard_Real aTolerance = (aLastPoint.Tolerance() > Vtx1.Tolerance()) ? aLastPoint.Tolerance() : Vtx1.Tolerance();
1046         if(aLastPoint.Value().IsEqual(Vtx1.Value(), aTolerance)) {
1047           Standard_Boolean appendwline = Standard_True;
1048           if(rank==1) {
1049             if(!aWLine->HasArcOnS1() && !TestWLineAlongRestriction(aWLine, rank, theSurface1, theDomain1, theTolArc)) {     
1050               appendwline = Standard_False;
1051             }
1052           }
1053           if(rank==2) {
1054             if(!aWLine->HasArcOnS2() && !TestWLineAlongRestriction(aWLine, rank, theSurface2, theDomain2, theTolArc)) {
1055               appendwline = Standard_False;
1056             }
1057           }
1058           wlineWasAppended = appendwline;
1059           if(appendwline)
1060             aSeqOfWLine.Append(aWLine);   
1061         }
1062         else {
1063           aSeqOfWLine.Clear();
1064         }
1065       }
1066
1067       isvertex = Standard_False;
1068       if(rank==1)
1069         isvertex = Vtx2.IsVertexOnS1();
1070       else
1071         isvertex = Vtx2.IsVertexOnS2();
1072
1073       if(wlineWasAppended && isvertex) {
1074         // build rline based on sequence of wlines.
1075         Handle(IntPatch_RLine) anRLine;
1076         if(rank==1) {
1077           anRLine = BuildRLine(aSeqOfWLine, rank, theSurface1, theDomain1, theTolArc);
1078         }
1079         else {
1080           anRLine = BuildRLine(aSeqOfWLine, rank, theSurface2, theDomain2, theTolArc);
1081         }
1082         
1083         if(!anRLine.IsNull()) {
1084           aSeqOfRLine.Append(anRLine);
1085           for(Standard_Integer k=1; k<=aSeqOfWLine.Length(); k++) {
1086             for(Standard_Integer j=1; j<=slin.Length(); j++) {
1087               if(aSeqOfWLine(k)==slin(j)) {
1088                 slin.Remove(j);
1089                 break;
1090               }
1091             }
1092           }
1093         }
1094         aSeqOfWLine.Clear();
1095       }
1096     }
1097   }
1098   
1099   for(Standard_Integer i=1; i<=aSeqOfRLine.Length(); i++) {
1100     slin.Append(aSeqOfRLine.Value(i));
1101   }  
1102 }
1103 // modified by NIZHNY-MKK  Mon Apr  2 12:18:34 2001.END
1104
1105 //====================================================================================
1106 // function: MergeWLinesIfAllSegmentsAlongRestriction
1107 //
1108 //  purpose: If the result of LineConstructor is a set of WLines segments which are
1109 //           placed along RESTRICTION, we can suppose that this result is not correct:
1110 //           here we should have a RLine. If it is not possible to construct RLine
1111 //           we should merge segments of WLines into single WLine equals to the same
1112 //           RLine.
1113 //====================================================================================
1114 static void MergeWLinesIfAllSegmentsAlongRestriction(IntPatch_SequenceOfLine&           theSlin,
1115                                                      const Handle(Adaptor3d_HSurface)&  theSurface1,
1116                                                      const Handle(Adaptor3d_TopolTool)& theDomain1,
1117                                                      const Handle(Adaptor3d_HSurface)&  theSurface2,
1118                                                      const Handle(Adaptor3d_TopolTool)& theDomain2,
1119                                                      const Standard_Real                theTolArc)
1120 {
1121   Standard_Integer i = 0, rank = 0;
1122   Standard_Real tol = 1.e-9;
1123
1124   // here we check that all segments of WLines placed along restriction
1125   Standard_Integer WLOnRS1 = 0;
1126   Standard_Integer WLOnRS2 = 0;
1127   Standard_Integer NbWLines = 0;
1128   TColgp_SequenceOfPnt sqVertexPoints;
1129
1130   for(rank = 1; rank <= 2; rank++)
1131     {
1132       NbWLines = 0;
1133       for(i = 1; i <= theSlin.Length(); i++)
1134         {
1135           if( theSlin.Value(i)->ArcType() != IntPatch_Walking )
1136             continue;
1137           NbWLines++;
1138           const Handle(IntPatch_WLine)& aWLine = *((Handle(IntPatch_WLine) *)& (theSlin.Value(i)));
1139           Standard_Integer nbvtx = aWLine->NbVertex();
1140           const IntPatch_Point& Vtx1 = aWLine->Vertex(1);
1141           const IntPatch_Point& Vtx2 = aWLine->Vertex(nbvtx);
1142           if( rank==1 )
1143             {
1144               sqVertexPoints.Append(Vtx1.Value());
1145               sqVertexPoints.Append(Vtx2.Value());
1146               if( TestWLineAlongRestriction(aWLine, rank, theSurface1, theDomain1, theTolArc) )
1147                 WLOnRS1++;
1148             }
1149           else
1150             {
1151               if( TestWLineAlongRestriction(aWLine, rank, theSurface2, theDomain2, theTolArc) )
1152                 WLOnRS2++;
1153             }
1154         }
1155       if( NbWLines == WLOnRS1 || NbWLines == WLOnRS2 ) break;
1156     }
1157
1158   Standard_Integer WLineRank = 0;   // not possible to merge WLines
1159
1160   if( WLOnRS1 == NbWLines )
1161     WLineRank = 1;                  // create merged WLine based on arc of S1
1162   else if( WLOnRS2 == NbWLines )
1163     WLineRank = 2;                  // create merged WLine based on arc of S2
1164   else
1165     return;
1166
1167   // avoid closed (degenerated) edges
1168   if( sqVertexPoints.Length() <= 2 )
1169     return;
1170   if( sqVertexPoints.Value(1).IsEqual(sqVertexPoints.Value(sqVertexPoints.Length()),tol) )
1171     return;
1172
1173   Standard_Real TolVrtx = 1.e-5;
1174   Standard_Integer testPointIndex = ( sqVertexPoints.Length() > 3 ) ? ((Standard_Integer) sqVertexPoints.Length() / 2) : 2;
1175   gp_Pnt testPoint = sqVertexPoints.Value( testPointIndex );
1176   Standard_Real Fp = 0., Lp = 0.;
1177
1178
1179   Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
1180   //
1181   Standard_Integer arcnumber = (WLineRank == 1) ?
1182       GetArc(theSlin,WLineRank,theSurface1,theDomain1,theSurface2,testPoint,TolVrtx,aLineOn2S,Fp,Lp) :
1183       GetArc(theSlin,WLineRank,theSurface2,theDomain2,theSurface1,testPoint,TolVrtx,aLineOn2S,Fp,Lp);
1184   //    
1185   if (arcnumber == 0) {
1186     return;
1187   }
1188   //
1189   Handle(IntPatch_WLine) anWLine = GetMergedWLineOnRestriction(theSlin,TolVrtx,aLineOn2S);
1190   if (!anWLine.IsNull()) {
1191     theSlin.Clear();
1192     theSlin.Append(anWLine);
1193 #ifdef OCCT_DEBUG
1194     cout << "*** TopOpeBRep_FaceIntersector: Merge WLines on Restriction " 
1195          << ((WLineRank == 1) ? "S1" : "S2") << " to WLine***" << endl;
1196 #endif
1197   }
1198 }
1199
1200 //=========================================================================================
1201 // function: GetArc
1202 //
1203 //  purpose: Define arc on (OBJ) surface which all WLine segments are placed along.
1204 //           Check states of points in the gaps between segments on (TOOL). If those states
1205 //           are IN or ON return the LineOn2S based on points3D were given from detected arc.
1206 //           Returns 0 if it is not possible to create merged WLine.
1207 //========================================================================================
1208 static Standard_Integer GetArc(IntPatch_SequenceOfLine&           theSlin,
1209                                const Standard_Integer&            theRankS,
1210                                const Handle(Adaptor3d_HSurface)&  theSurfaceObj,
1211                                const Handle(Adaptor3d_TopolTool)& theDomainObj,
1212                                const Handle(Adaptor3d_HSurface)&  theSurfaceTool,
1213                                const gp_Pnt&                      theTestPoint,
1214                                Standard_Real&                     theVrtxTol,
1215                                Handle(IntSurf_LineOn2S)&          theLineOn2S,
1216                                Standard_Real&                     theFirst,
1217                                Standard_Real&                     theLast)
1218 {
1219   // 1. find number of arc (edge) on which the WLine segments are placed.
1220
1221   Standard_Real MinDistance2 = 1.e+200, firstES1 = 0., lastES1 = 0.;
1222   Standard_Integer ArcNumber = 0, CurArc = 0, i = 0, j = 0;
1223   theFirst = 0.;
1224   theLast = 0.;
1225
1226   for(theDomainObj->Init(); theDomainObj->More(); theDomainObj->Next())
1227     {
1228       CurArc++;
1229       Standard_Address anEAddress = theDomainObj->Edge();
1230
1231       if( anEAddress == NULL )
1232         continue;
1233       
1234       TopoDS_Edge* anE=(TopoDS_Edge*)anEAddress;
1235       Handle(Geom_Curve) aCEdge=BRep_Tool::Curve(*anE, firstES1, lastES1);
1236       if ( aCEdge.IsNull() ) // e.g. degenerated edge, see OCC21770
1237         continue;
1238       GeomAdaptor_Curve CE;
1239       CE.Load(aCEdge);
1240       Extrema_ExtPC epc(theTestPoint, CE, 1.e-7);
1241
1242       if( epc.IsDone() )
1243         {
1244           for( i = 1; i <= epc.NbExt(); i++ )
1245             {
1246               if( epc.SquareDistance( i ) < MinDistance2 )
1247                 {
1248                   MinDistance2 = epc.SquareDistance( i );
1249                   ArcNumber = CurArc;
1250                 }
1251             }
1252         }
1253     }
1254
1255   if( ArcNumber == 0 )
1256     return 0;
1257
1258   // 2. load parameters of founded edge and its arc.
1259   CurArc = 0;
1260   TColgp_SequenceOfPnt PointsFromArc;
1261   Handle(Adaptor2d_HCurve2d) arc = NULL;
1262   Standard_Real tol = 1.e-7;
1263   TColStd_SequenceOfReal WLVertexParameters;
1264   Standard_Boolean classifyOK = Standard_True;
1265   Standard_Real CheckTol = 1.e-5;
1266
1267   for(theDomainObj->Init(); theDomainObj->More(); theDomainObj->Next())
1268     {
1269       CurArc++;
1270       if( CurArc != ArcNumber )
1271         continue;
1272
1273       arc = theDomainObj->Value();
1274
1275       for(i = 1; i <= theSlin.Length(); i++)
1276         {
1277           if( theSlin.Value(i)->ArcType() != IntPatch_Walking )
1278             continue;
1279
1280           const Handle(IntPatch_WLine)& aWLine = *((Handle(IntPatch_WLine) *)& (theSlin.Value(i)));
1281
1282           Standard_Integer nbpnts = aWLine->NbPnts();
1283           const IntSurf_PntOn2S& POn2S_F = aWLine->Point(1);
1284           const IntSurf_PntOn2S& POn2S_L = aWLine->Point(nbpnts);
1285
1286           Standard_Real Upf = 0., Vpf = 0., Upl = 0., Vpl = 0.;
1287
1288           if(theRankS == 1)
1289             {
1290               POn2S_F.ParametersOnS1(Upf, Vpf);
1291               POn2S_L.ParametersOnS1(Upl, Vpl);
1292             }
1293           else
1294             {
1295               POn2S_F.ParametersOnS2(Upf, Vpf);
1296               POn2S_L.ParametersOnS2(Upl, Vpl);
1297             }
1298
1299           gp_Pnt2d aPOnLine_F(Upf, Vpf);
1300           gp_Pnt2d aPOnLine_L(Upl, Vpl);
1301
1302           Standard_Real par_F = Geom2dInt_TheProjPCurOfGInter::FindParameter(arc->Curve2d(), aPOnLine_F, tol);
1303           Standard_Real par_L = Geom2dInt_TheProjPCurOfGInter::FindParameter(arc->Curve2d(), aPOnLine_L, tol);
1304
1305           WLVertexParameters.Append(par_F);
1306           WLVertexParameters.Append(par_L);
1307         }
1308       
1309       for(i = 1; i <= WLVertexParameters.Length(); i++)
1310         {
1311           for(j = i; j <= WLVertexParameters.Length(); j++)
1312             {
1313               if(j == i)
1314                 continue;
1315           
1316               if(WLVertexParameters.Value(i) > WLVertexParameters.Value(j))
1317                 {
1318                   Standard_Real pol = WLVertexParameters.Value(i);
1319                   WLVertexParameters.SetValue(i, WLVertexParameters.Value(j));
1320                   WLVertexParameters.SetValue(j, pol);
1321                 }
1322             }
1323         }
1324
1325       Standard_Address anEAddress = theDomainObj->Edge();
1326       TopoDS_Edge* anE=(TopoDS_Edge*)anEAddress;
1327       TopoDS_Vertex V1, V2;
1328       TopExp::Vertices(*anE,V1,V2);
1329       Standard_Real MaxVertexTol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2));
1330       theVrtxTol = MaxVertexTol;
1331       Standard_Real EdgeTol = BRep_Tool::Tolerance(*anE);
1332       CheckTol = Max(MaxVertexTol, EdgeTol);
1333       Handle(Geom_Curve) aCEdge=BRep_Tool::Curve(*anE, firstES1, lastES1);
1334       // classification gaps
1335       //  a. min - first
1336       if(Abs(firstES1 - WLVertexParameters.Value(1)) > arc->Resolution(MaxVertexTol))
1337         {
1338           Standard_Real param = (firstES1 + WLVertexParameters.Value(1)) / 2.;
1339           gp_Pnt point;
1340           aCEdge->D0(param, point);
1341           if( !IsPointOK(point, theSurfaceTool->Surface(), CheckTol) )
1342             {
1343               classifyOK = Standard_False;
1344               break;
1345             }
1346         }
1347       //  b. max - last
1348       if(Abs(lastES1 - WLVertexParameters.Value(WLVertexParameters.Length())) > arc->Resolution(MaxVertexTol))
1349         {
1350           Standard_Real param = (lastES1 + WLVertexParameters.Value(WLVertexParameters.Length())) / 2.;
1351           gp_Pnt point;
1352           aCEdge->D0(param, point);
1353           if( !IsPointOK(point, theSurfaceTool->Surface(), CheckTol) )
1354             {
1355               classifyOK = Standard_False;
1356               break;
1357             }
1358         }
1359       //  c. all middle gaps
1360       Standard_Integer NbChkPnts = WLVertexParameters.Length() / 2 - 1;
1361       for(i = 1; i <= NbChkPnts; i++)
1362         {
1363           if( Abs(WLVertexParameters.Value(i*2+1) - WLVertexParameters.Value(i*2)) > arc->Resolution(MaxVertexTol))
1364             {
1365               Standard_Real param = (WLVertexParameters.Value(i*2) + WLVertexParameters.Value(i*2+1)) / 2.;
1366               gp_Pnt point;
1367               aCEdge->D0(param, point);
1368               if( !IsPointOK(point, theSurfaceTool->Surface(), CheckTol) )
1369                 {
1370                   classifyOK = Standard_False;
1371                   break;
1372                 }
1373             }
1374         }
1375       
1376       if( !classifyOK )
1377         break;
1378
1379       // if classification gaps OK, fill sequence by the points from arc (edge)
1380       Standard_Real ParamFirst = WLVertexParameters.Value(1);
1381       Standard_Real ParamLast  = WLVertexParameters.Value(WLVertexParameters.Length());
1382       Standard_Real dParam     = Abs(ParamLast - ParamFirst) / 100.;
1383       Standard_Real cParam = ParamFirst;
1384       for( i = 0; i < 100; i++ )
1385         {
1386           if( i == 99 )
1387             cParam = ParamLast;
1388
1389           gp_Pnt cPnt;
1390           aCEdge->D0(cParam, cPnt);
1391           PointsFromArc.Append(cPnt);
1392           cParam += dParam;
1393         }
1394       theFirst = ParamFirst;
1395       theLast  = ParamLast;
1396
1397     }
1398
1399   if( !classifyOK )
1400     return 0;
1401
1402   // create IntSurf_LineOn2S from points < PointsFromArc >
1403   for( i = 1; i <= PointsFromArc.Length(); i++ )
1404     {
1405       Extrema_POnSurf pOnS1;
1406       Extrema_POnSurf pOnS2;
1407       gp_Pnt arcpoint = PointsFromArc.Value( i );
1408       Standard_Boolean isOnS1 = GetPointOn2S( arcpoint, theSurfaceObj->Surface(), CheckTol, pOnS1 );
1409       Standard_Boolean isOnS2 = GetPointOn2S( arcpoint, theSurfaceTool->Surface(), CheckTol, pOnS2 );
1410       if( isOnS1 && isOnS2 )
1411         {
1412           Standard_Real u1 = 0., v1 = 0., u2 = 0., v2 = 0.;
1413           pOnS1.Parameter(u1, v1);
1414           pOnS2.Parameter(u2, v2);
1415           IntSurf_PntOn2S pOn2S;
1416           pOn2S.SetValue(arcpoint, u1, v1, u2, v2 );
1417           theLineOn2S->Add( pOn2S );
1418         }
1419     }
1420
1421   return ArcNumber;
1422 }
1423
1424 //=========================================================================================
1425 // function: IsPointOK
1426 //
1427 //  purpose: returns the state of testPoint on OTHER face.
1428 //========================================================================================
1429 static Standard_Boolean IsPointOK(const gp_Pnt&            theTestPnt,
1430                                   const Adaptor3d_Surface& theTestSurface,
1431                                   const Standard_Real&     theTol)
1432 {
1433   Standard_Boolean result = Standard_False;
1434   Standard_Real ExtTol = theTol;//1.e-7;
1435   Extrema_ExtPS extPS(theTestPnt,theTestSurface,ExtTol,ExtTol);
1436   if( extPS.IsDone() && extPS.NbExt() > 0 )
1437     {
1438       Standard_Integer i = 0;
1439       Standard_Real MinDist2 = 1.e+200;
1440       for(i = 1; i <= extPS.NbExt(); i++)
1441         {
1442           if( extPS.SquareDistance(i) < MinDist2 )
1443             {
1444               MinDist2 = extPS.SquareDistance(i);
1445             }
1446         }
1447       if( MinDist2 <= theTol * theTol )
1448           result = Standard_True;
1449     }
1450   return result;
1451 }
1452
1453 //=========================================================================================
1454 // function: GetPointOn2S
1455 //
1456 //  purpose: check state of testPoint and returns result point if state is OK.
1457 //========================================================================================
1458 static Standard_Boolean GetPointOn2S(const gp_Pnt&            theTestPnt,
1459                                      const Adaptor3d_Surface& theTestSurface,
1460                                      const Standard_Real&     theTol,
1461                                      Extrema_POnSurf&         theResultPoint)
1462 {
1463   Standard_Boolean result = Standard_False;
1464   Standard_Real ExtTol = theTol;//1.e-7;
1465   Extrema_ExtPS extPS(theTestPnt,theTestSurface,ExtTol,ExtTol);
1466   if( extPS.IsDone() && extPS.NbExt() > 0 )
1467     {
1468       Standard_Integer i = 0, minext = 1;
1469       Standard_Real MinDist2 = 1.e+200;
1470       for(i = 1; i <= extPS.NbExt(); i++)
1471         {
1472           if( extPS.SquareDistance(i) < MinDist2 )
1473             {
1474               minext = i;
1475               MinDist2 = extPS.SquareDistance(i);
1476             }
1477         }
1478       if( MinDist2 <= theTol * theTol )
1479         {
1480           result = Standard_True;
1481           theResultPoint = extPS.Point(minext);
1482         }
1483     }
1484   return result;
1485 }
1486
1487 //=========================================================================================
1488 // function: GetMergedWLineOnRestriction
1489 //
1490 //  purpose: merge sequence of WLines all placed along restriction if the conditions of
1491 //           merging are OK.
1492 //========================================================================================
1493 static Handle(IntPatch_WLine) GetMergedWLineOnRestriction(IntPatch_SequenceOfLine&           theSlin,
1494                                                                            const Standard_Real&               theVrtxTol,
1495                                                                            const Handle(IntSurf_LineOn2S)&    theLineOn2S)
1496 {
1497   Handle(IntPatch_WLine) mWLine;
1498   if (theLineOn2S->NbPoints() == 0) {
1499     return mWLine;
1500   }
1501   //
1502   IntSurf_TypeTrans trans1 = IntSurf_Undecided;
1503   IntSurf_TypeTrans trans2 = IntSurf_Undecided;
1504   Standard_Integer i = 0;
1505
1506   for(i = 1; i <= theSlin.Length(); i++)
1507     {
1508       if( theSlin.Value(i)->ArcType() != IntPatch_Walking )
1509         continue;
1510
1511       const Handle(IntPatch_WLine)& aWLine = *((Handle(IntPatch_WLine) *)& (theSlin.Value(i)));
1512
1513       if( aWLine->TransitionOnS1() != IntSurf_Undecided  &&  aWLine->TransitionOnS1() != IntSurf_Touch )
1514         trans1 = aWLine->TransitionOnS1();
1515       if( aWLine->TransitionOnS2() != IntSurf_Undecided  &&  aWLine->TransitionOnS2() != IntSurf_Touch )
1516         trans2 = aWLine->TransitionOnS2();
1517     }
1518
1519   mWLine = new IntPatch_WLine(theLineOn2S, Standard_False, trans1, trans2);
1520
1521   Standard_Integer NbPnts = mWLine->NbPnts();
1522   IntPatch_Point aFirstVertex, aLastVertex;
1523
1524   aFirstVertex.SetValue(mWLine->Point(1).Value(),theVrtxTol,Standard_False);
1525   aLastVertex.SetValue(mWLine->Point(NbPnts).Value(),theVrtxTol,Standard_False);
1526
1527   Standard_Real u1 = 0., v1 = 0., u2 = 0., v2 = 0.;
1528
1529   mWLine->Point(1).Parameters(u1, v1, u2, v2);
1530   aFirstVertex.SetParameters(u1, v1, u2, v2);
1531
1532   mWLine->Point(NbPnts).Parameters(u1, v1, u2, v2);
1533   aLastVertex.SetParameters(u1, v1, u2, v2);
1534
1535   aFirstVertex.SetParameter(1);
1536   aLastVertex.SetParameter(theLineOn2S->NbPoints());
1537
1538   mWLine->AddVertex(aFirstVertex);
1539   mWLine->AddVertex(aLastVertex);
1540
1541   mWLine->ComputeVertexParameters(theVrtxTol);
1542
1543   return mWLine;
1544 }