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