Intrepid
/usr/src/RPM/BUILD/trilinos-11.12.1/packages/intrepid/src/Shared/MiniTensor/Intrepid_MiniTensor_Geometry.t.h
00001 // @HEADER
00002 // ************************************************************************
00003 //
00004 //                           Intrepid Package
00005 //                 Copyright (2007) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions: Alejandro Mota (amota@sandia.gov)
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 
00042 #if !defined(Intrepid_MiniTensor_Geometry_t_h)
00043 #define Intrepid_MiniTensor_Geometry_t_h
00044 
00045 #include <iterator>
00046 
00047 namespace Intrepid {
00048 
00049 //
00050 // Length of a segment
00051 //
00052 template<typename T, Index N>
00053 T
00054 length(Vector<T, N> const & p0, Vector<T, N> const & p1)
00055 {
00056   Vector<T, N> const v = p1 - p0;
00057   return norm(v);
00058 }
00059 
00060 //
00061 // Area of a triangle
00062 //
00063 template<typename T, Index N>
00064 T
00065 area(Vector<T, N> const & p0, Vector<T, N> const & p1,
00066     Vector<T, N> const & p2)
00067 {
00068   Vector<T, N> const u = p1 - p0;
00069   Vector<T, N> const v = p2 - p0;
00070 
00071   T const base = norm(u);
00072 
00073   Vector<T, N> const i = u / base;
00074   Vector<T, N> const n = v - dot(v, i) * i;
00075 
00076   T const height = norm(n);
00077   T const area = 0.5 * base * height;
00078 
00079   return area;
00080 }
00081 
00082 //
00083 // Area of a quadrilateral, assumed planar. If not planar, returns
00084 // the sum of the areas of the two triangles p0,p1,p2 and p0,p2,p3
00085 //
00086 template<typename T, Index N>
00087 T
00088 area(Vector<T, N> const & p0, Vector<T, N> const & p1,
00089     Vector<T, N> const & p2, Vector<T, N> const & p3)
00090 {
00091   return area(p0, p1, p2) + area(p0, p2, p3);
00092 }
00093 
00094 //
00095 // Volume of tetrahedron
00096 //
00097 template<typename T, Index N>
00098 T
00099 volume(Vector<T, N> const & p0, Vector<T, N> const & p1,
00100     Vector<T, N> const & p2, Vector<T, N> const & p3)
00101 {
00102   // Area of base triangle
00103   T const
00104   base = area(p0, p1, p2);
00105 
00106   // Height
00107   Vector<T, N> const u = p1 - p0;
00108   Vector<T, N> const v = p2 - p0;
00109   Vector<T, N> const w = p3 - p0;
00110 
00111   Vector<T, N> const i = u / norm(u);
00112   Vector<T, N> const j = v / norm(v);
00113 
00114   Vector<T, N> const n = w - dot(w, i) * i - dot(w, j) * j;
00115 
00116   T const height = norm(n);
00117 
00118   // Volume
00119   T const volume = base * height / 3.0;
00120 
00121   return volume;
00122 }
00123 
00124 //
00125 // Volume of pyramid of quadrilateral base
00126 // Base is assumed planar
00127 // Base is p0,p1,p2,p3
00128 // Apex is p4
00129 //
00130 template<typename T, Index N>
00131 T
00132 volume(Vector<T, N> const & p0, Vector<T, N> const & p1,
00133     Vector<T, N> const & p2, Vector<T, N> const & p3,
00134     Vector<T, N> const & p4)
00135 {
00136   // Area of base quadrilateral
00137   T const
00138   base = area(p0, p1, p2, p3);
00139 
00140   // Height
00141   Vector<T, N> const u = p1 - p0;
00142   Vector<T, N> const v = p2 - p0;
00143   Vector<T, N> const w = p4 - p0;
00144 
00145   Vector<T, N> const i = u / norm(u);
00146   Vector<T, N> const j = v / norm(v);
00147 
00148   Vector<T, N> const n = w - dot(w, i) * i - dot(w, j) * j;
00149 
00150   T const height = norm(n);
00151 
00152   // Volume
00153   T const volume = base * height / 3.0;
00154 
00155   return volume;
00156 }
00157 
00158 //
00159 // Volume of hexahedron
00160 // Assumption: all faces are planar
00161 // Decompose into 3 pyramids
00162 //
00163 template<typename T, Index N>
00164 T
00165 volume(Vector<T, N> const & p0, Vector<T, N> const & p1,
00166     Vector<T, N> const & p2, Vector<T, N> const & p3,
00167     Vector<T, N> const & p4, Vector<T, N> const & p5,
00168     Vector<T, N> const & p6, Vector<T, N> const & p7)
00169 {
00170   // 1st pyramid
00171   T const V1 = volume(p4, p7, p6, p5, p0);
00172 
00173   // 2nd pyramid
00174   T const V2 = volume(p3, p2, p6, p7, p0);
00175 
00176   // 3rd pyramid
00177   T const V3 = volume(p1, p5, p6, p2, p0);
00178 
00179   return V1 + V2 + V3;
00180 }
00181 
00182 //
00183 // Centroids of segment, triangle, tetrahedron, quadrilateral
00184 // and hexahedron
00185 // For these we can just take the average of the vertices.
00186 // WARNING: This is not the center of mass.
00187 //
00188 template<typename T, Index N>
00189 Vector<T, N>
00190 centroid(std::vector<Vector<T, N> > const & points)
00191 {
00192   Vector<T, N> C(points[0].get_dimension());
00193   C.clear();
00194   typedef typename std::vector<Vector<T, N> >::size_type sizeT;
00195   sizeT const n = points.size();
00196 
00197   for (sizeT i = 0; i < n; ++i) {
00198     C += points[i];
00199   }
00200   return C / static_cast<T>(n);
00201 }
00202 
00203 //
00204 // The surface normal of a face
00205 // Input: 3 independent nodes on the face
00206 // Output: unit normal vector
00207 //
00208 template<typename T, Index N>
00209 Vector<T, N>
00210 normal(Vector<T, N> const & p0,
00211     Vector<T, N> const & p1,
00212     Vector<T, N> const & p2)
00213 {
00214   // Construct 2 independent vectors
00215   Vector<T, N> const v0 = p1 - p0;
00216   Vector<T, N> const v1 = p2 - p0;
00217 
00218   Vector<T, N> const n = unit(cross(v0, v1));
00219 
00220   return n;
00221 }
00222 
00223 //
00224 // Given 3 points p0, p1, p2 that define a plane
00225 // determine if point p is in the same side of the normal
00226 // to the plane as defined by the right hand rule.
00227 //
00228 template<typename T, Index N>
00229 bool
00230 in_normal_side(
00231     Vector<T, N> const & p,
00232     Vector<T, N> const & p0,
00233     Vector<T, N> const & p1,
00234     Vector<T, N> const & p2,
00235     T const tolerance)
00236 {
00237   Vector<T, N> const v0 = p1 - p0;
00238   Vector<T, N> const v1 = p2 - p0;
00239 
00240   T const h = std::min(norm(v0), norm(v1));
00241 
00242   Vector<T, N> const n = unit(cross(v0, v1));
00243   Vector<T, N> const v = p - p0;
00244 
00245   T const s = dot(v, n);
00246 
00247   if (s < -tolerance * h) return false;
00248 
00249   return true;
00250 }
00251 
00252 //
00253 // Given two iterators to a container of points,
00254 // find the associated bounding box.
00255 // \param start, end: define sequence of points
00256 // \return vectors that define the bounding box
00257 //
00258 template<typename T, typename I, Index N>
00259 std::pair< Vector<T, N>, Vector<T, N> >
00260 bounding_box(I start, I end)
00261 {
00262   I
00263   it = start;
00264 
00265   Vector<T, N>
00266   min = (*it);
00267 
00268   Vector<T, N>
00269   max = min;
00270 
00271   Index const
00272   dimension = min.get_dimension();
00273 
00274   ++it;
00275 
00276   for (; it != end; ++it) {
00277 
00278     Vector<T, N> const &
00279     point = (*it);
00280 
00281     for (Index i = 0; i < dimension; ++i) {
00282       T const s = point(i);
00283       if (s < min(i)) min(i) = s;
00284       if (s > max(i)) max(i) = s;
00285     }
00286 
00287   }
00288 
00289   return std::make_pair(min, max);
00290 }
00291 
00292 template<typename T, typename I>
00293 std::pair< Vector<T, DYNAMIC>, Vector<T, DYNAMIC> >
00294 bounding_box(I start, I end)
00295 {
00296   return bounding_box<T, I, DYNAMIC>(start, end);
00297 }
00298 
00299 //
00300 // Determine if a given point is inside a bounding box.
00301 // \param p the point
00302 // \param min, max points defining the box
00303 // \return whether the point is inside
00304 //
00305 template<typename T, Index N>
00306 bool
00307 in_box(
00308     Vector<T, N> const & p,
00309     Vector<T, N> const & min,
00310     Vector<T, N> const & max)
00311 {
00312   Index const
00313   dimension = p.get_dimension();
00314 
00315   assert(min.get_dimension() == dimension);
00316   assert(max.get_dimension() == dimension);
00317 
00318   for (Index i = 0; i < dimension; ++i) {
00319     T const & s = p(i);
00320     if (s < min(i)) return false;
00321     if (s > max(i)) return false;
00322   }
00323 
00324   return true;
00325 }
00326 
00327 //
00328 // Generate random point inside bounding box
00329 // \param min, max the bounding box
00330 // \return p point inside box
00331 //
00332 template<typename T, Index N>
00333 Vector<T, N>
00334 random_in_box(Vector<T, N> const & min, Vector<T, N> const & max)
00335 {
00336   Index const
00337   dimension = min.get_dimension();
00338 
00339   assert(max.get_dimension() == dimension);
00340 
00341   Vector<T, N> p(dimension);
00342 
00343   for (Index i = 0; i < dimension; ++i) {
00344     p(i) = (max(i) - min(i)) * T(std::rand())/T(RAND_MAX) + min(i);
00345   }
00346 
00347   return p;
00348 }
00349 
00350 //
00351 // Given 4 points p0, p1, p2, p3 that define a tetrahedron
00352 // determine if point p is inside it.
00353 //
00354 template<typename T, Index N>
00355 bool
00356 in_tetrahedron(
00357     Vector<T, N> const & p,
00358     Vector<T, N> const & p0,
00359     Vector<T, N> const & p1,
00360     Vector<T, N> const & p2,
00361     Vector<T, N> const & p3,
00362     T const tolerance)
00363 {
00364   if (in_normal_side(p, p0, p1, p2, tolerance) == false) {
00365 
00366     return false;
00367 
00368   } else if (in_normal_side(p, p0, p3, p1, tolerance) == false) {
00369 
00370     return false;
00371 
00372   } else if (in_normal_side(p, p1, p3, p2, tolerance) == false) {
00373 
00374     return false;
00375 
00376   } else if (in_normal_side(p, p2, p3, p0, tolerance) == false) {
00377 
00378     return false;
00379 
00380   }
00381 
00382   return true;
00383 }
00384 
00385 //
00386 // Given 8 points that define a hexahedron
00387 // determine if point p is inside it.
00388 // Assumption: faces are planar
00389 //
00390 template<typename T, Index N>
00391 bool
00392 in_hexahedron(
00393     Vector<T, N> const & p,
00394     Vector<T, N> const & p0,
00395     Vector<T, N> const & p1,
00396     Vector<T, N> const & p2,
00397     Vector<T, N> const & p3,
00398     Vector<T, N> const & p4,
00399     Vector<T, N> const & p5,
00400     Vector<T, N> const & p6,
00401     Vector<T, N> const & p7,
00402     T const tolerance)
00403 {
00404   if (in_normal_side(p, p0, p1, p2, tolerance) == false) {
00405 
00406     return false;
00407 
00408   } else if (in_normal_side(p, p0, p4, p5, tolerance) == false) {
00409 
00410     return false;
00411 
00412   } else if (in_normal_side(p, p1, p5, p6, tolerance) == false) {
00413 
00414     return false;
00415 
00416   } else if (in_normal_side(p, p2, p6, p7, tolerance) == false) {
00417 
00418     return false;
00419 
00420   } else if (in_normal_side(p, p3, p7, p4, tolerance) == false) {
00421 
00422     return false;
00423 
00424   } else if (in_normal_side(p, p4, p7, p6, tolerance) == false) {
00425 
00426     return false;
00427 
00428   }
00429 
00430   return true;
00431 }
00432 
00433 //
00434 // Closest point
00435 // \param p the point
00436 // \param n vector of points to test
00437 // \return index to closest point
00438 //
00439 template<typename T, Index N>
00440 typename std::vector< Vector<T, N> >::size_type
00441 closest_point(Vector<T, N> const & p, std::vector< Vector<T, N> > const & n)
00442 {
00443   assert(n.size() > 0);
00444 
00445   typename std::vector< Vector<T, N> >::size_type
00446   index = 0;
00447 
00448   Vector<T, N> const
00449   v0 = p - n[0];
00450 
00451   T
00452   min = norm_square(v0);
00453 
00454   for (typename std::vector< Vector<T, N> >::size_type i = 1;
00455       i < n.size();
00456       ++i) {
00457 
00458     Vector<T, N> const
00459     vi = p - n[i];
00460 
00461     T const
00462     s = norm_square(vi);
00463 
00464     if (s < min) {
00465       min = s;
00466       index = i;
00467     }
00468 
00469   }
00470 
00471   return index;
00472 }
00473 
00474 // Median of a sequence defined by random
00475 // access iterators. Undefined for empty set.
00476 // \param begin, end Iterators that define the sequence
00477 // \return median of sequence
00478 //
00479 template<typename T, typename Iterator>
00480 T
00481 median(Iterator begin, Iterator end)
00482 {
00483   // Firewall
00484   if (begin == end) {
00485     std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00486     std::cerr << std::endl;
00487     std::cerr << "Median undefined for empty set." << std::endl;
00488     exit(1);
00489   }
00490 
00491   Index const
00492   size = static_cast<Index>(std::distance(begin, end));
00493 
00494   T
00495   median;
00496 
00497   Index const
00498   mid_index = size / 2;
00499 
00500   Iterator
00501   mid_iterator = begin + mid_index;
00502 
00503   std::partial_sort(begin, mid_iterator, end);
00504 
00505   if (size % 2 == 0) {
00506 
00507     // Even number of elements
00508     T const
00509     b = *mid_iterator;
00510 
00511     Iterator
00512     previous = mid_iterator - 1;
00513 
00514     T const
00515     a = *previous;
00516 
00517     median = (a + b) / 2.0;
00518 
00519   } else {
00520 
00521     // Odd number of elements
00522     median = *mid_iterator;
00523 
00524   }
00525 
00526   return median;
00527 }
00528 
00529 //
00530 // Given quadrilateral nodes and a position
00531 // in parametric coordinates, interpolate.
00532 // \param xi position in parametric coordinates
00533 // \param p0 ... corner nodes
00534 // \return interpolated position
00535 //
00536 template<typename T, Index N>
00537 Vector<T, N>
00538 interpolate_quadrilateral(
00539     Vector<T, dimension_const<N, 2>::value> & xi,
00540     Vector<T, N> const & p0,
00541     Vector<T, N> const & p1,
00542     Vector<T, N> const & p2,
00543     Vector<T, N> const & p3)
00544 {
00545 
00546   T const
00547   N0 = 0.25 * (1 - xi(0)) * (1 - xi(1));
00548 
00549   T const
00550   N1 = 0.25 * (1 + xi(0)) * (1 - xi(1));
00551 
00552   T const
00553   N2 = 0.25 * (1 + xi(0)) * (1 + xi(1));
00554 
00555   T const
00556   N3 = 0.25 * (1 - xi(0)) * (1 + xi(1));
00557 
00558   Vector<T, N> const
00559   p = N0 * p0 + N1 * p1 + N2 * p2 + N3 * p3;
00560 
00561   return p;
00562 }
00563 
00564 //
00565 // Given triangle nodes and a position
00566 // in parametric coordinates, interpolate.
00567 // \param xi position in parametric coordinates
00568 // \param p0 ... corner nodes
00569 // \return interpolated position
00570 //
00571 template<typename T, Index N>
00572 Vector<T, N>
00573 interpolate_triangle(
00574     Vector<T, dimension_const<N, 3>::value> & xi,
00575     Vector<T, N> const & p0,
00576     Vector<T, N> const & p1,
00577     Vector<T, N> const & p2)
00578 {
00579   xi(2) = 1.0 - xi(0) - xi(1);
00580 
00581   Vector<T, N> const
00582   p = xi(0) * p0 + xi(1) * p1 + xi(2) * p2;
00583 
00584   return p;
00585 }
00586 
00587 //
00588 // Given hexahedron nodes and a position
00589 // in parametric coordinates, interpolate.
00590 // \param xi position in parametric coordinates
00591 // \param p0 ... corner nodes
00592 // \return interpolated position
00593 //
00594 template<typename T, Index N>
00595 Vector<T, N>
00596 interpolate_hexahedron(
00597     Vector<T, dimension_const<N, 3>::value> & xi,
00598     Vector<T, N> const & p0,
00599     Vector<T, N> const & p1,
00600     Vector<T, N> const & p2,
00601     Vector<T, N> const & p3,
00602     Vector<T, N> const & p4,
00603     Vector<T, N> const & p5,
00604     Vector<T, N> const & p6,
00605     Vector<T, N> const & p7)
00606 {
00607 
00608   T const
00609   N0 = 0.125 * (1 - xi(0)) * (1 - xi(1)) * (1 - xi(2));
00610 
00611   T const
00612   N1 = 0.125 * (1 + xi(0)) * (1 - xi(1)) * (1 - xi(2));
00613 
00614   T const
00615   N2 = 0.125 * (1 + xi(0)) * (1 + xi(1)) * (1 - xi(2));
00616 
00617   T const
00618   N3 = 0.125 * (1 - xi(0)) * (1 + xi(1)) * (1 - xi(2));
00619 
00620   T const
00621   N4 = 0.125 * (1 - xi(0)) * (1 - xi(1)) * (1 + xi(2));
00622 
00623   T const
00624   N5 = 0.125 * (1 + xi(0)) * (1 - xi(1)) * (1 + xi(2));
00625 
00626   T const
00627   N6 = 0.125 * (1 + xi(0)) * (1 + xi(1)) * (1 + xi(2));
00628 
00629   T const
00630   N7 = 0.125 * (1 - xi(0)) * (1 + xi(1)) * (1 + xi(2));
00631 
00632   Vector<T, N> const
00633   p =
00634       N0 * p0 + N1 * p1 + N2 * p2 + N3 * p3 +
00635       N4 * p4 + N5 * p5 + N6 * p6 + N7 * p7;
00636 
00637   return p;
00638 }
00639 
00640 //
00641 // Given tetrahedron nodes and a position
00642 // in parametric coordinates, interpolate.
00643 // \param xi position in parametric coordinates
00644 // \param p0 ... corner nodes
00645 // \return interpolated position
00646 //
00647 template<typename T, Index N>
00648 Vector<T, N>
00649 interpolate_tetrahedron(
00650     Vector<T, dimension_const<N, 4>::value> & xi,
00651     Vector<T, N> const & p0,
00652     Vector<T, N> const & p1,
00653     Vector<T, N> const & p2,
00654     Vector<T, N> const & p3)
00655 {
00656   xi(3) = 1.0 - xi(0) - xi(1) - xi(2);
00657 
00658   Vector<T, N> const
00659   p = xi(0) * p0 + xi(1) * p1 + xi(2) * p2 + xi(3) * p3;
00660 
00661   return p;
00662 }
00663 
00672 template<typename T, Index M, Index N>
00673 Vector<T, N>
00674 interpolate_element(
00675     ELEMENT::Type element_type,
00676     Vector<T, M> & xi,
00677     std::vector< Vector<T, N> > const & v)
00678 {
00679   Vector<T, N> p;
00680 
00681   switch (element_type) {
00682 
00683     case ELEMENT::TRIANGULAR:
00684       p = interpolate_triangle(xi, v[0], v[1], v[2]);
00685       break;
00686 
00687     case ELEMENT::QUADRILATERAL:
00688       p = interpolate_quadrilateral(xi, v[0], v[1], v[2], v[3]);
00689       break;
00690 
00691     case ELEMENT::TETRAHEDRAL:
00692       p = interpolate_tetrahedron(xi, v[0], v[1], v[2], v[3]);
00693       break;
00694 
00695     case ELEMENT::HEXAHEDRAL:
00696       p = interpolate_hexahedron(
00697           xi, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
00698       break;
00699 
00700     default:
00701       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00702       std::cerr << std::endl;
00703       std::cerr << "Unknown element type in interpolation.";
00704       std::cerr << std::endl;
00705       exit(1);
00706       break;
00707 
00708   }
00709 
00710   return p;
00711 }
00712 
00713 //
00714 // Given a vector of points, determine
00715 // distances between all of them.
00716 // \param vector of points
00717 // \return distance matrix
00718 //
00719 template<typename T, Index N>
00720 std::vector< std::vector<T> >
00721 distance_matrix(std::vector< Vector<T, N> > const & points)
00722 {
00723   Index const
00724   number_points = points.size();
00725 
00726   std::vector< std::vector<T> >
00727   distances(number_points);
00728 
00729   for (Index i = 0; i < number_points; ++i) {
00730 
00731     distances[i].resize(number_points);
00732 
00733     distances[i][i] = 0.0;
00734 
00735     for (Index j = i + 1; j < number_points; ++j) {
00736 
00737       T const
00738       distance = norm(points[i] - points[j]);
00739 
00740       distances[i][j] = distance;
00741       distances[j][i] = distance;
00742 
00743     }
00744 
00745   }
00746 
00747   return distances;
00748 }
00749 
00750 //
00751 // Given a distance matrix, determine the minimum
00752 // distance between two distinct points.
00753 // \param distance matrix
00754 // \return minimum distance
00755 //
00756 template<typename T>
00757 std::vector<T>
00758 minimum_distances(std::vector< std::vector<T> > const & distances)
00759 {
00760   Index const
00761   number_points = distances.size();
00762 
00763   std::vector<T>
00764   minima(number_points);
00765 
00766   // First row
00767   T
00768   minimum = distances[0][1];
00769 
00770   for (Index j = 2; j < number_points; ++j) {
00771     minimum = std::min(minimum, distances[0][j]);
00772   }
00773 
00774   minima[0] = minimum;
00775 
00776   // Remaining rows
00777   for (Index i = 1; i < number_points; ++i) {
00778 
00779     minimum = distances[i][0];
00780 
00781     for (Index j = 1; j < number_points; ++j) {
00782 
00783       if (i == j) continue;
00784 
00785       minimum = std::min(minimum, distances[i][j]);
00786 
00787     }
00788 
00789     minima[i] = minimum;
00790 
00791   }
00792 
00793   return minima;
00794 }
00795 
00796 } // namespace Intrepid
00797 
00798 #endif // Intrepid_MiniTensor_Geometry_t_h