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