| 1 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
| 2 | // |
| 3 | // This file is part of Open CASCADE Technology software library. |
| 4 | // |
| 5 | // This library is free software; you can redistribute it and/or modify it under |
| 6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
| 7 | // by the Free Software Foundation, with special exception defined in the file |
| 8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
| 9 | // distribution for complete text of the license and disclaimer of any warranty. |
| 10 | // |
| 11 | // Alternatively, this file may be used under the terms of Open CASCADE |
| 12 | // commercial license or contractual agreement. |
| 13 | |
| 14 | |
| 15 | #include <Adaptor3d_Surface.hxx> |
| 16 | #include <ElSLib.hxx> |
| 17 | #include <Geom_BezierSurface.hxx> |
| 18 | #include <Geom_BSplineSurface.hxx> |
| 19 | #include <gp_Circ.hxx> |
| 20 | #include <gp_Cone.hxx> |
| 21 | #include <gp_Pnt.hxx> |
| 22 | #include <gp_Pnt2d.hxx> |
| 23 | #include <IntTools_TopolTool.hxx> |
| 24 | #include <Precision.hxx> |
| 25 | #include <Standard_NotImplemented.hxx> |
| 26 | #include <Standard_Type.hxx> |
| 27 | #include <TColgp_Array2OfPnt.hxx> |
| 28 | #include <TColStd_HArray1OfReal.hxx> |
| 29 | |
| 30 | IMPLEMENT_STANDARD_RTTIEXT(IntTools_TopolTool,Adaptor3d_TopolTool) |
| 31 | |
| 32 | static void Analyse(const TColgp_Array2OfPnt& array2, |
| 33 | Standard_Integer& theNbSamplesU, |
| 34 | Standard_Integer& theNbSamplesV); |
| 35 | |
| 36 | // ===================================================================================== |
| 37 | // function: Constructor |
| 38 | // purpose: |
| 39 | // ===================================================================================== |
| 40 | IntTools_TopolTool::IntTools_TopolTool() |
| 41 | { |
| 42 | myNbSmplU = 0; |
| 43 | myNbSmplV = 0; |
| 44 | myDU = 1.; |
| 45 | myDV = 1.; |
| 46 | } |
| 47 | |
| 48 | // ===================================================================================== |
| 49 | // function: Constructor |
| 50 | // purpose: |
| 51 | // ===================================================================================== |
| 52 | IntTools_TopolTool::IntTools_TopolTool(const Handle(Adaptor3d_Surface)& theSurface) |
| 53 | { |
| 54 | Initialize(theSurface); |
| 55 | myNbSmplU = 0; |
| 56 | myNbSmplV = 0; |
| 57 | myDU = 1.; |
| 58 | myDV = 1.; |
| 59 | } |
| 60 | |
| 61 | // ===================================================================================== |
| 62 | // function: Initialize |
| 63 | // purpose: |
| 64 | // ===================================================================================== |
| 65 | void IntTools_TopolTool::Initialize() |
| 66 | { |
| 67 | throw Standard_NotImplemented("IntTools_TopolTool::Initialize ()"); |
| 68 | } |
| 69 | |
| 70 | // ===================================================================================== |
| 71 | // function: Initialize |
| 72 | // purpose: |
| 73 | // ===================================================================================== |
| 74 | void IntTools_TopolTool::Initialize(const Handle(Adaptor3d_Surface)& theSurface) |
| 75 | { |
| 76 | Adaptor3d_TopolTool::Initialize(theSurface); |
| 77 | //myS = theSurface; |
| 78 | myNbSmplU = 0; |
| 79 | myNbSmplV = 0; |
| 80 | myDU = 1.; |
| 81 | myDV = 1.; |
| 82 | } |
| 83 | |
| 84 | // ===================================================================================== |
| 85 | // function: ComputeSamplePoints |
| 86 | // purpose: |
| 87 | // ===================================================================================== |
| 88 | void IntTools_TopolTool::ComputeSamplePoints() |
| 89 | { |
| 90 | Standard_Real uinf, usup, vinf, vsup; |
| 91 | uinf = myS->FirstUParameter(); |
| 92 | usup = myS->LastUParameter(); |
| 93 | vinf = myS->FirstVParameter(); |
| 94 | vsup = myS->LastVParameter(); |
| 95 | const Standard_Integer aMaxNbSample = 50; |
| 96 | |
| 97 | if (usup < uinf) { Standard_Real temp = uinf; uinf = usup; usup = temp; } |
| 98 | if (vsup < vinf) { Standard_Real temp = vinf; vinf = vsup; vsup = temp; } |
| 99 | Standard_Boolean isbiguinf, isbigusup, isbigvinf, isbigvsup; |
| 100 | isbiguinf = Precision::IsNegativeInfinite(uinf); |
| 101 | isbigusup = Precision::IsPositiveInfinite(usup); |
| 102 | isbigvinf = Precision::IsNegativeInfinite(vinf); |
| 103 | isbigvsup = Precision::IsPositiveInfinite(vsup); |
| 104 | |
| 105 | if(isbiguinf && isbigusup) {uinf = -1.e5; usup = 1.e5;} |
| 106 | else if(isbiguinf) {uinf = usup - 2.e5;} |
| 107 | else if(isbigusup) {usup = uinf + 2.e5;} |
| 108 | |
| 109 | if(isbigvinf && isbigvsup) {vinf = -1.e5; vsup = 1.e5;} |
| 110 | else if(isbigvinf) {vinf = vsup - 2.e5;} |
| 111 | else if(isbigvsup) {vsup = vinf + 2.e5;} |
| 112 | myU0 = uinf; |
| 113 | myV0 = vinf; |
| 114 | |
| 115 | Standard_Integer nbsu = 0,nbsv = 0; |
| 116 | GeomAbs_SurfaceType typS = myS->GetType(); |
| 117 | |
| 118 | switch(typS) { |
| 119 | case GeomAbs_Plane: { |
| 120 | nbsu = 10; nbsv = 10; |
| 121 | } |
| 122 | break; |
| 123 | case GeomAbs_Cylinder: { |
| 124 | Standard_Real aRadius = myS->Cylinder().Radius(); |
| 125 | Standard_Real aMaxAngle = M_PI * 0.5; |
| 126 | Standard_Real aDeflection = 1.e-02; |
| 127 | |
| 128 | if(aRadius > aDeflection) { |
| 129 | aMaxAngle = ACos(1. - aDeflection / aRadius) * 2.; |
| 130 | } |
| 131 | if(aMaxAngle > Precision::Angular()) { |
| 132 | nbsu = Standard_Integer((usup-uinf) / aMaxAngle); |
| 133 | } |
| 134 | nbsv = (Standard_Integer)(vsup-vinf); |
| 135 | nbsv /= 10; |
| 136 | |
| 137 | if(nbsu < 2) nbsu = 2; |
| 138 | if(nbsv < 2) nbsv = 2; |
| 139 | |
| 140 | // if(nbsu < 10) nbsu = 10; |
| 141 | // if(nbsv < 10) nbsv = 10; |
| 142 | if(nbsu > aMaxNbSample) nbsu = aMaxNbSample; |
| 143 | if(nbsv > aMaxNbSample) nbsv = aMaxNbSample; |
| 144 | } |
| 145 | break; |
| 146 | case GeomAbs_Cone: { |
| 147 | gp_Cone aCone = myS->Cone(); |
| 148 | gp_Circ aCircle = ElSLib::ConeVIso(aCone.Position(), aCone.RefRadius(), aCone.SemiAngle(), vinf); |
| 149 | Standard_Real aRadius = aCircle.Radius(); |
| 150 | aCircle = ElSLib::ConeVIso(aCone.Position(), aCone.RefRadius(), aCone.SemiAngle(), vsup); |
| 151 | |
| 152 | if(aRadius < aCircle.Radius()) |
| 153 | aRadius = aCircle.Radius(); |
| 154 | Standard_Real aMaxAngle = M_PI * 0.5; |
| 155 | Standard_Real aDeflection = 1.e-02; |
| 156 | |
| 157 | if(aRadius > aDeflection) { |
| 158 | aMaxAngle = ACos(1. - aDeflection / aRadius) * 2.; |
| 159 | } |
| 160 | |
| 161 | if(aMaxAngle > Precision::Angular()) { |
| 162 | nbsu = Standard_Integer((usup - uinf) / aMaxAngle); |
| 163 | } |
| 164 | nbsv = (Standard_Integer)(vsup - vinf); |
| 165 | nbsv /= 10; |
| 166 | |
| 167 | // if(nbsu < 2) nbsu = 2; |
| 168 | // if(nbsv < 2) nbsv = 2; |
| 169 | |
| 170 | if(nbsu < 10) nbsu = 10; |
| 171 | if(nbsv < 10) nbsv = 10; |
| 172 | if(nbsu > aMaxNbSample) nbsu = aMaxNbSample; |
| 173 | if(nbsv > aMaxNbSample) nbsv = aMaxNbSample; |
| 174 | } |
| 175 | break; |
| 176 | case GeomAbs_Sphere: |
| 177 | case GeomAbs_Torus: { |
| 178 | gp_Circ aCircle; |
| 179 | Standard_Real aRadius1, aRadius2; |
| 180 | |
| 181 | if(typS == GeomAbs_Torus) { |
| 182 | gp_Torus aTorus = myS->Torus(); |
| 183 | aCircle = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), uinf); |
| 184 | aRadius2 = aCircle.Radius(); |
| 185 | aCircle = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), usup); |
| 186 | aRadius2 = (aRadius2 < aCircle.Radius()) ? aCircle.Radius() : aRadius2; |
| 187 | |
| 188 | aCircle = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), vinf); |
| 189 | aRadius1 = aCircle.Radius(); |
| 190 | aCircle = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(), aTorus.MinorRadius(), vsup); |
| 191 | aRadius1 = (aRadius1 < aCircle.Radius()) ? aCircle.Radius() : aRadius1; |
| 192 | } |
| 193 | else { |
| 194 | gp_Sphere aSphere = myS->Sphere(); |
| 195 | aRadius1 = aSphere.Radius(); |
| 196 | aRadius2 = aSphere.Radius(); |
| 197 | } |
| 198 | Standard_Real aMaxAngle = M_PI * 0.5; |
| 199 | Standard_Real aDeflection = 1.e-02; |
| 200 | |
| 201 | if(aRadius1 > aDeflection) { |
| 202 | aMaxAngle = ACos(1. - aDeflection / aRadius1) * 2.; |
| 203 | } |
| 204 | |
| 205 | if(aMaxAngle > Precision::Angular()) { |
| 206 | nbsu = Standard_Integer((usup - uinf) / aMaxAngle); |
| 207 | } |
| 208 | aMaxAngle = M_PI * 0.5; |
| 209 | |
| 210 | if(aRadius2 > aDeflection) { |
| 211 | aMaxAngle = ACos(1. - aDeflection / aRadius2) * 2.; |
| 212 | } |
| 213 | |
| 214 | if(aMaxAngle > Precision::Angular()) { |
| 215 | nbsv = Standard_Integer((vsup - vinf) / aMaxAngle); |
| 216 | } |
| 217 | if(nbsu < 10) nbsu = 10; |
| 218 | if(nbsv < 10) nbsv = 10; |
| 219 | if(nbsu > aMaxNbSample) nbsu = aMaxNbSample; |
| 220 | if(nbsv > aMaxNbSample) nbsv = aMaxNbSample; |
| 221 | } |
| 222 | break; |
| 223 | case GeomAbs_BezierSurface: { |
| 224 | nbsv = 3 + myS->NbVPoles(); |
| 225 | nbsu = 3 + myS->NbUPoles(); |
| 226 | |
| 227 | if(nbsu > 10 || nbsv > 10) { |
| 228 | TColgp_Array2OfPnt array2(1, myS->NbUPoles(), 1, myS->NbVPoles()); |
| 229 | myS->Bezier()->Poles(array2); |
| 230 | Analyse(array2, nbsu, nbsv); |
| 231 | } |
| 232 | |
| 233 | if(nbsu < 10) nbsu = 10; |
| 234 | if(nbsv < 10) nbsv = 10; |
| 235 | } |
| 236 | break; |
| 237 | case GeomAbs_BSplineSurface: { |
| 238 | nbsv = myS->NbVKnots(); nbsv *= myS->VDegree(); if(nbsv < 4) nbsv=4; |
| 239 | nbsu = myS->NbUKnots(); nbsu *= myS->UDegree(); if(nbsu < 4) nbsu=4; |
| 240 | |
| 241 | if(nbsu > 10 || nbsv > 10) { |
| 242 | TColgp_Array2OfPnt array2(1, myS->NbUPoles(), 1, myS->NbVPoles()); |
| 243 | myS->BSpline()->Poles(array2); |
| 244 | Analyse(array2, nbsu, nbsv); |
| 245 | } |
| 246 | if(nbsu < 10) nbsu = 10; |
| 247 | if(nbsv < 10) nbsv = 10; |
| 248 | // Check anisotropy |
| 249 | Standard_Real anULen = (usup - uinf) / myS->UResolution(1.); |
| 250 | Standard_Real anVLen = (vsup - vinf) / myS->VResolution(1.); |
| 251 | Standard_Real aRatio = anULen / anVLen; |
| 252 | if (aRatio >= 10.) |
| 253 | { |
| 254 | nbsu *= 2; |
| 255 | nbsu = Min(nbsu, aMaxNbSample); |
| 256 | } |
| 257 | else if (aRatio <= 0.1 ) |
| 258 | { |
| 259 | nbsv *= 2; |
| 260 | nbsv = Min(nbsv, aMaxNbSample); |
| 261 | } |
| 262 | } |
| 263 | break; |
| 264 | case GeomAbs_SurfaceOfExtrusion: { |
| 265 | nbsu = 15; |
| 266 | nbsv = (Standard_Integer)(vsup - vinf); |
| 267 | nbsv /= 10; |
| 268 | if(nbsv < 15) nbsv = 15; |
| 269 | if(nbsv > aMaxNbSample) nbsv = aMaxNbSample; |
| 270 | } |
| 271 | break; |
| 272 | case GeomAbs_SurfaceOfRevolution: { |
| 273 | nbsv = 15; nbsu = 15; |
| 274 | } |
| 275 | break; |
| 276 | default: { |
| 277 | nbsu = 10; nbsv = 10; |
| 278 | } |
| 279 | break; |
| 280 | } |
| 281 | myNbSmplU = nbsu; |
| 282 | myNbSmplV = nbsv; |
| 283 | |
| 284 | myNbSamplesU = myNbSmplU; |
| 285 | myNbSamplesV = myNbSmplV; |
| 286 | |
| 287 | myDU = (usup - uinf)/(myNbSmplU + 1); |
| 288 | myDV = (vsup - vinf)/(myNbSmplV + 1); |
| 289 | } |
| 290 | |
| 291 | // ===================================================================================== |
| 292 | // function: NbSamplesU |
| 293 | // purpose: |
| 294 | // ===================================================================================== |
| 295 | Standard_Integer IntTools_TopolTool::NbSamplesU() |
| 296 | { |
| 297 | if(myNbSmplU <= 0) { |
| 298 | ComputeSamplePoints(); |
| 299 | } |
| 300 | return myNbSmplU; |
| 301 | } |
| 302 | |
| 303 | // ===================================================================================== |
| 304 | // function: NbSamplesV |
| 305 | // purpose: |
| 306 | // ===================================================================================== |
| 307 | Standard_Integer IntTools_TopolTool::NbSamplesV() |
| 308 | { |
| 309 | if(myNbSmplV <= 0) { |
| 310 | ComputeSamplePoints(); |
| 311 | } |
| 312 | return myNbSmplV; |
| 313 | } |
| 314 | |
| 315 | // ===================================================================================== |
| 316 | // function: NbSamples |
| 317 | // purpose: |
| 318 | // ===================================================================================== |
| 319 | Standard_Integer IntTools_TopolTool::NbSamples() |
| 320 | { |
| 321 | if(myNbSmplU <= 0) { |
| 322 | ComputeSamplePoints(); |
| 323 | } |
| 324 | return(myNbSmplU * myNbSmplV); |
| 325 | } |
| 326 | |
| 327 | // ===================================================================================== |
| 328 | // function: SamplePoint |
| 329 | // purpose: |
| 330 | // ===================================================================================== |
| 331 | void IntTools_TopolTool::SamplePoint(const Standard_Integer Index, |
| 332 | gp_Pnt2d& P2d, |
| 333 | gp_Pnt& P3d) |
| 334 | { |
| 335 | if (myUPars.IsNull()) |
| 336 | { |
| 337 | if(myNbSmplU <= 0) { |
| 338 | ComputeSamplePoints(); |
| 339 | } |
| 340 | Standard_Integer iv = 1 + Index / myNbSmplU; |
| 341 | Standard_Integer iu = 1 + Index - (iv - 1) * myNbSmplU; |
| 342 | Standard_Real u = myU0 + iu * myDU; |
| 343 | Standard_Real v = myV0 + iv * myDV; |
| 344 | P2d.SetCoord(u, v); |
| 345 | P3d = myS->Value(u, v); |
| 346 | } |
| 347 | else |
| 348 | Adaptor3d_TopolTool::SamplePoint(Index, P2d, P3d); |
| 349 | } |
| 350 | |
| 351 | |
| 352 | //======================================================================= |
| 353 | // function : Analyse |
| 354 | // purpose : |
| 355 | //======================================================================= |
| 356 | void Analyse(const TColgp_Array2OfPnt& array2, |
| 357 | Standard_Integer& theNbSamplesU, |
| 358 | Standard_Integer& theNbSamplesV) |
| 359 | { |
| 360 | gp_Vec Vi,Vip1; |
| 361 | Standard_Integer sh,nbch,i,j; |
| 362 | const Standard_Integer nbup = array2.UpperRow() - array2.LowerRow() + 1; |
| 363 | const Standard_Integer nbvp = array2.UpperCol() - array2.LowerCol() + 1; |
| 364 | |
| 365 | sh = 1; |
| 366 | nbch = 0; |
| 367 | if(nbvp>2) { |
| 368 | |
| 369 | for(i = array2.LowerRow(); i <= array2.UpperRow(); i++) { |
| 370 | const gp_Pnt& A=array2.Value(i,1); |
| 371 | const gp_Pnt& B=array2.Value(i,2); |
| 372 | const gp_Pnt& C=array2.Value(i,3); |
| 373 | Vi.SetCoord(C.X()-B.X()-B.X()+A.X(), |
| 374 | C.Y()-B.Y()-B.Y()+A.Y(), |
| 375 | C.Z()-B.Z()-B.Z()+A.Z()); |
| 376 | Standard_Integer locnbch=0; |
| 377 | |
| 378 | for(j = array2.LowerCol() + 2; j < array2.UpperCol();j++) { //-- essai |
| 379 | const gp_Pnt& Ax=array2.Value(i,j-1); |
| 380 | const gp_Pnt& Bx=array2.Value(i,j); |
| 381 | const gp_Pnt& Cx=array2.Value(i,j+1); |
| 382 | Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(), |
| 383 | Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(), |
| 384 | Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z()); |
| 385 | Standard_Real pd = Vi.Dot(Vip1); |
| 386 | Vi=Vip1; |
| 387 | if(pd>1.0e-7 || pd<-1.0e-7) { |
| 388 | if(pd>0) { if(sh==-1) { sh=1; locnbch++; } } |
| 389 | else { if(sh==1) { sh=-1; locnbch++; } } |
| 390 | } |
| 391 | } |
| 392 | if(locnbch>nbch) { |
| 393 | nbch=locnbch; |
| 394 | } |
| 395 | } |
| 396 | } |
| 397 | theNbSamplesV = nbch+5; |
| 398 | |
| 399 | |
| 400 | nbch=0; |
| 401 | if(nbup > 2) { |
| 402 | for(j = array2.LowerCol(); j <= array2.UpperCol(); j++) { |
| 403 | const gp_Pnt& A=array2.Value(array2.LowerRow(), j); |
| 404 | const gp_Pnt& B=array2.Value(array2.LowerRow() + 1, j); |
| 405 | const gp_Pnt& C=array2.Value(array2.LowerRow() + 2, j); |
| 406 | Vi.SetCoord(C.X()-B.X()-B.X()+A.X(), |
| 407 | C.Y()-B.Y()-B.Y()+A.Y(), |
| 408 | C.Z()-B.Z()-B.Z()+A.Z()); |
| 409 | Standard_Integer locnbch=0; |
| 410 | |
| 411 | for(i = array2.LowerRow() + 2; i < array2.UpperRow(); i++) { //-- essai |
| 412 | const gp_Pnt& Ax=array2.Value(i-1,j); |
| 413 | const gp_Pnt& Bx=array2.Value(i,j); |
| 414 | const gp_Pnt& Cx=array2.Value(i+1,j); |
| 415 | Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(), |
| 416 | Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(), |
| 417 | Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z()); |
| 418 | Standard_Real pd = Vi.Dot(Vip1); |
| 419 | Vi=Vip1; |
| 420 | if(pd>1.0e-7 || pd<-1.0e-7) { |
| 421 | if(pd>0) { if(sh==-1) { sh=1; locnbch++; } } |
| 422 | else { if(sh==1) { sh=-1; locnbch++; } } |
| 423 | } |
| 424 | } |
| 425 | if(locnbch>nbch) nbch=locnbch; |
| 426 | } |
| 427 | } |
| 428 | theNbSamplesU = nbch+5; |
| 429 | } |
| 430 | |
| 431 | //Modified IFV |
| 432 | //======================================================================= |
| 433 | //function : SamplePnts |
| 434 | //purpose : |
| 435 | //======================================================================= |
| 436 | |
| 437 | void IntTools_TopolTool::SamplePnts(const Standard_Real theDefl, |
| 438 | const Standard_Integer theNUmin, |
| 439 | const Standard_Integer theNVmin) |
| 440 | { |
| 441 | Adaptor3d_TopolTool::SamplePnts(theDefl, theNUmin, theNVmin); |
| 442 | |
| 443 | myNbSmplU = Adaptor3d_TopolTool::NbSamplesU(); |
| 444 | myNbSmplV = Adaptor3d_TopolTool::NbSamplesV(); |
| 445 | |
| 446 | myU0 = myUPars->Value(1); |
| 447 | myV0 = myVPars->Value(1); |
| 448 | |
| 449 | myDU = (myUPars->Value(myNbSmplU) - myU0)/(myNbSmplU-1); |
| 450 | myDV = (myVPars->Value(myNbSmplV) - myV0)/(myNbSmplV-1); |
| 451 | } |