Geometric.hpp
00001 //
00002 // Geometric Tool for SAL3D.
00003 // Copyright 2010 AQSENSE, S.L.
00004 //
00005 #if !defined (AQSENSE_SAL3DPP_GEOMETRIC_HPP)
00006 #define AQSENSE_SAL3DPP_GEOMETRIC_HPP
00007 
00008 #if defined (_MSC_VER) && (_MSC_VER >= 1020)
00009 #pragma once
00010 #endif
00011 
00012 #include <cassert>
00013 #include <cmath>
00014 #include <stdexcept>
00015 #include <vector>
00016 
00017 #include <sal3d/cop.h>
00018 #include <sal3d/geometric.h>
00019 #include <sal3dpp/Common.hpp>
00020 #include <sal3dpp/COP.hpp>
00021 
00022 namespace sal3d
00023 {
00058     namespace Geometric
00059     {
00064         class InsufficientPoints: public std::invalid_argument
00065         {
00066             public:
00067                 InsufficientPoints ():
00068                     invalid_argument ("insufficient points to find the result")
00069                 {
00070                 }
00071         };
00072 
00081         class Plane
00082         {
00083             public:
00089                 Plane () :
00090                     _plane ()
00091                 {}
00092 
00101                 explicit Plane (const sal3d_geometric_plane &plane) :
00102                     _plane (plane)
00103                 {}
00104 
00112                 Plane (const Plane &plane) :
00113                     _plane (plane._plane)
00114                 {}
00115 
00124                 Plane (float A, float B, float C, float D)
00125                 {
00126                     _plane.p[0] = A;
00127                     _plane.p[1] = B;
00128                     _plane.p[2] = C;
00129                     _plane.p[3] = D;
00130                 }
00131 
00143                 Plane (const Point3D& p1, const Point3D& p2, const Point3D& p3)
00144                 {
00145                     sal3d_geometric_plane_from_three_points (p1.c_point_3d (),
00146                             p2.c_point_3d (), p3.c_point_3d (), &_plane);
00147                 }
00148 
00154                 const sal3d_geometric_plane &
00155                 c_plane () const
00156                 {
00157                     return _plane;
00158                 }
00159 
00166                 const float &
00167                 a() const
00168                 {
00169                     return _plane.p[0];
00170                 }
00171 
00177                 float &
00178                 a()
00179                 {
00180                     return _plane.p[0];
00181                 }
00182 
00189                 const float &
00190                 b() const
00191                 {
00192                     return _plane.p[1];
00193                 }
00194 
00200                 float &
00201                 b()
00202                 {
00203                     return _plane.p[1];
00204                 }
00205 
00212                 const float &
00213                 c() const
00214                 {
00215                     return _plane.p[2];
00216                 }
00217 
00223                 float &
00224                 c()
00225                 {
00226                     return _plane.p[2];
00227                 }
00228 
00235                 const float &
00236                 d() const {
00237                     return _plane.p[3];
00238                 }
00239 
00245                 float &
00246                 d() {
00247                     return _plane.p[3];
00248                 }
00249 
00264                 Movement3D
00265                 alignToZ (const Point3D& point) const
00266                 {
00267                     sal3d_movement_3d m;
00268 
00269                     sal3d_geometric_align_plane_to_z (point.c_point_3d (),
00270                             _plane, &m);
00271 
00272                     return Movement3D (m);
00273                 }
00274 
00284                 Plane &
00285                 operator= (const Plane& rhs)
00286                 {
00287                     for (int i=0; i < 4; ++i)
00288                         (*this)[i] = rhs[i];
00289 
00290                     return *this;
00291                 }
00292 
00301                 const float &
00302                 operator[] (int idx) const
00303                 {
00304                     assert (idx >= 0 && idx < 4 && "invalid index");
00305                     return _plane.p[idx];
00306                 }
00307 
00316                 float &
00317                 operator[] (int idx)
00318                 {
00319                     return const_cast<float &> (
00320                             static_cast<const Plane &>(*this)[idx]);
00321                 }
00322 
00323             private:
00325                 sal3d_geometric_plane _plane;
00326         };
00327 
00336         class Sphere
00337         {
00338             public:
00344                 Sphere () :
00345                     _sphere ()
00346                 {}
00347 
00356                 explicit Sphere (const sal3d_geometric_sphere &sphere) :
00357                     _sphere (sphere)
00358                 {}
00359                
00367                 Sphere (const Sphere &sphere) :
00368                     _sphere (sphere._sphere)
00369                 {}
00370 
00377                 Sphere (const Point3D &centre, float r) 
00378                 {
00379                     _sphere.centre.p[0] = centre.x();
00380                     _sphere.centre.p[1] = centre.y();
00381                     _sphere.centre.p[2] = centre.z();
00382                     _sphere.radius = r;
00383                 }
00384 
00390                 const sal3d_geometric_sphere &
00391                 c_sphere () const
00392                 {
00393                     return _sphere;
00394                 }
00395 
00401                 Point3D
00402                 centre () const
00403                 {
00404                     return Point3D (_sphere.centre.p[0],
00405                             _sphere.centre.p[1], _sphere.centre.p[2]);
00406                 }
00407 
00414                 void
00415                 setCentre (const Point3D& centre)
00416                 {
00417                     _sphere.centre.p[0] = centre.x ();
00418                     _sphere.centre.p[1] = centre.y ();
00419                     _sphere.centre.p[2] = centre.z ();
00420                 }
00421 
00427                 const float &
00428                 radius () const
00429                 {
00430                     return _sphere.radius;
00431                 }
00432 
00438                 float &
00439                 radius ()
00440                 {
00441                     return _sphere.radius;
00442                 }
00443 
00444             private:
00446                 sal3d_geometric_sphere _sphere;
00447         };
00448 
00473         inline Plane
00474         getRobustTangentPlane (const COP &cop,
00475                 float expectedInliersRatio, float &inliersRatio)
00476         {
00477             sal3d_geometric_plane plane;
00478             std::vector<sal3d_point3d> points (cop.height() *
00479                     cop.width());
00480             int size;
00481 
00482             Error e;
00483             sal3d_geometric_get_robust_tangent_plane(cop.c_cop(),
00484                     expectedInliersRatio, &plane, &points[0], &size,
00485                     &inliersRatio, &e.e);
00486 
00487             if (e.e.value < 0)
00488                 throw e;
00489 
00490             return Plane (plane);
00491         }
00492 
00518         inline Plane
00519         getRobustTangentPlane (const COP &cop,
00520                 float expectedInliersRatio,
00521                 std::vector<Point3D> &inliers, float &inliersRatio)
00522         {
00523             sal3d_geometric_plane plane;
00524             std::vector<sal3d_point3d> points (cop.height() *
00525                     cop.width());
00526 
00527             int size;
00528             Error e;
00529             sal3d_geometric_get_robust_tangent_plane(cop.c_cop(),
00530                     expectedInliersRatio, &plane, &points[0], &size,
00531                     &inliersRatio, &e.e);
00532 
00533             if (e.e.value < 0)
00534                 throw e;
00535 
00536             inliers.clear ();
00537             inliers.reserve (size);
00538             for (int i = 0; i < size; ++i)
00539             {
00540                 Point3D p (points[i]);
00541                 inliers.push_back (p);
00542             }
00543 
00544             return Plane (plane);
00545         }
00546 
00561         inline Plane
00562         getAveragePlane (const COP &cop)
00563         {
00564             sal3d_geometric_plane plane;
00565 
00566             sal3d_geometric_get_average_plane(cop.c_cop(), &plane);
00567 
00568             return Plane (plane);
00569         }
00570 
00591         inline float
00592         distanceToPlane(const Point3D& point, const Plane& plane,
00593                 Point3D& intersectionPoint)
00594         {
00595             float distance;
00596             sal3d_point3d intersect;
00597 
00598             sal3d_geometric_get_distance_to_plane (point.c_point_3d (),
00599                     plane.c_plane (), &intersect ,
00600                     &distance);
00601 
00602             intersectionPoint = Point3D (intersect);
00603 
00604             return distance;
00605         }
00606 
00621         inline Sphere
00622         fitSphere (std::vector<Point3D> points)
00623         {
00624             if (points.size() < 4)
00625                 throw InsufficientPoints();
00626 
00627             std::vector<sal3d_point3d> points_c(points.size());
00628             for (unsigned int i = 0; i < points.size (); ++i)
00629                 points_c[i] = points[i].c_point_3d ();
00630 
00631             sal3d_geometric_sphere sphere;
00632             sal3d_geometric_fit_sphere (&points_c[0], points_c.size(), &sphere);
00633 
00634             return Sphere(sphere);
00635         }
00636 
00651         inline Sphere
00652         fitCOPToSphere (const COP &cop)
00653         {
00654             sal3d_geometric_sphere sphere;
00655             sal3d_geometric_fit_cop_to_sphere (cop.c_cop(), &sphere);
00656 
00657             return Sphere(sphere);
00658         }
00659 
00660     }   // !namespace Geometric
00661 }   // !namespace sal3d
00662 
00663 #endif // !AQSENSE_SAL3DPP_GEOMETRIC_HPP