Sphere3.cpp
上传用户:chinafayin
上传日期:2022-04-05
资源大小:153k
文件大小:5k
源码类别:

并行计算

开发平台:

Visual C++

  1. /*
  2.     Linear Algebra / Math library
  3.     Copyright (C) 2003-2009, Marek Olsak (maraeo@gmail.com), All Rights Reserved.
  4.     Copyright (C) 2003-2005, Tomas Pastorek (tomas@tomaspastorek.cz), All Rights Reserved.
  5.     This program is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU General Public License
  7.     as published by the Free Software Foundation; either version 2
  8.     of the License, or (at your option) any later version.
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.     You should have received a copy of the GNU General Public License
  14.     along with this program; if not, write to the Free Software
  15.     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  16. */
  17. #include "../All.h"
  18. namespace Rune
  19. {
  20.     /**
  21.         Spocita bounding sphere, pouziva 3 ruzne zpusoby, vypocet neni uplne presny
  22.     **************************************************************************************************/
  23.     template<typename T>
  24.     void Sphere3<T>::ApproximateBestOf3(const Vec3<T> *vertices, int count)
  25.     {
  26.         Sphere3<T> aabb, av, md;
  27.         aabb.ApproximateFromAABB(vertices, count);
  28.         av.ApproximateFromAverage(vertices, count);
  29.         md.ApproximateFromMostDistantVerts(vertices, count);
  30.         // Nastavi tu nejmensi
  31.         if (aabb.radius < av.radius && aabb.radius < md.radius)
  32.             *this = aabb;
  33.         else if (av.radius < md.radius)
  34.             *this = av;
  35.         else
  36.             *this = md;
  37.     }
  38.     template<typename T>
  39.     void Sphere3<T>::ApproximateFromAABB(const Vec3<T> *vertices, int count)
  40.     {
  41.         pos = FindAABBCenter(vertices, count);
  42.         radius = CalculateRadius(pos, vertices, count);
  43.     }
  44.     template<typename T>
  45.     void Sphere3<T>::ApproximateFromAABB(const Sphere3<T> *spheres, int count)
  46.     {
  47.         // TODO: tato aproximace je hodne nepresna, pro presnejsi aproximaci by bylo lepsi vyuzit knihovnu CGAL (je pod LGPL)
  48.         Vec3<T> *vertices = new Vec3<T>[count];
  49.         T maxR = 0;
  50.         for (int i = 0; i < count; i++)
  51.         {
  52.             vertices[i] = spheres[i].pos;
  53.             if (maxR < spheres[i].radius)
  54.                 maxR = spheres[i].radius;
  55.         }
  56.         ApproximateFromAABB(vertices, count);
  57.         delete [] vertices;
  58.         radius += maxR;
  59.     }
  60.     template<typename T>
  61.     void Sphere3<T>::ApproximateFromAverage(const Vec3<T> *vertices, int count)
  62.     {
  63.         pos = FindAverageCenter(vertices, count);
  64.         radius = CalculateRadius(pos, vertices, count);
  65.     }
  66.     template<typename T>
  67.     void Sphere3<T>::ApproximateFromMostDistantVerts(const Vec3<T> *vertices, int count)
  68.     {
  69.         pos = FindCenterFromMostDistantVerts(vertices, count);
  70.         radius = CalculateRadius(pos, vertices, count);
  71.     }
  72.     template<typename T>
  73.     Vec3<T> Sphere3<T>::FindAABBCenter(const Vec3<T> *vertices, int count)
  74.     {
  75.         AxisAlignedBox3<T> box;
  76.         box.Approximate(vertices, count);
  77.         return Vec3<T>::Center(box.min, box.max);
  78.     }
  79.     template<typename T>
  80.     Vec3<T> Sphere3<T>::FindAverageCenter(const Vec3<T> *vertices, int count)
  81.     {
  82.         Vec3<T> result = *vertices;
  83.         const Vec3<T> *it, *last = vertices+count;
  84.         for (it = vertices+1; it != last; ++it)
  85.             result += *it;
  86.         result *= 1 / T(count);
  87.         return result;
  88.     }
  89.     template<typename T>
  90.     Vec3<T> Sphere3<T>::FindCenterFromMostDistantVerts(const Vec3<T> *vertices, int count)
  91.     {
  92.         T maxDist = 0;
  93.         Vec3<T> result;
  94.         const Vec3<T> *it, *it2, *last = vertices+count;
  95.         for (it = vertices; it != last; ++it)
  96.             for (it2 = it; it2 != last; ++it2)
  97.             {
  98.                 T dist = Vec3<T>::DistanceSqr(*it, *it2);
  99.                 if (dist > maxDist)
  100.                 {
  101.                     maxDist = dist;
  102.                     result = Vec3<T>::Center(*it, *it2);
  103.                 }
  104.             }
  105.         return result;
  106.     }
  107.     template<typename T>
  108.     T Sphere3<T>::CalculateRadius(const Vec3<T> &center, const Vec3<T> *vertices, int count)
  109.     {
  110.         T maxRadius = 0;
  111.         const Vec3<T> *it, *last = vertices+count;
  112.         for (it = vertices; it != last; ++it)
  113.         {
  114.             T radius = Vec3<T>::DistanceSqr(*it, center);
  115.             if (radius > maxRadius) maxRadius = radius;
  116.         }
  117.         return Math<T>::Sqrt(maxRadius);
  118.     }
  119.     template
  120.     class RUNEMATH_API Sphere3<float>;
  121.     template
  122.     class RUNEMATH_API Sphere3<double>;
  123. }