$extrastylesheet
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