0029866: Intersector returns two overlapped curves as a result
[occt.git] / src / IntWalk / IntWalk_IWalking_3.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <NCollection_IncAllocator.hxx>
16 #include <NCollection_LocalArray.hxx>
17
18
19 // modified by NIZHNY-MKK  Thu Nov  2 15:07:26 2000.BEGIN
20 static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
21                                                             const TColStd_SequenceOfReal& Umult,
22                                                             const TColStd_SequenceOfReal& Vmult,
23                                                             const Standard_Real& prevUp, 
24                                                             const Standard_Real& prevVp,
25                                                             const IntWalk_VectorOfInteger& nbMultiplicities,
26                                                             const math_Vector& tolerance,
27                                                             TheIWFunction& sp,
28                                                             math_Vector& UV,
29                                                             Standard_Integer& Irang);
30 // modified by NIZHNY-MKK  Thu Nov  2 15:07:39 2000.END
31
32
33 void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
34                                        const TColStd_SequenceOfReal& Vmult,
35                                        const ThePOPIterator& Pnts1,
36                                        TheIWFunction& Func,
37                                        Standard_Boolean& Rajout) 
38
39 // Processing of open line.
40 //
41 // 1) for any starting point, which is not passing and not tangent and not yet processed,
42 //    calculation of the step of advancement = step depending on the arrow and the maximum step.
43 //
44 // 2) calculate a point of approach (this point is on the tangent to the section
45 // of distance = no point in the interior)
46 //  
47 // 3) conditions  {
48 //            (all calculated points do not exceed a point in the
49 //             list of starting points)
50 //                              or                    
51 //            (all points do not form an open line going 
52 //            from one border of the domain to the other or from a point tangent 
53 //            to border or from 2 tangent points : single cases)
54 //  
55 //     1) framing of approached point on borders if necessary (there is
56 //        calculation of step)
57 //     2) calculation of the point
58 //     3) if the point is not found the step is divided
59 //     4) stpo tests    
60 //     5) calculation of the step depending on the arrow and the max step,
61 //        (TestDeflection)
62 //        stop  possible.
63 //    end of conditions.
64
65 {
66   Standard_Integer I, N = 0, SaveN = 0;
67   Standard_Real aBornInf[2], aBornSup[2], aUVap[2];
68   math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2), UVap(aUVap,1,2);
69   Standard_Real PasC, PasCu, PasCv;
70   Standard_Boolean Arrive; // shows if the line ends
71   Standard_Boolean Cadre;  // shows if one is on border of the domain
72   Standard_Boolean ArretAjout;  //shows if one is on added point
73   IntSurf_PntOn2S Psol;
74   Handle(IntWalk_TheIWLine)  CurrentLine;    // line under construction
75   Standard_Boolean Tgtend;
76
77   IntWalk_StatusDeflection aStatus, StatusPrecedent;
78   
79   Standard_Integer NbDivision; 
80   // number of divisions of step for each section
81
82   Standard_Integer StepSign;
83   
84   ThePointOfPath PathPnt;
85
86   BornInf(1) = Um;
87   BornSup(1) = UM;
88   BornInf(2) = Vm;
89   BornSup(2) = VM;
90
91   math_FunctionSetRoot Rsnld(Func, tolerance);
92   Standard_Integer nbPath = Pnts1.Length();
93
94   // modified by NIZHNY-MKK  Fri Oct 27 12:32:34 2000.BEGIN
95   NCollection_LocalArray<Standard_Integer> movementdirectioninfoarr (nbPath + 1);
96   Standard_Integer* movementdirectioninfo = movementdirectioninfoarr;
97   for (I = 0; I <= nbPath; I++) {
98     movementdirectioninfo[I] = 0;
99   }
100   // modified by NIZHNY-MKK  Fri Oct 27 12:32:38 2000.END
101
102   TheIWFunction aFuncForDuplicate = Func;
103
104   for (I = 1; I <= nbPath; I++) {
105     //start point of the progression
106     //     if (wd1[I].etat > 11) {                
107     // modified by NIZHNY-MKK  Fri Oct 27 12:33:37 2000.BEGIN
108     if ((wd1[I].etat > 11) || ((wd1[I].etat < -11) && (movementdirectioninfo[I]!=0))) {
109     // modified by NIZHNY-MKK  Fri Oct 27 12:33:43 2000.END
110       PathPnt = Pnts1.Value(I);
111       UVap(1) = wd1[I].ustart;
112       UVap(2) = wd1[I].vstart;
113       MakeWalkingPoint(11, UVap(1), UVap(2), Func, previousPoint);
114
115       if (IsPointOnLine(previousPoint, BornInf, BornSup, Rsnld, aFuncForDuplicate))
116       {
117         wd1[I].etat = -Abs(wd1[I].etat); //mark point as processed
118         continue;
119       }
120
121       CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
122       CurrentLine->SetTangencyAtBegining(Standard_False);
123       Tgtend = Standard_False;
124       CurrentLine->AddStatusFirst(Standard_False, Standard_True, I, PathPnt);
125       previousd3d = Func.Direction3d();
126       previousd2d = Func.Direction2d();
127       CurrentLine->AddPoint(previousPoint);
128       // modified by NIZHNY-MKK  Fri Oct 27 12:34:32 2000.BEGIN
129       if(movementdirectioninfo[I] !=0) {
130         if(movementdirectioninfo[I] < 0) {
131           StepSign = -1;
132           CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
133         } else {
134           StepSign = 1; 
135           CurrentLine->SetTangentVector(previousd3d,1);
136         }
137       } else {
138         Standard_Real tyutuyt=ThePointOfPathTool::Direction3d(PathPnt) * previousd3d;
139         if( tyutuyt < 0) {
140           StepSign = -1;
141           CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
142         }
143         else {
144           StepSign = 1; 
145           CurrentLine->SetTangentVector(previousd3d,1);
146         }
147       }
148       // modified by NIZHNY-MKK  Fri Oct 27 12:34:37 2000.END
149
150       //  Modified by Sergey KHROMOV - Tue Nov 20 10:41:45 2001 Begin
151       wd1[I].etat = -Abs(wd1[I].etat);
152       movementdirectioninfo[I] = (movementdirectioninfo[I]==0) ? StepSign : 0;
153 //  Modified by Sergey KHROMOV - Tue Nov 20 10:41:56 2001 End
154       // first step of advancement
155       Standard_Real d2dx = Abs(previousd2d.X()); 
156       Standard_Real d2dy = Abs(previousd2d.Y()); 
157       if (d2dx < tolerance(1)) {
158         PasC = pas * (VM-Vm)/d2dy;
159       }
160       else if (d2dy < tolerance(2)) {
161         PasC = pas * (UM-Um)/d2dx;
162       }
163       else {
164         PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
165       }
166
167       Arrive = Standard_False;
168       ArretAjout = Standard_False;
169       NbDivision = 0;
170       StatusPrecedent = IntWalk_OK;
171       // modified by NIZHNY-MKK  Fri Oct 27 12:39:37 2000
172       Standard_Integer IndexOfPathPointDoNotCheck=0;
173       Standard_Integer aNbIter = 10;
174       while (!Arrive) { //    as one of stop tests is not checked
175         Cadre = Cadrage(BornInf,BornSup,UVap,PasC,StepSign);
176         //  Border?
177
178 #ifdef CHRONO
179         Chronrsnld.Start();
180 #endif
181
182         Rsnld.Perform(Func,UVap,BornInf,BornSup);
183
184 #ifdef CHRONO
185         Chronrsnld.Stop();
186 #endif
187
188         if (Cadre) {
189           BornInf(1) = Um; BornSup(1) = UM; BornInf(2) = Vm; BornSup(2) = VM;
190         }
191         if (Rsnld.IsDone()) {
192           if (Abs(Func.Root()) > Func.Tolerance()) {
193             PasC = PasC / 2.0;
194             PasCu = Abs(PasC*previousd2d.X());
195             PasCv = Abs(PasC*previousd2d.Y());
196             if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
197               if (CurrentLine->NbPoints() == 1) break;
198               Arrive = Standard_True;
199               CurrentLine->AddStatusLast(Standard_False);
200               Tgtend = Standard_True; // check
201               Rajout = Standard_True;
202               seqAlone.Append(lines.Length() + 1);
203               seqAjout.Append(lines.Length() + 1);
204             }  
205           }
206           else { // test stop
207             Rsnld.Root(UVap);
208             Arrive = TestArretPassage(Umult, Vmult, Func, UVap, N);
209             if (Arrive) {
210               Cadre = Standard_False;
211               //in case if there is a frame and arrive at the same time
212             }
213             else {
214               if (Rajout) {
215                 ArretAjout =TestArretAjout(Func, UVap, N, Psol);
216                 SaveN = N;
217                 if (ArretAjout) {
218                   // jag 940615
219                   Tgtend = lines.Value(N)->IsTangentAtEnd();
220                   N = -N;
221                 }
222               }
223               // modified by NIZHNY-MKK  Thu Nov  2 15:09:08 2000.BEGIN
224               if(!(Rajout && ArretAjout)) {
225                 Standard_Real prevUp, prevVp;
226                 if (!reversed) {
227                   previousPoint.ParametersOnS2(prevUp, prevVp);
228                 }
229                 else {
230                   previousPoint.ParametersOnS1(prevUp, prevVp);
231                 }
232                 Arrive = TestPassedSolutionWithNegativeState(wd1, Umult, Vmult, prevUp, prevVp,
233                   nbMultiplicities, tolerance, Func, UVap, N);          
234                 if(Arrive) {
235                   Cadre = Standard_False;
236                 }
237               }
238               // modified by NIZHNY-MKK  Thu Nov  2 15:09:13 2000.END
239               if (!ArretAjout && Cadre) {
240                 if (CurrentLine->NbPoints() == 1) break; // cancel the line
241                 TestArretCadre(Umult, Vmult, CurrentLine, Func, UVap, N);
242                 //              if (N == 0) {
243                 if (N <= 0) { // jag 941017
244                   MakeWalkingPoint(2, UVap(1), UVap(2), Func, Psol);
245                   Tgtend = Func.IsTangent();
246                   N = -N;
247                 }
248               }
249             }
250             aStatus = TestDeflection(Func, Arrive, UVap, StatusPrecedent,
251               NbDivision,PasC,StepSign);
252             StatusPrecedent = aStatus;
253             if (aStatus == IntWalk_PasTropGrand) {
254               Arrive = Standard_False;
255               ArretAjout = Standard_False;
256               Tgtend = Standard_False; // jag 940615
257               if (!reversed) {
258                 previousPoint.ParametersOnS2(UVap(1), UVap(2));
259               }
260               else {
261                 previousPoint.ParametersOnS1(UVap(1), UVap(2));
262               }
263             }
264             else if (ArretAjout || Cadre) {
265               Arrive = Standard_True;
266               CurrentLine->AddStatusLast(Standard_False);
267               //if (aStatus != IntWalk_ArretSurPointPrecedent)
268               CurrentLine->AddPoint(Psol);                      
269               //Remove <SaveN> from <seqAlone>
270               for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
271                 if (seqAlone(iseq) == SaveN)
272                 {
273                   seqAlone.Remove(iseq);
274                   break;
275                 }
276
277               if (Cadre && N==0) {
278                 Rajout = Standard_True;
279                 seqAjout.Append(lines.Length()+1);
280               }
281             }
282             else if (aStatus == IntWalk_ArretSurPointPrecedent) {
283               if (CurrentLine->NbPoints() == 1) { //cancel the line
284                 Arrive = Standard_False;
285                 break;
286               }
287               Arrive = Standard_True;
288               Rajout = Standard_True;
289               //AddAlonePoint();
290               seqAlone.Append(lines.Length() + 1);
291               seqAjout.Append(lines.Length() + 1);
292               CurrentLine->AddStatusLast(Standard_False);
293               Tgtend = Standard_True; // check
294             }
295             else if (Arrive)  {
296               if (CurrentLine->NbPoints() == 1 &&    // cancel the line
297                 (N == I || aStatus == IntWalk_PointConfondu) ) {
298                   // if N == I the main uv is probably lost
299                   // or the point is a point of accumulation
300                   // if point is confused the start data is bad
301                   Arrive =  Standard_False;
302                   break;
303               }
304               // necessairily N > 0 jag 940617
305               // point of stop given at input 
306               PathPnt = Pnts1.Value(N);
307
308               Standard_Integer etat1N=wd1[N].etat;
309               // modified by NIZHNY-MKK  Thu Nov  2 15:09:51 2000.BEGIN
310               //              if (etat1N < 11) { // passing point that is a stop  
311               if (Abs(etat1N) < 11) { // passing point that is a stop    
312                 // modified by NIZHNY-MKK  Thu Nov  2 15:12:11 2000.END
313                 if (aStatus == IntWalk_ArretSurPoint) {
314                   CurrentLine->AddStatusLast(Standard_False);
315                   Tgtend = Standard_True; // need check
316                 }
317                 else { 
318                   Arrive = Standard_False;
319                 }
320                 CurrentLine->AddIndexPassing(N);
321               }
322               else { // point of stop given at input
323                 if (etat1N == 11) {
324                   Tgtend = Standard_True;
325                 }
326                 CurrentLine->AddStatusLast(Standard_True, N, PathPnt);
327               }
328               AddPointInCurrentLine(N,PathPnt,CurrentLine);
329               if ((etat1N != 1 && etat1N != 11)) {
330                 // modified by NIZHNY-MKK  Fri Oct 27 12:43:05 2000.BEGIN
331                 //              wd1[N].etat= - wd1[N].etat;
332                 wd1[N].etat = - Abs(etat1N);            
333                 movementdirectioninfo[N] = (movementdirectioninfo[N]==0) ? StepSign : 0;
334                 if(Arrive && movementdirectioninfo[N]!=0) {
335                   IndexOfPathPointDoNotCheck = N;
336                 }
337
338                 if(Arrive) {
339                   Rajout = Standard_True;
340                   seqAjout.Append(lines.Length() + 1);
341                 }
342                 // modified by NIZHNY-MKK  Fri Oct 27 12:45:33 2000.END
343               }
344             }
345             else if (aStatus == IntWalk_ArretSurPoint) {
346               Arrive = Standard_True;                   
347               CurrentLine->AddStatusLast(Standard_False);
348               Tgtend = Standard_True;
349               MakeWalkingPoint(1, UVap(1), UVap(2), Func, Psol);
350               CurrentLine->AddPoint(Psol);
351               Rajout = Standard_True;
352               seqAlone.Append(lines.Length() + 1);
353               seqAjout.Append(lines.Length() + 1);
354             }
355             else if (aStatus == IntWalk_OK) {
356               MakeWalkingPoint(2, UVap(1), UVap(2), Func, previousPoint);
357               previousd3d = Func.Direction3d();
358               previousd2d = Func.Direction2d();
359               CurrentLine->AddPoint(previousPoint);
360             }     
361             else if (aStatus == IntWalk_PointConfondu)
362             {
363               aNbIter --;
364             }
365           }
366         }
367         else { // no numerical solution
368           PasC = PasC / 2.;
369           PasCu = Abs(PasC*previousd2d.X());
370           PasCv = Abs(PasC*previousd2d.Y());
371           if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
372             if (CurrentLine->NbPoints()==1) break;
373             Arrive = Standard_True;
374             CurrentLine->AddStatusLast(Standard_False);
375             Tgtend = Standard_True; // need check
376             Rajout = Standard_True;
377             seqAlone.Append(lines.Length() + 1);
378             seqAjout.Append(lines.Length() + 1);
379           }  
380         }
381
382         if(aNbIter < 0)
383           break;
384       } // end of started line
385       
386       if (Arrive) {
387         CurrentLine->SetTangencyAtEnd(Tgtend);
388         lines.Append(CurrentLine);
389         // modified by NIZHNY-MKK  Fri Oct 27 12:59:29 2000.BEGIN
390         movementdirectioninfo[I]=0;
391         if(wd1[I].etat > 0)
392           // modified by NIZHNY-MKK  Fri Oct 27 12:59:42 2000.END
393           wd1[I].etat=-wd1[I].etat;
394
395         //-- lbr le 5 juin 97 (Pb ds Contap)
396         for(Standard_Integer av=1; av<=nbPath; av++) { 
397           // modified by NIZHNY-MKK  Fri Oct 27 13:00:22 2000.BEGIN
398           //      if (wd1[av].etat > 11) {
399           if ((wd1[av].etat > 11) || 
400             ((av!=I) && 
401             (av!=IndexOfPathPointDoNotCheck) && 
402             (wd1[av].etat < -11)  && 
403             (movementdirectioninfo[av]!=0)))
404           {
405             // modified by NIZHNY-MKK  Fri Oct 27 13:00:26 2000.END
406             Standard_Real Uav=wd1[av].ustart;
407             Standard_Real Vav=wd1[av].vstart;
408             Standard_Real Uavp,Vavp;
409             const IntSurf_PntOn2S &avP=CurrentLine->Value(CurrentLine->NbPoints());
410             if (!reversed) {
411               avP.ParametersOnS2(Uavp,Vavp);
412             }
413             else {
414               avP.ParametersOnS1(Uavp,Vavp);
415             }
416             Uav-=Uavp;
417             Vav-=Vavp;
418             Uav*=0.001; Vav*=0.001;
419             if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) { 
420               // modified by NIZHNY-MKK  Fri Oct 27 13:01:38 2000.BEGIN
421               //              wd1[av].etat=-wd1[av].etat;
422               if(wd1[av].etat < 0) {
423                 movementdirectioninfo[av] = 0;
424               } else {
425                 wd1[av].etat=-wd1[av].etat;
426                 movementdirectioninfo[av] = StepSign;
427               }
428               // modified by NIZHNY-MKK  Fri Oct 27 13:01:42 2000.END
429               CurrentLine->AddStatusLast(Standard_True, av, Pnts1.Value(av));
430               //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
431             }
432
433             const IntSurf_PntOn2S &avPP=CurrentLine->Value(1);
434             if (!reversed) {
435               avPP.ParametersOnS2(Uavp,Vavp);
436             }
437             else {
438               avPP.ParametersOnS1(Uavp,Vavp);
439             }
440             Uav=wd1[av].ustart;
441             Vav=wd1[av].vstart;
442             Uav-=Uavp;
443             Vav-=Vavp;
444             Uav*=0.001; Vav*=0.001;
445             if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) { 
446               // modified by NIZHNY-MKK  Fri Oct 27 13:02:49 2000.BEGIN
447               //              wd1[av].etat=-wd1[av].etat;
448               if(wd1[av].etat < 0) {
449                 movementdirectioninfo[av] = 0;
450               } else {
451                 wd1[av].etat=-wd1[av].etat;
452                 movementdirectioninfo[av] = -StepSign;
453               }
454               // modified by NIZHNY-MKK  Fri Oct 27 13:02:52 2000.END
455               //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
456               CurrentLine->AddStatusFirst(Standard_False, Standard_True, av, Pnts1.Value(av));
457             }
458           }
459         }
460       }
461     } //end of point processing
462   } //end of all points
463 }
464
465 // modified by NIZHNY-MKK  Thu Nov  2 15:07:53 2000.BEGIN
466 static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
467                                                             const TColStd_SequenceOfReal& Umult,
468                                                             const TColStd_SequenceOfReal& Vmult,
469                                                             const Standard_Real& prevUp,
470                                                             const Standard_Real& prevVp,
471                                                             const IntWalk_VectorOfInteger& nbMultiplicities,
472                                                             const math_Vector& tolerance,
473                                                             TheIWFunction& sp,
474                                                             math_Vector& UV,
475                                                             Standard_Integer& Irang) {
476   Standard_Boolean Arrive = Standard_False;
477   Standard_Real Dup, Dvp, Utest,Vtest;
478   Standard_Real tolu = tolerance(1);
479   Standard_Real tolv = tolerance(2);
480   Standard_Integer i, j, k, N;
481   for (i = 1; i < (int)wd.size(); i++) {
482     if (wd[i].etat < -11) {
483
484  // debug jag see with isg
485
486       Utest = wd[i].ustart;
487       Vtest = wd[i].vstart;
488       Dup = prevUp - Utest;
489       Dvp = prevVp - Vtest;
490       if (Abs(Dup) >= tolu || Abs(Dvp) >= tolv) {
491         Standard_Real UV1mUtest = UV(1)-Utest;
492         Standard_Real UV2mVtest = UV(2)-Vtest;
493         if(( (Dup*UV1mUtest + Dvp*UV2mVtest) < 0) ||
494            (   Abs(UV1mUtest) < tolu 
495             && Abs(UV2mVtest) < tolv)) {
496           Irang=i;
497           Arrive = Standard_True;
498           UV(1) = Utest;
499           UV(2) = Vtest;
500         }
501         else if (nbMultiplicities[i] > 0) {
502           N=0;
503           for (k = 1; k < i; k++) { 
504             N+=nbMultiplicities[k];
505           }
506           for (j = N + 1; j <= N + nbMultiplicities[i]; j++) {
507             if (((prevUp-Umult(j))*(UV(1)-Umult(j)) +
508                  (prevVp-Vmult(j))*(UV(2)-Vmult(j)) < 0) ||
509                 (Abs(UV(1)-Umult(j)) < tolu &&
510                  Abs(UV(2)-Vmult(j)) < tolv)) {
511               Irang=i;
512               Arrive = Standard_True;
513               UV(1) = Utest;
514               UV(2) = Vtest;
515               break;
516             }
517           }
518         }
519         if (Arrive) {
520           Standard_Real abidF[1], abidD[1][2];
521           math_Vector bidF(abidF,1,1);
522           math_Matrix bidD(abidD,1,1,1,2); 
523       sp.Values(UV,bidF,bidD);
524           break;
525         }
526       }
527     }    
528   }
529   return Arrive;
530 }
531 // modified by NIZHNY-MKK  Thu Nov  2 15:07:58 2000.END