00001
00002
00003 #include "Point.hpp"
00004 #include "Line.hpp"
00005
00006 namespace jafar {
00007 namespace geom {
00008
00009 template<int dimension>
00010 Line<dimension>::EuclideanDriver::EuclideanDriver(const HomogenousVecD& origin, const HomogenousVecD& direction, const RepereD* reference ) : Driver(), m_reference(reference), m_hasCov(false)
00011 {
00012 m_origin = origin;
00013 m_origin /= m_origin(dimension);
00014 m_direction = direction / ublas::norm_2(direction);
00015 JFR_ASSERT(fabs(m_direction(dimension)) < 1e-6, "direction is not a vector");
00016 }
00017
00018 template<int dimension>
00019 Line<dimension>::EuclideanDriver::EuclideanDriver(const VecD& origin, const VecD& direction, const RepereD* reference ) : Driver(), m_reference(reference), m_hasCov(false)
00020 {
00021 m_origin(dimension) = 1.0;
00022 ublas::vector_range<HomogenousVecD>(m_origin, this->rangeDimension) = origin;
00023 m_direction(dimension) = 0.0;
00024 ublas::vector_range<HomogenousVecD>(m_direction, this->rangeDimension) = direction;
00025 m_direction /= ublas::norm_2(m_direction);
00026 }
00027 template<int dimension>
00028 void Line<dimension>::EuclideanDriver::setCov(HomogenousSymMatrixD _originCov, HomogenousSymMatrixD _directionCov)
00029 {
00030 m_directionCov = _directionCov;
00031 m_originCov = _originCov;
00032 m_hasCov = true;
00033 }
00034 template<int dimension>
00035 typename Line<dimension>::HomogenousVecD Line<dimension>::EuclideanDriver::pointAt(double t) const
00036 {
00037 return m_origin + t * m_direction;
00038 }
00039 template<int dimension>
00040 typename Line<dimension>::HomogenousVecD Line<dimension>::EuclideanDriver::origin() const
00041 {
00042 return m_origin;
00043 }
00044 template<int dimension>
00045 typename Line<dimension>::HomogenousSymMatrixD Line<dimension>::EuclideanDriver::originCov() const
00046 {
00047 return m_originCov;
00048 }
00049 template<int dimension>
00050 typename Line<dimension>::HomogenousVecD Line<dimension>::EuclideanDriver::direction() const
00051 {
00052 return m_direction;
00053 }
00054 template<int dimension>
00055 typename Line<dimension>::HomogenousSymMatrixD Line<dimension>::EuclideanDriver::directionCov() const
00056 {
00057 return m_directionCov;
00058 }
00059 template<int dimension>
00060 typename Line<dimension>::Driver* Line<dimension>::EuclideanDriver::cloneLineDriver() const
00061 {
00062 return new EuclideanDriver(*this);
00063 }
00064 template<int dimension>
00065 void Line<dimension>::EuclideanDriver::changeReference( const RepereD* reference )
00066 {
00067 typename Atom<dimension>::HomogenousMatrixD m;
00068 this->m_reference->localToRepere(m, reference);
00069 m_origin = ublas::prod(m, m_origin);
00070 m_direction = ublas::prod(m, m_direction);
00071 m_direction /= ublas::norm_2(m_direction);
00072 this->m_reference = reference;
00073 }
00074 template<int dimension>
00075 const Repere<dimension>* Line<dimension>::EuclideanDriver::reference( ) const
00076 {
00077 return m_reference;
00078 }
00079
00080 template<int dimension>
00081 struct Line<dimension>::TwoPointsPointerDriver::Private {
00082 Private(const Point<dimension>* _p1, const Point<dimension>* _p2) : p1(_p1), p2(_p2) {}
00083 const Point<dimension>* p1;
00084 const Point<dimension>* p2;
00085 };
00086
00087 template<int dimension>
00088 Line<dimension>::TwoPointsPointerDriver::TwoPointsPointerDriver(const Point<dimension>* p1, const Point<dimension>* p2) : Driver(), d( new Private(p1,p2) )
00089 {
00090 }
00091
00092 template<int dimension>
00093 Line<dimension>::TwoPointsPointerDriver::~TwoPointsPointerDriver()
00094 {
00095 delete d;
00096 }
00097
00098 template<int dimension>
00099 typename Line<dimension>::HomogenousVecD Line<dimension>::TwoPointsPointerDriver::pointAt(double t) const
00100 {
00101 return origin() + t * direction();
00102 }
00103
00104 template<int dimension>
00105 typename Line<dimension>::HomogenousVecD Line<dimension>::TwoPointsPointerDriver::origin() const
00106 {
00107 return d->p1->homogenousCoordinates();
00108 }
00109
00110 template<int dimension>
00111 typename Line<dimension>::HomogenousSymMatrixD Line<dimension>::TwoPointsPointerDriver::originCov() const
00112 {
00113 return d->p1->homogenousCoordinatesCov();
00114 }
00115
00116 template<int dimension>
00117 typename Line<dimension>::HomogenousVecD Line<dimension>::TwoPointsPointerDriver::direction() const
00118 {
00119 HomogenousVecD v1 = d->p1->homogenousCoordinates();
00120 HomogenousVecD v2 = d->p2->reference()->convertIn( d->p2->homogenousCoordinates(), d->p1->reference());
00121 HomogenousVecD dir = v2 - v1;
00122 return dir / ublas::norm_2(dir) ;
00123 }
00124
00125 template<int dimension>
00126 typename Line<dimension>::HomogenousSymMatrixD Line<dimension>::TwoPointsPointerDriver::directionCov() const
00127 {
00128 if( d->p1->reference() != d->p2->reference())
00129 {
00130 JFR_ERROR(GeomException, GeomException::Unimplemented, "Unimplemented." );
00131 }
00132 HomogenousVecD v1 = d->p1->homogenousCoordinates();
00133 HomogenousVecD v2 = d->p2->reference()->convertIn( d->p2->homogenousCoordinates(), d->p1->reference());
00134 HomogenousVecD dir = v2 - v1;
00135 return (d->p1->homogenousCoordinatesCov() + d->p2->homogenousCoordinatesCov()) / ublas::inner_prod(dir,dir);
00136 }
00137
00138 template<int dimension>
00139 typename Line<dimension>::Driver* Line<dimension>::TwoPointsPointerDriver::cloneLineDriver() const
00140 {
00141 return new TwoPointsPointerDriver(d->p1, d->p2 );
00142 }
00143 template<int dimension>
00144 const Repere<dimension>* Line<dimension>::TwoPointsPointerDriver::reference( ) const
00145 {
00146 return d->p1->reference();
00147 }
00148 template<int dimension>
00149 bool Line<dimension>::TwoPointsPointerDriver::hasCov() const
00150 {
00151 return d->p1->hasCov() and d->p2->hasCov();
00152 }
00153
00154 template<int dimension>
00155 Line<dimension>::Line( Driver* d ) : Atom<dimension>((typename Atom<dimension>::Driver*)d), m_driver(d) {
00156 }
00157 template<int dimension>
00158 Line<dimension>::Line( const Line& l ) : Atom<dimension>(0), m_driver(l.m_driver->cloneLineDriver())
00159 {
00160 Atom<dimension>::setDriver(m_driver);
00161 this->setId( l.id() );
00162 }
00163 template<int dimension>
00164 inline Line<dimension>& Line<dimension>::operator=(const Line& rhs)
00165 {
00166 m_driver = rhs.m_driver->cloneLineDriver();
00167 Atom<dimension>::setDriver(m_driver);
00168 this->setId( rhs.id() );
00169 return *this;
00170 }
00171 template<int dimension>
00172 Line<dimension>::~Line() { }
00173 template<int dimension>
00174 inline typename Line<dimension>::HomogenousVecD Line<dimension>::pointAt(double t) const
00175 {
00176 return m_driver->pointAt( t );
00177 }
00178 template<int dimension>
00179 inline typename Line<dimension>::HomogenousSymMatrixD Line<dimension>::pointAtCov(double t, double tCov) const
00180 {
00181 return m_driver->originCov() + tCov * ublas::outer_prod(m_driver->direction(), m_driver->direction()) + t * t * m_driver->directionCov();
00182 }
00183 template<int dimension>
00184 inline typename Line<dimension>::HomogenousVecD Line<dimension>::origin() const
00185 {
00186 return m_driver->origin();
00187 }
00188 template<int dimension>
00189 inline typename Line<dimension>::HomogenousSymMatrixD Line<dimension>::originCov() const
00190 {
00191 return m_driver->originCov();
00192 }
00193
00194 template<int dimension>
00195 inline typename Line<dimension>::HomogenousVecD Line<dimension>::direction() const
00196 {
00197 return m_driver->direction();
00198 }
00199 template<int dimension>
00200 inline typename Line<dimension>::HomogenousSymMatrixD Line<dimension>::directionCov() const
00201 {
00202 return m_driver->directionCov();
00203 }
00204
00205 template<int dimension>
00206 typename Line<dimension>::HomogenousVecD Line<dimension>::project(const HomogenousVecD& p) const
00207 {
00208 HomogenousVecD d = direction();
00209 HomogenousVecD o = origin();
00210 return ublas::inner_prod(d, p - o ) * d + o ;
00211 }
00212 template<int dimension>
00213 typename Line<dimension>::HomogenousVecD Line<dimension>::project(const Point<dimension>& p) const
00214 {
00215 return project(p.homogenousCoordinates() );
00216 }
00217 template<int dimension>
00218 void Line<dimension>::projectCov( const HomogenousVecD& p, const HomogenousSymMatrixD& pCov, HomogenousVecD& v, HomogenousSymMatrixD& vCov) const
00219 {
00220 HomogenousMatrixD Jp, Jo, Jd;
00221 HomogenousVecD d = direction();
00222 HomogenousVecD o = origin();
00223
00224 Jp = ublas::outer_prod( d, d);
00225
00226 Jo = -Jp;
00227 ublas::subrange( Jo, 0, 3, 0, 3 ) += jblas::identity_mat( 3, 3 );
00228
00229 Jd = ublas::outer_prod( d, p - o );
00230 double ip = ublas::inner_prod(d, p - o );
00231 ublas::subrange( Jd, 0, 3, 0, 3 ) += jblas::identity_mat( 3, 3) * ip;
00232 v = ip * d + o;
00233 vCov = ublas::prod( Jp, HomogenousMatrixD( ublas::prod( pCov, ublas::trans(Jp) ) ) )
00234 + ublas::prod( Jo, HomogenousMatrixD( ublas::prod( originCov(), ublas::trans(Jo) ) ) )
00235 + ublas::prod( Jd, HomogenousMatrixD( ublas::prod( directionCov(), ublas::trans(Jd) ) ) );
00236 }
00237 template<int dimension>
00238 void Line<dimension>::projectCov( const Point<dimension>& p, Line<dimension>::HomogenousVecD& v, HomogenousSymMatrixD& vCov) const
00239 {
00240 projectCov(p.homogenousCoordinates(), p.homogenousCoordinatesCov(), v, vCov);
00241 }
00242 template<int dimension>
00243 inline void Line<dimension>::closestPoint( const Line<dimension>& line2, HomogenousVecD& v1, HomogenousVecD& v2) const
00244 {
00245 HomogenousMatrixD m;
00246 HomogenousVecD u1 = direction();
00247 HomogenousVecD o1 = origin();
00248 HomogenousVecD u2 = line2.direction();
00249 HomogenousVecD o2 = line2.origin();
00250 if(line2.reference() != this->reference())
00251 {
00252 line2.reference()->localToRepere(m, this->reference());
00253 u2 = ublas::prod(m, u2);
00254 o2 = ublas::prod(m, o2);
00255 }
00256 HomogenousVecD O1O2 = o1 - o2;
00257 double u1u2 = ublas::inner_prod(u1, u2);
00258 double denom = 1.0 - u1u2 * u1u2;
00259 if(denom > 1e-6)
00260 {
00261 double u1O1O2 = ublas::inner_prod(u1, O1O2);
00262 double u2O1O2 = ublas::inner_prod(u2, O1O2);
00263 double t2 = ( u2O1O2 - u1u2 * u1O1O2) / denom;
00264 double t1 = ( u1u2 * u2O1O2 - u1O1O2) / denom;
00265 v1 = t1 * u1 + o1;
00266 v2 = t2 * u2 + o2;
00267 } else {
00268 v1 = origin();
00269 if(line2.reference() == this->reference())
00270 {
00271 v2 = line2.project(v1);
00272 } else {
00273 HomogenousMatrixD m2;
00274 this->reference()->localToRepere(m2, line2.reference());
00275 v2 = line2.project(ublas::prod(m2, v1));
00276 v2 = ublas::prod(m, v2);
00277 }
00278 }
00279 }
00280
00281 template<>
00282 inline void Line<3>::closestPointJac( const HomogenousVecD& O1, const HomogenousVecD& u1, const HomogenousVecD& O2, const HomogenousVecD& u2, HomogenousMatrixD& O1Jac, HomogenousMatrixD& u1Jac, HomogenousMatrixD& O2Jac, HomogenousMatrixD& u2Jac) const
00283 {
00284 O1Jac = jblas::zero_mat(4,4); O1Jac(3,3) = 1.0;
00285 u1Jac = jblas::zero_mat(4,4); u1Jac(3,3) = 1.0;
00286 O2Jac = jblas::zero_mat(4,4); O2Jac(3,3) = 1.0;
00287 u2Jac = jblas::zero_mat(4,4); u2Jac(3,3) = 1.0;
00288
00289 double xu1 = u1(0);
00290 double yu1 = u1(1);
00291 double zu1 = u1(2);
00292 double xO1 = O1(0);
00293 double yO1 = O1(1);
00294 double zO1 = O1(2);
00295 double xu2 = u2(0);
00296 double yu2 = u2(1);
00297 double zu2 = u2(2);
00298 double xO2 = O2(0);
00299 double yO2 = O2(1);
00300 double zO2 = O2(2);
00301
00302 {
00303 double t4 = ((double) xu1 * (double) xu2 + (double) yu1 * (double) yu2 + (double) zu1 * (double) zu2);
00304 double t7 = (int) ((double) t4 * (double) t4);
00305 double t9 = 1 / (1 - t7);
00306 double t10 = (-t4 * xu2 + xu1) * t9;
00307 double t15 = (-t4 * yu2 + yu1) * t9;
00308 double t19 = (-t4 * zu2 + zu1) * t9;
00309 O1Jac(0, 0) = t10 * xu1 + 1;
00310 O1Jac(0, 1) = t15 * xu1;
00311 O1Jac(0, 2) = t19 * xu1;
00312 O1Jac(1, 0) = t10 * yu1;
00313 O1Jac(1, 1) = t15 * yu1 + 1;
00314 O1Jac(1, 2) = t19 * yu1;
00315 O1Jac(2, 0) = t10 * zu1;
00316 O1Jac(2, 1) = t15 * zu1;
00317 O1Jac(2, 2) = t19 * zu1 + 1;
00318 }
00319
00320 {
00321 double t1 = ((double) xO2 - (double) xO1);
00322 double t3 = ((double) yO2 - (double) yO1);
00323 double t5 = ((double) zO2 - (double) zO1);
00324 double t7 = ((double) xu2 * (double) t1 + (double) yu2 * (double) t3 + (double) zu2 * (double) t5);
00325 double t13 = ((double) xu1 * (double) xu2 + (double) yu1 * (double) yu2 + (double) zu1 * (double) zu2);
00326 double t14 = ((double) t13 * (double) t13);
00327 double t15 = 1 - t14;
00328 double t16 = 1 / t15;
00329 double t17 = (xu2 * t7 - xO2 + xO1) * t16;
00330 double t23 = t13 * t7 - xu1 * t1 - yu1 * t3 - zu1 * t5;
00331 double t24 = t15 * t15;
00332 double t26 = t23 / t24;
00333 double t27 = xu1 * t13;
00334 double t31 = t23 * t16;
00335 double t35 = (yu2 * t7 - yO2 + yO1) * t16;
00336 double t43 = (zu2 * t7 - zO2 + zO1) * t16;
00337 double t50 = yu1 * t13;
00338 double t66 = zu1 * t13;
00339 u1Jac(0, 0) = t17 * xu1 + 2 * t26 * t27 * xu2 + t31;
00340 u1Jac(0, 1) = t35 * xu1 + 2 * t26 * t27 * yu2;
00341 u1Jac(0, 2) = t43 * xu1 + 2 * t26 * t27 * zu2;
00342 u1Jac(1, 0) = t17 * yu1 + 2 * t26 * t50 * xu2;
00343 u1Jac(1, 1) = t35 * yu1 + 2 * t26 * t50 * yu2 + t31;
00344 u1Jac(1, 2) = t43 * yu1 + 2 * t26 * t50 * zu2;
00345 u1Jac(2, 0) = t17 * zu1 + 2 * t26 * t66 * xu2;
00346 u1Jac(2, 1) = t35 * zu1 + 2 * t26 * t66 * yu2;
00347 u1Jac(2, 2) = t43 * zu1 + 2 * t26 * t66 * zu2 + t31;
00348 }
00349
00350
00351 {
00352 double t4 = ((double) xu1 * (double) xu2 + (double) yu1 * (double) yu2 + (double) zu1 * (double) zu2);
00353 double t7 = ((double) t4 * (double) t4);
00354 double t9 = 1 / (1 - t7);
00355 double t10 = (t4 * xu2 - xu1) * t9;
00356 double t14 = (t4 * yu2 - yu1) * t9;
00357 double t18 = (t4 * zu2 - zu1) * t9;
00358 O2Jac(0, 0) = t10 * xu1;
00359 O2Jac(0, 1) = t14 * xu1;
00360 O2Jac(0, 2) = t18 * xu1;
00361 O2Jac(1, 0) = t10 * yu1;
00362 O2Jac(1, 1) = t14 * yu1;
00363 O2Jac(1, 2) = t18 * yu1;
00364 O2Jac(2, 0) = t10 * zu1;
00365 O2Jac(2, 1) = t14 * zu1;
00366 O2Jac(2, 2) = t18 * zu1;
00367 }
00368
00369
00370 {
00371 double t1 = (xO2 - xO1);
00372 double t3 = (yO2 - yO1);
00373 double t5 = (zO2 - zO1);
00374 double t7 = (xu2 * (double) t1 + yu2 * (double) t3 + zu2 * (double) t5);
00375 double t12 = ((double) xu1 * xu2 + (double) yu1 * yu2 + (double) zu1 * zu2);
00376 double t15 = ((double) t12 * (double) t12);
00377 double t16 = 1 - t15;
00378 double t17 = 1 / t16;
00379 double t18 = (xu1 * t7 + t12 * t1) * t17;
00380 double t25 = t16 * t16;
00381 double t27 = (t12 * t7 - xu1 * t1 - yu1 * t3 - zu1 * t5) / t25;
00382 double t28 = xu1 * xu1;
00383 double t36 = (yu1 * t7 + t12 * t3) * t17;
00384 double t38 = xu1 * t12;
00385 double t41 = 2 * t27 * t38 * yu1;
00386 double t46 = (zu1 * t7 + t12 * t5) * t17;
00387 double t50 = 2 * t27 * t38 * zu1;
00388 double t55 = yu1 * yu1;
00389 double t64 = 2 * t27 * yu1 * t12 * zu1;
00390 double t71 = zu1 * zu1;
00391 u2Jac(0, 0) = t18 * xu1 + 2 * t27 * t28 * t12;
00392 u2Jac(0, 1) = t36 * xu1 + t41;
00393 u2Jac(0, 2) = t46 * xu1 + t50;
00394 u2Jac(1, 0) = t18 * yu1 + t41;
00395 u2Jac(1, 1) = t36 * yu1 + 2 * t27 * t55 * t12;
00396 u2Jac(1, 2) = t46 * yu1 + t64;
00397 u2Jac(2, 0) = t18 * zu1 + t50;
00398 u2Jac(2, 1) = t36 * zu1 + t64;
00399 u2Jac(2, 2) = t46 * zu1 + 2 * t27 * t71 * t12;
00400 }
00401 }
00402 template<int dimension>
00403 void Line<dimension>::closestPointJac( const HomogenousVecD& O1, const HomogenousVecD& u1, const HomogenousVecD& O2, const HomogenousVecD& u2, HomogenousMatrixD& O1Jac, HomogenousMatrixD& u1Jac, HomogenousMatrixD& O2Jac, HomogenousMatrixD& u2Jac) const
00404 {
00405 JFR_ASSERT(false, "Unimplemented go to mapple to get one.");
00406 }
00407
00408 template<int dimension>
00409 void Line<dimension>::closestPointCov( const Line<dimension>& line2, HomogenousVecD& v1, HomogenousSymMatrixD& cov1, HomogenousVecD& v2, HomogenousSymMatrixD& cov2) const
00410 {
00411 HomogenousMatrixD m;
00412 line2.reference()->localToRepere(m, this->reference());
00413 HomogenousVecD u1 = direction();
00414 HomogenousVecD o1 = origin();
00415 HomogenousVecD u2 = ublas::prod(m, line2.direction());
00416 HomogenousVecD o2 = ublas::prod(m, line2.origin());
00417 JFR_ASSERT( fabs(ublas::norm_2(u1) - 1.0) < 1e-6, "Vector norm should be equal to 1");
00418 JFR_ASSERT( fabs(ublas::norm_2(u2) - 1.0) < 1e-6, "Vector norm should be equal to 1");
00419 HomogenousVecD O1O2 = o1 - o2;
00420 double u1u2 = ublas::inner_prod(u1, u2);
00421 double denom = 1.0 - u1u2 * u1u2;
00422 if(denom > 1e-6)
00423 {
00424 double u1O1O2 = ublas::inner_prod(u1, O1O2);
00425 double u2O1O2 = ublas::inner_prod(u2, O1O2);
00426 double t2 = ( u2O1O2 - u1u2 * u1O1O2) / denom;
00427 double t1 = ( u1u2 * u2O1O2 - u1O1O2) / denom;
00428 v1 = t1 * u1 + o1;
00429 v2 = t2 * u2 + o2;
00430
00431 HomogenousMatrixD O1Jac, u1Jac, O2Jac, u2Jac;
00432
00433 closestPointJac(o1, u1, o2, u2, O1Jac, u1Jac, O2Jac, u2Jac);
00434 cov1 = ublas::prod( O1Jac, HomogenousMatrixD( ublas::prod( m_driver->originCov(), ublas::trans(O1Jac) ) ) )
00435 + ublas::prod( u1Jac, HomogenousMatrixD( ublas::prod( m_driver->directionCov(), ublas::trans(u1Jac) ) ) )
00436 + ublas::prod( O2Jac, HomogenousMatrixD( ublas::prod( line2.m_driver->originCov(), ublas::trans(O2Jac) ) ) )
00437 + ublas::prod( u2Jac, HomogenousMatrixD( ublas::prod( line2.m_driver->directionCov(), ublas::trans(u2Jac) ) ) );
00438
00439 closestPointJac(o2, u2, o1, u1, O2Jac, u2Jac, O1Jac, u1Jac);
00440 cov2 = ublas::prod( O1Jac, HomogenousMatrixD( ublas::prod( m_driver->originCov(), ublas::trans(O1Jac) ) ) )
00441 + ublas::prod( u1Jac, HomogenousMatrixD( ublas::prod( m_driver->directionCov(), ublas::trans(u1Jac) ) ) )
00442 + ublas::prod( O2Jac, HomogenousMatrixD( ublas::prod( line2.m_driver->originCov(), ublas::trans(O2Jac) ) ) )
00443 + ublas::prod( u2Jac, HomogenousMatrixD( ublas::prod( line2.m_driver->directionCov(), ublas::trans(u2Jac) ) ) );
00444
00445 } else {
00446 v1 = origin();
00447 cov1 = originCov();
00448 line2.projectCov(v1, cov1, v2, cov2);
00449 }
00450 }
00451 template<int dimension>
00452 typename Line<dimension>::Driver* Line<dimension>::clonedDriver() const
00453 {
00454 return m_driver->cloneLineDriver();
00455 }
00456 template<int dimension>
00457 void Line<dimension>::setDriver(Driver* d)
00458 {
00459 Atom<dimension>::setDriver(d);
00460 m_driver = d;
00461 }
00462 template<int dimension>
00463 inline BoundingBox<dimension> Line<dimension>::boundingBox() const
00464 {
00465 return BoundingBox<dimension>();
00466 }
00467 }
00468 }