Warning, /include/opencascade/IntWalk_IWalking_4.gxx is written in an unsupported language. File is not indexed.
0001 // Copyright (c) 1995-1999 Matra Datavision
0002 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014
0015 #include <NCollection_IncAllocator.hxx>
0016
0017 void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
0018 const TColStd_SequenceOfReal& Vmult,
0019 const ThePOPIterator& Pnts1,
0020 const ThePOLIterator& Pnts2,
0021 TheIWFunction& Func,
0022 Standard_Boolean& Rajout )
0023 // *********** Processing of closed line **********************
0024 //
0025 // for any interior non-processed point
0026 // calculate the step of advancement=step depending on the arrow and max step
0027 // calculate a point of approach (this point is on the tangent to the section
0028 // of distance = no interior point)
0029 // conditions
0030 // (all calculated points do not form a closed loop)
0031 // or
0032 // (all points do not form an open line going from
0033 // one border of the domain to the other or from a point tangent
0034 // to the border or from 2 tangent points : single cases)
0035 //
0036 // frame the point of approach on borders if necessary
0037 // calculate the point
0038 // if point not found divide the step
0039 // test of stop
0040 // calculate step depending on the arrow and the max step (stop possible)
0041 //
0042 // ********************************************************************
0043 {
0044 Standard_Integer I = 0, N = 0,SaveN = 0;
0045 Standard_Real aBornInf[2] = {}, aBornSup[2] = {}, aUVap[2] = {};
0046 math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2);
0047 math_Vector Uvap(aUVap,1,2);// parameters of current approach
0048 Standard_Real PasC = 0.0; // step of advancement on the tangent
0049 Standard_Real PasCu = 0.0; // step of advancement current by U
0050 Standard_Real PasCv = 0.0; // step of advancement current by V
0051 Standard_Real PasSav = 0.0; // save first step of advancement
0052 Standard_Boolean Arrive = false;// show if line ends
0053 Standard_Boolean Cadre = false; // show if on border of the domains
0054 Standard_Boolean ArretAjout = false; // show if on the added point
0055 IntSurf_PntOn2S Psol;
0056 Handle(IntWalk_TheIWLine) CurrentLine; //line under construction
0057 ThePointOfPath PathPnt;
0058 ThePointOfLoop LoopPnt;
0059
0060 Standard_Boolean Tgtbeg = false, Tgtend = false;
0061
0062 Standard_Integer StepSign = 0;
0063
0064 IntWalk_StatusDeflection aStatus = IntWalk_OK, StatusPrecedent;
0065 Standard_Integer NbDivision = 0; // number of divisions of step
0066 // during calculation of 1 section
0067
0068 Standard_Integer Ipass = 0;
0069 //index in the iterator of points on edge of point of passage
0070
0071
0072 BornInf(1) = Um;
0073 BornSup(1) = UM;
0074 BornInf(2) = Vm;
0075 BornSup(2) = VM;
0076
0077 math_FunctionSetRoot Rsnld(Func,tolerance);
0078 Standard_Integer nbLoop = Pnts2.Length();
0079
0080 // Check borders for degeneracy:
0081 math_Matrix D(1,1,1,2);
0082 const Standard_Integer aNbSamplePnt = 10;
0083 Standard_Boolean isLeftDegeneratedBorder[2] = {Standard_True, Standard_True};
0084 Standard_Boolean isRightDegeneratedBorder[2] = {Standard_True, Standard_True};
0085 math_Vector aStep(1,2);
0086 aStep = (BornSup - BornInf) / (aNbSamplePnt - 1);
0087 for(Standard_Integer aBorderIdx = 1; aBorderIdx <= 2; aBorderIdx++)
0088 {
0089 Standard_Integer aChangeIdx = aBorderIdx == 2? 1 : 2;
0090 math_Vector UV(1,2);
0091
0092 // Left border.
0093 UV(aBorderIdx) = BornInf(aBorderIdx);
0094 for(Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++)
0095 {
0096 Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx);
0097 UV(aChangeIdx) = aParam;
0098 Func.Derivatives(UV, D);
0099 if ( Abs(D(1, aChangeIdx) ) > Precision::Confusion())
0100 {
0101 isLeftDegeneratedBorder[aBorderIdx - 1] = Standard_False;
0102 break;
0103 }
0104 }
0105
0106 // Right border.
0107 UV(aBorderIdx) = BornSup(aBorderIdx);
0108 for(Standard_Integer aParamIdx = 0; aParamIdx < aNbSamplePnt; aParamIdx++)
0109 {
0110 Standard_Real aParam = BornInf(aChangeIdx) + aParamIdx * aStep(aChangeIdx);
0111 UV(aChangeIdx) = aParam;
0112 Func.Derivatives(UV, D);
0113 if ( Abs(D(1, aChangeIdx) ) > Precision::Confusion())
0114 {
0115 isRightDegeneratedBorder[aBorderIdx - 1] = Standard_False;
0116 break;
0117 }
0118 }
0119 }
0120
0121 TheIWFunction aFuncForDuplicate = Func;
0122
0123 for (I = 1;I<=nbLoop;I++) {
0124 if (wd2[I].etat > 12)
0125 { // start point of closed line
0126 LoopPnt = Pnts2.Value(I);
0127 previousPoint.SetValue(ThePointOfLoopTool::Value3d(LoopPnt), reversed,
0128 wd2[I].ustart, wd2[I].vstart);
0129
0130 if (IsPointOnLine(previousPoint, BornInf, BornSup, Rsnld, aFuncForDuplicate))
0131 {
0132 wd2[I].etat = -wd2[I].etat; //mark point as processed
0133 continue;
0134 }
0135
0136 previousd3d = ThePointOfLoopTool::Direction3d(LoopPnt);
0137 previousd2d = ThePointOfLoopTool::Direction2d(LoopPnt);
0138
0139 CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
0140 CurrentLine->AddPoint(previousPoint);
0141 CurrentLine->SetTangentVector(previousd3d,1);
0142 Tgtbeg = Standard_False;
0143 Tgtend = Standard_False;
0144 Uvap(1) = wd2[I].ustart;
0145 Uvap(2) = wd2[I].vstart;
0146
0147 StepSign = 1;
0148
0149 // first step of advancement
0150
0151 Standard_Real d2dx = Abs(previousd2d.X());
0152 Standard_Real d2dy = Abs(previousd2d.Y());
0153 if (d2dx < tolerance(1)) {
0154 PasC = pas * (VM-Vm)/d2dy;
0155 }
0156 else if (d2dy < tolerance(2)) {
0157 PasC = pas * (UM-Um)/d2dx;
0158 }
0159 else {
0160 PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
0161 }
0162
0163 PasSav = PasC;
0164
0165 Arrive = Standard_False;
0166 ArretAjout = Standard_False;
0167 NbDivision = 0;
0168 StatusPrecedent = IntWalk_OK;
0169 Standard_Integer aNbIter = 10;
0170 while (!Arrive) { // as no test of stop is passed
0171 Cadre=Cadrage(BornInf,BornSup,Uvap,PasC, StepSign); // border?
0172 #ifdef CHRONO
0173 Chronrsnld.Start();
0174 #endif
0175
0176 Rsnld.Perform(Func,Uvap,BornInf,BornSup);
0177
0178 #ifdef CHRONO
0179 Chronrsnld.Stop();
0180 #endif
0181 Standard_Boolean isOnDegeneratedBorder = Standard_False;
0182
0183 if (Cadre) { // update of limits.
0184 BornInf(1) = Um;BornSup(1) = UM;BornInf(2) = Vm;BornSup(2) = VM;
0185 }
0186 if (Rsnld.IsDone()) {
0187 if (Abs(Func.Root()) > Func.Tolerance()) { // no solution for the tolerance
0188 PasC = PasC/2.;
0189 PasCu = Abs(PasC*previousd2d.X());
0190 PasCv = Abs(PasC*previousd2d.Y());
0191
0192 if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
0193 if (CurrentLine->NbPoints()==1)
0194 {
0195 RemoveTwoEndPoints(I);
0196 break; //cancel the line
0197 }
0198 if (wd2[I].etat >12) { //the line should become open
0199 wd2[I].etat = 12; //declare it open
0200 ArretAjout = Standard_False;
0201 OpenLine(0,Psol,Pnts1,Func,CurrentLine);
0202 StepSign = -1;
0203 StatusPrecedent = IntWalk_OK;
0204 Arrive = Standard_False;
0205 PasC = PasSav;
0206 Rajout = Standard_True;
0207 seqAlone.Append(-lines.Length()-1);
0208 seqAjout.Append(-lines.Length()-1);
0209 }
0210 else { // line s is open
0211 Arrive =Standard_True;
0212 CurrentLine->AddStatusLast(Standard_False);
0213 Rajout = Standard_True;
0214 seqAlone.Append(lines.Length()+1);
0215 seqAjout.Append(lines.Length()+1);
0216 Tgtend = Standard_True;
0217 }
0218 /*
0219 Arrive = Standard_True;
0220 CurrentLine->AddStatusFirstLast(Standard_False,
0221 Standard_False,Standard_False);
0222 Rajout = Standard_True;
0223 seqAlone.Append(lines.Length()+1);
0224 seqAjout.Append(lines.Length()+1);
0225 Tgtend = Standard_True;
0226 */
0227 }
0228 }
0229 else { // there is a solution
0230 Rsnld.Root(Uvap);
0231
0232 // Avoid uninitialized memory access.
0233 if (CurrentLine->NbPoints() > 2)
0234 {
0235 for(Standard_Integer aCoordIdx = 1; aCoordIdx <= 2; aCoordIdx++)
0236 {
0237 // Check degenerated cases and fix if possible.
0238 if ( ( isLeftDegeneratedBorder[aCoordIdx - 1]
0239 && Abs (Uvap(aCoordIdx) - BornInf(aCoordIdx)) < Precision::PConfusion())||
0240 (isRightDegeneratedBorder[aCoordIdx - 1]
0241 && Abs (Uvap(aCoordIdx) - BornSup(aCoordIdx)) < Precision::PConfusion()) )
0242 {
0243 Standard_Real uvprev[2], uv[2];
0244 if (!reversed)
0245 {
0246 CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS2(uvprev[0], uvprev[1]);
0247 CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS2(uv[0], uv[1]);
0248 }
0249 else
0250 {
0251 CurrentLine->Value(CurrentLine->NbPoints() - 1).ParametersOnS1(uvprev[0], uvprev[1]);
0252 CurrentLine->Value(CurrentLine->NbPoints()).ParametersOnS1(uv[0], uv[1]);
0253 }
0254
0255 Standard_Real aScaleCoeff = 0.0;
0256
0257 // Avoid finite cycle which lead to stop computing iline.
0258 if (aStatus != IntWalk_PasTropGrand)
0259 {
0260 // Make linear extrapolation.
0261 if ( Abs(uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]) > gp::Resolution())
0262 aScaleCoeff = Abs ((Uvap(aCoordIdx) - uv[aCoordIdx - 1])
0263 / (uv[aCoordIdx - 1] - uvprev[aCoordIdx - 1]) );
0264 Standard_Integer aFixIdx = aCoordIdx == 1? 2 : 1; // Fixing index;
0265 Uvap(aFixIdx) = uv[aFixIdx - 1] + (uv[aFixIdx - 1] - uvprev[aFixIdx - 1]) * aScaleCoeff;
0266 isOnDegeneratedBorder = Standard_True;
0267 }
0268 }
0269 }
0270 }
0271
0272 Arrive = TestArretPassage(Umult,Vmult,Uvap,I,Ipass);
0273 if (Arrive) {//reset proper parameter to test the arrow.
0274 Psol = CurrentLine->Value(1);
0275 if (!reversed) {
0276 Psol.ParametersOnS2(Uvap(1),Uvap(2));
0277 }
0278 else {
0279 Psol.ParametersOnS1(Uvap(1),Uvap(2));
0280 }
0281 Cadre=Standard_False;
0282 //in case if there is a frame and arrival at the same time
0283 }
0284 else { // modif jag 940615
0285 if (Rajout) { // test on added points
0286 ArretAjout =TestArretAjout(Func,Uvap,N,Psol);
0287 SaveN = N;
0288 if (ArretAjout) {
0289 if (N >0) {
0290 Tgtend = lines.Value(N)->IsTangentAtEnd();
0291 N = -N;
0292 }
0293 else {
0294 Tgtend = lines.Value(-N)->IsTangentAtBegining();
0295 }
0296 Arrive = (wd2[I].etat == 12);
0297 }
0298 }
0299
0300 if (!ArretAjout&& Cadre) { // test on already marked points
0301 if (CurrentLine->NbPoints() == 1)
0302 {
0303 RemoveTwoEndPoints(I);
0304 break; // cancel the line
0305 }
0306 TestArretCadre(Umult,Vmult,CurrentLine,Func,Uvap,N);
0307 SaveN = N;
0308 // if (N==0) {
0309 if (N <= 0) { // jag 941017
0310 MakeWalkingPoint(2,Uvap(1),Uvap(2),Func,Psol);
0311 Tgtend = Func.IsTangent(); // jag 940616
0312 if (isOnDegeneratedBorder)
0313 Tgtend = Standard_True;
0314 N = -N;
0315 }
0316 Arrive = (wd2[I].etat == 12); // the line is open
0317 }
0318 }
0319 aStatus = TestDeflection(Func, Arrive,Uvap,StatusPrecedent,
0320 NbDivision,PasC,StepSign);
0321
0322 if (isOnDegeneratedBorder && Tgtend)
0323 aStatus = IntWalk_ArretSurPoint;
0324
0325 StatusPrecedent = aStatus;
0326 if (aStatus == IntWalk_PasTropGrand) {// division of the step
0327 Arrive = Standard_False;
0328 ArretAjout = Standard_False;
0329 Tgtend = Standard_False; // jag 940616
0330 if (!reversed) {
0331 previousPoint.ParametersOnS2(Uvap(1),Uvap(2));
0332 }
0333 else {
0334 previousPoint.ParametersOnS1(Uvap(1),Uvap(2));
0335 }
0336 }
0337 else if (ArretAjout || Cadre) {
0338
0339 if (Arrive) { // line s is open
0340 CurrentLine->AddStatusLast(Standard_False);
0341 //if (aStatus != IntWalk_ArretSurPointPrecedent)
0342 CurrentLine->AddPoint(Psol);
0343
0344 //Remove <SaveN> from <seqAlone> and, if it is first found point,
0345 //from <seqAjout> too
0346 if (IsValidEndPoint(I, SaveN))
0347 {
0348 for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
0349 if (seqAlone(iseq) == SaveN)
0350 {
0351 seqAlone.Remove(iseq);
0352 break;
0353 }
0354 if (CurrentLine->NbPoints() <= 3)
0355 for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++)
0356 if (seqAjout(iseq) == SaveN)
0357 {
0358 seqAjout.Remove(iseq);
0359 break;
0360 }
0361 }
0362 else
0363 {
0364 if (seqAlone.Last() == -lines.Length()-1)
0365 {
0366 seqAlone.Remove(seqAlone.Length());
0367 seqAjout.Remove(seqAjout.Length());
0368 }
0369 RemoveTwoEndPoints(I);
0370 Arrive = Standard_False;
0371 break; //cancel the line
0372 }
0373
0374 if (Cadre && N==0) {
0375 Rajout = Standard_True;
0376 //seqAlone.Append(lines.Length()+1);
0377 seqAjout.Append(lines.Length()+1);
0378 }
0379
0380 }
0381 else { // open
0382 wd2[I].etat = 12; // declare it open
0383 Tgtbeg = Tgtend;
0384 Tgtend = Standard_False;
0385 ArretAjout = Standard_False;
0386 StepSign = -1;
0387 StatusPrecedent = IntWalk_OK;
0388 PasC = PasSav;
0389 //Check if <Psol> has been really updated
0390 if (Arrive || Rajout || (!ArretAjout && Cadre && SaveN <= 0))
0391 {
0392 if (aStatus == IntWalk_ArretSurPointPrecedent) {
0393 CurrentLine->AddPoint(Psol);
0394 OpenLine(0,Psol,Pnts1,Func,CurrentLine);
0395 }
0396 else {
0397 OpenLine(-lines.Length()-1,Psol,Pnts1,Func,CurrentLine);
0398 }
0399 }
0400 //Remove <SaveN> from <seqAlone> and, if it is first found point,
0401 //from <seqAjout> too
0402 if (IsValidEndPoint(I, SaveN))
0403 {
0404 for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
0405 if (seqAlone(iseq) == SaveN)
0406 {
0407 seqAlone.Remove(iseq);
0408 break;
0409 }
0410 if (CurrentLine->NbPoints() <= 2)
0411 for (Standard_Integer iseq = 1; iseq <= seqAjout.Length(); iseq++)
0412 if (seqAjout(iseq) == SaveN)
0413 {
0414 seqAjout.Remove(iseq);
0415 break;
0416 }
0417 }
0418 else
0419 {
0420 RemoveTwoEndPoints(I);
0421 break; //cancel the line
0422 }
0423
0424 if (Cadre && N==0) {
0425 Rajout = Standard_True;
0426 seqAjout.Append(-lines.Length()-1);
0427 }
0428 }
0429 }
0430 else if (aStatus == IntWalk_ArretSurPointPrecedent) {
0431 if (CurrentLine->NbPoints() == 1) { //cancel the line
0432 Arrive = Standard_False;
0433 RemoveTwoEndPoints(I);
0434 break;
0435 }
0436 if (wd2[I].etat >12) { //the line should become open
0437 wd2[I].etat = 12; //declare it open
0438 ArretAjout = Standard_False;
0439 OpenLine(0,Psol,Pnts1,Func,CurrentLine);
0440 StepSign = -1;
0441 StatusPrecedent = IntWalk_OK;
0442 Arrive = Standard_False;
0443 PasC = PasSav;
0444 Rajout = Standard_True;
0445 seqAlone.Append(-lines.Length()-1);
0446 seqAjout.Append(-lines.Length()-1);
0447 }
0448 else { // line s is open
0449 Arrive =Standard_True;
0450 CurrentLine->AddStatusLast(Standard_False);
0451 Rajout = Standard_True;
0452 seqAlone.Append(lines.Length()+1);
0453 seqAjout.Append(lines.Length()+1);
0454 }
0455 }
0456 else if (Arrive) {
0457 if (wd2[I].etat > 12) { //line closed good case
0458 CurrentLine->AddStatusFirstLast(Standard_True,
0459 Standard_False,Standard_False);
0460 CurrentLine->AddPoint(CurrentLine->Value(1));
0461 }
0462 else if ((N >0) && (Pnts1.Length() >= N))
0463 {
0464 //point of stop given at input
0465 PathPnt = Pnts1.Value(N);
0466 CurrentLine->AddStatusLast(Standard_True,N,PathPnt);
0467 AddPointInCurrentLine(N,PathPnt,CurrentLine);
0468 }
0469 }
0470 else if (aStatus == IntWalk_ArretSurPoint) {
0471 if (wd2[I].etat >12) { //line should become open
0472 wd2[I].etat = 12; //declare it open
0473 Tgtbeg = Standard_True;
0474 Tgtend = Standard_False;
0475 N= -lines.Length()-1;
0476 Psol.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
0477 OpenLine(N,Psol,Pnts1,Func,CurrentLine);
0478 StepSign = -1;
0479 Rajout = Standard_True;
0480 seqAlone.Append(N);
0481 seqAjout.Append(N);
0482 StatusPrecedent = IntWalk_OK;
0483 Arrive = Standard_False;
0484 PasC = PasSav;
0485 }
0486 else {
0487 Arrive = Standard_True;
0488 if (Ipass!=0) { //point of passage, point of stop
0489 PathPnt = Pnts1.Value(Ipass);
0490 CurrentLine->AddStatusLast(Standard_True,Ipass,PathPnt);
0491 AddPointInCurrentLine(Ipass,PathPnt,CurrentLine);
0492 }
0493 else {
0494 CurrentLine->AddStatusLast(Standard_False);
0495 IntSurf_PntOn2S newP;
0496 newP.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
0497 CurrentLine->AddPoint(newP);
0498 Rajout = Standard_True;
0499 seqAlone.Append(lines.Length()+1);
0500 seqAjout.Append(lines.Length()+1);
0501 }
0502 }
0503 }
0504 else if (aStatus == IntWalk_OK) {
0505 if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass);
0506 previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
0507 previousd3d = Func.Direction3d();
0508 previousd2d = Func.Direction2d();
0509 CurrentLine->AddPoint(previousPoint);
0510 }
0511 else if (aStatus == IntWalk_PointConfondu)
0512 {
0513 aNbIter --;
0514 }
0515 }
0516 }
0517 else { //no numerical solution NotDone
0518 PasC = PasC/2.;
0519 PasCu = Abs(PasC*previousd2d.X());
0520 PasCv = Abs(PasC*previousd2d.Y());
0521
0522 if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
0523 if (CurrentLine->NbPoints() == 1)
0524 {
0525 RemoveTwoEndPoints(I);
0526 break; // cancel the line
0527 }
0528 if (wd2[I].etat >12) { //the line should become open
0529 wd2[I].etat = 12; //declare it open
0530 ArretAjout = Standard_False;
0531 OpenLine(0,Psol,Pnts1,Func,CurrentLine);
0532 StepSign = -1;
0533 StatusPrecedent = IntWalk_OK;
0534 Arrive = Standard_False;
0535 PasC = PasSav;
0536 Rajout = Standard_True;
0537 seqAlone.Append(-lines.Length()-1);
0538 seqAjout.Append(-lines.Length()-1);
0539 }
0540 else { // line s is open
0541 Arrive =Standard_True;
0542 CurrentLine->AddStatusLast(Standard_False);
0543 Tgtend = Standard_True;
0544 Rajout = Standard_True;
0545 seqAlone.Append(lines.Length()+1);
0546 seqAjout.Append(lines.Length()+1);
0547 }
0548 /*
0549 Arrive = Standard_True;
0550 CurrentLine->AddStatusFirstLast(Standard_False,Standard_False,
0551 Standard_False);
0552 Tgtend = Standard_True;
0553 Rajout = Standard_True;
0554 seqAlone.Append(lines.Length()+1);
0555 seqAjout.Append(lines.Length()+1);
0556 */
0557 }
0558 }
0559
0560 if(aNbIter < 0)
0561 break;
0562 }// end of started line
0563 if (Arrive) {
0564 CurrentLine->SetTangencyAtBegining(Tgtbeg);
0565 CurrentLine->SetTangencyAtEnd(Tgtend);
0566
0567 lines.Append(CurrentLine);
0568 wd2[I].etat=-wd2[I].etat; //mark point as processed
0569 }
0570 } //end of processing of start point
0571 } //end of all start points
0572 }