1 //============================================================================ 2 // Copyright (c) Kitware, Inc. 3 // All rights reserved. 4 // See LICENSE.txt for details. 5 // 6 // This software is distributed WITHOUT ANY WARRANTY; without even 7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 8 // PURPOSE. See the above copyright notice for more information. 9 //============================================================================ 10 #ifndef vtk_m_ImplicitFunction_h 11 #define vtk_m_ImplicitFunction_h 12 13 #include <vtkm/Bounds.h> 14 #include <vtkm/Deprecated.h> 15 #include <vtkm/Math.h> 16 #include <vtkm/VectorAnalysis.h> 17 18 #include <vtkm/exec/internal/Variant.h> 19 20 // For interface class only. 21 #include <vtkm/cont/ExecutionAndControlObjectBase.h> 22 23 #ifndef VTKM_NO_DEPRECATED_VIRTUAL 24 #include <vtkm/VirtualObjectBase.h> 25 #endif // VTKM_NO_DEPRECATED_VIRTUAL 26 27 namespace vtkm 28 { 29 30 //============================================================================ 31 #ifndef VTKM_NO_DEPRECATED_VIRTUAL 32 class VTKM_DEPRECATED(1.6, "ImplicitFunction with virtual methods no longer supported.") 33 VTKM_ALWAYS_EXPORT ImplicitFunction : public vtkm::VirtualObjectBase 34 { 35 public: 36 using Scalar = vtkm::FloatDefault; 37 using Vector = vtkm::Vec<Scalar, 3>; 38 39 VTKM_EXEC_CONT virtual Scalar Value(const Vector& point) const = 0; 40 VTKM_EXEC_CONT virtual Vector Gradient(const Vector& point) const = 0; 41 42 VTKM_DEPRECATED_SUPPRESS_BEGIN Value(Scalar x,Scalar y,Scalar z)43 VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const 44 { 45 return this->Value(Vector(x, y, z)); 46 } 47 Gradient(Scalar x,Scalar y,Scalar z)48 VTKM_EXEC_CONT Vector Gradient(Scalar x, Scalar y, Scalar z) const 49 { 50 return this->Gradient(Vector(x, y, z)); 51 } 52 VTKM_DEPRECATED_SUPPRESS_END 53 }; 54 #endif // VTKM_NO_DEPRECATED_VIRTUAL 55 56 //============================================================================ 57 namespace internal 58 { 59 60 /// \brief Base class for all `ImplicitFunction` classes. 61 /// 62 /// `ImplicitFunctionBase` uses the curiously recurring template pattern (CRTP). Subclasses 63 /// must provide their own type for the template parameter. Subclasses must implement 64 /// `Value` and `Gradient` methods. 65 /// 66 /// Also, all subclasses must be trivially copiable. This is so they can be copied among 67 /// host and devices. 68 /// 69 template <typename Derived> 70 class ImplicitFunctionBase : public vtkm::cont::ExecutionAndControlObjectBase 71 { 72 public: 73 using Scalar = vtkm::FloatDefault; 74 using Vector = vtkm::Vec<Scalar, 3>; 75 Value(Scalar x,Scalar y,Scalar z)76 VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const 77 { 78 return reinterpret_cast<const Derived*>(this)->Value(Vector(x, y, z)); 79 } 80 Gradient(Scalar x,Scalar y,Scalar z)81 VTKM_EXEC_CONT Vector Gradient(Scalar x, Scalar y, Scalar z) const 82 { 83 return reinterpret_cast<const Derived*>(this)->Gradient(Vector(x, y, z)); 84 } 85 PrepareForExecution(vtkm::cont::DeviceAdapterId,vtkm::cont::Token &)86 VTKM_CONT Derived PrepareForExecution(vtkm::cont::DeviceAdapterId, vtkm::cont::Token&) const 87 { 88 return *reinterpret_cast<const Derived*>(this); 89 } 90 PrepareForControl()91 VTKM_CONT Derived PrepareForControl() const { return *reinterpret_cast<const Derived*>(this); } 92 }; 93 94 } // namespace vtkm::internal 95 96 //============================================================================ 97 #ifndef VTKM_NO_DEPRECATED_VIRTUAL 98 VTKM_DEPRECATED_SUPPRESS_BEGIN 99 100 /// A helpful functor that calls the (virtual) value method of a given ImplicitFunction. Can be 101 /// passed to things that expect a functor instead of an ImplictFunction class (like an array 102 /// transform). 103 /// 104 class VTKM_DEPRECATED(1.6, 105 "Use ImplicitFunctionValueFunctor.") VTKM_ALWAYS_EXPORT ImplicitFunctionValue 106 { 107 public: 108 using Scalar = vtkm::ImplicitFunction::Scalar; 109 using Vector = vtkm::ImplicitFunction::Vector; 110 ImplicitFunctionValue()111 VTKM_EXEC_CONT ImplicitFunctionValue() 112 : Function(nullptr) 113 { 114 } 115 ImplicitFunctionValue(const ImplicitFunction * function)116 VTKM_EXEC_CONT ImplicitFunctionValue(const ImplicitFunction* function) 117 : Function(function) 118 { 119 } 120 operator()121 VTKM_EXEC_CONT Scalar operator()(const Vector& point) const 122 { 123 return this->Function->Value(point); 124 } 125 126 private: 127 const vtkm::ImplicitFunction* Function; 128 }; 129 130 /// A helpful functor that calls the (virtual) gradient method of a given ImplicitFunction. Can be 131 /// passed to things that expect a functor instead of an ImplictFunction class (like an array 132 /// transform). 133 /// 134 class VTKM_DEPRECATED(1.6, "Use ImplicitFunctionGradientFunctor.") 135 VTKM_ALWAYS_EXPORT ImplicitFunctionGradient 136 { 137 public: 138 using Scalar = vtkm::ImplicitFunction::Scalar; 139 using Vector = vtkm::ImplicitFunction::Vector; 140 ImplicitFunctionGradient()141 VTKM_EXEC_CONT ImplicitFunctionGradient() 142 : Function(nullptr) 143 { 144 } 145 ImplicitFunctionGradient(const ImplicitFunction * function)146 VTKM_EXEC_CONT ImplicitFunctionGradient(const ImplicitFunction* function) 147 : Function(function) 148 { 149 } 150 operator()151 VTKM_EXEC_CONT Vector operator()(const Vector& point) const 152 { 153 return this->Function->Gradient(point); 154 } 155 156 private: 157 const vtkm::ImplicitFunction* Function; 158 }; 159 160 VTKM_DEPRECATED_SUPPRESS_END 161 #endif // VTKM_NO_DEPRECATED_VIRTUAL 162 163 //============================================================================ 164 /// A helpful functor that calls the value method of a given `ImplicitFunction`. Can be 165 /// passed to things that expect a functor instead of an `ImplictFunction` class (like an array 166 /// transform). 167 /// 168 template <typename FunctionType> 169 class ImplicitFunctionValueFunctor 170 { 171 public: 172 using Scalar = typename FunctionType::Scalar; 173 using Vector = typename FunctionType::Vector; 174 175 ImplicitFunctionValueFunctor() = default; 176 ImplicitFunctionValueFunctor(const vtkm::internal::ImplicitFunctionBase<FunctionType> & function)177 VTKM_EXEC_CONT ImplicitFunctionValueFunctor( 178 const vtkm::internal::ImplicitFunctionBase<FunctionType>& function) 179 : Function(reinterpret_cast<const FunctionType&>(function)) 180 { 181 } 182 ImplicitFunctionValueFunctor(const FunctionType & function)183 VTKM_EXEC_CONT ImplicitFunctionValueFunctor(const FunctionType& function) 184 : Function(function) 185 { 186 } 187 operator()188 VTKM_EXEC_CONT Scalar operator()(const Vector& point) const 189 { 190 return this->Function.Value(point); 191 } 192 193 private: 194 FunctionType Function; 195 }; 196 197 /// A helpful functor that calls the gradient method of a given `ImplicitFunction`. Can be 198 /// passed to things that expect a functor instead of an `ImplictFunction` class (like an array 199 /// transform). 200 /// 201 template <typename FunctionType> 202 class ImplicitFunctionGradientFunctor 203 { 204 public: 205 using Scalar = typename FunctionType::Scalar; 206 using Vector = typename FunctionType::Vector; 207 208 ImplicitFunctionGradientFunctor() = default; 209 ImplicitFunctionGradientFunctor(const vtkm::internal::ImplicitFunctionBase<FunctionType> & function)210 VTKM_EXEC_CONT ImplicitFunctionGradientFunctor( 211 const vtkm::internal::ImplicitFunctionBase<FunctionType>& function) 212 : Function(reinterpret_cast<const FunctionType&>(function)) 213 { 214 } 215 ImplicitFunctionGradientFunctor(const FunctionType & function)216 VTKM_EXEC_CONT ImplicitFunctionGradientFunctor(const FunctionType& function) 217 : Function(function) 218 { 219 } 220 operator()221 VTKM_EXEC_CONT Vector operator()(const Vector& point) const 222 { 223 return this->Function->Gradient(point); 224 } 225 226 private: 227 FunctionType Function; 228 }; 229 230 //============================================================================ 231 /// \brief Implicit function for a box 232 /// 233 /// \c Box computes the implicit function and/or gradient for a axis-aligned 234 /// bounding box. Each side of the box is orthogonal to all other sides 235 /// meeting along shared edges and all faces are orthogonal to the x-y-z 236 /// coordinate axes. 237 238 class VTKM_ALWAYS_EXPORT Box : public internal::ImplicitFunctionBase<Box> 239 { 240 public: 241 /// \brief Construct box with center at (0,0,0) and each side of length 1.0. Box()242 VTKM_EXEC_CONT Box() 243 : MinPoint(Vector(Scalar(-0.5))) 244 , MaxPoint(Vector(Scalar(0.5))) 245 { 246 } 247 Box(const Vector & minPoint,const Vector & maxPoint)248 VTKM_EXEC_CONT Box(const Vector& minPoint, const Vector& maxPoint) 249 : MinPoint(minPoint) 250 , MaxPoint(maxPoint) 251 { 252 } 253 Box(Scalar xmin,Scalar xmax,Scalar ymin,Scalar ymax,Scalar zmin,Scalar zmax)254 VTKM_EXEC_CONT Box(Scalar xmin, Scalar xmax, Scalar ymin, Scalar ymax, Scalar zmin, Scalar zmax) 255 : MinPoint(xmin, ymin, zmin) 256 , MaxPoint(xmax, ymax, zmax) 257 { 258 } 259 Box(const vtkm::Bounds & bounds)260 VTKM_CONT Box(const vtkm::Bounds& bounds) { this->SetBounds(bounds); } 261 SetMinPoint(const Vector & point)262 VTKM_CONT void SetMinPoint(const Vector& point) { this->MinPoint = point; } 263 SetMaxPoint(const Vector & point)264 VTKM_CONT void SetMaxPoint(const Vector& point) { this->MaxPoint = point; } 265 GetMinPoint()266 VTKM_EXEC_CONT const Vector& GetMinPoint() const { return this->MinPoint; } 267 GetMaxPoint()268 VTKM_EXEC_CONT const Vector& GetMaxPoint() const { return this->MaxPoint; } 269 SetBounds(const vtkm::Bounds & bounds)270 VTKM_CONT void SetBounds(const vtkm::Bounds& bounds) 271 { 272 this->SetMinPoint({ Scalar(bounds.X.Min), Scalar(bounds.Y.Min), Scalar(bounds.Z.Min) }); 273 this->SetMaxPoint({ Scalar(bounds.X.Max), Scalar(bounds.Y.Max), Scalar(bounds.Z.Max) }); 274 } 275 GetBounds()276 VTKM_EXEC_CONT vtkm::Bounds GetBounds() const 277 { 278 return vtkm::Bounds(vtkm::Range(this->MinPoint[0], this->MaxPoint[0]), 279 vtkm::Range(this->MinPoint[1], this->MaxPoint[1]), 280 vtkm::Range(this->MinPoint[2], this->MaxPoint[2])); 281 } 282 Value(const Vector & point)283 VTKM_EXEC_CONT Scalar Value(const Vector& point) const 284 { 285 Scalar minDistance = vtkm::NegativeInfinity32(); 286 Scalar diff, t, dist; 287 Scalar distance = Scalar(0.0); 288 vtkm::IdComponent inside = 1; 289 290 for (vtkm::IdComponent d = 0; d < 3; d++) 291 { 292 diff = this->MaxPoint[d] - this->MinPoint[d]; 293 if (diff != Scalar(0.0)) 294 { 295 t = (point[d] - this->MinPoint[d]) / diff; 296 // Outside before the box 297 if (t < Scalar(0.0)) 298 { 299 inside = 0; 300 dist = this->MinPoint[d] - point[d]; 301 } 302 // Outside after the box 303 else if (t > Scalar(1.0)) 304 { 305 inside = 0; 306 dist = point[d] - this->MaxPoint[d]; 307 } 308 else 309 { 310 // Inside the box in lower half 311 if (t <= Scalar(0.5)) 312 { 313 dist = MinPoint[d] - point[d]; 314 } 315 // Inside the box in upper half 316 else 317 { 318 dist = point[d] - MaxPoint[d]; 319 } 320 if (dist > minDistance) 321 { 322 minDistance = dist; 323 } 324 } 325 } 326 else 327 { 328 dist = vtkm::Abs(point[d] - MinPoint[d]); 329 if (dist > Scalar(0.0)) 330 { 331 inside = 0; 332 } 333 } 334 if (dist > Scalar(0.0)) 335 { 336 distance += dist * dist; 337 } 338 } 339 340 distance = vtkm::Sqrt(distance); 341 if (inside) 342 { 343 return minDistance; 344 } 345 else 346 { 347 return distance; 348 } 349 } 350 Gradient(const Vector & point)351 VTKM_EXEC_CONT Vector Gradient(const Vector& point) const 352 { 353 vtkm::IdComponent minAxis = 0; 354 Scalar dist = 0.0; 355 Scalar minDist = vtkm::Infinity32(); 356 vtkm::IdComponent3 location; 357 Vector normal(Scalar(0)); 358 Vector inside(Scalar(0)); 359 Vector outside(Scalar(0)); 360 Vector center((this->MaxPoint + this->MinPoint) * Scalar(0.5)); 361 362 // Compute the location of the point with respect to the box 363 // Point will lie in one of 27 separate regions around or within the box 364 // Gradient vector is computed differently in each of the regions. 365 for (vtkm::IdComponent d = 0; d < 3; d++) 366 { 367 if (point[d] < this->MinPoint[d]) 368 { 369 // Outside the box low end 370 location[d] = 0; 371 outside[d] = -1.0; 372 } 373 else if (point[d] > this->MaxPoint[d]) 374 { 375 // Outside the box high end 376 location[d] = 2; 377 outside[d] = 1.0; 378 } 379 else 380 { 381 location[d] = 1; 382 if (point[d] <= center[d]) 383 { 384 // Inside the box low end 385 dist = point[d] - this->MinPoint[d]; 386 inside[d] = -1.0; 387 } 388 else 389 { 390 // Inside the box high end 391 dist = this->MaxPoint[d] - point[d]; 392 inside[d] = 1.0; 393 } 394 if (dist < minDist) // dist is negative 395 { 396 minDist = dist; 397 minAxis = d; 398 } 399 } 400 } 401 402 vtkm::Id indx = location[0] + 3 * location[1] + 9 * location[2]; 403 switch (indx) 404 { 405 // verts - gradient points away from center point 406 case 0: 407 case 2: 408 case 6: 409 case 8: 410 case 18: 411 case 20: 412 case 24: 413 case 26: 414 for (vtkm::IdComponent d = 0; d < 3; d++) 415 { 416 normal[d] = point[d] - center[d]; 417 } 418 vtkm::Normalize(normal); 419 break; 420 421 // edges - gradient points out from axis of cube 422 case 1: 423 case 3: 424 case 5: 425 case 7: 426 case 9: 427 case 11: 428 case 15: 429 case 17: 430 case 19: 431 case 21: 432 case 23: 433 case 25: 434 for (vtkm::IdComponent d = 0; d < 3; d++) 435 { 436 if (outside[d] != 0.0) 437 { 438 normal[d] = point[d] - center[d]; 439 } 440 else 441 { 442 normal[d] = 0.0; 443 } 444 } 445 vtkm::Normalize(normal); 446 break; 447 448 // faces - gradient points perpendicular to face 449 case 4: 450 case 10: 451 case 12: 452 case 14: 453 case 16: 454 case 22: 455 for (vtkm::IdComponent d = 0; d < 3; d++) 456 { 457 normal[d] = outside[d]; 458 } 459 break; 460 461 // interior - gradient is perpendicular to closest face 462 case 13: 463 normal[0] = normal[1] = normal[2] = 0.0; 464 normal[minAxis] = inside[minAxis]; 465 break; 466 default: 467 VTKM_ASSERT(false); 468 break; 469 } 470 return normal; 471 } 472 473 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 474 VTKM_EXEC Box* operator->() { return this; } 475 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 476 VTKM_EXEC const Box* operator->() const { return this; } 477 478 private: 479 Vector MinPoint; 480 Vector MaxPoint; 481 }; 482 483 //============================================================================ 484 /// \brief Implicit function for a cylinder 485 /// 486 /// \c Cylinder computes the implicit function and function gradient 487 /// for a cylinder using F(r)=r^2-Radius^2. By default the Cylinder is 488 /// centered at the origin and the axis of rotation is along the 489 /// y-axis. You can redefine the center and axis of rotation by setting 490 /// the Center and Axis data members. 491 /// 492 /// Note that the cylinder is infinite in extent. 493 /// 494 class VTKM_ALWAYS_EXPORT Cylinder : public vtkm::internal::ImplicitFunctionBase<Cylinder> 495 { 496 public: 497 /// Construct cylinder radius of 0.5; centered at origin with axis 498 /// along y coordinate axis. Cylinder()499 VTKM_EXEC_CONT Cylinder() 500 : Center(Scalar(0)) 501 , Axis(Scalar(0), Scalar(1), Scalar(0)) 502 , Radius(Scalar(0.5)) 503 { 504 } 505 Cylinder(const Vector & axis,Scalar radius)506 VTKM_EXEC_CONT Cylinder(const Vector& axis, Scalar radius) 507 : Center(Scalar(0)) 508 , Axis(axis) 509 , Radius(radius) 510 { 511 } 512 Cylinder(const Vector & center,const Vector & axis,Scalar radius)513 VTKM_EXEC_CONT Cylinder(const Vector& center, const Vector& axis, Scalar radius) 514 : Center(center) 515 , Axis(vtkm::Normal(axis)) 516 , Radius(radius) 517 { 518 } 519 SetCenter(const Vector & center)520 VTKM_CONT void SetCenter(const Vector& center) { this->Center = center; } 521 SetAxis(const Vector & axis)522 VTKM_CONT void SetAxis(const Vector& axis) { this->Axis = vtkm::Normal(axis); } 523 SetRadius(Scalar radius)524 VTKM_CONT void SetRadius(Scalar radius) { this->Radius = radius; } 525 Value(const Vector & point)526 VTKM_EXEC_CONT Scalar Value(const Vector& point) const 527 { 528 Vector x2c = point - this->Center; 529 FloatDefault proj = vtkm::Dot(this->Axis, x2c); 530 return vtkm::Dot(x2c, x2c) - (proj * proj) - (this->Radius * this->Radius); 531 } 532 Gradient(const Vector & point)533 VTKM_EXEC_CONT Vector Gradient(const Vector& point) const 534 { 535 Vector x2c = point - this->Center; 536 FloatDefault t = this->Axis[0] * x2c[0] + this->Axis[1] * x2c[1] + this->Axis[2] * x2c[2]; 537 vtkm::Vec<FloatDefault, 3> closestPoint = this->Center + (this->Axis * t); 538 return (point - closestPoint) * FloatDefault(2); 539 } 540 541 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 542 VTKM_EXEC Cylinder* operator->() { return this; } 543 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 544 VTKM_EXEC const Cylinder* operator->() const { return this; } 545 546 private: 547 Vector Center; 548 Vector Axis; 549 Scalar Radius; 550 }; 551 552 //============================================================================ 553 /// \brief Implicit function for a frustum 554 class VTKM_ALWAYS_EXPORT Frustum : public vtkm::internal::ImplicitFunctionBase<Frustum> 555 { 556 public: 557 /// \brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0. 558 Frustum() = default; 559 Frustum(const Vector points[6],const Vector normals[6])560 VTKM_EXEC_CONT Frustum(const Vector points[6], const Vector normals[6]) 561 { 562 this->SetPlanes(points, normals); 563 } 564 Frustum(const Vector points[8])565 VTKM_EXEC_CONT explicit Frustum(const Vector points[8]) { this->CreateFromPoints(points); } 566 SetPlanes(const Vector points[6],const Vector normals[6])567 VTKM_EXEC void SetPlanes(const Vector points[6], const Vector normals[6]) 568 { 569 for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 }) 570 { 571 this->Points[index] = points[index]; 572 } 573 for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 }) 574 { 575 this->Normals[index] = normals[index]; 576 } 577 } 578 SetPlane(int idx,const Vector & point,const Vector & normal)579 VTKM_EXEC void SetPlane(int idx, const Vector& point, const Vector& normal) 580 { 581 VTKM_ASSERT((idx >= 0) && (idx < 6)); 582 this->Points[idx] = point; 583 this->Normals[idx] = normal; 584 } 585 GetPlanes(Vector points[6],Vector normals[6])586 VTKM_EXEC_CONT void GetPlanes(Vector points[6], Vector normals[6]) const 587 { 588 for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 }) 589 { 590 points[index] = this->Points[index]; 591 } 592 for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 }) 593 { 594 normals[index] = this->Normals[index]; 595 } 596 } 597 GetPoints()598 VTKM_EXEC_CONT const Vector* GetPoints() const { return this->Points; } 599 GetNormals()600 VTKM_EXEC_CONT const Vector* GetNormals() const { return this->Normals; } 601 602 // The points should be specified in the order of hex-cell vertices CreateFromPoints(const Vector points[8])603 VTKM_EXEC_CONT void CreateFromPoints(const Vector points[8]) 604 { 605 // XXX(clang-format-3.9): 3.8 is silly. 3.9 makes it look like this. 606 // clang-format off 607 int planes[6][3] = { 608 { 3, 2, 0 }, { 4, 5, 7 }, { 0, 1, 4 }, { 1, 2, 5 }, { 2, 3, 6 }, { 3, 0, 7 } 609 }; 610 // clang-format on 611 612 for (int i = 0; i < 6; ++i) 613 { 614 const Vector& v0 = points[planes[i][0]]; 615 const Vector& v1 = points[planes[i][1]]; 616 const Vector& v2 = points[planes[i][2]]; 617 618 this->Points[i] = v0; 619 this->Normals[i] = vtkm::Normal(vtkm::TriangleNormal(v0, v1, v2)); 620 } 621 } 622 Value(const Vector & point)623 VTKM_EXEC_CONT Scalar Value(const Vector& point) const 624 { 625 Scalar maxVal = vtkm::NegativeInfinity<Scalar>(); 626 for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 }) 627 { 628 const Vector& p = this->Points[index]; 629 const Vector& n = this->Normals[index]; 630 const Scalar val = vtkm::Dot(point - p, n); 631 maxVal = vtkm::Max(maxVal, val); 632 } 633 return maxVal; 634 } 635 Gradient(const Vector & point)636 VTKM_EXEC_CONT Vector Gradient(const Vector& point) const 637 { 638 Scalar maxVal = vtkm::NegativeInfinity<Scalar>(); 639 vtkm::Id maxValIdx = 0; 640 for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 }) 641 { 642 const Vector& p = this->Points[index]; 643 const Vector& n = this->Normals[index]; 644 Scalar val = vtkm::Dot(point - p, n); 645 if (val > maxVal) 646 { 647 maxVal = val; 648 maxValIdx = index; 649 } 650 } 651 return this->Normals[maxValIdx]; 652 } 653 654 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 655 VTKM_EXEC Frustum* operator->() { return this; } 656 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 657 VTKM_EXEC const Frustum* operator->() const { return this; } 658 659 private: 660 Vector Points[6] = { { -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, { 0.0f, -0.5f, 0.0f }, 661 { 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } }; 662 Vector Normals[6] = { { -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, 663 { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } }; 664 }; 665 666 //============================================================================ 667 /// \brief Implicit function for a plane 668 /// 669 /// A plane is defined by a point in the plane and a normal to the plane. 670 /// The normal does not have to be a unit vector. The implicit function will 671 /// still evaluate to 0 at the plane, but the values outside the plane 672 /// (and the gradient) will be scaled by the length of the normal vector. 673 class VTKM_ALWAYS_EXPORT Plane : public vtkm::internal::ImplicitFunctionBase<Plane> 674 { 675 public: 676 /// Construct plane passing through origin and normal to z-axis. Plane()677 VTKM_EXEC_CONT Plane() 678 : Origin(Scalar(0)) 679 , Normal(Scalar(0), Scalar(0), Scalar(1)) 680 { 681 } 682 683 /// Construct a plane through the origin with the given normal. Plane(const Vector & normal)684 VTKM_EXEC_CONT explicit Plane(const Vector& normal) 685 : Origin(Scalar(0)) 686 , Normal(normal) 687 { 688 } 689 690 /// Construct a plane through the given point with the given normal. Plane(const Vector & origin,const Vector & normal)691 VTKM_EXEC_CONT Plane(const Vector& origin, const Vector& normal) 692 : Origin(origin) 693 , Normal(normal) 694 { 695 } 696 SetOrigin(const Vector & origin)697 VTKM_CONT void SetOrigin(const Vector& origin) { this->Origin = origin; } 698 SetNormal(const Vector & normal)699 VTKM_CONT void SetNormal(const Vector& normal) { this->Normal = normal; } 700 GetOrigin()701 VTKM_EXEC_CONT const Vector& GetOrigin() const { return this->Origin; } GetNormal()702 VTKM_EXEC_CONT const Vector& GetNormal() const { return this->Normal; } 703 Value(const Vector & point)704 VTKM_EXEC_CONT Scalar Value(const Vector& point) const 705 { 706 return vtkm::Dot(point - this->Origin, this->Normal); 707 } 708 Gradient(const Vector &)709 VTKM_EXEC_CONT Vector Gradient(const Vector&) const { return this->Normal; } 710 711 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 712 VTKM_EXEC Plane* operator->() { return this; } 713 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 714 VTKM_EXEC const Plane* operator->() const { return this; } 715 716 private: 717 Vector Origin; 718 Vector Normal; 719 }; 720 721 //============================================================================ 722 /// \brief Implicit function for a sphere 723 /// 724 /// A sphere is defined by its center and a radius. 725 /// 726 /// The value of the sphere implicit function is the square of the distance 727 /// from the center biased by the radius (so the surface of the sphere is 728 /// at value 0). 729 class VTKM_ALWAYS_EXPORT Sphere : public vtkm::internal::ImplicitFunctionBase<Sphere> 730 { 731 public: 732 /// Construct sphere with center at (0,0,0) and radius = 0.5. Sphere()733 VTKM_EXEC_CONT Sphere() 734 : Radius(Scalar(0.5)) 735 , Center(Scalar(0)) 736 { 737 } 738 739 /// Construct a sphere with center at (0,0,0) and the given radius. Sphere(Scalar radius)740 VTKM_EXEC_CONT explicit Sphere(Scalar radius) 741 : Radius(radius) 742 , Center(Scalar(0)) 743 { 744 } 745 Sphere(Vector center,Scalar radius)746 VTKM_EXEC_CONT Sphere(Vector center, Scalar radius) 747 : Radius(radius) 748 , Center(center) 749 { 750 } 751 SetRadius(Scalar radius)752 VTKM_CONT void SetRadius(Scalar radius) { this->Radius = radius; } 753 SetCenter(const Vector & center)754 VTKM_CONT void SetCenter(const Vector& center) { this->Center = center; } 755 GetRadius()756 VTKM_EXEC_CONT Scalar GetRadius() const { return this->Radius; } 757 GetCenter()758 VTKM_EXEC_CONT const Vector& GetCenter() const { return this->Center; } 759 Value(const Vector & point)760 VTKM_EXEC_CONT Scalar Value(const Vector& point) const 761 { 762 return vtkm::MagnitudeSquared(point - this->Center) - (this->Radius * this->Radius); 763 } 764 Gradient(const Vector & point)765 VTKM_EXEC_CONT Vector Gradient(const Vector& point) const 766 { 767 return Scalar(2) * (point - this->Center); 768 } 769 770 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 771 VTKM_EXEC Sphere* operator->() { return this; } 772 VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.") 773 VTKM_EXEC const Sphere* operator->() const { return this; } 774 775 private: 776 Scalar Radius; 777 Vector Center; 778 }; 779 780 namespace detail 781 { 782 783 struct ImplicitFunctionValueFunctor 784 { 785 template <typename ImplicitFunctionType> operatorImplicitFunctionValueFunctor786 VTKM_EXEC_CONT typename ImplicitFunctionType::Scalar operator()( 787 const ImplicitFunctionType& function, 788 const typename ImplicitFunctionType::Vector& point) const 789 { 790 return function.Value(point); 791 } 792 }; 793 794 struct ImplicitFunctionGradientFunctor 795 { 796 template <typename ImplicitFunctionType> operatorImplicitFunctionGradientFunctor797 VTKM_EXEC_CONT typename ImplicitFunctionType::Vector operator()( 798 const ImplicitFunctionType& function, 799 const typename ImplicitFunctionType::Vector& point) const 800 { 801 return function.Gradient(point); 802 } 803 }; 804 805 } // namespace detail 806 807 //============================================================================ 808 /// \brief Implicit function that can switch among different types. 809 /// 810 /// An `ImplicitFunctionMultiplexer` is a templated `ImplicitFunction` that takes 811 /// as template arguments any number of other `ImplicitFunction`s that it can 812 /// behave as. This allows you to decide at runtime which of these implicit 813 /// functions to define and compute. 814 /// 815 /// For example, let's say you want a filter that finds points either inside 816 /// a sphere or inside a box. Rather than create 2 different filters, one for 817 /// each type of implicit function, you can use `ImplicitFunctionMultiplexer<Sphere, Box>` 818 /// and then set either a `Sphere` or a `Box` at runtime. 819 /// 820 /// To use `ImplicitFunctionMultiplexer`, simply create the actual implicit 821 /// function that you want to use, and then set the `ImplicitFunctionMultiplexer` 822 /// to that concrete implicit function object. 823 /// 824 template <typename... ImplicitFunctionTypes> 825 class ImplicitFunctionMultiplexer 826 : public vtkm::internal::ImplicitFunctionBase< 827 ImplicitFunctionMultiplexer<ImplicitFunctionTypes...>> 828 { 829 vtkm::exec::internal::Variant<ImplicitFunctionTypes...> Variant; 830 831 using Superclass = 832 vtkm::internal::ImplicitFunctionBase<ImplicitFunctionMultiplexer<ImplicitFunctionTypes...>>; 833 834 public: 835 using Scalar = typename Superclass::Scalar; 836 using Vector = typename Superclass::Vector; 837 838 ImplicitFunctionMultiplexer() = default; 839 840 template <typename FunctionType> ImplicitFunctionMultiplexer(const vtkm::internal::ImplicitFunctionBase<FunctionType> & function)841 VTKM_EXEC_CONT ImplicitFunctionMultiplexer( 842 const vtkm::internal::ImplicitFunctionBase<FunctionType>& function) 843 : Variant(reinterpret_cast<const FunctionType&>(function)) 844 { 845 } 846 Value(const Vector & point)847 VTKM_EXEC_CONT Scalar Value(const Vector& point) const 848 { 849 return this->Variant.CastAndCall(detail::ImplicitFunctionValueFunctor{}, point); 850 } 851 Gradient(const Vector & point)852 VTKM_EXEC_CONT Vector Gradient(const Vector& point) const 853 { 854 return this->Variant.CastAndCall(detail::ImplicitFunctionGradientFunctor{}, point); 855 } 856 }; 857 858 //============================================================================ 859 /// \brief Implicit function that can switch among known implicit function types. 860 /// 861 /// `ImplicitFunctionGeneral` can behave as any of the predefined implicit functions 862 /// provided by VTK-m. This is helpful when the type of implicit function is not 863 /// known at compile time. For example, say you want a filter that can operate on 864 /// an implicit function. Rather than compile separate versions of the filter, one 865 /// for each type of implicit function, you can compile the filter once for 866 /// `ImplicitFunctionGeneral` and then set the desired implicit function at runtime. 867 /// 868 /// To use `ImplicitFunctionGeneral`, simply create the actual implicit 869 /// function that you want to use, and then set the `ImplicitFunctionGeneral` 870 /// to that concrete implicit function object. 871 /// 872 class ImplicitFunctionGeneral 873 : public vtkm::ImplicitFunctionMultiplexer<vtkm::Box, 874 vtkm::Cylinder, 875 vtkm::Frustum, 876 vtkm::Plane, 877 vtkm::Sphere> 878 { 879 using Superclass = vtkm::ImplicitFunctionMultiplexer<vtkm::Box, 880 vtkm::Cylinder, 881 vtkm::Frustum, 882 vtkm::Plane, 883 vtkm::Sphere>; 884 885 public: 886 using Superclass::Superclass; 887 }; 888 889 } // namespace vtkm 890 891 #endif //vtk_m_ImplicitFunction_h 892