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
20static 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
33void 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) stop 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 = 0, 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 = 0.0, PasCu = 0.0, PasCv = 0.0;
70  Standard_Boolean Arrive = false; // shows if the line ends
71  Standard_Boolean Cadre = false;  // shows if one is on border of the domain
72  Standard_Boolean ArretAjout = false;  //shows if one is on added point
73  IntSurf_PntOn2S Psol;
74  Handle(IntWalk_TheIWLine)  CurrentLine;    // line under construction
75  Standard_Boolean Tgtend = false;
76
77  IntWalk_StatusDeflection aStatus = IntWalk_OK, StatusPrecedent = IntWalk_OK;
78
79  Standard_Integer NbDivision = 0;
80  // number of divisions of step for each section
81
82  Standard_Integer StepSign = 0;
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
466static 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
532