Warning, /include/opencascade/IntWalk_IWalking_5.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 namespace {
0016 static const Standard_Real CosRef3D = 0.98;// rule by tests in U4
0017 // correspond to 11.478 d
0018 static const Standard_Real CosRef2D = 0.88; // correspond to 25 d
0019 static const Standard_Integer MaxDivision = 60; // max number of step division
0020 // because the angle is too great in 2d (U4)
0021 }
0022
0023 IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
0024 (TheIWFunction& sp,
0025 const Standard_Boolean Finished,
0026 const math_Vector& UV,
0027 const IntWalk_StatusDeflection StatusPrecedent,
0028 Standard_Integer& NbDivision,
0029 Standard_Real& Step,
0030 const Standard_Integer StepSign)
0031 {
0032 // Check the step of advancement, AND recalculate this step :
0033 //
0034 // 1) test point confused
0035 // if yes other tests are not done
0036 // 2) test angle 3d too great
0037 // if yes divide the step and leave
0038 // angle3d = angle ((previous point, calculated point),
0039 // previous tangent)
0040 // 3) check step of advancement in 2d
0041 // 4) test point confused
0042 // 5) test angle 2d too great
0043 // 6) test point of tangency
0044 // if yes leave
0045 // 7) calculate the tangent by u,v of the section
0046 // 8) test angle 3d too great
0047 // angle3d = angle ((previous point, calculated point),
0048 // new tangent)
0049 // 9) test angle 2d too great
0050 //10) test change of side (pass the tangent point not knowing it)
0051 //11) calculate the step of advancement depending on the vector
0052 //12) adjust the step depending on the previous steps
0053
0054 IntWalk_StatusDeflection aStatus = IntWalk_OK;
0055
0056 //---------------------------------------------------------------------------------
0057 //-- lbr le 4 Avril 95 : it is possible that the status returns points confused
0058 //-- if epsilon is great enough (1e-11). In this case one loops
0059 //-- without ever changing the values sent to Rsnld.
0060 //---------------------------------------------------------------------------------
0061 Standard_Real Paramu = 0.0, Paramv = 0.0;
0062
0063 if (!reversed) {
0064 previousPoint.ParametersOnS2(Paramu, Paramv);
0065 }
0066 else
0067 {
0068 previousPoint.ParametersOnS1(Paramu, Paramv);
0069 }
0070
0071 const Standard_Real Du = UV(1) - Paramu;
0072 const Standard_Real Dv = UV(2) - Paramv;
0073 const Standard_Real Duv = Du * Du + Dv * Dv;
0074
0075 gp_Vec Corde(previousPoint.Value(), sp.Point());
0076
0077 const Standard_Real Norme = Corde.SquareMagnitude();
0078
0079 if ((Norme <= 4.0*Precision::SquareConfusion()) &&
0080 ((Duv <= Precision::SquarePConfusion()) || (StatusPrecedent != IntWalk_OK)))
0081 { // the square is already taken in the constructor
0082 aStatus = IntWalk_PointConfondu;
0083 if (StatusPrecedent == IntWalk_PasTropGrand)
0084 {
0085 return IntWalk_ArretSurPointPrecedent;
0086 }
0087 }
0088 else
0089 {
0090 Standard_Real Cosi = Corde * previousd3d;
0091 Standard_Real Cosi2 = 0.0;
0092
0093 if (Cosi*StepSign >= 0.) {// angle 3d <= pi/2 !!!!
0094 const Standard_Real aDiv = previousd3d.SquareMagnitude()*Norme;
0095 if(aDiv == 0)
0096 return aStatus;
0097 Cosi2 = Cosi * Cosi / aDiv;
0098 }
0099 if (Cosi2 < CosRef3D) { //angle 3d too great
0100 Step = Step /2.0;
0101 Standard_Real StepU = Abs(Step*previousd2d.X()),
0102 StepV = Abs(Step*previousd2d.Y());
0103 if (StepU < tolerance(1) && StepV < tolerance(2))
0104 aStatus = IntWalk_ArretSurPointPrecedent;
0105 else
0106 aStatus = IntWalk_PasTropGrand;
0107 return aStatus;
0108 }
0109 }
0110
0111 const Standard_Real aMinTolU = 0.1*Abs(Step*previousd2d.X()),
0112 aMinTolV = 0.1*Abs(Step*previousd2d.Y());
0113 const Standard_Real aTolU = (aMinTolU > 0.0) ? Min(tolerance(1), aMinTolU) : tolerance(1),
0114 aTolV = (aMinTolV > 0.0) ? Min(tolerance(2), aMinTolV) : tolerance(2);
0115
0116 //If aMinTolU==0.0 then (Abs(Du) < aMinTolU) is equivalent of (Abs(Du) < 0.0).
0117 //It is impossible. Therefore, this case should be processed separately.
0118 //Analogically for aMinTolV.
0119
0120 if ((Abs(Du) < aTolU) && (Abs(Dv) < aTolV))
0121 {
0122 //Thin shapes (for which Ulast-Ufirst or/and Vlast-Vfirst is quite small)
0123 //exists (see bug #25820). In this case, step is quite small too.
0124 //Nevertheless, it not always means that we mark time. Therefore, Du and Dv
0125 //must consider step (aMinTolU and aMinTolV parameters).
0126
0127 return IntWalk_ArretSurPointPrecedent; //confused point 2d
0128 }
0129
0130 Standard_Real Cosi = StepSign * (Du * previousd2d.X() + Dv * previousd2d.Y());
0131
0132 if (Cosi < 0 && aStatus == IntWalk_PointConfondu)
0133 return IntWalk_ArretSurPointPrecedent; // leave as step back
0134 // with confused point
0135
0136 if (sp.IsTangent())
0137 return IntWalk_ArretSurPoint;
0138
0139 //if during routing one has subdivided more than MaxDivision for each
0140 //previous step, bug on the square; do nothing (experience U4)
0141
0142 if ((NbDivision < MaxDivision) && (aStatus != IntWalk_PointConfondu) &&
0143 (StatusPrecedent!= IntWalk_PointConfondu))
0144 {
0145 Standard_Real Cosi2 = Cosi * Cosi / Duv;
0146 if (Cosi2 < CosRef2D || Cosi < 0 ) {
0147 Step = Step / 2.0;
0148 Standard_Real StepU = Abs(Step*previousd2d.X()),
0149 StepV = Abs(Step*previousd2d.Y());
0150
0151 if (StepU < tolerance(1) && StepV < tolerance(2))
0152 aStatus = IntWalk_ArretSurPointPrecedent;
0153 else
0154 aStatus = IntWalk_PasTropGrand;
0155 NbDivision = NbDivision + 1;
0156 return aStatus;
0157 }
0158
0159 Cosi = Corde * sp.Direction3d();
0160 Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
0161 if (Cosi2 < CosRef3D ){ //angle 3d too great
0162 Step = Step / 2.;
0163 Standard_Real StepU = Abs(Step*previousd2d.X()),
0164 StepV = Abs(Step*previousd2d.Y());
0165 if (StepU < tolerance(1) && StepV < tolerance(2))
0166 aStatus = IntWalk_ArretSurPoint;
0167 else
0168 aStatus = IntWalk_PasTropGrand;
0169 return aStatus;
0170 }
0171 Cosi = Du * sp.Direction2d().X() +
0172 Dv * sp.Direction2d().Y();
0173 Cosi2 = Cosi * Cosi / Duv;
0174 if (Cosi2 < CosRef2D ||
0175 sp.Direction2d() * previousd2d < 0) {
0176 //angle 2d too great or change the side
0177 Step = Step / 2.;
0178 Standard_Real StepU = Abs(Step*previousd2d.X()),
0179 StepV = Abs(Step*previousd2d.Y());
0180 if (StepU < tolerance(1) && StepV < tolerance(2))
0181 aStatus = IntWalk_ArretSurPointPrecedent;
0182 else
0183 aStatus = IntWalk_PasTropGrand;
0184 return aStatus;
0185 }
0186 }
0187
0188 if (!Finished) {
0189 if (aStatus == IntWalk_PointConfondu)
0190 {
0191 Standard_Real StepU = Min(Abs(1.5 * Du),pas*(UM-Um)),
0192 StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
0193
0194 Standard_Real d2dx = Abs(previousd2d.X());
0195 Standard_Real d2dy = Abs(previousd2d.Y());
0196
0197 if (d2dx < tolerance(1))
0198 {
0199 Step = StepV/d2dy;
0200 }
0201 else if (d2dy < tolerance(2))
0202 {
0203 Step = StepU/d2dx;
0204 }
0205 else
0206 {
0207 Step = Min(StepU/d2dx,StepV/d2dy);
0208 }
0209 }
0210 else
0211 {
0212 // estimate the current vector.
0213 // if vector/2<=current vector<= vector it is considered that the criterion
0214 // is observed.
0215 // otherwise adjust the step depending on the previous step
0216
0217 /*
0218 Standard_Real Dist = Sqrt(Norme)/3.;
0219 TColgp_Array1OfPnt Poles(1,4);
0220 gp_Pnt POnCurv,Milieu;
0221 Poles(1) = previousPoint.Value();
0222 Poles(4) = sp.Point();
0223 Poles(2) = Poles(1).XYZ() +
0224 StepSign * Dist* previousd3d.Normalized().XYZ();
0225 Poles(3) = Poles(4).XYZ() -
0226 StepSign * Dist*sp.Direction3d().Normalized().XYZ();
0227 BzCLib::PntPole(0.5,Poles,POnCurv);
0228 Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
0229 // FlecheCourante = Milieu.Distance(POnCurv);
0230 Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
0231 */
0232
0233 // Direct calculation :
0234 // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
0235 // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
0236 // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
0237 // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
0238 // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
0239 // the norm (square) of 3.*lambda (d1 - d4)/8.
0240 // either the norm of :
0241 // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
0242 // which produces, takin the square :
0243 // Norme * (d1-d4).SquareMagnitude()/64.
0244
0245 Standard_Real FlecheCourante =
0246 (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
0247
0248
0249 // if (FlecheCourante <= 0.5*fleche) {
0250 if (FlecheCourante <= 0.25*fleche*fleche)
0251 {
0252 Standard_Real d2dx = Abs(sp.Direction2d().X());
0253 Standard_Real d2dy = Abs(sp.Direction2d().Y());
0254
0255 Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
0256 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
0257
0258 if (d2dx < tolerance(1))
0259 {
0260 Step = StepV/d2dy;
0261 }
0262 else if (d2dy < tolerance(2))
0263 {
0264 Step = StepU/d2dx;
0265 }
0266 else
0267 {
0268 Step = Min(StepU/d2dx,StepV/d2dy);
0269 }
0270 }
0271 else
0272 {
0273 //if (FlecheCourante > fleche) { // step too great
0274 if (FlecheCourante > fleche*fleche)
0275 { // step too great
0276 Step = Step /2.;
0277 Standard_Real StepU = Abs(Step*previousd2d.X()),
0278 StepV = Abs(Step*previousd2d.Y());
0279
0280 if (StepU < tolerance(1) && StepV < tolerance(2))
0281 aStatus = IntWalk_ArretSurPointPrecedent;
0282 else
0283 aStatus = IntWalk_PasTropGrand;
0284 }
0285 else
0286 {
0287 Standard_Real d2dx = Abs(sp.Direction2d().X());
0288 Standard_Real d2dy = Abs(sp.Direction2d().Y());
0289
0290 Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
0291 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
0292
0293 if (d2dx < tolerance(1))
0294 {
0295 Step = Min(Step,StepV/d2dy);
0296 }
0297 else if (d2dy < tolerance(2))
0298 {
0299 Step = Min(Step,StepU/d2dx);
0300 }
0301 else
0302 {
0303 Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
0304 }
0305 }
0306 }
0307 }
0308 }
0309 return aStatus;
0310 }