$extrastylesheet
sphere.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 // C++ includes
00021 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00022 #include <cmath> // for std::abs
00023 
00024 
00025 // Local includes
00026 #include "libmesh/tensor_value.h"
00027 #include "libmesh/sphere.h"
00028 
00029 namespace libMesh
00030 {
00031 
00032 
00033 
00034 // ------------------------------------------------------------
00035 // Sphere class member functions
00036 Sphere::Sphere () :
00037   _rad(-1.)
00038 {
00039 }
00040 
00041 
00042 
00043 Sphere::Sphere (const Point& c,
00044                 const Real   r)
00045 {
00046   libmesh_assert_greater (r, 0.);
00047 
00048   this->create_from_center_radius (c, r);
00049 }
00050 
00051 
00052 
00053 Sphere::Sphere (const Sphere& other_sphere) :
00054   Surface()
00055 {
00056   this->create_from_center_radius (other_sphere.center(),
00057                                    other_sphere.radius());
00058 }
00059 
00060 
00061 
00062 Sphere::Sphere(const Point& pa,
00063                const Point& pb,
00064                const Point& pc,
00065                const Point& pd)
00066 {
00067   Point pad = pa - pd;
00068   Point pbd = pb - pd;
00069   Point pcd = pc - pd;
00070 
00071   TensorValue<Real> T(pad,pbd,pcd);
00072 
00073   Real D = T.det();
00074 
00075   // The points had better not be coplanar
00076   libmesh_assert_greater (std::abs(D), 1e-12);
00077 
00078   Real e = 0.5*(pa.size_sq() - pd.size_sq());
00079   Real f = 0.5*(pb.size_sq() - pd.size_sq());
00080   Real g = 0.5*(pc.size_sq() - pd.size_sq());
00081 
00082   TensorValue<Real> T1(e,pad(1),pad(2),
00083                        f,pbd(1),pbd(2),
00084                        g,pcd(1),pcd(2));
00085   Real sx = T1.det()/D;
00086 
00087   TensorValue<Real> T2(pad(0),e,pad(2),
00088                        pbd(0),f,pbd(2),
00089                        pcd(0),g,pcd(2));
00090   Real sy = T2.det()/D;
00091 
00092   TensorValue<Real> T3(pad(0),pad(1),e,
00093                        pbd(0),pbd(1),f,
00094                        pcd(0),pcd(1),g);
00095   Real sz = T3.det()/D;
00096 
00097   Point c(sx,sy,sz);
00098   Real r = (c-pa).size();
00099 
00100   this->create_from_center_radius(c,r);
00101 }
00102 
00103 
00104 
00105 Sphere::~Sphere ()
00106 {
00107 }
00108 
00109 
00110 
00111 void Sphere::create_from_center_radius (const Point& c, const Real r)
00112 {
00113   this->center() = c;
00114   this->radius() = r;
00115 
00116   libmesh_assert_greater (this->radius(), 0.);
00117 }
00118 
00119 
00120 
00121 bool Sphere::intersects (const Sphere& other_sphere) const
00122 {
00123   return distance(other_sphere) < 0 ? true : false;
00124 }
00125 
00126 
00127 
00128 Real Sphere::distance (const Sphere& other_sphere) const
00129 {
00130   libmesh_assert_greater ( this->radius(), 0. );
00131   libmesh_assert_greater ( other_sphere.radius(), 0. );
00132 
00133   const Real the_distance = (this->center() - other_sphere.center()).size();
00134 
00135   return the_distance - (this->radius() + other_sphere.radius());
00136 }
00137 
00138 
00139 
00140 bool Sphere::above_surface (const Point& p) const
00141 {
00142   libmesh_assert_greater (this->radius(), 0.);
00143 
00144   // create a vector from the center to the point.
00145   const Point w = p - this->center();
00146 
00147   if (w.size() > this->radius())
00148     return true;
00149 
00150   return false;
00151 }
00152 
00153 
00154 
00155 bool Sphere::below_surface (const Point& p) const
00156 {
00157   libmesh_assert_greater (this->radius(), 0.);
00158 
00159   return ( !this->above_surface (p) );
00160 }
00161 
00162 
00163 
00164 bool Sphere::on_surface (const Point& p) const
00165 {
00166   libmesh_assert_greater (this->radius(), 0.);
00167 
00168   // Create a vector from the center to the point.
00169   const Point w = p - this->center();
00170 
00171   // if the size of that vector is the same as the radius() then
00172   // the point is on the surface.
00173   if (std::abs(w.size() - this->radius()) < 1.e-10)
00174     return true;
00175 
00176   return false;
00177 }
00178 
00179 
00180 
00181 Point Sphere::closest_point (const Point& p) const
00182 {
00183   libmesh_assert_greater (this->radius(), 0.);
00184 
00185   // get the normal from the surface in the direction
00186   // of p
00187   Point normal = this->unit_normal (p);
00188 
00189   // The closest point on the sphere is in the direction
00190   // of the normal a distance r from the center.
00191   const Point cp = this->center() + normal*this->radius();
00192 
00193   return cp;
00194 }
00195 
00196 
00197 
00198 Point Sphere::unit_normal (const Point& p) const
00199 {
00200   libmesh_assert_greater (this->radius(), 0.);
00201 
00202   libmesh_assert_not_equal_to (p, this->center());
00203 
00204   // Create a vector from the center to the point
00205   Point n = p - this->center();
00206 
00207   return n.unit();
00208 }
00209 
00210 } // namespace libMesh