| 101 | | void expandRadiusBy(const Vec3f& v); |
| 102 | | |
| 103 | | /** Expands the sphere to encompass the given point. Repositions the |
| 104 | | * sphere center to minimize the radius increase. If the sphere is |
| 105 | | * uninitialized, set its center to v and radius to zero. */ |
| 106 | | void expandBy(const Vec3d& v); |
| 107 | | |
| 108 | | /** Expands the sphere to encompass the given point. Does not |
| 109 | | * reposition the sphere center. If the sphere is |
| 110 | | * uninitialized, set its center to v and radius to zero. */ |
| 111 | | void expandRadiusBy(const Vec3d& v); |
| | 98 | template<typename vector_type> |
| | 99 | void expandRadiusBy(const vector_type& v); |
| 148 | | } |
| 149 | | |
| | 136 | |
| | 137 | template<typename VT> |
| | 138 | template<typename vector_type> |
| | 139 | void BoundingSphereImpl<VT>::expandBy(const vector_type& v) |
| | 140 | { |
| | 141 | if (valid()) |
| | 142 | { |
| | 143 | vec_type dv = v-_center; |
| | 144 | value_type r = dv.length(); |
| | 145 | if (r>_radius) |
| | 146 | { |
| | 147 | value_type dr = (r-_radius)*0.5; |
| | 148 | _center += dv*(dr/r); |
| | 149 | _radius += dr; |
| | 150 | } // else do nothing as vertex is within sphere. |
| | 151 | } |
| | 152 | else |
| | 153 | { |
| | 154 | _center = v; |
| | 155 | _radius = 0.0; |
| | 156 | } |
| | 157 | } |
| | 158 | |
| | 159 | template<typename VT> |
| | 160 | template<typename vector_type> |
| | 161 | void BoundingSphereImpl<VT>::expandRadiusBy(const vector_type& v) |
| | 162 | { |
| | 163 | if (valid()) |
| | 164 | { |
| | 165 | value_type r = (v-_center).length(); |
| | 166 | if (r>_radius) _radius = r; |
| | 167 | // else do nothing as vertex is within sphere. |
| | 168 | } |
| | 169 | else |
| | 170 | { |
| | 171 | _center = v; |
| | 172 | _radius = 0.0; |
| | 173 | } |
| | 174 | } |
| | 175 | |
| | 176 | template<typename VT> |
| | 177 | void BoundingSphereImpl<VT>::expandBy(const BoundingSphereImpl& sh) |
| | 178 | { |
| | 179 | // ignore operation if incomming BoundingSphere is invalid. |
| | 180 | if (!sh.valid()) return; |
| | 181 | |
| | 182 | // This sphere is not set so use the inbound sphere |
| | 183 | if (!valid()) |
| | 184 | { |
| | 185 | _center = sh._center; |
| | 186 | _radius = sh._radius; |
| | 187 | |
| | 188 | return; |
| | 189 | } |
| | 190 | |
| | 191 | |
| | 192 | // Calculate d == The distance between the sphere centers |
| | 193 | double d = ( _center - sh.center() ).length(); |
| | 194 | |
| | 195 | // New sphere is already inside this one |
| | 196 | if ( d + sh.radius() <= _radius ) |
| | 197 | { |
| | 198 | return; |
| | 199 | } |
| | 200 | |
| | 201 | // New sphere completely contains this one |
| | 202 | if ( d + _radius <= sh.radius() ) |
| | 203 | { |
| | 204 | _center = sh._center; |
| | 205 | _radius = sh._radius; |
| | 206 | return; |
| | 207 | } |
| | 208 | |
| | 209 | |
| | 210 | // Build a new sphere that completely contains the other two: |
| | 211 | // |
| | 212 | // The center point lies halfway along the line between the furthest |
| | 213 | // points on the edges of the two spheres. |
| | 214 | // |
| | 215 | // Computing those two points is ugly - so we'll use similar triangles |
| | 216 | double new_radius = (_radius + d + sh.radius() ) * 0.5; |
| | 217 | double ratio = ( new_radius - _radius ) / d ; |
| | 218 | |
| | 219 | _center[0] += ( sh.center()[0] - _center[0] ) * ratio; |
| | 220 | _center[1] += ( sh.center()[1] - _center[1] ) * ratio; |
| | 221 | _center[2] += ( sh.center()[2] - _center[2] ) * ratio; |
| | 222 | |
| | 223 | _radius = new_radius; |
| | 224 | |
| | 225 | } |
| | 226 | |
| | 227 | template<typename VT> |
| | 228 | void BoundingSphereImpl<VT>::expandRadiusBy(const BoundingSphereImpl& sh) |
| | 229 | { |
| | 230 | if (sh.valid()) |
| | 231 | { |
| | 232 | if (valid()) |
| | 233 | { |
| | 234 | value_type r = (sh._center-_center).length()+sh._radius; |
| | 235 | if (r>_radius) _radius = r; |
| | 236 | // else do nothing as vertex is within sphere. |
| | 237 | } |
| | 238 | else |
| | 239 | { |
| | 240 | _center = sh._center; |
| | 241 | _radius = sh._radius; |
| | 242 | } |
| | 243 | } |
| | 244 | } |
| | 245 | |
| | 246 | template<typename VT> |
| | 247 | void BoundingSphereImpl<VT>::expandBy(const BoundingBoxImpl<VT>& bb) |
| | 248 | { |
| | 249 | if (bb.valid()) |
| | 250 | { |
| | 251 | if (valid()) |
| | 252 | { |
| | 253 | BoundingBoxImpl<vec_type> newbb(bb); |
| | 254 | |
| | 255 | for(unsigned int c=0;c<8;++c) |
| | 256 | { |
| | 257 | vec_type v = bb.corner(c)-_center; // get the direction vector from corner |
| | 258 | v.normalize(); // normalise it. |
| | 259 | v *= -_radius; // move the vector in the opposite direction distance radius. |
| | 260 | v += _center; // move to absolute position. |
| | 261 | newbb.expandBy(v); // add it into the new bounding box. |
| | 262 | } |
| | 263 | |
| | 264 | _center = newbb.center(); |
| | 265 | _radius = newbb.radius(); |
| | 266 | |
| | 267 | } |
| | 268 | else |
| | 269 | { |
| | 270 | _center = bb.center(); |
| | 271 | _radius = bb.radius(); |
| | 272 | } |
| | 273 | } |
| | 274 | } |
| | 275 | |
| | 276 | template<typename VT> |
| | 277 | void BoundingSphereImpl<VT>::expandRadiusBy(const BoundingBoxImpl<VT>& bb) |
| | 278 | { |
| | 279 | if (bb.valid()) |
| | 280 | { |
| | 281 | if (valid()) |
| | 282 | { |
| | 283 | for(unsigned int c=0;c<8;++c) |
| | 284 | { |
| | 285 | expandRadiusBy(bb.corner(c)); |
| | 286 | } |
| | 287 | } |
| | 288 | else |
| | 289 | { |
| | 290 | _center = bb.center(); |
| | 291 | _radius = bb.radius(); |
| | 292 | } |
| | 293 | } |
| | 294 | } |
| | 295 | |
| | 296 | typedef BoundingSphereImpl<Vec3f> BoundingSpheref; |
| | 297 | typedef BoundingSphereImpl<Vec3d> BoundingSphered; |
| | 298 | |
| | 299 | #ifdef OSG_USE_FLOAT_BOUNDINGSPHERE |
| | 300 | typedef BoundingSpheref BoundingSphere; |
| | 301 | #else |
| | 302 | typedef BoundingSphered BoundingSphere; |