// Copyright (c) 1995-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #ifndef OCCT_DEBUG #define No_Standard_RangeError #define No_Standard_OutOfRange #endif void IntWalk_IWalking::AddPointInCurrentLine (const Standard_Integer N, const ThePointOfPath& PathPnt, const Handle(IntWalk_TheIWLine)& CurrentLine) const { IntSurf_PntOn2S Psol; Psol.SetValue(ThePointOfPathTool::Value3d(PathPnt), reversed,wd1[N].ustart,wd1[N].vstart); CurrentLine->AddPoint(Psol); } void IntWalk_IWalking::MakeWalkingPoint (const Standard_Integer Case, const Standard_Real U, const Standard_Real V, TheIWFunction& sp, IntSurf_PntOn2S& Psol ) { // Case == 1 : make a WalkinkPoint. // Case == 2 : make a WalkinkPoint. // The computation of the tangency on is done // Case == 10 + i : make a WalkinkPoint according to i. // but F is updated according to U and V // Case == other : the exception Standard_Failure is raised. if ((Case == 1) || (Case == 2)) { Psol.SetValue(sp.Point(), reversed, U, V); } else if (Case == 11 || Case == 12) { Standard_Real aUV[2] = {}, aFF[1] = {}, aDD[1][2] = {}; math_Vector UV(aUV, 1, 2); math_Vector FF(aFF, 1, 1); math_Matrix DD(aDD, 1, 1, 1, 2); UV(1) = U; UV(2) = V; sp.Values(UV, FF, DD); MakeWalkingPoint(Case - 10, U, V, sp, Psol); } else { throw Standard_ConstructionError(); } } void IntWalk_IWalking::OpenLine(const Standard_Integer N, const IntSurf_PntOn2S& Psol, const ThePOPIterator& Pnts1, TheIWFunction& sp, const Handle(IntWalk_TheIWLine)& Line ) // **************** open the line and restart in the other direction******** { ThePointOfPath PathPnt; Standard_Real aUV[2], aFF[1], aDD[1][2]; math_Vector UV(aUV,1, 2); math_Vector FF(aFF,1, 1); math_Matrix DD(aDD,1, 1, 1, 2); previousPoint = Line->Value(1); if (!reversed) { previousPoint.ParametersOnS2(UV(1),UV(2)); } else { previousPoint.ParametersOnS1(UV(1),UV(2)); } sp.Values(UV, FF, DD); previousd3d = sp.Direction3d(); previousd2d = sp.Direction2d(); if (N>0) { //departure point given at input PathPnt = Pnts1.Value(N); //mark the line as open with a given stop point Line->AddStatusFirst(Standard_False,Standard_True,N,PathPnt); AddPointInCurrentLine(N,PathPnt,Line); } else { if (N <0) Line->AddPoint(Psol); Line->AddStatusFirst(Standard_False,Standard_False); //mark the line as open without given stop point } Line->Reverse(); //inverser la ligne Line->SetTangentVector(previousd3d.Reversed(),Line->NbPoints()); } Standard_Boolean IntWalk_IWalking::IsValidEndPoint(const Standard_Integer IndOfPoint, const Standard_Integer IndOfLine) { if (PointLineLine.IsEmpty()) return Standard_True; TColStd_ListIteratorOfListOfInteger itl(PointLineLine(IndOfPoint)); for (; itl.More(); itl.Next()) if (itl.Value() == IndOfLine) { PointLineLine(IndOfPoint).Remove(itl); return Standard_True; } return Standard_False; } void IntWalk_IWalking::RemoveTwoEndPoints(const Standard_Integer IndOfPoint) { if (PointLineLine.IsBound(IndOfPoint)) { Standard_Integer Line1 = PointLineLine(IndOfPoint).First(); Standard_Integer Line2 = PointLineLine(IndOfPoint).Last(); for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++) { if (seqAlone(iseq) == Line1 || seqAlone(iseq) == Line2) seqAlone.Remove(iseq--); } } } Standard_Boolean IntWalk_IWalking::IsPointOnLine(const gp_Pnt2d& theP2d, const Standard_Integer Irang) { const Handle(IntWalk_TheIWLine)& aLine = lines.Value(Abs(Irang)); for (Standard_Integer i = 1; i <= aLine->NbPoints(); i++) { gp_Pnt2d P2d1 = aLine->Value(i).ValueOnSurface(reversed); if (Abs(P2d1.X() - theP2d.X()) <= tolerance(1) && Abs(P2d1.Y() - theP2d.Y()) <= tolerance(2)) return Standard_True; if (i < aLine->NbPoints()) { gp_Pnt2d P2d2 = aLine->Value(i+1).ValueOnSurface(reversed); gp_Vec2d PP1(theP2d, P2d1); gp_Vec2d PP2(theP2d, P2d2); if (PP1 * PP2 < 0) return Standard_True; } } return Standard_False; } //================================================================================== //function : IsPointOnLine //purpose : Projects thePOn2S on the nearest segment of the already computed line. // The retrieved projection point (aPa) is refined using theSolver. // After the refinement, we will obtain a point aPb. // If thePOn2S is quite far from aPb then thePOn2S is not // in the line. // Every already computed line is checked. //================================================================================== Standard_Boolean IntWalk_IWalking::IsPointOnLine(const IntSurf_PntOn2S& thePOn2S, const math_Vector& theInfBounds, const math_Vector& theSupBounds, math_FunctionSetRoot& theSolver, TheIWFunction& theFunc) { const Standard_Real eps = Epsilon(1.); const gp_Pnt &aP3d = thePOn2S.Value(); for (Standard_Integer aLIdx = 1; aLIdx <= lines.Length(); aLIdx++) { const Handle(IntSurf_LineOn2S) &aL = lines(aLIdx)->Line(); if (aL->IsOutBox(aP3d)) continue; //Look for the nearest segment Standard_Real aUMin = 0.0, aVMin = 0.0; Standard_Real aMinSqDist = RealLast(); for (Standard_Integer aPtIdx = 1; aPtIdx < aL->NbPoints(); aPtIdx++) { const gp_Pnt &aP1 = aL->Value(aPtIdx).Value(); const gp_Pnt &aP2 = aL->Value(aPtIdx + 1).Value(); const gp_XYZ aP1P(aP3d.XYZ() - aP1.XYZ()); const gp_XYZ aP1P2(aP2.XYZ() - aP1.XYZ()); const Standard_Real aSq12 = aP1P2.SquareModulus(); if (aSq12 < gp::Resolution()) continue; const Standard_Real aDP = aP1P.Dot(aP1P2); Standard_Real aSqD = RealLast(); if (aDP < 0.0) { continue; } else if (aDP > aSq12) { continue; } else { aSqD = aP1P.CrossSquareMagnitude(aP1P2) / aSq12; } if (aSqD < aMinSqDist) { aMinSqDist = aSqD; const Standard_Real aL1 = aDP / aSq12; const Standard_Real aL2 = 1.0 - aL1; if (aL1 < eps || aL2 < eps) { return Standard_True; } Standard_Real aU1, aV1, aU2, aV2; aL->Value(aPtIdx).ParametersOnSurface(reversed, aU1, aV1); aL->Value(aPtIdx + 1).ParametersOnSurface(reversed, aU2, aV2); aUMin = aL1*aU2 + aL2*aU1; aVMin = aL1*aV2 + aL2*aV1; } } if (aMinSqDist > Precision::Infinite()) continue; math_Vector aVecPrms(1, 2); aVecPrms(1) = aUMin; aVecPrms(2) = aVMin; theSolver.Perform(theFunc, aVecPrms, theInfBounds, theSupBounds); if (!theSolver.IsDone()) continue; theSolver.Root(aVecPrms); const gp_Pnt aPa(theFunc.PSurface()->Value(aUMin, aVMin)), aPb(theFunc.PSurface()->Value(aVecPrms(1), aVecPrms(2))); const Standard_Real aSqD1 = aPb.SquareDistance(aP3d); const Standard_Real aSqD2 = aPa.SquareDistance(aPb); if (aSqD1 < 4.0*aSqD2) { return Standard_True; } } return Standard_False; }