00001
00015 #ifndef _DLR_GEOMETRY_PLANE3D_H_
00016 #define _DLR_GEOMETRY_PLANE3D_H_
00017
00018 #include <iostream>
00019 #include <dlrNumeric/vector3D.h>
00020
00021
00022 #include <dlrNumeric/utilities.h>
00023
00024 namespace dlr {
00025
00026 namespace geometry {
00027
00031 class Plane3D {
00032 public:
00033
00037 Plane3D()
00038 : m_origin(0.0, 0.0, 0.0), m_directionVector0(1.0, 0.0, 0.0),
00039 m_directionVector1(0.0, 1.0, 0.0) {}
00040
00041
00058 Plane3D(const Vector3D& point0,
00059 const Vector3D& point1,
00060 const Vector3D& point2,
00061 bool orthonormalize = true);
00062
00063
00080 template <class Iterator>
00081 Plane3D(Iterator beginIterator,
00082 Iterator endIterator,
00083 double inlierPercentage = 1.0);
00084
00085
00091 Plane3D(const Plane3D& source);
00092
00093
00097 ~Plane3D() {}
00098
00099
00107 Plane3D&
00108 operator=(const Plane3D& source);
00109
00110
00122 const Vector3D&
00123 getDirectionVector0() const {return m_directionVector0;}
00124
00125
00137 const Vector3D&
00138 getDirectionVector1() const {return m_directionVector1;}
00139
00140
00141
00142 Vector3D
00143 getNormal() const {
00144 return dlr::cross(m_directionVector0, m_directionVector1);
00145 }
00146
00147
00156 const Vector3D&
00157 getOrigin() const {return m_origin;}
00158
00159
00160 double
00161 findDistance(const Vector3D& point) {
00162 Vector3D offset = point - m_origin;
00163 offset -= dot(offset, m_directionVector0) * m_directionVector0;
00164 offset -= dot(offset, m_directionVector1) * m_directionVector1;
00165 return magnitude(offset);
00166 }
00167
00168
00169 private:
00170
00171 template <class Iterator>
00172 void
00173 estimateFromSequence(Iterator beginIterator,
00174 Iterator endIterator);
00175
00176
00177
00178 Vector3D m_origin;
00179 Vector3D m_directionVector0;
00180 Vector3D m_directionVector1;
00181
00182 };
00183
00184
00185
00186
00187
00188 std::ostream&
00189 operator<<(std::ostream& stream, const Plane3D& plane);
00190
00191
00192 }
00193
00194 }
00195
00196
00197
00198
00199 #include <dlrLinearAlgebra/linearAlgebra.h>
00200 #include <dlrNumeric/subArray1D.h>
00201
00202 namespace dlr {
00203
00204 namespace geometry {
00205
00206
00207
00208
00209 template <class Iterator>
00210 Plane3D::
00211 Plane3D(Iterator beginIterator,
00212 Iterator endIterator,
00213 double inlierPercentage)
00214 : m_origin(0.0, 0.0, 0.0),
00215 m_directionVector0(1.0, 0.0, 0.0),
00216 m_directionVector1(0.0, 1.0, 0.0)
00217 {
00218
00219 std::vector<Vector3D> allPointsVector;
00220 std::copy(beginIterator, endIterator,
00221 std::back_inserter(allPointsVector));
00222
00223 int numberToInclude =
00224 static_cast<int>(allPointsVector.size() * inlierPercentage + 0.5);
00225 int numberToIgnore = allPointsVector.size() - numberToInclude;
00226
00227 Array1D<double> distances(allPointsVector.size());
00228 Array1D<size_t> ignoredPoints(numberToIgnore);
00229 Array1D<Vector3D> currentPoints(allPointsVector.size());
00230 std::copy(allPointsVector.begin(), allPointsVector.end(),
00231 currentPoints.begin());
00232 bool isDone = false;
00233 ignoredPoints = 0;
00234
00235 size_t iterationCount = 0;
00236 while(!isDone) {
00237 this->estimateFromSequence(currentPoints.begin(), currentPoints.end());
00238 for(size_t index0 = 0; index0 < allPointsVector.size(); ++index0) {
00239 distances[index0] = this->findDistance(allPointsVector[index0]);
00240 }
00241 Array1D<size_t> pointIndices = argsort(distances);
00242 if(static_cast<int>(currentPoints.size()) != numberToInclude) {
00243 currentPoints.reinit(numberToInclude);
00244 }
00245 for(int index1 = 0; index1 < numberToInclude; ++index1) {
00246 currentPoints[index1] = allPointsVector[pointIndices[index1]];
00247 }
00248 int index3 = 0;
00249 isDone = true;
00250 for(int index2 = numberToInclude;
00251 index2 < static_cast<int>(allPointsVector.size());
00252 ++index2) {
00253 if(ignoredPoints[index3] != pointIndices[index2]) {
00254 isDone = false;
00255 break;
00256 }
00257 }
00258
00259 if(++iterationCount >= 3) {
00260 break;
00261 }
00262 if(numberToInclude < static_cast<int>(allPointsVector.size())) {
00263 ignoredPoints = subArray(pointIndices, Slice(numberToInclude, 0));
00264 } else {
00265 ignoredPoints.clear();
00266 }
00267 }
00268 }
00269
00270
00271
00272 template <class Iterator>
00273 void
00274 Plane3D::
00275 estimateFromSequence(Iterator beginIterator,
00276 Iterator endIterator)
00277 {
00278
00279 dlr::Vector3D meanPoint;
00280 Iterator targetIterator = beginIterator;
00281 size_t count = 0;
00282 while(targetIterator != endIterator) {
00283 meanPoint += *targetIterator;
00284 ++count;
00285 ++targetIterator;
00286 }
00287 meanPoint /= static_cast<double>(count);
00288
00289
00290 dlr::Array2D<double> covarianceMatrix(3, 3);
00291 covarianceMatrix = 0.0;
00292 targetIterator = beginIterator;
00293 while(targetIterator != endIterator) {
00294 const double xValue = targetIterator->x() - meanPoint.x();
00295 const double yValue = targetIterator->y() - meanPoint.y();
00296 const double zValue = targetIterator->z() - meanPoint.z();
00297 covarianceMatrix(0, 0) += xValue * xValue;
00298 covarianceMatrix(0, 1) += xValue * yValue;
00299 covarianceMatrix(0, 2) += xValue * zValue;
00300 covarianceMatrix(1, 1) += yValue * yValue;
00301 covarianceMatrix(1, 2) += yValue * zValue;
00302 covarianceMatrix(2, 2) += zValue * zValue;
00303 ++targetIterator;
00304 }
00305 covarianceMatrix(1, 0) = covarianceMatrix(0, 1);
00306 covarianceMatrix(2, 0) = covarianceMatrix(0, 2);
00307 covarianceMatrix(2, 1) = covarianceMatrix(1, 2);
00308 covarianceMatrix /= static_cast<double>(count);
00309
00310
00311 dlr::Array1D<double> eigenvalues;
00312 dlr::Array2D<double> eigenvectors;
00313 dlr::linearAlgebra::eigenvectorsSymmetric(
00314 covarianceMatrix, eigenvalues, eigenvectors);
00315 dlr::Vector3D direction0(
00316 eigenvectors(0, 0), eigenvectors(1, 0), eigenvectors(2, 0));
00317 dlr::Vector3D direction1(
00318 eigenvectors(0, 1), eigenvectors(1, 1), eigenvectors(2, 1));
00319 direction0 /= dlr::magnitude(direction0);
00320 direction1 /= dlr::magnitude(direction1);
00321
00322 m_origin = meanPoint;
00323 m_directionVector0 = direction0;
00324 m_directionVector1 = direction1;
00325 }
00326
00327
00328 }
00329
00330 }
00331
00332
00333 #endif