// 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. #include void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult, const TColStd_SequenceOfReal& Vmult, const ThePOPIterator& Pnts1, const ThePOLIterator& Pnts2, TheIWFunction& Func, Standard_Boolean& Rajout ) // *********** Processing of closed line ********************** // // for any interior non-processed point // calculate the step of advancement=step depending on the arrow and max step // calculate a point of approach (this point is on the tangent to the section // of distance = no interior point) // conditions // (all calculated points do not form a closed loop) // or // (all points do not form an open line going from // one border of the domain to the other or from a point tangent // to the border or from 2 tangent points : single cases) // // frame the point of approach on borders if necessary // calculate the point // if point not found divide the step // test of stop // calculate step depending on the arrow and the max step (stop possible) // // ******************************************************************** { Standard_Integer I,N = 0,SaveN = 0; Standard_Real aBornInf[2], aBornSup[2], aUVap[2]; math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2); math_Vector Uvap(aUVap,1,2);// parameters of current approach Standard_Real PasC; // step of advancement on the tangent Standard_Real PasCu; // step of advancement current by U Standard_Real PasCv; // step of advancement current by V Standard_Real PasSav; // save first step of advancement Standard_Boolean Arrive;// show if line ends Standard_Boolean Cadre; // show if on border of the domains Standard_Boolean ArretAjout; // show if on the added point IntSurf_PntOn2S Psol; Handle(IntWalk_TheIWLine) CurrentLine; //line under construction ThePointOfPath PathPnt; ThePointOfLoop LoopPnt; Standard_Boolean Tgtbeg,Tgtend; Standard_Integer StepSign; IntWalk_StatusDeflection aStatus = IntWalk_OK, StatusPrecedent; Standard_Integer NbDivision ; // number of divisions of step // during calculation of 1 section Standard_Integer Ipass ; //index in the iterator of points on edge of point of passage BornInf(1) = Um; BornSup(1) = UM; BornInf(2) = Vm; BornSup(2) = VM; math_FunctionSetRoot Rsnld(Func,tolerance); Standard_Integer nbLoop = Pnts2.Length(); // Check borders for degeneracy: math_Matrix D(1,1,1,2); const Standard_Integer aNbSamplePnt = 10; Standard_Boolean isLeftDegeneratedBorder[2] = {Standard_True, Standard_True}; Standard_Boolean isRightDegeneratedBorder[2] = {Standard_True, Standard_True}; math_Vector aStep(1,2); aStep = (BornSup - BornInf) / (aNbSamplePnt - 1); for(Standard_Integer aBorderIdx = 1; aBorderIdx <= 2; aBorderIdx++) { Standard_Integer aChangeIdx = aBorderIdx == 2? 1 : 2; math_Vector UV(1,2); // Left border. UV(aBorderIdx) = BornInf(aBorderIdx); for(Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++) { Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx); UV(aChangeIdx) = aParam; Func.Derivatives(UV, D); if ( Abs(D(1, aChangeIdx) ) > Precision::Confusion()) { isLeftDegeneratedBorder[aBorderIdx - 1] = Standard_False; break; } } // Right border. UV(aBorderIdx) = BornSup(aBorderIdx); for(Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++) { Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx); UV(aChangeIdx) = aParam; Func.Derivatives(UV, D); if ( Abs(D(1, aChangeIdx) ) > Precision::Confusion()) { isRightDegeneratedBorder[aBorderIdx - 1] = Standard_False; break; } } } for (I = 1;I<=nbLoop;I++) { if (wd2[I].etat > 12) { // start point of closed line LoopPnt = Pnts2.Value(I); previousPoint.SetValue(ThePointOfLoopTool::Value3d(LoopPnt),reversed, wd2[I].ustart,wd2[I].vstart); previousd3d = ThePointOfLoopTool::Direction3d(LoopPnt); previousd2d = ThePointOfLoopTool::Direction2d(LoopPnt); CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator()); CurrentLine->AddPoint(previousPoint); CurrentLine->SetTangentVector(previousd3d,1); Tgtbeg = Standard_False; Tgtend = Standard_False; Uvap(1) = wd2[I].ustart; Uvap(2) = wd2[I].vstart; StepSign = 1; // first step of advancement Standard_Real d2dx = Abs(previousd2d.X()); Standard_Real d2dy = Abs(previousd2d.Y()); if (d2dx < tolerance(1)) { PasC = pas * (VM-Vm)/d2dy; } else if (d2dy < tolerance(2)) { PasC = pas * (UM-Um)/d2dx; } else { PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy); } PasSav = PasC; Arrive = Standard_False; ArretAjout = Standard_False; NbDivision = 0; StatusPrecedent = IntWalk_OK; Standard_Integer aNbIter = 10; while (!Arrive) { // as no test of stop is passed Cadre=Cadrage(BornInf,BornSup,Uvap,PasC, StepSign); // border? #ifdef CHRONO Chronrsnld.Start(); #endif Rsnld.Perform(Func,Uvap,BornInf,BornSup); #ifdef CHRONO Chronrsnld.Stop(); #endif if (Cadre) { // update of limits. BornInf(1) = Um;BornSup(1) = UM;BornInf(2) = Vm;BornSup(2) = VM; } if (Rsnld.IsDone()) { if (Abs(Func.Root()) > Func.Tolerance()) { // no solution for the tolerance PasC = PasC/2.; PasCu = Abs(PasC*previousd2d.X()); PasCv = Abs(PasC*previousd2d.Y()); if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) { if (CurrentLine->NbPoints()==1) { RemoveTwoEndPoints(I); break; //cancel the line } if (wd2[I].etat >12) { //the line should become open wd2[I].etat = 12; //declare it open ArretAjout = Standard_False; OpenLine(0,Psol,Pnts1,Func,CurrentLine); StepSign = -1; StatusPrecedent = IntWalk_OK; Arrive = Standard_False; PasC = PasSav; Rajout = Standard_True; seqAlone.Append(-lines.Length()-1); seqAjout.Append(-lines.Length()-1); } else { // line s is open Arrive =Standard_True; CurrentLine->AddStatusLast(Standard_False); Rajout = Standard_True; seqAlone.Append(lines.Length()+1); seqAjout.Append(lines.Length()+1); Tgtend = Standard_True; } /* Arrive = Standard_True; CurrentLine->AddStatusFirstLast(Standard_False, Standard_False,Standard_False); Rajout = Standard_True; seqAlone.Append(lines.Length()+1); seqAjout.Append(lines.Length()+1); Tgtend = Standard_True; */ } } else { // there is a solution Rsnld.Root(Uvap); // Avoid unitialized memory access. if (CurrentLine->NbPoints() > 2) { for(Standard_Integer aCoordIdx = 1; aCoordIdx <= 2; aCoordIdx++) { // Check degenerated cases and fix if possible. if ( ( isLeftDegeneratedBorder[aCoordIdx - 1] && Abs (Uvap(aCoordIdx) - BornInf(aCoordIdx)) < Precision::PConfusion())|| (isRightDegeneratedBorder[aCoordIdx - 1] && Abs (Uvap(aCoordIdx) - BornSup(aCoordIdx)) < Precision::PConfusion()) ) { Standard_Real uvprev[2], uv[2]; if (!reversed) { CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS2(uvprev[0], uvprev[1]); CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS2(uv[0], uv[1]); } else { CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS1(uvprev[0], uvprev[1]); CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS1(uv[0], uv[1]); } Standard_Real aScaleCoeff = 0.0; // Avoid finite cycle which lead to stop computing iline. if (aStatus != IntWalk_PasTropGrand) { // Make linear extrapolation. if ( Abs(uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]) > gp::Resolution()) aScaleCoeff = Abs ((Uvap(aCoordIdx) - uv[aCoordIdx - 1]) / (uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]) ); Standard_Integer aFixIdx = aCoordIdx == 1? 2 : 1; // Fixing index; Uvap(aFixIdx) = uv[aFixIdx - 1] + (uv[aFixIdx - 1] - uvprev[aFixIdx - 1]) * aScaleCoeff; } } } } Arrive = TestArretPassage(Umult,Vmult,Uvap,I,Ipass); if (Arrive) {//reset proper parameter to test the arrow. Psol = CurrentLine->Value(1); if (!reversed) { Psol.ParametersOnS2(Uvap(1),Uvap(2)); } else { Psol.ParametersOnS1(Uvap(1),Uvap(2)); } Cadre=Standard_False; //in case if there is a frame and arrival at the same time } else { // modif jag 940615 if (Rajout) { // test on added points ArretAjout =TestArretAjout(Func,Uvap,N,Psol); SaveN = N; if (ArretAjout) { if (N >0) { Tgtend = lines.Value(N)->IsTangentAtEnd(); N = -N; } else { Tgtend = lines.Value(-N)->IsTangentAtBegining(); } Arrive = (wd2[I].etat == 12); } } if (!ArretAjout&& Cadre) { // test on already marked points if (CurrentLine->NbPoints() == 1) { RemoveTwoEndPoints(I); break; // cancel the line } TestArretCadre(Umult,Vmult,CurrentLine,Func,Uvap,N); SaveN = N; // if (N==0) { if (N <= 0) { // jag 941017 MakeWalkingPoint(2,Uvap(1),Uvap(2),Func,Psol); Tgtend = Func.IsTangent(); // jag 940616 N = -N; } Arrive = (wd2[I].etat == 12); // the line is open } } aStatus = TestDeflection(Func, Arrive,Uvap,StatusPrecedent, NbDivision,PasC,StepSign); StatusPrecedent = aStatus; if (aStatus == IntWalk_PasTropGrand) {// division of the step Arrive = Standard_False; ArretAjout = Standard_False; Tgtend = Standard_False; // jag 940616 if (!reversed) { previousPoint.ParametersOnS2(Uvap(1),Uvap(2)); } else { previousPoint.ParametersOnS1(Uvap(1),Uvap(2)); } } else if (ArretAjout || Cadre) { if (Arrive) { // line s is open CurrentLine->AddStatusLast(Standard_False); //if (aStatus != IntWalk_ArretSurPointPrecedent) CurrentLine->AddPoint(Psol); //Remove from and, if it is first found point, //from too if (IsValidEndPoint(I, SaveN)) { for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++) if (seqAlone(iseq) == SaveN) { seqAlone.Remove(iseq); break; } if (CurrentLine->NbPoints() <= 3) for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++) if (seqAjout(iseq) == SaveN) { seqAjout.Remove(iseq); break; } } else { if (seqAlone.Last() == -lines.Length()-1) { seqAlone.Remove(seqAlone.Length()); seqAjout.Remove(seqAjout.Length()); } RemoveTwoEndPoints(I); Arrive = Standard_False; break; //cancel the line } if (Cadre && N==0) { Rajout = Standard_True; //seqAlone.Append(lines.Length()+1); seqAjout.Append(lines.Length()+1); } } else { // open wd2[I].etat = 12; // declare it open Tgtbeg = Tgtend; Tgtend = Standard_False; ArretAjout = Standard_False; StepSign = -1; StatusPrecedent = IntWalk_OK; PasC = PasSav; if (aStatus == IntWalk_ArretSurPointPrecedent) { CurrentLine->AddPoint(Psol); OpenLine(0,Psol,Pnts1,Func,CurrentLine); } else { OpenLine(-lines.Length()-1,Psol,Pnts1,Func,CurrentLine); } //Remove from and, if it is first found point, //from too if (IsValidEndPoint(I, SaveN)) { for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++) if (seqAlone(iseq) == SaveN) { seqAlone.Remove(iseq); break; } if (CurrentLine->NbPoints() <= 2) for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++) if (seqAjout(iseq) == SaveN) { seqAjout.Remove(iseq); break; } } else { RemoveTwoEndPoints(I); break; //cancel the line } if (Cadre && N==0) { Rajout = Standard_True; seqAjout.Append(-lines.Length()-1); } } } else if (aStatus == IntWalk_ArretSurPointPrecedent) { if (CurrentLine->NbPoints() == 1) { //cancel the line Arrive = Standard_False; RemoveTwoEndPoints(I); break; } if (wd2[I].etat >12) { //the line should become open wd2[I].etat = 12; //declare it open ArretAjout = Standard_False; OpenLine(0,Psol,Pnts1,Func,CurrentLine); StepSign = -1; StatusPrecedent = IntWalk_OK; Arrive = Standard_False; PasC = PasSav; Rajout = Standard_True; seqAlone.Append(-lines.Length()-1); seqAjout.Append(-lines.Length()-1); } else { // line s is open Arrive =Standard_True; CurrentLine->AddStatusLast(Standard_False); Rajout = Standard_True; seqAlone.Append(lines.Length()+1); seqAjout.Append(lines.Length()+1); } } else if (Arrive) { if (wd2[I].etat > 12) { //line closed good case CurrentLine->AddStatusFirstLast(Standard_True, Standard_False,Standard_False); CurrentLine->AddPoint(CurrentLine->Value(1)); } else if (N >0) { //point of stop given at input PathPnt = Pnts1.Value(N); CurrentLine->AddStatusLast(Standard_True,N,PathPnt); AddPointInCurrentLine(N,PathPnt,CurrentLine); } } else if (aStatus == IntWalk_ArretSurPoint) { if (wd2[I].etat >12) { //line should become open wd2[I].etat = 12; //declare it open Tgtbeg = Standard_True; Tgtend = Standard_False; N= -lines.Length()-1; Psol.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2)); OpenLine(N,Psol,Pnts1,Func,CurrentLine); StepSign = -1; Rajout = Standard_True; seqAlone.Append(N); seqAjout.Append(N); StatusPrecedent = IntWalk_OK; Arrive = Standard_False; PasC = PasSav; } else { Arrive = Standard_True; if (Ipass!=0) { //point of passage, point of stop PathPnt = Pnts1.Value(Ipass); CurrentLine->AddStatusLast(Standard_True,Ipass,PathPnt); AddPointInCurrentLine(Ipass,PathPnt,CurrentLine); } else { CurrentLine->AddStatusLast(Standard_False); IntSurf_PntOn2S newP; newP.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2)); CurrentLine->AddPoint(newP); Rajout = Standard_True; seqAlone.Append(lines.Length()+1); seqAjout.Append(lines.Length()+1); } } } else if (aStatus == IntWalk_OK) { if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass); previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2)); previousd3d = Func.Direction3d(); previousd2d = Func.Direction2d(); CurrentLine->AddPoint(previousPoint); } else if (aStatus == IntWalk_PointConfondu) { aNbIter --; } } } else { //no numerical solution NotDone PasC = PasC/2.; PasCu = Abs(PasC*previousd2d.X()); PasCv = Abs(PasC*previousd2d.Y()); if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) { if (CurrentLine->NbPoints() == 1) { RemoveTwoEndPoints(I); break; // cancel the line } if (wd2[I].etat >12) { //the line should become open wd2[I].etat = 12; //declare it open ArretAjout = Standard_False; OpenLine(0,Psol,Pnts1,Func,CurrentLine); StepSign = -1; StatusPrecedent = IntWalk_OK; Arrive = Standard_False; PasC = PasSav; Rajout = Standard_True; seqAlone.Append(-lines.Length()-1); seqAjout.Append(-lines.Length()-1); } else { // line s is open Arrive =Standard_True; CurrentLine->AddStatusLast(Standard_False); Tgtend = Standard_True; Rajout = Standard_True; seqAlone.Append(lines.Length()+1); seqAjout.Append(lines.Length()+1); } /* Arrive = Standard_True; CurrentLine->AddStatusFirstLast(Standard_False,Standard_False, Standard_False); Tgtend = Standard_True; Rajout = Standard_True; seqAlone.Append(lines.Length()+1); seqAjout.Append(lines.Length()+1); */ } } if(aNbIter < 0) break; }// end of started line if (Arrive) { CurrentLine->SetTangencyAtBegining(Tgtbeg); CurrentLine->SetTangencyAtEnd(Tgtend); lines.Append(CurrentLine); wd2[I].etat=-wd2[I].etat; //mark point as processed } } //end of processing of start point } //end of all start points }