Warning, /include/opencascade/Approx_ComputeLine.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 <Approx_ParametrizationType.hxx>
0016 #include <TColStd_Array1OfReal.hxx>
0017 #include <TColgp_Array1OfPnt.hxx>
0018 #include <TColgp_Array1OfPnt2d.hxx>
0019 #include <gp_Pnt.hxx>
0020 #include <gp_Pnt2d.hxx>
0021 #include <gp_Vec.hxx>
0022 #include <gp_Vec2d.hxx>
0023 #include <TColgp_Array1OfVec.hxx>
0024 #include <TColgp_Array1OfVec2d.hxx>
0025 #include <AppParCurves_Constraint.hxx>
0026 #include <AppParCurves_HArray1OfConstraintCouple.hxx>
0027 #include <AppParCurves_MultiPoint.hxx>
0028 #include <Precision.hxx>
0029 #include <math_IntegerVector.hxx>
0030 #include <math_Gauss.hxx>
0031 #include <math_Uzawa.hxx>
0032 #include <Approx_MCurvesToBSpCurve.hxx>
0033 #include <AppParCurves_ConstraintCouple.hxx>
0034
0035 #include <stdio.h>
0036
0037 #ifdef OCCT_DEBUG
0038 static Standard_Boolean mydebug = Standard_False;
0039
0040 #include <Geom_BezierCurve.hxx>
0041 #include <Geom2d_BezierCurve.hxx>
0042 #ifdef DRAW
0043 #include <DrawTrSurf.hxx>
0044 #include <Draw.hxx>
0045 #include <Draw_Appli.hxx>
0046 #endif
0047
0048 static void DUMP(const MultiLine& Line)
0049 {
0050 Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP;
0051 gp_Pnt P1;
0052 gp_Pnt2d P12d;
0053
0054 firstP = LineTool::FirstPoint(Line);
0055 lastP = LineTool::LastPoint(Line);
0056
0057 nbP3d = LineTool::NbP3d(Line);
0058 nbP2d = LineTool::NbP2d(Line);
0059 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0060 if (nbP3d == 0) mynbP3d = 1;
0061 if (nbP2d == 0) mynbP2d = 1;
0062
0063 TColgp_Array1OfPnt tabP(1, mynbP3d);
0064 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
0065
0066 std::cout <<"DUMP de la MultiLine entre "<<firstP <<" et "<<lastP<<": "<<std::endl;
0067 for (i = firstP; i <= lastP; i++) {
0068 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabP, tabP2d);
0069 else if (nbP2d != 0) LineTool::Value(Line, i, tabP2d);
0070 else if (nbP3d != 0) LineTool::Value(Line, i, tabP);
0071
0072 std::cout << "point "<<i<<":"<< std::endl;
0073 for (j = 1; j <= nbP3d; j++) {
0074 P1 = tabP(j);
0075 std::cout <<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<std::endl;
0076 }
0077 for (j = 1; j <= nbP2d; j++) {
0078 P12d = tabP2d(j);
0079 std::cout <<P12d.X()<<" "<<P12d.Y()<<std::endl;
0080 }
0081 }
0082
0083 }
0084
0085 static void DUMP(const AppParCurves_MultiCurve& C) {
0086 static Standard_Integer nbappel = 0;
0087 Standard_Integer i;
0088 Standard_Integer nbpoles = C.NbPoles();
0089
0090 Handle(Geom_BezierCurve) BSp;
0091 Handle(Geom2d_BezierCurve) BSp2d;
0092
0093 TColgp_Array1OfPnt tabPoles(1, nbpoles);
0094 TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles);
0095 char solname[100];
0096
0097 nbappel++;
0098 for (i = 1; i <= C.NbCurves(); i++) {
0099 if (C.Dimension(i) == 3) {
0100 C.Curve(i, tabPoles);
0101 BSp = new Geom_BezierCurve(tabPoles);
0102 sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel);
0103 #ifdef DRAW
0104 char* Temp = solname;
0105 DrawTrSurf::Set(Temp, BSp);
0106 // DrawTrSurf::Set(solname, BSp);
0107 #endif
0108 }
0109 else {
0110 C.Curve(i, tabPoles2d);
0111 BSp2d = new Geom2d_BezierCurve(tabPoles2d);
0112 sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel);
0113 #ifdef DRAW
0114 char* Temp = solname;
0115 DrawTrSurf::Set(Temp, BSp2d);
0116 // DrawTrSurf::Set(solname, BSp2d);
0117 #endif
0118 }
0119 }
0120 #ifdef DRAW
0121 dout.Flush();
0122 #endif
0123 }
0124
0125 #endif
0126
0127 static Standard_Boolean CheckMultiCurve(const AppParCurves_MultiCurve& theMultiCurve,
0128 const MultiLine& theLine,
0129 const Standard_Integer theIndfirst,
0130 const Standard_Integer theIndlast,
0131 Standard_Integer& theIndbad)
0132 {
0133 const Standard_Integer nbp3d = LineTool::NbP3d(theLine);
0134 const Standard_Integer nbp2d = LineTool::NbP2d(theLine);
0135
0136 const Standard_Real coeff = 4.; //2*2
0137
0138 if (nbp3d > 1) //only simple cases are analysed
0139 return Standard_True;
0140
0141 const Standard_Real MinScalProd = -0.9;
0142 const Standard_Real SqTol3d = Precision::SquareConfusion();
0143
0144 theIndbad = 0;
0145 Standard_Integer indbads [4];
0146 indbads[1] = indbads[2] = indbads[3] = 0;
0147
0148 Standard_Integer NbCur = theMultiCurve.NbCurves();
0149 Standard_Boolean LoopFound = Standard_False;
0150
0151 Standard_Integer aNbP3d = Max(nbp3d, 1);
0152 Standard_Integer aNbP2d = Max(nbp2d, 1);
0153
0154 TColgp_Array1OfPnt tabP(1, aNbP3d);
0155 TColgp_Array1OfPnt2d tabP2d(1, aNbP2d);
0156
0157 #ifdef DRAW
0158 char* name = new char[100];
0159 Standard_Integer nbbc = 1;
0160 Standard_Integer indc = 1;
0161 #endif
0162 if (theMultiCurve.Dimension(1) == 3 /*myNbP3d == 1*/)
0163 {
0164 TColgp_Array1OfPnt aPoles(1, theMultiCurve.NbPoles());
0165 theMultiCurve.Curve(1, aPoles);
0166 #ifdef DRAW
0167 Handle(Geom_Curve) theBezier = new Geom_BezierCurve(aPoles);
0168 sprintf(name, "bc3d_%d_%d", indc, nbbc);
0169 DrawTrSurf::Set(name, theBezier);
0170 #endif
0171 gp_Vec FirstVec, SecondVec;
0172 Standard_Integer indp = 2;
0173 while (indp <= aPoles.Upper())
0174 {
0175 FirstVec = gp_Vec(aPoles(1), aPoles(indp++));
0176 Standard_Real aLength = FirstVec.Magnitude();
0177 if (aLength > gp::Resolution())
0178 {
0179 FirstVec /= aLength;
0180 break;
0181 }
0182 }
0183 gp_Pnt MidPnt = aPoles(indp-1);
0184 //for (Standard_Integer k = 3; k <= aPoles.Upper(); k++)
0185 while (indp <= aPoles.Upper())
0186 {
0187 SecondVec = gp_Vec(MidPnt, aPoles(indp));
0188 Standard_Real aLength = SecondVec.Magnitude();
0189 if (aLength <= gp::Resolution())
0190 {
0191 indp++;
0192 continue;
0193 }
0194 SecondVec /= aLength;
0195 Standard_Real ScalProd = FirstVec * SecondVec;
0196 if (ScalProd < MinScalProd)
0197 {
0198 #ifdef DRAW
0199 std::cout<<"ScalProd("<<indp-2<<","<<indp-1<<")-("<<indp-1<<","<<indp<<") = "<<ScalProd<<std::endl;
0200 #endif
0201 LoopFound = Standard_True;
0202 break;
0203 }
0204 FirstVec = SecondVec;
0205 MidPnt = aPoles(indp);
0206 indp++;
0207 }
0208 //Check: may be it is a real loop
0209 if (LoopFound)
0210 {
0211 #ifdef DRAW
0212 for (Standard_Integer ipoint = theIndfirst; ipoint <= theIndlast; ipoint++)
0213 {
0214 LineTool::Value(theLine, ipoint, tabP);
0215 gp_Pnt aPnt = tabP(1);
0216 sprintf(name, "p%d", ipoint);
0217 DrawTrSurf::Set(name, aPnt);
0218 }
0219 #endif
0220 for (Standard_Integer FirstInd = theIndfirst;
0221 FirstInd <= theIndlast - 2; FirstInd++)
0222 {
0223 LineTool::Value(theLine, FirstInd, tabP);
0224 gp_Pnt FirstPnt = tabP(1);
0225 for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
0226 {
0227 LineTool::Value(theLine, k, tabP);
0228 gp_Pnt Pnt1 = tabP(1);
0229 LineTool::Value(theLine, k+1, tabP);
0230 gp_Pnt Pnt2 = tabP(1);
0231 if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
0232 FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
0233 {
0234 LoopFound = Standard_False;
0235 break;
0236 }
0237 gp_Vec Vec1(FirstPnt, Pnt1);
0238 Vec1.Normalize();
0239 gp_Vec Vec2(FirstPnt, Pnt2);
0240 Vec2.Normalize();
0241 Standard_Real ScalProd = Vec1 * Vec2;
0242 if (ScalProd < MinScalProd)
0243 {
0244 LoopFound = Standard_False;
0245 break;
0246 }
0247 }
0248 if (LoopFound == Standard_False)
0249 break;
0250 }
0251 }
0252 if (LoopFound)
0253 {
0254 //search <indbad>
0255 Standard_Real MaxSqDist = 0.;
0256 Standard_Real MinSqDist = RealLast();
0257 for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
0258 {
0259 LineTool::Value(theLine, k-1, tabP);
0260 gp_Pnt PrevPnt = tabP(1);
0261 LineTool::Value(theLine, k, tabP);
0262 gp_Pnt CurPnt = tabP(1);
0263 Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
0264 if (aSqDist > MaxSqDist)
0265 {
0266 MaxSqDist = aSqDist;
0267 indbads[1] = k;
0268 }
0269 if (aSqDist > gp::Resolution() &&
0270 aSqDist < MinSqDist)
0271 MinSqDist = aSqDist;
0272 }
0273 Standard_Real Relation = MaxSqDist / MinSqDist;
0274 if (Relation < coeff)
0275 LoopFound = Standard_False;
0276 else
0277 for (Standard_Integer indcur = 2; indcur <= NbCur; indcur++)
0278 {
0279 MaxSqDist = 0.;
0280 for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
0281 {
0282 LineTool::Value(theLine, k-1, tabP2d);
0283 gp_Pnt2d PrevPnt = tabP2d(indcur-1);
0284 LineTool::Value(theLine, k, tabP2d);
0285 gp_Pnt2d CurPnt = tabP2d(indcur-1);
0286 Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
0287 if (aSqDist > MaxSqDist)
0288 {
0289 MaxSqDist = aSqDist;
0290 indbads[indcur] = k;
0291 }
0292 }
0293 }
0294 }
0295 } //if (myNbP3d == 1)
0296 else //2d case
0297 {
0298 TColgp_Array1OfPnt2d aPoles2d(1, theMultiCurve.NbPoles());
0299 theMultiCurve.Curve(1, aPoles2d);
0300 #ifdef DRAW
0301 Handle(Geom2d_Curve) theBezier2d = new Geom2d_BezierCurve(aPoles2d);
0302 sprintf(name, "bc2d_%d_%d", indc, nbbc);
0303 DrawTrSurf::Set(name, theBezier2d);
0304 #endif
0305 const Standard_Real aSqNormToler = Epsilon(1.0)*Epsilon(1.0);
0306 gp_Vec2d FirstVec(aPoles2d(1), aPoles2d(2)), SecondVec;
0307 Standard_Real aVecSqNorm = FirstVec.SquareMagnitude();
0308 if (aVecSqNorm < aSqNormToler)
0309 {
0310 theIndbad = theIndfirst + 1;
0311 return Standard_False;
0312 }
0313
0314 FirstVec /= Sqrt(aSqNormToler);
0315 gp_Pnt2d MidPnt = aPoles2d(2);
0316 for (Standard_Integer k = 3; k <= aPoles2d.Upper(); k++)
0317 {
0318 SecondVec.SetXY(aPoles2d(k).XY() - MidPnt.XY());
0319 aVecSqNorm = SecondVec.SquareMagnitude();
0320 if (aVecSqNorm < aSqNormToler)
0321 {
0322 theIndbad = theIndfirst + k - 1;
0323 return Standard_False;
0324 }
0325
0326 SecondVec /= Sqrt(aVecSqNorm);
0327 Standard_Real ScalProd = FirstVec * SecondVec;
0328 if (ScalProd < MinScalProd)
0329 {
0330 #ifdef DRAW
0331 std::cout<<"ScalProd("<<k-2<<","<<k-1<<")-("<<k-1<<","<<k<<") = "<<ScalProd<<std::endl;
0332 #endif
0333 LoopFound = Standard_True;
0334 break;
0335 }
0336 FirstVec = SecondVec;
0337 MidPnt = aPoles2d(k);
0338 }
0339 //Check: may be it is a real loop
0340 if (LoopFound)
0341 {
0342 #ifdef DRAW
0343 for (Standard_Integer ipoint = theIndfirst; ipoint <= theIndlast; ipoint++)
0344 {
0345 LineTool::Value(theLine, ipoint, tabP2d);
0346 gp_Pnt2d aPnt2d = tabP2d(1);
0347 sprintf(name, "p%d", ipoint);
0348 DrawTrSurf::Set(name, aPnt2d);
0349 }
0350 #endif
0351 for (Standard_Integer FirstInd = theIndfirst;
0352 FirstInd <= theIndlast - 2; FirstInd++)
0353 {
0354 LineTool::Value(theLine, FirstInd, tabP2d);
0355 gp_Pnt2d FirstPnt = tabP2d(1);
0356 for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
0357 {
0358 LineTool::Value(theLine, k, tabP2d);
0359 gp_Pnt2d Pnt1 = tabP2d(1);
0360 LineTool::Value(theLine, k+1, tabP2d);
0361 gp_Pnt2d Pnt2 = tabP2d(1);
0362 if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
0363 FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
0364 {
0365 LoopFound = Standard_False;
0366 break;
0367 }
0368 gp_Vec2d Vec1(FirstPnt, Pnt1);
0369 Vec1.Normalize();
0370 gp_Vec2d Vec2(FirstPnt, Pnt2);
0371 Vec2.Normalize();
0372 Standard_Real ScalProd = Vec1 * Vec2;
0373 if (ScalProd < MinScalProd)
0374 {
0375 LoopFound = Standard_False;
0376 break;
0377 }
0378 }
0379 if (LoopFound == Standard_False)
0380 break;
0381 }
0382 }
0383 if (LoopFound)
0384 {
0385 //search <indbad>
0386 for (Standard_Integer indcur = 1; indcur <= NbCur; indcur++)
0387 {
0388 Standard_Real MaxSqDist = 0.;
0389 Standard_Real MinSqDist = RealLast();
0390 for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
0391 {
0392 LineTool::Value(theLine, k-1, tabP2d);
0393 gp_Pnt2d PrevPnt = tabP2d(indcur);
0394 LineTool::Value(theLine, k, tabP2d);
0395 gp_Pnt2d CurPnt = tabP2d(indcur);
0396 Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
0397 if (aSqDist > MaxSqDist)
0398 {
0399 MaxSqDist = aSqDist;
0400 indbads[indcur] = k;
0401 }
0402 if (aSqDist > gp::Resolution() &&
0403 aSqDist < MinSqDist)
0404 MinSqDist = aSqDist;
0405 }
0406 Standard_Real Relation = MaxSqDist / MinSqDist;
0407 if (Relation < coeff)
0408 LoopFound = Standard_False;
0409 }
0410 }
0411 }
0412
0413 //Define <indbad>
0414 for (Standard_Integer i = 1; i <= 3; i++)
0415 if (indbads[i] != 0)
0416 {
0417 theIndbad = indbads[i];
0418 break;
0419 }
0420
0421 if (!LoopFound)
0422 theIndbad = 0;
0423
0424 return (!LoopFound);
0425 }
0426
0427 void Approx_ComputeLine::FirstTangencyVector(const MultiLine& Line,
0428 const Standard_Integer index,
0429 math_Vector& V) const
0430 {
0431
0432 Standard_Integer i, j, nbP2d, nbP3d;
0433 nbP3d = LineTool::NbP3d(Line);
0434 nbP2d = LineTool::NbP2d(Line);
0435 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0436 if (nbP3d == 0) mynbP3d = 1;
0437 if (nbP2d == 0) mynbP2d = 1;
0438 Standard_Boolean Ok=Standard_False;
0439 TColgp_Array1OfVec TabV(1, mynbP3d);
0440 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
0441
0442 if (nbP3d != 0 && nbP2d != 0)
0443 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
0444 else if (nbP2d != 0)
0445 Ok = LineTool::Tangency(Line, index, TabV2d);
0446 else if (nbP3d != 0)
0447 Ok = LineTool::Tangency(Line, index, TabV);
0448
0449 if (Ok) {
0450 if (nbP3d != 0) {
0451 j = 1;
0452 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
0453 V(j) = TabV(i).X();
0454 V(j+1) = TabV(i).Y();
0455 V(j+2) = TabV(i).Z();
0456 j += 3;
0457 }
0458 }
0459 if (nbP2d != 0) {
0460 j = nbP3d*3+1;
0461 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
0462 V(j) = TabV2d(i).X();
0463 V(j+1) = TabV2d(i).Y();
0464 j += 2;
0465 }
0466 }
0467 }
0468 else {
0469
0470 // recherche d un vecteur tangent par construction d une parabole:
0471 AppParCurves_Constraint firstC, lastC;
0472 firstC = lastC = AppParCurves_PassPoint;
0473 Standard_Integer nbpoles = 3;
0474 math_Vector mypar(index, index+2);
0475 Parameters(Line, index, index+2, mypar);
0476 Approx_ParLeastSquareOfMyGradient
0477 LSQ(Line, index, index+2, firstC, lastC, mypar, nbpoles);
0478 AppParCurves_MultiCurve C = LSQ.BezierValue();
0479
0480 gp_Pnt myP;
0481 gp_Vec myV;
0482 gp_Pnt2d myP2d;
0483 gp_Vec2d myV2d;
0484 j = 1;
0485 for (i = 1; i <= nbP3d; i++) {
0486 C.D1(i, 0.0, myP, myV);
0487 V(j) = myV.X();
0488 V(j+1) = myV.Y();
0489 V(j+2) = myV.Z();
0490 j += 3;
0491 }
0492 j = nbP3d*3+1;
0493 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
0494 C.D1(i, 0.0, myP2d, myV2d);
0495 V(j) = myV2d.X();
0496 V(j+1) = myV2d.Y();
0497 j += 2;
0498 }
0499 }
0500 }
0501
0502
0503 void Approx_ComputeLine::LastTangencyVector(const MultiLine& Line,
0504 const Standard_Integer index,
0505 math_Vector& V) const
0506 {
0507 Standard_Integer i, j, nbP2d, nbP3d;
0508 nbP3d = LineTool::NbP3d(Line);
0509 nbP2d = LineTool::NbP2d(Line);
0510 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0511 if (nbP3d == 0) mynbP3d = 1;
0512 if (nbP2d == 0) mynbP2d = 1;
0513 Standard_Boolean Ok=Standard_False;
0514 TColgp_Array1OfVec TabV(1, mynbP3d);
0515 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
0516
0517
0518 if (nbP3d != 0 && nbP2d != 0)
0519 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
0520 else if (nbP2d != 0)
0521 Ok = LineTool::Tangency(Line, index, TabV2d);
0522 else if (nbP3d != 0)
0523 Ok = LineTool::Tangency(Line, index, TabV);
0524
0525 if (Ok) {
0526 if (nbP3d != 0) {
0527 j = 1;
0528 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
0529 V(j) = TabV(i).X();
0530 V(j+1) = TabV(i).Y();
0531 V(j+2) = TabV(i).Z();
0532 j += 3;
0533 }
0534 }
0535 if (nbP2d != 0) {
0536 j = nbP3d*3+1;
0537 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
0538 V(j) = TabV2d(i).X();
0539 V(j+1) = TabV2d(i).Y();
0540 j += 2;
0541 }
0542 }
0543 }
0544 else {
0545
0546 // recherche d un vecteur tangent par construction d une parabole:
0547 AppParCurves_Constraint firstC, lastC;
0548 firstC = lastC = AppParCurves_PassPoint;
0549 Standard_Integer nbpoles = 3;
0550 math_Vector mypar(index-2, index);
0551 Parameters(Line, index-2, index, mypar);
0552 Approx_ParLeastSquareOfMyGradient
0553 LSQ(Line, index-2, index, firstC, lastC, mypar, nbpoles);
0554 AppParCurves_MultiCurve C = LSQ.BezierValue();
0555
0556 gp_Pnt myP;
0557 gp_Vec myV;
0558 gp_Pnt2d myP2d;
0559 gp_Vec2d myV2d;
0560 j = 1;
0561 for (i = 1; i <= nbP3d; i++) {
0562 C.D1(i, 1.0, myP, myV);
0563 V(j) = myV.X();
0564 V(j+1) = myV.Y();
0565 V(j+2) = myV.Z();
0566 j += 3;
0567 }
0568 j = nbP3d*3+1;
0569 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
0570 C.D1(i, 1.0, myP2d, myV2d);
0571 V(j) = myV2d.X();
0572 V(j+1) = myV2d.Y();
0573 j += 2;
0574 }
0575 }
0576
0577 }
0578
0579
0580
0581 Standard_Real Approx_ComputeLine::
0582 SearchFirstLambda(const MultiLine& Line,
0583 const math_Vector& TheParam,
0584 const math_Vector& V,
0585 const Standard_Integer index) const
0586 {
0587
0588 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
0589
0590 Standard_Integer nbP2d, nbP3d;
0591 gp_Pnt P1, P2;
0592 gp_Pnt2d P12d, P22d;
0593 nbP3d = LineTool::NbP3d(Line);
0594 nbP2d = LineTool::NbP2d(Line);
0595 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0596 if (nbP3d == 0) mynbP3d = 1;
0597 if (nbP2d == 0) mynbP2d = 1;
0598 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d);
0599 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d);
0600
0601
0602 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d);
0603 else if (nbP2d != 0) LineTool::Value(Line, index, tabP12d);
0604 else if (nbP3d != 0) LineTool::Value(Line, index, tabP1);
0605
0606 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index+1, tabP2, tabP22d);
0607 else if (nbP2d != 0) LineTool::Value(Line, index+1, tabP22d);
0608 else if (nbP3d != 0) LineTool::Value(Line, index+1, tabP2);
0609
0610
0611 Standard_Real U1 = TheParam(index), U2 = TheParam(index+1);
0612 Standard_Real lambda, S;
0613 Standard_Integer low = V.Lower();
0614
0615 if (nbP3d != 0) {
0616 P1 = tabP1(1);
0617 P2 = tabP2(1);
0618 gp_Vec P1P2(P1, P2), myV;
0619 myV.SetCoord(V(low), V(low+1), V(low+2));
0620 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0621 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0622 }
0623 else {
0624 P12d = tabP12d(1);
0625 P22d = tabP22d(1);
0626 gp_Vec2d P1P2(P12d, P22d), myV;
0627 myV.SetCoord(V(low), V(low+1));
0628 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0629 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0630 }
0631 return (S*lambda);
0632
0633 }
0634
0635
0636 Standard_Real Approx_ComputeLine::
0637 SearchLastLambda(const MultiLine& Line,
0638 const math_Vector& TheParam,
0639 const math_Vector& V,
0640 const Standard_Integer index) const
0641 {
0642 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
0643
0644 Standard_Integer nbP2d, nbP3d;
0645 gp_Pnt P1, P2;
0646 gp_Pnt2d P12d, P22d;
0647 nbP3d = LineTool::NbP3d(Line);
0648 nbP2d = LineTool::NbP2d(Line);
0649 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0650 if (nbP3d == 0) mynbP3d = 1;
0651 if (nbP2d == 0) mynbP2d = 1;
0652 TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d);
0653 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d);
0654
0655 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index-1, tabP, tabP2d);
0656 else if (nbP2d != 0) LineTool::Value(Line, index-1, tabP2d);
0657 else if (nbP3d != 0) LineTool::Value(Line, index-1, tabP);
0658
0659 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d);
0660 else if (nbP2d != 0) LineTool::Value(Line, index, tabP22d);
0661 else if (nbP3d != 0) LineTool::Value(Line, index, tabP2);
0662
0663
0664 Standard_Real U1 = TheParam(index-1), U2 = TheParam(index);
0665 Standard_Real lambda, S;
0666 Standard_Integer low = V.Lower();
0667
0668 if (nbP3d != 0) {
0669 P1 = tabP(1);
0670 P2 = tabP2(1);
0671 gp_Vec P1P2(P1, P2), myV;
0672 myV.SetCoord(V(low), V(low+1), V(low+2));
0673 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0674 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0675 }
0676 else {
0677 P12d = tabP2d(1);
0678 P22d = tabP22d(1);
0679 gp_Vec2d P1P2(P12d, P22d), myV;
0680 myV.SetCoord(V(low), V(low+1));
0681 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0682 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0683 }
0684
0685 return (S*lambda);
0686 }
0687
0688
0689
0690 Approx_ComputeLine::Approx_ComputeLine
0691 (const MultiLine& Line,
0692 const math_Vector& Parameters,
0693 const Standard_Integer degreemin,
0694 const Standard_Integer degreemax,
0695 const Standard_Real Tolerance3d,
0696 const Standard_Real Tolerance2d,
0697 const Standard_Integer NbIterations,
0698 const Standard_Boolean cutting,
0699 const Standard_Boolean Squares)
0700 : myMultiLineNb (0),
0701 myIsClear (Standard_False)
0702 {
0703 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
0704 Parameters.Upper());
0705 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
0706 myfirstParam->SetValue(i, Parameters(i));
0707 }
0708 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0709 Par = Approx_IsoParametric;
0710 mydegremin = degreemin;
0711 mydegremax = degreemax;
0712 mytol3d = Tolerance3d;
0713 mytol2d = Tolerance2d;
0714 mysquares = Squares;
0715 mycut = cutting;
0716 myitermax = NbIterations;
0717 alldone = Standard_False;
0718 myfirstC = AppParCurves_TangencyPoint;
0719 mylastC = AppParCurves_TangencyPoint;
0720 Perform(Line);
0721 }
0722
0723
0724 Approx_ComputeLine::Approx_ComputeLine
0725 (const math_Vector& Parameters,
0726 const Standard_Integer degreemin,
0727 const Standard_Integer degreemax,
0728 const Standard_Real Tolerance3d,
0729 const Standard_Real Tolerance2d,
0730 const Standard_Integer NbIterations,
0731 const Standard_Boolean cutting,
0732 const Standard_Boolean Squares)
0733 : myMultiLineNb (0),
0734 myIsClear (Standard_False)
0735 {
0736 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
0737 Parameters.Upper());
0738 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
0739 myfirstParam->SetValue(i, Parameters(i));
0740 }
0741 myfirstC = AppParCurves_TangencyPoint;
0742 mylastC = AppParCurves_TangencyPoint;
0743 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0744 Par = Approx_IsoParametric;
0745 mydegremin = degreemin;
0746 mydegremax = degreemax;
0747 mytol3d = Tolerance3d;
0748 mytol2d = Tolerance2d;
0749 mysquares = Squares;
0750 mycut = cutting;
0751 myitermax = NbIterations;
0752 alldone = Standard_False;
0753 }
0754
0755 Approx_ComputeLine::Approx_ComputeLine
0756 (const Standard_Integer degreemin,
0757 const Standard_Integer degreemax,
0758 const Standard_Real Tolerance3d,
0759 const Standard_Real Tolerance2d,
0760 const Standard_Integer NbIterations,
0761 const Standard_Boolean cutting,
0762 const Approx_ParametrizationType parametrization,
0763 const Standard_Boolean Squares)
0764 : myMultiLineNb (0),
0765 myIsClear (Standard_False)
0766 {
0767 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0768 Par = parametrization;
0769 mydegremin = degreemin;
0770 mydegremax = degreemax;
0771 mytol3d = Tolerance3d;
0772 mytol2d = Tolerance2d;
0773 mysquares = Squares;
0774 mycut = cutting;
0775 myitermax = NbIterations;
0776 myfirstC = AppParCurves_TangencyPoint;
0777 mylastC = AppParCurves_TangencyPoint;
0778 alldone = Standard_False;
0779 }
0780
0781
0782 Approx_ComputeLine::Approx_ComputeLine
0783 (const MultiLine& Line,
0784 const Standard_Integer degreemin,
0785 const Standard_Integer degreemax,
0786 const Standard_Real Tolerance3d,
0787 const Standard_Real Tolerance2d,
0788 const Standard_Integer NbIterations,
0789 const Standard_Boolean cutting,
0790 const Approx_ParametrizationType parametrization,
0791 const Standard_Boolean Squares)
0792 : myMultiLineNb (0),
0793 myIsClear (Standard_False)
0794 {
0795 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0796 alldone = Standard_False;
0797 mydegremin = degreemin;
0798 mydegremax = degreemax;
0799 mytol3d = Tolerance3d;
0800 mytol2d = Tolerance2d;
0801 mysquares = Squares;
0802 mycut = cutting;
0803 myitermax = NbIterations;
0804 Par = parametrization;
0805 myfirstC = AppParCurves_TangencyPoint;
0806 mylastC = AppParCurves_TangencyPoint;
0807
0808 Perform(Line);
0809 }
0810
0811
0812
0813 void Approx_ComputeLine::Perform(const MultiLine& Line)
0814 {
0815 #ifdef OCCT_DEBUG
0816 if (mydebug) DUMP(Line);
0817 #endif
0818 if (!myIsClear)
0819 {
0820 myMultiCurves.Clear();
0821 myPar.Clear();
0822 Tolers3d.Clear();
0823 Tolers2d.Clear();
0824 myMultiLineNb = 0;
0825 }
0826 else myIsClear = Standard_False;
0827
0828 Standard_Integer i, nbp, Thefirstpt, Thelastpt, oldlastpt;
0829 Standard_Boolean Finish = Standard_False,
0830 begin = Standard_True, Ok = Standard_False,
0831 GoUp = Standard_False, Interpol;
0832 Standard_Real thetol3d, thetol2d;
0833 Approx_Status MyStatus;
0834 // gp_Vec V13d, V23d;
0835 // gp_Vec2d V2d;
0836 Thefirstpt = LineTool::FirstPoint(Line);
0837 Thelastpt = LineTool::LastPoint(Line);
0838 Standard_Integer myfirstpt = Thefirstpt;
0839 Standard_Integer mylastpt = Thelastpt;
0840
0841 AppParCurves_ConstraintCouple myCouple1(myfirstpt, myfirstC);
0842 AppParCurves_ConstraintCouple myCouple2(mylastpt, mylastC);
0843 myConstraints->SetValue(1, myCouple1);
0844 myConstraints->SetValue(2, myCouple2);
0845
0846 math_Vector TheParam(Thefirstpt, Thelastpt);
0847
0848
0849 if (!mycut) {
0850 if(myfirstParam.IsNull()) {
0851 Parameters(Line, Thefirstpt, Thelastpt, TheParam);
0852 }
0853 else {
0854 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
0855 TheParam(i+Thefirstpt-1) = myfirstParam->Value(i);
0856 }
0857 }
0858 TheMultiCurve = AppParCurves_MultiCurve();
0859 MultiLine anOtherLine0;
0860 Standard_Boolean isOtherLine0Made = Standard_False;
0861 Standard_Integer indbad = 0;
0862 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, thetol3d, thetol2d, indbad);
0863 if (indbad != 0)
0864 {
0865 isOtherLine0Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine0);
0866 }
0867 if (isOtherLine0Made)
0868 {
0869 myIsClear = Standard_True;
0870 //++myMultiLineNb;
0871 Perform(anOtherLine0);
0872 alldone = Standard_True;
0873 }
0874 if(!alldone && TheMultiCurve.NbCurves() > 0) {
0875 #ifdef OCCT_DEBUG
0876 if (mydebug) DUMP(TheMultiCurve);
0877 #endif
0878 myMultiCurves.Append(TheMultiCurve);
0879 Tolers3d.Append(currenttol3d);
0880 Tolers2d.Append(currenttol2d);
0881 Standard_Integer mylen = mylastpt-myfirstpt+1;
0882 Standard_Integer myParLen = myParameters->Length();
0883 Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
0884 Handle(TColStd_HArray1OfReal) ThePar =
0885 new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
0886 for (i = 0; i < aLen; i++)
0887 ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
0888 myPar.Append(ThePar);
0889 }
0890 }
0891 else {
0892 while (!Finish) {
0893 oldlastpt = mylastpt;
0894 // Gestion du decoupage de la multiline pour approximer:
0895 if(!begin) {
0896 if (!GoUp) {
0897 if (Ok) {
0898 // Calcul de la partie a approximer.
0899 myfirstpt = mylastpt;
0900 mylastpt = Thelastpt;
0901 if (myfirstpt == Thelastpt) {
0902 Finish = Standard_True;
0903 alldone = Standard_True;
0904 return;
0905 }
0906 }
0907 else {
0908 nbp = mylastpt - myfirstpt + 1;
0909 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
0910 if (MyStatus == Approx_NoPointsAdded && nbp <= mydegremax+1) {
0911 Interpol = ComputeCurve(Line, myfirstpt, mylastpt);
0912 if (Interpol) {
0913 if (mylastpt == Thelastpt) {
0914 Finish = Standard_True;
0915 alldone = Standard_True;
0916 return;
0917 }
0918 }
0919 }
0920 mylastpt = Standard_Integer((myfirstpt + mylastpt)/2);
0921 }
0922 }
0923 GoUp = Standard_False;
0924 }
0925
0926 // Verification du nombre de points restants par rapport au degre
0927 // demande.
0928 // ==============================================================
0929 nbp = mylastpt - myfirstpt + 1;
0930 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
0931 if (nbp <= mydegremax+5 ) {
0932 // Rajout necessaire de points si possible.
0933 // ========================================
0934 GoUp = Standard_False;
0935 Ok = Standard_True;
0936 if (MyStatus == Approx_PointsAdded) {
0937 // Appel recursif du decoupage:
0938 GoUp = Standard_True;
0939
0940 MultiLine anOtherLine1 = LineTool::MakeMLBetween(Line, myfirstpt, mylastpt, nbp-1);
0941
0942 Standard_Integer nbpdsotherligne = LineTool::FirstPoint (anOtherLine1) - LineTool::LastPoint (anOtherLine1);
0943
0944 //-- Si MakeML a echoue on retourne une ligne vide
0945 if ((nbpdsotherligne == 0) || myMultiLineNb >= 3)
0946 {
0947 //-- cout<<" ** ApproxComputeLine MakeML Echec ** LBR lbr "<<endl;
0948 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
0949 // planter la station !!
0950 myCouple1.SetIndex(myfirstpt);
0951 myCouple2.SetIndex(mylastpt);
0952 myConstraints->SetValue(1, myCouple1);
0953 myConstraints->SetValue(2, myCouple2);
0954
0955 math_Vector Param(myfirstpt, mylastpt);
0956 Approx_ParametrizationType SavePar = Par;
0957 Par = Approx_IsoParametric;
0958 Parameters(Line, myfirstpt, mylastpt, Param);
0959 TheMultiCurve = AppParCurves_MultiCurve();
0960 MultiLine anOtherLine2;
0961 Standard_Boolean isOtherLine2Made = Standard_False;
0962 Standard_Integer indbad = 0;
0963 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
0964 if (indbad != 0)
0965 {
0966 isOtherLine2Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine2);
0967 }
0968 if (isOtherLine2Made)
0969 {
0970 myIsClear = Standard_True;
0971 //++myMultiLineNb;
0972 Par = SavePar;
0973 Perform(anOtherLine2);
0974 Ok = Standard_True;
0975 }
0976
0977 if (!Ok) {
0978 Standard_Real tt3d = currenttol3d, tt2d = currenttol2d;
0979 Handle(TColStd_HArray1OfReal) saveParameters = myParameters;
0980 AppParCurves_MultiCurve saveMultiCurve = TheMultiCurve;
0981
0982 if(SavePar != Approx_IsoParametric)
0983 Par = SavePar;
0984 else
0985 Par = Approx_ChordLength;
0986
0987 Parameters(Line, myfirstpt, mylastpt, Param);
0988 isOtherLine2Made = Standard_False;
0989 indbad = 0;
0990 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
0991 if (indbad != 0)
0992 {
0993 isOtherLine2Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad, anOtherLine2);
0994 }
0995 if (isOtherLine2Made)
0996 {
0997 myIsClear = Standard_True;
0998 //++myMultiLineNb;
0999 Perform (anOtherLine2);
1000 Ok = Standard_True;
1001 }
1002
1003 if (!Ok && tt3d <= currenttol3d && tt2d <= currenttol2d) {
1004 currenttol3d = tt3d; currenttol2d = tt2d;
1005 myParameters = saveParameters;
1006 TheMultiCurve = saveMultiCurve;
1007 }
1008 }
1009 Par = SavePar;
1010 if (myfirstpt == Thelastpt)
1011 {
1012 Finish = Standard_True;
1013 alldone = Standard_True;
1014 return;
1015 }
1016
1017 oldlastpt = mylastpt;
1018 if (!Ok) {
1019 tolreached = Standard_False;
1020 if (TheMultiCurve.NbCurves() == 0) {
1021 myMultiCurves.Clear();
1022 return;
1023 }
1024 #ifdef OCCT_DEBUG
1025 if (mydebug) DUMP(TheMultiCurve);
1026 #endif
1027 MultiLine anOtherLine3;
1028 Standard_Boolean isOtherLine3Made = Standard_False;
1029 Standard_Integer indbad2 = 0;
1030 if (!CheckMultiCurve(TheMultiCurve, Line,
1031 myfirstpt, mylastpt,
1032 indbad2))
1033 {
1034 isOtherLine3Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad2, anOtherLine3);
1035 }
1036 if (isOtherLine3Made)
1037 {
1038 myIsClear = Standard_True;
1039 //++myMultiLineNb;
1040 Perform(anOtherLine3);
1041 myfirstpt = mylastpt;
1042 mylastpt = Thelastpt;
1043 }
1044 else
1045 {
1046 myMultiCurves.Append(TheMultiCurve);
1047 Tolers3d.Append(currenttol3d);
1048 Tolers2d.Append(currenttol2d);
1049 Standard_Integer mylen = oldlastpt-myfirstpt+1;
1050 Standard_Integer myParLen = myParameters->Length();
1051 Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
1052 Handle(TColStd_HArray1OfReal) ThePar =
1053 new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
1054 for (i = 0; i < aLen; i++)
1055 ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
1056 myPar.Append(ThePar);
1057 }
1058 }
1059 myfirstpt = oldlastpt;
1060 mylastpt = Thelastpt;
1061
1062 }
1063 else
1064 {
1065 myIsClear = Standard_True;
1066 ++myMultiLineNb;
1067 Perform(anOtherLine1);
1068 myfirstpt = mylastpt;
1069 mylastpt = Thelastpt;
1070 }
1071 }
1072
1073 if (MyStatus == Approx_NoPointsAdded && !begin) {
1074 // On rend la meilleure approximation obtenue precedemment.
1075 // ========================================================
1076 GoUp = Standard_True;
1077 tolreached = Standard_False;
1078 if (TheMultiCurve.NbCurves() == 0) {
1079 myMultiCurves.Clear();
1080 return;
1081 }
1082 #ifdef OCCT_DEBUG
1083 if (mydebug) DUMP(TheMultiCurve);
1084 #endif
1085 myMultiCurves.Append(TheMultiCurve);
1086 Tolers3d.Append(currenttol3d);
1087 Tolers2d.Append(currenttol2d);
1088 Standard_Integer mylen = oldlastpt-myfirstpt+1;
1089 Standard_Integer myParLen = myParameters->Length();
1090 Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
1091 Handle(TColStd_HArray1OfReal) ThePar =
1092 new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
1093 for (i = 0; i < aLen; i++)
1094 ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
1095 myPar.Append(ThePar);
1096
1097 myfirstpt = oldlastpt;
1098 mylastpt = Thelastpt;
1099 }
1100
1101 else if (MyStatus == Approx_NoApproximation) {
1102 // On ne fait pas d approximation entre myfirstpt et mylastpt.
1103 // ===========================================================
1104 // On stocke pour pouvoir en informer l utilisateur.
1105 GoUp = Standard_True;
1106 myfirstpt = mylastpt;
1107 mylastpt = Thelastpt;
1108 }
1109 }
1110
1111 if (myfirstpt == Thelastpt) {
1112 Finish = Standard_True;
1113 alldone = Standard_True;
1114 return;
1115 }
1116 if (!GoUp) {
1117 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
1118 // planter la station !!
1119 myCouple1.SetIndex(myfirstpt);
1120 myCouple2.SetIndex(mylastpt);
1121 myConstraints->SetValue(1, myCouple1);
1122 myConstraints->SetValue(2, myCouple2);
1123
1124 // Calcul des parametres sur ce nouvel intervalle.
1125 // On recupere les parametres initiaux lors du decoupage.
1126
1127 math_Vector Param(myfirstpt, mylastpt);
1128 if (begin) {
1129 if(myfirstParam.IsNull()) {
1130 Parameters(Line, myfirstpt, mylastpt, Param);
1131 }
1132 else {
1133 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
1134 Param(i) = myfirstParam->Value(i);
1135 }
1136 myfirstParam.Nullify();
1137 }
1138 TheParam = Param;
1139 begin = Standard_False;
1140 }
1141 else {
1142 Standard_Real pfirst = TheParam.Value(myfirstpt);
1143 Standard_Real plast = TheParam.Value(mylastpt);
1144 for (i = myfirstpt; i <= mylastpt; i++) {
1145 Param(i) = (TheParam.Value(i)-pfirst)/(plast-pfirst);
1146 }
1147 }
1148
1149 TheMultiCurve = AppParCurves_MultiCurve();
1150 Standard_Integer indbad = 0;
1151 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
1152 if (myfirstpt == Thelastpt)
1153 {
1154 Finish = Standard_True;
1155 alldone = Standard_True;
1156 return;
1157 }
1158 }
1159 }
1160 }
1161 }
1162
1163
1164
1165 const TColStd_Array1OfReal& Approx_ComputeLine::Parameters(const Standard_Integer Index) const
1166 {
1167 return (myPar.Value(Index))->Array1();
1168 }
1169
1170
1171 Standard_Integer Approx_ComputeLine::NbMultiCurves()const
1172 {
1173 return myMultiCurves.Length();
1174 }
1175
1176 AppParCurves_MultiCurve& Approx_ComputeLine::ChangeValue(const Standard_Integer Index)
1177 {
1178 return myMultiCurves.ChangeValue(Index);
1179 }
1180
1181
1182 const AppParCurves_MultiCurve& Approx_ComputeLine::Value(const Standard_Integer Index)
1183 const
1184 {
1185 return myMultiCurves.Value(Index);
1186 }
1187
1188
1189 const AppParCurves_MultiBSpCurve& Approx_ComputeLine::SplineValue()
1190 {
1191 Approx_MCurvesToBSpCurve Trans;
1192 Trans.Perform(myMultiCurves);
1193 myspline = Trans.Value();
1194 return myspline;
1195 }
1196
1197
1198
1199
1200
1201 void Approx_ComputeLine::Parameters(const MultiLine& Line,
1202 const Standard_Integer firstP,
1203 const Standard_Integer lastP,
1204 math_Vector& TheParameters) const
1205 {
1206 Standard_Integer i, j, nbP2d, nbP3d;
1207 Standard_Real dist;
1208
1209 if(Par == Approx_ChordLength || Par == Approx_Centripetal)
1210 {
1211 nbP3d = LineTool::NbP3d(Line);
1212 nbP2d = LineTool::NbP2d(Line);
1213 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
1214 if(nbP3d == 0) mynbP3d = 1;
1215 if(nbP2d == 0) mynbP2d = 1;
1216
1217 TheParameters(firstP) = 0.0;
1218 dist = 0.0;
1219 TColgp_Array1OfPnt tabP(1, mynbP3d);
1220 TColgp_Array1OfPnt tabPP(1, mynbP3d);
1221 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
1222 TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
1223
1224 for(i = firstP + 1; i <= lastP; i++)
1225 {
1226 if(nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i - 1, tabP, tabP2d);
1227 else if(nbP2d != 0) LineTool::Value(Line, i - 1, tabP2d);
1228 else if(nbP3d != 0) LineTool::Value(Line, i - 1, tabP);
1229
1230 if(nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d);
1231 else if(nbP2d != 0) LineTool::Value(Line, i, tabPP2d);
1232 else if(nbP3d != 0) LineTool::Value(Line, i, tabPP);
1233 dist = 0;
1234 for(j = 1; j <= nbP3d; j++)
1235 {
1236 const gp_Pnt &aP1 = tabP(j),
1237 &aP2 = tabPP(j);
1238 dist += aP2.SquareDistance(aP1);
1239 }
1240 for(j = 1; j <= nbP2d; j++)
1241 {
1242 const gp_Pnt2d &aP12d = tabP2d(j),
1243 &aP22d = tabPP2d(j);
1244
1245 dist += aP22d.SquareDistance(aP12d);
1246 }
1247
1248 dist = Sqrt(dist);
1249 if(Par == Approx_ChordLength)
1250 {
1251 TheParameters(i) = TheParameters(i - 1) + dist;
1252 }
1253 else
1254 {// Par == Approx_Centripetal
1255 TheParameters(i) = TheParameters(i - 1) + Sqrt(dist);
1256 }
1257 }
1258 for(i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
1259 }
1260 else {
1261 for (i = firstP; i <= lastP; i++) {
1262 TheParameters(i) = (Standard_Real(i)-firstP)/
1263 (Standard_Real(lastP)-Standard_Real(firstP));
1264 }
1265 }
1266 }
1267
1268
1269 Standard_Boolean Approx_ComputeLine::Compute(const MultiLine& Line,
1270 const Standard_Integer fpt,
1271 const Standard_Integer lpt,
1272 math_Vector& Para,
1273 Standard_Real& TheTol3d,
1274 Standard_Real& TheTol2d,
1275 Standard_Integer& indbad)
1276 {
1277 indbad = 0;
1278 Standard_Integer deg, i;
1279 Standard_Boolean mydone;
1280 Standard_Real Fv;
1281 Standard_Integer nbp = lpt-fpt+1;
1282
1283 math_Vector ParSav(Para.Lower(), Para.Upper());
1284 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1285 ParSav(i) = Para(i);
1286 }
1287 Standard_Integer Mdegmax = mydegremax;
1288 if(nbp < Mdegmax+5 && mycut) {
1289 Mdegmax = nbp - 5;
1290 }
1291 if(Mdegmax < mydegremin) {
1292 Mdegmax = mydegremin;
1293 }
1294
1295 currenttol3d = currenttol2d = RealLast();
1296 for (deg = Min(nbp-1,mydegremin); deg <= Mdegmax; deg++) {
1297 AppParCurves_MultiCurve mySCU(deg+1);
1298 if (mysquares) {
1299 Approx_ParLeastSquareOfMyGradient SQ(Line, fpt, lpt,
1300 myfirstC, mylastC, Para, deg+1);
1301 mydone = SQ.IsDone();
1302 mySCU = SQ.BezierValue();
1303 SQ.Error(Fv, TheTol3d, TheTol2d);
1304 }
1305 else {
1306 Approx_MyGradient GRAD(Line, fpt, lpt, myConstraints,
1307 Para, deg, mytol3d, mytol2d, myitermax);
1308 mydone = GRAD.IsDone();
1309 mySCU = GRAD.Value();
1310 if (mySCU.NbCurves() == 0)
1311 continue;
1312 TheTol3d = GRAD.MaxError3d();
1313 TheTol2d = GRAD.MaxError2d();
1314 }
1315 Standard_Real uu1 = Para(Para.Lower()), uu2;
1316 Standard_Boolean restau = Standard_False;
1317 for ( i = Para.Lower()+1; i <= Para.Upper(); i++) {
1318 uu2 = Para(i);
1319 if (uu2 <= uu1) {
1320 restau = Standard_True;
1321 // cout << "restau = Standard_True" << endl;
1322 break;
1323 }
1324 uu1 = uu2;
1325 }
1326 if (restau) {
1327 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1328 Para(i) = ParSav(i);
1329 }
1330 }
1331 if (mydone) {
1332 if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
1333 // Stockage de la multicurve approximee.
1334 tolreached = Standard_True;
1335 #ifdef OCCT_DEBUG
1336 if (mydebug) DUMP(mySCU);
1337 #endif
1338 if (!CheckMultiCurve(mySCU, Line,
1339 fpt, lpt,
1340 indbad))
1341 {
1342 return Standard_False;
1343 }
1344 else
1345 {
1346 myMultiCurves.Append(mySCU);
1347 // Stockage des parametres de la partie de MultiLine approximee:
1348 // A ameliorer !! (bq trop de recopies)
1349 Handle(TColStd_HArray1OfReal) ThePar =
1350 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1351 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1352 ThePar->SetValue(i, Para(i));
1353 }
1354 myPar.Append(ThePar);
1355 Tolers3d.Append(TheTol3d);
1356 Tolers2d.Append(TheTol2d);
1357 return Standard_True;
1358 }
1359 }
1360 }
1361
1362 if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) {
1363 TheMultiCurve = mySCU;
1364 currenttol3d = TheTol3d;
1365 currenttol2d = TheTol2d;
1366 myParameters = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1367 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1368 myParameters->SetValue(i, Para(i));
1369 }
1370 }
1371
1372 }
1373
1374 return Standard_False;
1375 }
1376
1377
1378
1379
1380 Standard_Boolean Approx_ComputeLine::ComputeCurve(const MultiLine& Line,
1381 const Standard_Integer firstpt,
1382 const Standard_Integer lastpt)
1383 {
1384 Standard_Integer i, j, nbP3d, nbP2d, deg;
1385 gp_Vec V13d, V23d;
1386 gp_Vec2d V12d, V22d;
1387 gp_Pnt P1, P2;
1388 gp_Pnt2d P12d, P22d;
1389 Standard_Boolean Tangent1, Tangent2, mydone= Standard_False;
1390 #ifdef OCCT_DEBUG
1391 Standard_Boolean Parallel;
1392 #endif
1393 Standard_Integer myfirstpt = firstpt, mylastpt = lastpt;
1394 Standard_Integer nbp = lastpt-firstpt+1;
1395 math_Vector Para(firstpt, lastpt);
1396
1397 Parameters(Line, firstpt, lastpt, Para);
1398
1399 nbP3d = LineTool::NbP3d(Line);
1400 nbP2d = LineTool::NbP2d(Line);
1401 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
1402 if (nbP3d == 0) mynbP3d = 1 ;
1403 if (nbP2d == 0) mynbP2d = 1 ;
1404
1405
1406 TColgp_Array1OfVec tabV1(1, mynbP3d), tabV2(1, mynbP3d);
1407 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d), tabP(1, mynbP3d);
1408 TColgp_Array1OfVec2d tabV12d(1, mynbP2d), tabV22d(1, mynbP2d);
1409 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d), tabP2d(1, mynbP2d);
1410
1411 if (nbP3d != 0 && nbP2d != 0) {
1412 LineTool::Value(Line, myfirstpt,tabP1,tabP12d);
1413 LineTool::Value(Line, mylastpt,tabP2,tabP22d);
1414 Tangent1 = LineTool::Tangency(Line, myfirstpt,tabV1,tabV12d);
1415 Tangent2 = LineTool::Tangency(Line, mylastpt,tabV2,tabV22d);
1416 }
1417 else if (nbP2d != 0) {
1418 LineTool::Value(Line, myfirstpt,tabP12d);
1419 LineTool::Value(Line, mylastpt,tabP22d);
1420 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV12d);
1421 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV22d);
1422 }
1423 else {
1424 LineTool::Value(Line, myfirstpt,tabP1);
1425 LineTool::Value(Line, mylastpt,tabP2);
1426 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV1);
1427 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV2);
1428 }
1429 if (nbp == 2) {
1430 // S il n y a que 2 points, on verifie quand meme que les tangentes sont
1431 // alignees.
1432 #ifdef OCCT_DEBUG
1433 Parallel = Standard_True;
1434 #endif
1435 if (Tangent1) {
1436 for (i = 1; i <= nbP3d; i++) {
1437 gp_Vec PVec(tabP1(i), tabP2(i));
1438 V13d = tabV1(i);
1439 if (!PVec.IsParallel(V13d, Precision::Angular())) {
1440 #ifdef OCCT_DEBUG
1441 Parallel = Standard_False;
1442 #endif
1443 break;
1444 }
1445 }
1446 for (i = 1; i <= nbP2d; i++) {
1447 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1448 V12d = tabV12d(i);
1449 if (!PVec2d.IsParallel(V12d, Precision::Angular())) {
1450 #ifdef OCCT_DEBUG
1451 Parallel = Standard_False;
1452 #endif
1453 break;
1454 }
1455 }
1456 }
1457
1458 if (Tangent2) {
1459 for (i = 1; i <= nbP3d; i++) {
1460 gp_Vec PVec(tabP1(i), tabP2(i));
1461 V23d = tabV2(i);
1462 if (!PVec.IsParallel(V23d, Precision::Angular())) {
1463 #ifdef OCCT_DEBUG
1464 Parallel = Standard_False;
1465 #endif
1466 break;
1467 }
1468 }
1469 for (i = 1; i <= nbP2d; i++) {
1470 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1471 V22d = tabV22d(i);
1472 if (!PVec2d.IsParallel(V22d, Precision::Angular())) {
1473 #ifdef OCCT_DEBUG
1474 Parallel = Standard_False;
1475 #endif
1476 break;
1477 }
1478 }
1479 }
1480
1481 #ifdef OCCT_DEBUG
1482 if (!Parallel) {
1483 if (mydebug) std::cout <<"droite mais tangentes pas vraiment paralleles!!"<< std::endl;
1484 }
1485 #endif
1486 AppParCurves_MultiCurve mySCU(mydegremin+1);
1487 if (nbP3d != 0 && nbP2d != 0) {
1488 AppParCurves_MultiPoint MPole1(tabP1, tabP12d);
1489 AppParCurves_MultiPoint MPole2(tabP2, tabP22d);
1490 mySCU.SetValue(1, MPole1);
1491 mySCU.SetValue(mydegremin+1, MPole2);
1492 for (i = 2; i <= mydegremin; i++) {
1493 for (j = 1; j<= nbP3d; j++) {
1494 P1 = tabP1(j);
1495 P2 = tabP2(j);
1496 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1497 }
1498 for (j = 1; j<= nbP2d; j++) {
1499 P12d = tabP12d(j);
1500 P22d = tabP22d(j);
1501 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1502 }
1503 AppParCurves_MultiPoint MPole(tabP, tabP2d);
1504 mySCU.SetValue(i, MPole);
1505 }
1506
1507 }
1508 else if (nbP3d != 0) {
1509 AppParCurves_MultiPoint MPole1(tabP1);
1510 AppParCurves_MultiPoint MPole2(tabP2);
1511 mySCU.SetValue(1, MPole1);
1512 mySCU.SetValue(mydegremin+1, MPole2);
1513 for (i = 2; i <= mydegremin; i++) {
1514 for (j = 1; j<= nbP3d; j++) {
1515 P1 = tabP1(j);
1516 P2 = tabP2(j);
1517 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1518 }
1519 AppParCurves_MultiPoint MPole(tabP);
1520 mySCU.SetValue(i, MPole);
1521 }
1522 }
1523 else if (nbP2d != 0) {
1524 AppParCurves_MultiPoint MPole1(tabP12d);
1525 AppParCurves_MultiPoint MPole2(tabP22d);
1526 mySCU.SetValue(1, MPole1);
1527 mySCU.SetValue(mydegremin+1, MPole2);
1528 for (i = 2; i <= mydegremin; i++) {
1529 for (j = 1; j<= nbP2d; j++) {
1530 P12d = tabP12d(j);
1531 P22d = tabP22d(j);
1532 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1533 }
1534 AppParCurves_MultiPoint MPole(tabP2d);
1535 mySCU.SetValue(i, MPole);
1536 }
1537 }
1538 mydone = Standard_True;
1539 // Stockage de la multicurve approximee.
1540 tolreached = Standard_True;
1541 #ifdef OCCT_DEBUG
1542 if (mydebug) DUMP(mySCU);
1543 #endif
1544 myMultiCurves.Append(mySCU);
1545 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1546 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1547 ThePar->SetValue(i, Para(i));
1548 }
1549 myPar.Append(ThePar);
1550 Tolers3d.Append(Precision::Confusion());
1551 Tolers2d.Append(Precision::PConfusion());
1552 return mydone;
1553 }
1554
1555 // avec les tangentes.
1556 deg = nbp+1;
1557 AppParCurves_MultiCurve mySCU(deg+1);
1558 AppParCurves_Constraint Cons = AppParCurves_TangencyPoint;
1559 Standard_Real lambda1, lambda2;
1560 math_Vector V1(1, nbP3d*3+nbP2d*2);
1561 math_Vector V2(1, nbP3d*3+nbP2d*2);
1562 FirstTangencyVector(Line, myfirstpt, V1);
1563 lambda1 = SearchFirstLambda(Line, Para, V1, myfirstpt);
1564
1565 LastTangencyVector(Line, mylastpt, V2);
1566 lambda2 = SearchLastLambda(Line, Para, V2, mylastpt);
1567
1568 Approx_ParLeastSquareOfMyGradient
1569 LSQ(Line, myfirstpt, mylastpt,
1570 Cons, Cons, Para, deg+1);
1571
1572 lambda1 = lambda1/deg;
1573 lambda2 = lambda2/deg;
1574 LSQ.Perform(Para, V1, V2, lambda1, lambda2);
1575 mydone = LSQ.IsDone();
1576 mySCU = LSQ.BezierValue();
1577
1578 if (mydone) {
1579 Standard_Real Fv, TheTol3d, TheTol2d;
1580 LSQ.Error(Fv, TheTol3d, TheTol2d);
1581
1582 // Stockage de la multicurve approximee.
1583 tolreached = Standard_True;
1584 #ifdef OCCT_DEBUG
1585 if (mydebug) DUMP(mySCU);
1586 #endif
1587 myMultiCurves.Append(mySCU);
1588 Handle(TColStd_HArray1OfReal) ThePar =
1589 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1590 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1591 ThePar->SetValue(i, Para(i));
1592 }
1593 myPar.Append(ThePar);
1594 Tolers3d.Append(TheTol3d);
1595 Tolers2d.Append(TheTol2d);
1596 return Standard_True;
1597 }
1598 return mydone;
1599 }
1600
1601
1602
1603 void Approx_ComputeLine::Init(const Standard_Integer degreemin,
1604 const Standard_Integer degreemax,
1605 const Standard_Real Tolerance3d,
1606 const Standard_Real Tolerance2d,
1607 const Standard_Integer NbIterations,
1608 const Standard_Boolean cutting,
1609 const Approx_ParametrizationType parametrization,
1610 const Standard_Boolean Squares)
1611 {
1612 mydegremin = degreemin;
1613 mydegremax = degreemax;
1614 mytol3d = Tolerance3d;
1615 mytol2d = Tolerance2d;
1616 Par = parametrization;
1617 mysquares = Squares;
1618 mycut = cutting;
1619 myitermax = NbIterations;
1620 }
1621
1622
1623
1624 void Approx_ComputeLine::SetDegrees(const Standard_Integer degreemin,
1625 const Standard_Integer degreemax)
1626 {
1627 mydegremin = degreemin;
1628 mydegremax = degreemax;
1629 }
1630
1631
1632 void Approx_ComputeLine::SetTolerances(const Standard_Real Tolerance3d,
1633 const Standard_Real Tolerance2d)
1634 {
1635 mytol3d = Tolerance3d;
1636 mytol2d = Tolerance2d;
1637 }
1638
1639
1640 void Approx_ComputeLine::SetConstraints(const AppParCurves_Constraint FirstC,
1641 const AppParCurves_Constraint LastC)
1642 {
1643 myfirstC = FirstC;
1644 mylastC = LastC;
1645 }
1646
1647
1648
1649 Standard_Boolean Approx_ComputeLine::IsAllApproximated()
1650 const {
1651 return alldone;
1652 }
1653
1654 Standard_Boolean Approx_ComputeLine::IsToleranceReached()
1655 const {
1656 return tolreached;
1657 }
1658
1659 void Approx_ComputeLine::Error(const Standard_Integer Index,
1660 Standard_Real& tol3d,
1661 Standard_Real& tol2d) const
1662 {
1663 tol3d = Tolers3d.Value(Index);
1664 tol2d = Tolers2d.Value(Index);
1665 }
1666
1667 Approx_ParametrizationType Approx_ComputeLine::Parametrization() const
1668 {
1669 return Par;
1670 }