00001
00002
00003
00004
00005
00006
00007
00008 #ifndef IMPALGEBRA_VECTOR_GENERATORS_H
00009 #define IMPALGEBRA_VECTOR_GENERATORS_H
00010
00011 #include "VectorD.h"
00012 #include "Cylinder3D.h"
00013 #include "Cone3D.h"
00014 #include "Sphere3D.h"
00015 #include "SpherePatch3D.h"
00016 #include "BoundingBoxD.h"
00017
00018 #include "internal/internal_vector_generators.h"
00019
00020 IMPALGEBRA_BEGIN_NAMESPACE
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 template <unsigned int D>
00037 VectorD<D>
00038 get_random_vector_in(const BoundingBoxD<D> &bb) {
00039 VectorD<D> ret;
00040 for (unsigned int i=0; i< D; ++i) {
00041 ::boost::uniform_real<> rand(bb.get_corner(0)[i],
00042 bb.get_corner(1)[i]);
00043 ret[i]=rand(random_number_generator);
00044 }
00045 return ret;
00046 }
00047
00048
00049
00050
00051
00052 template <unsigned int D>
00053 VectorD<D>
00054 get_random_vector_on(const BoundingBoxD<D> &bb) {
00055 double areas[D*2];
00056 VectorD<D> lb= bb.get_corner(0);
00057 VectorD<D> ub= bb.get_corner(1);
00058 for (unsigned int i=0; i< D; ++i) {
00059 areas[i]=1;
00060 for (unsigned int j=1; j< D; ++j) {
00061 areas[i] *= ub[(i+j)%D]-lb[(i+j)%D];
00062 }
00063 if (i!= 0) {
00064 areas[i]+= areas[i-1];
00065 }
00066 }
00067 for (unsigned int i=0; i< D; ++i) {
00068 areas[D+i]= areas[D-1]+areas[i];
00069 }
00070
00071
00072
00073 ::boost::uniform_real<> rand(0, areas[2*D-1]);
00074 double a= rand(random_number_generator);
00075
00076 unsigned int side;
00077 for (side=0; side< 2*D; ++side) {
00078 if (areas[side] > a) break;
00079 }
00080 unsigned int coord= (side>=D? side-D: side);
00081 VectorD<D-1> fmin, fmax, sv;
00082 for (unsigned int i=1; i< D; ++i) {
00083 fmin[i-1]= 0;
00084 fmax[i-1]= ub[(coord+i)%D]- lb[(coord+i)%D];
00085 }
00086 sv= get_random_vector_in(BoundingBoxD<D-1>(fmin, fmax));
00087
00088 VectorD<D> ret;
00089
00090 if (side >=D) {
00091 ret=ub;
00092 for (unsigned int i=1; i< D; ++i) {
00093 ret[(coord+i)%D]-= sv[i-1];
00094 }
00095 } else {
00096 ret=lb;
00097 for (unsigned int i=1; i< D; ++i) {
00098 ret[(coord+i)%D]+= sv[i-1];
00099 }
00100 }
00101
00102 return ret;
00103 }
00104
00105
00106
00107
00108
00109
00110 template <unsigned int D>
00111 VectorD<D>
00112 get_random_vector_in(const SphereD<D> &s){
00113 BoundingBoxD<D> bb= get_bounding_box(s);
00114 double norm;
00115 VectorD<D> ret;
00116 double r2= square(s.get_radius());
00117
00118 do {
00119 ret=get_random_vector_in(bb);
00120 norm= (s.get_center()- ret).get_squared_magnitude();
00121 } while (norm > r2);
00122 return ret;
00123 }
00124
00125
00126
00127
00128
00129 template <unsigned int D>
00130 VectorD<D>
00131 get_random_vector_on(const SphereD<D> &s) {
00132
00133 BOOST_STATIC_ASSERT(D>0);
00134 double cur_radius2=square(s.get_radius());
00135 VectorD<D> up;
00136 for (unsigned int i=D-1; i>0; --i) {
00137 double r= std::sqrt(cur_radius2);
00138 ::boost::uniform_real<> rand(-r, r);
00139 up[i]= rand(random_number_generator);
00140
00141 cur_radius2= cur_radius2-square(up[i]);
00142 }
00143 ::boost::uniform_int<> rand(0, 1);
00144 double x= std::sqrt(cur_radius2);
00145 if (rand(random_number_generator)) {
00146 x=-x;
00147 }
00148 up[0]=x;
00149
00150 IMP_INTERNAL_CHECK(std::abs(up.get_magnitude() -s.get_radius()) < .1,
00151 "Error generating vector on sphere: "
00152 << up << " for " << s.get_radius());
00153
00154
00155 return s.get_center()+ up;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 template <unsigned int D>
00171 std::vector<VectorD<D> >
00172 get_uniform_surface_cover(const SphereD<D> &s, unsigned int n) {
00173 return internal::uniform_cover_sphere(n, s.get_center(),
00174 s.get_radius(), true);
00175 }
00176
00177
00178
00179
00180
00181
00182 IMPALGEBRAEXPORT std::vector<VectorD<3> >
00183 get_uniform_surface_cover(const Cylinder3D &cyl,
00184 int number_of_points);
00185
00186
00187
00188
00189
00190 template <unsigned int D>
00191 std::vector<VectorD<D> >
00192 get_uniform_upper_hemisphere_cover(const SphereD<D> &s, unsigned int n) {
00193 return internal::uniform_cover_sphere(n, s.get_center(),
00194 s.get_radius(), false);
00195 }
00196
00197
00198
00199
00200
00201 IMPALGEBRAEXPORT std::vector<VectorD<3> >
00202 get_grid_surface_cover(const Cylinder3D &cyl,
00203 int number_of_cycles,
00204 int number_of_points_on_cycle);
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 IMPALGEBRAEXPORT std::vector<VectorD<3> >
00215 get_uniform_surface_cover(const SpherePatch3D &sph,
00216 unsigned int number_of_points);
00217
00218
00219
00220
00221 IMPALGEBRAEXPORT std::vector<VectorD<3> >
00222 get_uniform_surface_cover(const Cone3D &cone,
00223 unsigned int number_of_points);
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 IMPALGEBRAEXPORT std::vector<VectorD<3> >
00239 get_random_chain(unsigned int n, double r,
00240 const VectorD<3> &start
00241 = Vector3D(0,0,0),
00242 const std::vector<SphereD<3> > &obstacles
00243 =Sphere3Ds());
00244
00245
00246
00247 IMPALGEBRA_END_NAMESPACE
00248
00249 #endif