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