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#ifndef OCCT_DEBUG
16#define No_Standard_RangeError
17#define No_Standard_OutOfRange
18#endif
19
20
21void IntWalk_IWalking::AddPointInCurrentLine
22         (const Standard_Integer N,
23	  const ThePointOfPath& PathPnt,
24	  const Handle(IntWalk_TheIWLine)& CurrentLine) const {
25
26
27  IntSurf_PntOn2S Psol;
28  Psol.SetValue(ThePointOfPathTool::Value3d(PathPnt),
29		reversed,wd1[N].ustart,wd1[N].vstart);
30  CurrentLine->AddPoint(Psol);
31}
32
33
34void IntWalk_IWalking::MakeWalkingPoint
35         (const Standard_Integer Case,
36	  const Standard_Real U,
37	  const Standard_Real V,
38	  TheIWFunction& sp,
39	  IntSurf_PntOn2S& Psol )
40
41{
42
43// Case == 1      : make a WalkinkPoint.
44// Case == 2      : make a WalkinkPoint.
45//                  The computation of the tangency on is done
46// Case == 10 + i : make a WalkinkPoint according to i.
47//                  but F is updated according to U and V
48// Case == other  : the exception Standard_Failure is raised.
49
50  if ((Case == 1) || (Case == 2))
51  {
52    Psol.SetValue(sp.Point(), reversed, U, V);
53  }
54  else if (Case == 11 || Case == 12)
55  {
56    Standard_Real aUV[2] = {}, aFF[1] = {}, aDD[1][2] = {};
57    math_Vector UV(aUV, 1, 2);
58    math_Vector FF(aFF, 1, 1);
59    math_Matrix DD(aDD, 1, 1, 1, 2);
60    UV(1) = U;
61    UV(2) = V;
62    sp.Values(UV, FF, DD);
63    MakeWalkingPoint(Case - 10, U, V, sp, Psol);
64  }
65  else
66  {
67    throw Standard_ConstructionError();
68  }
69}
70
71
72
73void IntWalk_IWalking::OpenLine(const Standard_Integer N,
74                                const IntSurf_PntOn2S& Psol,
75				const ThePOPIterator& Pnts1,
76				TheIWFunction& sp,
77                                const Handle(IntWalk_TheIWLine)& Line )
78// **************** open the line and restart in the other direction********
79
80{
81  ThePointOfPath PathPnt;
82
83  Standard_Real aUV[2], aFF[1], aDD[1][2];
84  math_Vector UV(aUV,1, 2);
85  math_Vector FF(aFF,1, 1);
86  math_Matrix DD(aDD,1, 1, 1, 2);
87
88  previousPoint = Line->Value(1);
89  if (!reversed) {
90    previousPoint.ParametersOnS2(UV(1),UV(2));
91  }
92  else {
93    previousPoint.ParametersOnS1(UV(1),UV(2));
94  }
95  sp.Values(UV, FF, DD);
96  previousd3d = sp.Direction3d();
97  previousd2d = sp.Direction2d();
98
99  if (N>0) { //departure point given at input
100    PathPnt = Pnts1.Value(N);
101    //mark the line as open with a given stop point
102    Line->AddStatusFirst(Standard_False,Standard_True,N,PathPnt);
103
104
105    AddPointInCurrentLine(N,PathPnt,Line);
106
107  }
108  else  {
109    if (N <0) Line->AddPoint(Psol);
110    Line->AddStatusFirst(Standard_False,Standard_False);
111       //mark the line as open without given stop point
112  }
113  Line->Reverse();  //inverser la ligne
114  Line->SetTangentVector(previousd3d.Reversed(),Line->NbPoints());
115}
116
117Standard_Boolean IntWalk_IWalking::IsValidEndPoint(const Standard_Integer IndOfPoint,
118                                                   const Standard_Integer IndOfLine)
119{
120  if (PointLineLine.IsEmpty())
121    return Standard_True;
122
123  TColStd_ListIteratorOfListOfInteger itl(PointLineLine(IndOfPoint));
124  for (; itl.More(); itl.Next())
125    if (itl.Value() == IndOfLine)
126    {
127      PointLineLine(IndOfPoint).Remove(itl);
128      return Standard_True;
129    }
130  return Standard_False;
131}
132
133void IntWalk_IWalking::RemoveTwoEndPoints(const Standard_Integer IndOfPoint)
134{
135  if (PointLineLine.IsBound(IndOfPoint))
136  {
137    Standard_Integer Line1 = PointLineLine(IndOfPoint).First();
138    Standard_Integer Line2 = PointLineLine(IndOfPoint).Last();
139    for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
140    {
141      if (seqAlone(iseq) == Line1 ||
142          seqAlone(iseq) == Line2)
143        seqAlone.Remove(iseq--);
144    }
145  }
146}
147
148Standard_Boolean IntWalk_IWalking::IsPointOnLine(const gp_Pnt2d& theP2d,
149                                                 const Standard_Integer Irang)
150{
151  const Handle(IntWalk_TheIWLine)& aLine = lines.Value(Abs(Irang));
152  for (Standard_Integer i = 1; i <= aLine->NbPoints(); i++)
153  {
154    gp_Pnt2d P2d1 = aLine->Value(i).ValueOnSurface(reversed);
155    if (Abs(P2d1.X() - theP2d.X()) <= tolerance(1) &&
156        Abs(P2d1.Y() - theP2d.Y()) <= tolerance(2))
157      return Standard_True;
158    if (i < aLine->NbPoints())
159    {
160      gp_Pnt2d P2d2 = aLine->Value(i+1).ValueOnSurface(reversed);
161      gp_Vec2d PP1(theP2d, P2d1);
162      gp_Vec2d PP2(theP2d, P2d2);
163      if (PP1 * PP2 < 0)
164        return Standard_True;
165    }
166  }
167  return Standard_False;
168}
169
170//==================================================================================
171//function : IsPointOnLine
172//purpose  : Projects thePOn2S on the nearest segment of the already computed line.
173//           The retrieved projection point (aPa) is refined using theSolver.
174//            After the refinement, we will obtain a point aPb.
175//            If thePOn2S is quite far from aPb then thePOn2S is not
176//            in the line.
177//           Every already computed line is checked.
178//==================================================================================
179Standard_Boolean IntWalk_IWalking::IsPointOnLine(const IntSurf_PntOn2S& thePOn2S,
180                                                 const math_Vector& theInfBounds,
181                                                 const math_Vector& theSupBounds,
182                                                 math_FunctionSetRoot& theSolver,
183                                                 TheIWFunction& theFunc)
184{
185  const Standard_Real eps = Epsilon(1.);
186  const gp_Pnt &aP3d = thePOn2S.Value();
187
188  for (Standard_Integer aLIdx = 1; aLIdx <= lines.Length(); aLIdx++)
189  {
190    const Handle(IntSurf_LineOn2S) &aL = lines(aLIdx)->Line();
191
192    if (aL->IsOutBox(aP3d))
193      continue;
194
195    //Look for the nearest segment
196    Standard_Real aUMin = 0.0, aVMin = 0.0;
197    Standard_Real aMinSqDist = RealLast();
198    for (Standard_Integer aPtIdx = 1; aPtIdx < aL->NbPoints(); aPtIdx++)
199    {
200      const gp_Pnt &aP1 = aL->Value(aPtIdx).Value();
201      const gp_Pnt &aP2 = aL->Value(aPtIdx + 1).Value();
202
203      const gp_XYZ aP1P(aP3d.XYZ() - aP1.XYZ());
204      const gp_XYZ aP1P2(aP2.XYZ() - aP1.XYZ());
205
206      const Standard_Real aSq12 = aP1P2.SquareModulus();
207
208      if (aSq12 < gp::Resolution())
209        continue;
210
211      const Standard_Real aDP = aP1P.Dot(aP1P2);
212
213      Standard_Real aSqD = RealLast();
214      if (aDP < 0.0)
215      {
216        continue;
217      }
218      else if (aDP > aSq12)
219      {
220        continue;
221      }
222      else
223      {
224        aSqD = aP1P.CrossSquareMagnitude(aP1P2) / aSq12;
225      }
226
227      if (aSqD < aMinSqDist)
228      {
229        aMinSqDist = aSqD;
230
231        const Standard_Real aL1 = aDP / aSq12;
232        const Standard_Real aL2 = 1.0 - aL1;
233
234        if (aL1 < eps || aL2 < eps)
235        {
236          return Standard_True;
237        }
238
239        Standard_Real aU1, aV1, aU2, aV2;
240        aL->Value(aPtIdx).ParametersOnSurface(reversed, aU1, aV1);
241        aL->Value(aPtIdx + 1).ParametersOnSurface(reversed, aU2, aV2);
242
243        aUMin = aL1*aU2 + aL2*aU1;
244        aVMin = aL1*aV2 + aL2*aV1;
245      }
246    }
247
248    if (aMinSqDist > Precision::Infinite())
249      continue;
250
251    math_Vector aVecPrms(1, 2);
252    aVecPrms(1) = aUMin;
253    aVecPrms(2) = aVMin;
254    theSolver.Perform(theFunc, aVecPrms, theInfBounds, theSupBounds);
255    if (!theSolver.IsDone())
256      continue;
257
258    theSolver.Root(aVecPrms);
259
260    const gp_Pnt aPa(theFunc.PSurface()->Value(aUMin, aVMin)),
261                 aPb(theFunc.PSurface()->Value(aVecPrms(1), aVecPrms(2)));
262    const Standard_Real aSqD1 = aPb.SquareDistance(aP3d);
263    const Standard_Real aSqD2 = aPa.SquareDistance(aPb);
264
265    if (aSqD1 < 4.0*aSqD2)
266    {
267      return Standard_True;
268    }
269  }
270
271  return Standard_False;
272}
273