00001 #ifndef LINE3D_HPP 00002 #define LINE3D_HPP 00003 00004 #include <TRTK/Coordinate.hpp> 00005 #include <math.h> 00006 #include <Eigen/Dense> 00007 #include <Eigen/Core> 00008 #include "TRTK/ErrorObj.hpp" 00009 00010 using namespace Eigen; 00011 00059 namespace TRTK 00060 { 00061 template <class T> 00062 class Line3D 00063 { 00064 public: 00065 typedef T value_type; 00066 typedef TRTK::Coordinate<T> data_type; 00067 00068 Coordinate<T> point; 00069 Coordinate<T> direction; 00070 00071 Line3D<T>(); 00072 Line3D<T>(const Coordinate<T>&, const Coordinate<T>&); 00073 Line3D<T>(const Line3D<T> &line); 00074 00075 00076 Coordinate<T> getPoint() const; 00077 Coordinate<T> getDirection() const; 00078 00079 bool operator==(const Line3D &line1) const; 00080 bool operator!=(const Line3D &line1) const; 00081 00082 Line3D<T> operator *(const T &scalar) const; 00083 Line3D<T> operator /(const T &scalar) const; 00084 00085 void setPoint(const Coordinate<T>&); 00086 void setPoint(const T&, const T&, const T&); 00087 00088 void setDirection(const Coordinate<T>&); 00089 void setDirection(const T&, const T&, const T&); 00090 void set(const Coordinate<T>&, const Coordinate<T>&); 00091 00092 00093 bool isNormalized() const; 00094 Coordinate<T> normalize() const; 00095 bool isParallel(const Line3D&) const; 00096 bool isIntersecting(const Line3D&) const; 00097 bool isPointOnTheLine(const Coordinate<T>&) const; 00098 double getAngleBetweenLines(const Line3D&) const; 00099 double getMinDistance(const Line3D&) const; 00100 double getAngleBetweenVectorAndLine(const Coordinate<T>&) const; 00101 double getAngleBetweenVectors(const Coordinate<T>&) const; 00102 Coordinate<T> getMinDistancePoint(const Line3D<T> &line2) const; 00103 Coordinate<T> intersectionPoint(const Line3D<T>&) const; 00104 Line3D<T> getOrthogonal() const; 00105 double distancePoint2Line(const Coordinate<T>&) const; 00106 Coordinate<T> getProjectionPoint2Line(const Coordinate<T>&) const; 00107 00108 void ausgleichsgerade(const Coordinate<Coordinate<T>> aPointList, const Coordinate<T> &vLineNorm, const Coordinate<T> &vLinePoint); 00109 00110 private: 00111 data_type m_data; 00112 }; 00113 00114 00116 template <class T> 00117 double test(const int t){ 00118 return t; 00119 } 00120 00121 template <class T> 00122 Line3D<T>::Line3D() 00123 { 00124 point = Coordinate<T>(0, 0, 0); 00125 direction = Coordinate<T>(0, 0, 1); 00126 } 00127 00133 template <class T> 00134 Line3D<T>::Line3D(const Coordinate<T> &point, const Coordinate<T> &direction) 00135 { 00136 if (direction.norm() == 0){ 00137 ErrorObj error("Directons norm is null \n"); 00138 error.setClassName("Line3D"); 00139 error.setFunctionName("Construct"); 00140 throw error; 00141 } 00142 else{ 00143 00144 this->point = point; 00145 this->direction = direction; 00146 } 00147 } 00148 00153 template <class T> 00154 Line3D<T>::Line3D(const Line3D<T> &line) 00155 { 00156 point = line.point; 00157 direction = line.direction; 00158 } 00159 00160 00167 template <class T> 00168 bool Line3D<T>::operator==(const Line3D & line2) const 00169 { 00170 return (isParallel(line2) && line2.isPointOnTheLine(point)); 00171 } 00172 00173 00181 template <class T> 00182 bool Line3D<T>::operator!=(const Line3D & line1) const 00183 { 00184 if (isParallel(line1)){ 00185 if (line1.isPointOnTheLine(point)){ 00186 return false; 00187 } 00188 else{ 00189 return true; 00190 } 00191 00192 } 00193 else{ 00194 return true; 00195 } 00196 } 00197 00204 template <class T> 00205 Line3D<T> Line3D<T>::operator*(const T & scalar) const 00206 { 00207 if (scalar == 0){ 00208 ErrorObj error; 00209 error.setClassName("Line3D"); 00210 error.setFunctionName(__FUNCTION__); 00211 throw error; 00212 } 00213 return Line3D<T>(point, (Coordinate<T>(direction.x() * scalar, direction.y() * scalar, direction.z() * scalar))); 00214 00215 } 00216 00217 00218 00219 00226 template <class T> 00227 Line3D<T> Line3D<T>::operator/(const T & scalar) const 00228 { 00229 if (scalar == 0){ 00230 ErrorObj error; 00231 error.setClassName("Line3D"); 00232 error.setFunctionName(__FUNCTION__); 00233 throw error; 00234 } 00235 return Line3D<T>(point, (Coordinate<T>(direction.x() / scalar, direction.y() / scalar, direction.z() / scalar))); 00236 00237 } 00238 00246 template <class T> 00247 bool Line3D<T>::isNormalized()const{ 00248 if (direction.norm() == 0){ 00249 ErrorObj error("Directons norm is null \n"); 00250 error.setClassName("Line3D"); 00251 error.setFunctionName("Construct"); 00252 throw error; 00253 } 00254 if (direction.norm() == 1){ 00255 return true; 00256 } 00257 else { 00258 return false; 00259 } 00260 } 00261 00268 template <class T> 00269 Coordinate<T> Line3D<T>::normalize() const{ 00270 return direction * (1 / direction.norm()); 00271 } 00272 00273 00274 // Test if the vectors are parallel 00275 00282 template <class T> 00283 bool Line3D<T>::isParallel(const Line3D &line2) const 00284 { 00285 double r1 = direction.x() / line2.direction.x(); 00286 double r2 = direction.y() / line2.direction.y(); 00287 double r3 = direction.z() / line2.direction.z(); 00288 if (r1 == r2 && r2 == r3){ 00289 return true; 00290 } 00291 else{ 00292 return false; 00293 } 00294 } 00295 00296 00297 00304 template <class T> 00305 bool Line3D<T>::isPointOnTheLine(const Coordinate<T> & point2) const 00306 { 00307 if (point2.size() < 3){ 00308 ErrorObj error("The point hasn´t appropriate dimension \n"); 00309 error.setClassName("Line3D"); 00310 error.setFunctionName("isPointOnTheLine"); 00311 throw error; 00312 } 00313 else{ 00314 Coordinate<double> m_point = point2 - point; 00315 Coordinate<double> diff_point = m_point / direction; 00316 00317 if ((diff_point.x() == diff_point.y()) && (diff_point.z() == diff_point.y())){ 00318 return true; 00319 } 00320 else { 00321 return false; 00322 } 00323 return false; 00324 } 00325 } 00326 00333 template <class T> 00334 double Line3D<T>::getAngleBetweenLines(const Line3D & line2) const 00335 { 00336 //For an angle between two lines their vectors are essential 00337 //It´s enough to find an angle between both vectors to find the angle between the lines. 00338 if ((line2.direction.norm() == 0) || (direction.norm() == 0)) 00339 { 00340 ErrorObj error("The direction´s norm is null \n");; 00341 error.setClassName("Line3D"); 00342 error.setFunctionName("getAngleBetweenLines"); 00343 throw error; 00344 } 00345 00346 if (isParallel(line2) && getMinDistance(line2) == 0){ 00347 return 0; 00348 00349 } 00350 00351 else if (!isIntersecting(line2) && !isParallel(line2)){ 00352 ErrorObj error("The lines are not intersecting \n");; 00353 error.setClassName("Line3D"); 00354 error.setFunctionName("getAngleBetweenLines"); 00355 throw error; 00356 00357 } 00358 00359 else{ 00360 Coordinate<T> sum = line2.direction * direction; 00361 double coordinSumme = sum.x() + sum.y() + sum.z(); 00362 return acos(coordinSumme / (direction.norm() *line2.direction.norm())); 00363 00364 } 00365 00366 00367 } 00368 00369 00370 00377 template <class T> 00378 double Line3D<T>::getAngleBetweenVectorAndLine(const Coordinate<T> & vector2) const 00379 { 00380 if ((vector2.norm() == 0) || (direction.norm() == 0)) 00381 { 00382 ErrorObj error; 00383 error.setClassName("Line3D"); 00384 error.setFunctionName(__FUNCTION__); 00385 throw error; 00386 } 00387 return acos((vector2.dot(direction) / (vector2.norm()*direction.norm()))); 00388 00389 } 00390 00397 template <class T> 00398 bool Line3D<T>::isIntersecting(const Line3D & line2) const 00399 { 00400 if (isParallel(line2)){ 00401 return false; 00402 } 00403 else { 00404 if (getMinDistance(line2) == 0){ 00405 return true; 00406 00407 } 00408 else{ 00409 return false; 00410 } 00411 } 00412 00413 } 00414 00415 00422 template <class T> 00423 double Line3D<T>::getMinDistance(const Line3D & line2)const{ 00424 // Im folgenden wird der Punkt mit dem kleinsten Abstand von zwei (vielleicht windschiefen) Geraden berechnet. 00425 // Die Geraden sind: 00426 // vLine1Point + vLambda(0) * vLine1Direction 00427 // vLine2Point + vLambda(1) * vLine2Direction 00428 // Berechnung des Schnittpunkts der beiden Geraden. 00429 // Wenn das Gleichungssystem nicht lösbar ist, sind die Geraden parallel oder windschief, 00430 // wenn das Gleichungssystem eindeutig lösbar ist, schneiden die Geraden sich in einem Punkt, 00431 // wenn das Gleichungssystem unendlich viele Lösungen hat, liegen die Geraden auf einander. 00432 // 00433 // (1) point + vLambda(0) * direction = line2.point + vLambda(1) * line2.direction 00434 // 00435 // das lässt sich wie folgt um formen: 00436 // 00437 // (2) point - line2.point = vLambda(1) * line2.direction - vLambda(0) * direction 00438 // 00439 // in Vektor/Matrix-Schreibweise (Matrix * vLambda = X): 00440 // (3) 00441 // ( -direction(0) line2.direction(0) ) (vLambda(0)) (point(0) - line2.point(0)) 00442 // ( -direction(1) line2.direction(1) ) * (vLambda(1)) = (point(1) - line2.point(1)) 00443 // ( -direction(2) line2.direction(2) ) (point(2) - line2.point(2)) 00444 // 00445 // Multiplizieren von der linken Seite mit der transponierten (~) Matrix 00446 // (4) 00447 // ( -direction(0) -direction(2) -direction(2) ) ( -direction(0) line2.direction(0) ) (vLambda(0)) ( -direction(0) -direction(2) -direction(2) ) (point(0) - line2.point(0)) 00448 // ( line2.direction(0) line2.direction(1) line2.direction(2) ) * ( -direction(1) line2.direction(1) ) * (vLambda(1)) = ( line2.direction(0) line2.direction(1) line2.direction(2) ) * (point(1) - line2.point(1)) 00449 // 00450 Coordinate<T> vTmp2, vTmp; 00451 00452 Eigen::Vector2d vLambda(0, 0); 00453 Eigen::Matrix3d mEquations(3, 3); 00454 mEquations.setIdentity(); 00455 double dAngle = 0; 00456 Eigen::MatrixXd mTemp(3, 2); 00457 00458 mTemp(0, 0) = -direction.x(); 00459 mTemp(1, 0) = -direction.y(); 00460 mTemp(2, 0) = -direction.z(); 00461 mTemp(0, 1) = line2.direction.x(); 00462 mTemp(1, 1) = line2.direction.y(); 00463 mTemp(2, 1) = line2.direction.z(); 00464 00465 00466 //~mTemp * mTemp * Lambda = ~mTemp * (point - line2.point) 00467 Eigen::MatrixXd mMatrix = mTemp.transpose() * mTemp; 00468 00469 // Pruefen von mMatrix auf Singularitaet 00470 bool IsSingular = true; 00471 00472 00473 double det = mMatrix.determinant(); 00474 if (mMatrix.determinant() < 1.0e-12){ 00475 00476 IsSingular = true; 00477 } 00478 else{ 00479 IsSingular = false; 00480 } 00481 00482 if (IsSingular) { // Lines are parallel or a directions vector is null vector 00483 if ((line2.direction.norm() == 0) || (direction.norm() == 0)) 00484 { 00485 ErrorObj error; 00486 error.setClassName("Line3D"); 00487 error.setFunctionName(__FUNCTION__); 00488 throw error; 00489 00490 } 00491 else{ // Lines are parallel or identical 00492 00493 // When two lines are parallel, every point on the first line has a minimum distanse to other line 00494 00495 vTmp2 = point - line2.point; 00496 if (vTmp2.norm() == 0) 00497 { 00498 return 0.0; 00499 00500 } 00501 // Winkelbestimmung der Verbindung und des Richtungsvektors der ersten Geraden 00502 00503 00504 dAngle = getAngleBetweenVectorAndLine(vTmp2); 00505 // Bestimmung des Abstands durch Bildung des Betrages der durch Projektion entstandenen Strecke 00506 double ret = (vTmp2.norm() * sin(dAngle)); 00507 return ret; 00508 00509 } 00510 } 00511 else 00512 { 00513 //nicht singulär 00514 //gilt, wenn sie sich schneiden oder windschief sind. 00515 // Das Gleichungssystem wird gelöst 00516 // (1) von links mit der inversen (!) Matrix multiplizieren 00517 // 00518 // !mMatrix * mMatrix * vLambda = !mMatrix * ~mTemp * (point - line2.point) 00519 // 00520 // (2) da !mMatrix * mMatrix die Einheitsmatrix ist, erhält man folgende Gleichung: 00521 Coordinate < double> diffPoint = point - line2.point; 00522 Eigen::Vector3d diff(diffPoint.x(), diffPoint.y(), diffPoint.z()); 00523 vLambda = mMatrix.inverse() *mTemp.transpose() * diff; 00524 Coordinate<double> vpointOnLine1 = point + vLambda[0] * direction; 00525 Coordinate<double> vPointOnLine2 = line2.point + vLambda[1] * line2.direction; 00526 00527 return (vpointOnLine1 - vPointOnLine2).norm(); 00528 } 00529 } 00530 00531 00539 template <class T> 00540 Coordinate<T> Line3D<T>::intersectionPoint(const Line3D<T> &line2) const 00541 { 00542 if (line2.direction.norm() == 0){ 00543 ErrorObj error; 00544 error.setClassName("Line3D"); 00545 error.setFunctionName(__FUNCTION__); 00546 throw error; 00547 } 00548 // Wenn Geraden sich nicht schneiden 00549 if (!isIntersecting(line2)){ 00550 ErrorObj error; 00551 error.setClassName("Line3D"); 00552 error.setFunctionName(__FUNCTION__); 00553 throw error; 00554 } 00555 else{ 00556 /* 00557 g = p + t*r // p ist ein Punkt der Geraden, r die Richtung der Geraden. 00558 00559 g1 = p1+t1*r1 00560 g2 = p2+t2*r2 00561 g1 = g2 00562 00563 // und daraus ergibt sich: 00564 p1+t1*r1 = p2+t2*r2 00565 00566 // oder ausgeschrieben und umgeformt: 00567 r1x*t1 - r2x*t2 = p2x-p1x 00568 r1y*t1 - r2y*t2 = p2y-p1y 00569 r1z*t1 - r2z*t2 = p2z-p1z 00570 */ 00571 //Coordinate<T> vTmp(direction.normalized().cross(line2.direction.normalized())); 00572 // Überbestimmte gleichungssystem 00573 // 00574 00575 //Coordinate<T> vTmp(direction.normalized().cross(line2.direction.normalized())); 00576 Coordinate<T> vTmp((line2.point - point).x(), (line2.point - point).y(), (line2.point - point).z()); 00577 Eigen::Matrix3d mEquations(3, 3); 00578 mEquations(0, 0) = direction.normalized().x(); 00579 mEquations(1, 0) = direction.normalized().y(); 00580 mEquations(2, 0) = direction.normalized().z(); 00581 mEquations(0, 1) = -line2.direction.normalized().x(); 00582 mEquations(1, 1) = -line2.direction.normalized().y(); 00583 mEquations(2, 1) = -line2.direction.normalized().z(); 00584 mEquations(0, 2) = vTmp.x(); 00585 mEquations(1, 2) = vTmp.y(); 00586 mEquations(2, 2) = vTmp.z(); 00587 Eigen::Matrix2d xy(2, 2); 00588 xy(0, 0) = mEquations(0, 0); 00589 xy(1, 0) = mEquations(1, 0); 00590 xy(0, 1) = mEquations(0, 1); 00591 xy(1, 1) = mEquations(1, 1); 00592 00593 Eigen::Matrix2d mEquations2 = xy.transpose() * xy; 00594 00595 00596 Coordinate<T> diff(line2.point - point); 00597 Eigen::Vector3d m_temp(diff.x(), diff.y(), diff.z()); 00598 Eigen::Vector3d m_temp2 = mEquations.inverse() * m_temp; 00599 Coordinate<T> vLambda(m_temp2.x(), m_temp2.y(), m_temp2.z()); 00600 // Der gesuchte Punkt liegt dann jetzt an der Stelle vLine2Point + vLambda(1) * vLine2Norm 00601 vTmp = point + vLambda.x() * direction.normalized() + (vLambda.z() * vTmp) / 2.0; 00602 00603 // Den Punkt auf Line1, der den minimalen Abstand zu Line 2 hat in vPointOnLine1 zur�ckgeben 00604 // vPointOnLine1 = vTmp; 00605 00606 // R�ckgabewert ist der minimale Abstand der beiden Gerade 00607 double vTmpx = vTmp.x(); 00608 double vTmpy = vTmp.y(); 00609 double vTmpz = vTmp.z(); 00610 return vTmp; 00611 00612 00613 } 00614 00615 00616 } 00617 00618 00619 00620 00626 template <class T> 00627 Coordinate<T> Line3D<T>::getDirection() const 00628 { 00629 return direction; 00630 } 00631 00638 template <class T> 00639 Coordinate<T> Line3D<T>::getPoint() const 00640 { 00641 return point; 00642 } 00643 00644 00650 template <class T> 00651 void Line3D<T>::setDirection(const Coordinate<T> &direction2) 00652 { 00653 if (direction2.norm() == 0){ 00654 ErrorObj error("Directons norm is null \n"); 00655 error.setClassName("Line3D"); 00656 error.setFunctionName("Construct"); 00657 throw error; 00658 } 00659 direction = direction2; 00660 } 00661 00662 00668 template <class T> 00669 void Line3D<T>::setDirection(const T &x, const T &y, const T &z) 00670 { 00671 if (Coordinate<T>(x, y, z).norm() == 0){ 00672 ErrorObj error("Directons norm is null \n"); 00673 error.setClassName("Line3D"); 00674 error.setFunctionName("Construct"); 00675 throw error; 00676 } 00677 00678 direction = Coordinate<T>(x, y, z); 00679 } 00680 00681 00682 //Set both values : point and direction 00683 00689 template <class T> 00690 void Line3D<T>::set(const Coordinate<T> &point1, const Coordinate<T> &direction2) 00691 { 00692 if (direction2.norm() == 0){ 00693 ErrorObj error("Directons norm is null \n"); 00694 error.setClassName("Line3D"); 00695 error.setFunctionName("Construct"); 00696 throw error; 00697 } 00698 00699 point = point1; 00700 direction = direction2; 00701 } 00702 00703 00704 00710 template <class T> 00711 void Line3D<T>::setPoint(const T &x, const T &y, const T &z) 00712 { 00713 point = Coordinate<T>(x, y, z); 00714 direction = point2 - point; 00715 } 00716 00717 00723 template <class T> 00724 void Line3D<T>::setPoint(const Coordinate<T> &point2) 00725 { 00726 point = point2; 00727 direction = point2 - point; 00728 } 00729 00730 00736 template <class T> 00737 Line3D<T> Line3D<T>::getOrthogonal() const 00738 { 00739 Coordinate<T> ret = direction.orthogonal(); 00740 00741 if (ret.norm() == 0){ 00742 00743 ErrorObj error; 00744 error.setClassName("Line3D"); 00745 error.setFunctionName(__FUNCTION__); 00746 throw error; 00747 } 00748 00749 return Line3D<T>(point, ret); 00750 } 00751 00760 template <class T> 00761 Coordinate<T> Line3D<T>::getProjectionPoint2Line(const Coordinate<T> &vPoint) const 00762 { 00763 Line3D<T> v_line(vPoint, direction); 00764 return intersectionPoint(v_line); 00765 00766 } 00773 template <class T> 00774 double Line3D<T>::distancePoint2Line(const Coordinate<T> &point2) const 00775 { 00776 // Zuerst eine Ebene bilden, mit Normalenvektor=Geradenrichtung und durch den vPoint 00777 // dann diese Gerade mit der Ebene schneiden 00778 // und anschliessen den Abstand von dem Schnittpunkt zu dem 00779 // ubergebenen Punkt berechnen 00780 if (isPointOnTheLine(point2)){ 00781 return 0; 00782 } 00783 else{ 00784 Line3D<double> m_line(point2, direction); 00785 //Coordinate<T> vIntersection( intersectionLineAndPlane(m_line)); 00786 00787 00788 double dLambda = (m_line.point.dot(m_line.direction.normalized()) - point.dot(m_line.direction.normalized())) / (direction.dot(m_line.direction.normalized())); 00789 Coordinate<double> vIntersection = (point + dLambda * direction); 00790 return (vIntersection - point2).norm(); 00791 } 00792 00793 } 00794 00795 template <class T> 00796 00803 Coordinate<T> Line3D<T>::getMinDistancePoint(const Line3D<T> &line2) const 00804 { 00805 // Um den kleinsten Abstand von zwei Geradenstuecken zu berechnen, muessen 5 Faelle betrachtet werden: 00806 // Entweder, ist einer der 4 Endpunkte derjenige Punkt, mit dem kleinsten Abstand, oder aber 00807 // es liegt irgendwo dazwischen. 00808 // 00809 // Fuer die Berechnung wird zuerst geguckt, wo die Beiden Geraden den kleinsten Abstand haben, wenn man 00810 // die geraden unendlich verl�ngert. 00811 // Dann muss geschaut werden, ob der gefundene Punkt kleinsten Abstandes innerhalb derbeiden Geradenst�cke liegt. 00812 // 00813 // Nur wenn er ausserhalb liegt, dann ist einer der vier Endpunkte 00814 00815 00816 // Im folgenden wird der Punkt mit dem kleinsten Abstand von zwei (vielleicht windschiefen) Geraden berechnet. 00817 // Die Geraden sind: 00818 // vLine1Point + vLambda(0) * vLine1Norm 00819 // vLine2Point + vLambda(1) * vLine2Norm 00820 00821 Eigen::Matrix3d mEquations(3, 3); 00822 // Senkrechten Vektor auf beide Geraden bilden 00823 Coordinate<T> vTmp = direction.normalized().cross(line2.direction.normalized()); 00824 // Jetzt muss der Punkt auf Line2 gefunden werden, der den kleinsten Abstand zu Line1 hat. 00825 // 00826 // dazu muss folgende Gleichung geloest werden: 00827 // der Vektor, der mit kleinstem Abstand Line1 und Line2 verbindet, laest sich auf zwei Arten bestimmen, 00828 // die dann gleichgesetzt werden 00829 // vLambda(2) * (vLine1Norm x vLine2Norm) = (vLine2Point + vLambda(1) * vLine2Norm - (vLine1Point + vLambda(0) * vLine1Norm)) 00830 // 00831 // daraus folgt das Gleichungssystem: 00832 // mEquations * vLambda = vLine2Point - vLine1Point 00833 00834 mEquations(0, 0) = direction.normalized().x(); 00835 mEquations(1, 0) = direction.normalized().y(); 00836 mEquations(2, 0) = direction.normalized().z(); 00837 mEquations(0, 1) = -line2.direction.normalized().x(); 00838 mEquations(1, 1) = -line2.direction.normalized().y(); 00839 mEquations(2, 1) = -line2.direction.normalized().z(); 00840 mEquations(0, 2) = vTmp.x(); 00841 mEquations(1, 2) = vTmp.y(); 00842 mEquations(2, 2) = vTmp.z(); 00843 00844 // Das Gleichungssystem wird geloest, indem beide Seiten des Gleichungssystems von links 00845 // mit der inversen Matrix multipliziert werden 00846 Coordinate<T> point_diff = (line2.point - point); 00847 00848 Eigen::Vector3d m_temp = point_diff.toArray(); 00849 // m_temp(point_diff.x(), point_diff.y(), point_diff.z()); 00850 Eigen::Vector3d m_temp2 = mEquations.inverse() * m_temp; 00851 00852 Coordinate<T> vLambda(m_temp2.x(), m_temp2.y(), m_temp2.z()); 00853 // Der gesuchte Punkt liegt dann jetzt an der Stelle vLine2Point + vLambda(1) * vLine2Norm 00854 vTmp = point + vLambda.x() * direction.normalized() + (vLambda.z() * vTmp) / 2.0; 00855 00856 // Den Punkt auf Line1, der den minimalen Abstand zu Line 2 hat in vPointOnLine1 zur�ckgeben 00857 // vPointOnLine1 = vTmp; 00858 00859 // R�ckgabewert ist der minimale Abstand der beiden Gerade 00860 return vTmp; 00861 } 00862 00863 template <class T> 00864 void Line3D<T>::ausgleichsgerade(const Coordinate<Coordinate<T>> aPointList, const Coordinate<T> &vLineNorm, const Coordinate<T> &vLinePoint) 00865 { 00866 // �berpr�fe, ob genug Punkte �bergeben werden 00867 if (aPointList.size() < 3) { 00868 ErrorObj error; 00869 error.setClassName("Line3D"); 00870 error.setFunctionName(__FUNCTION__); 00871 throw error; 00872 00873 } 00874 // �berpr�fen, ob genug (verschiedene) Punkte �bergeben worden sind 00875 unsigned int iCounter = 0; 00876 for (unsigned int i = 0; i < aPointList.size() - 1; i++) { 00877 if (aPointList[i].x() == aPointList[i + 1].x() && aPointList[i].y() == aPointList[i + 1].y() && aPointList[i].z() == aPointList[i + 1].z()) { 00878 iCounter++; 00879 if (aPointList.size() - iCounter < 3) { 00880 00881 ErrorObj error; 00882 error.setClassName("Line3D"); 00883 error.setFunctionName(__FUNCTION__); 00884 throw error; 00885 00886 00887 } 00888 } 00889 } 00890 00891 Eigen::MatrixXd mA; 00892 mA.SetNull(); 00893 00894 // mean point 00895 double fXc = 0; 00896 double fYc = 0; 00897 double fZc = 0; 00898 for (unsigned int i = 0; i < aPointList.size(); i++) 00899 { 00900 fXc += aPointList[i].x(); 00901 fYc += aPointList[i].y(); 00902 fZc += aPointList[i].z(); 00903 } 00904 // Mittelwert �ber alle Punkte bilden, dieser Punkt sollt dann auf der Ebene liegen. 00905 fXc = fXc / aPointList.size(); 00906 fYc = fYc / aPointList.size(); 00907 fZc = fZc / aPointList.size(); 00908 00909 // matrix mA is 3x3 symmetrical matrix 00910 // with sum of squared distances between points and mean point on main diagonal 00911 // and sum of cross distances on off-diagonal 00912 for (unsigned int i = 0; i < aPointList.size(); i++) 00913 { 00914 mA(0, 0) += pow(aPointList[i](0) - fXc, 2); 00915 mA(1, 1) += pow(aPointList[i](1) - fYc, 2); 00916 mA(2, 2) += pow(aPointList[i](2) - fZc, 2); 00917 00918 mA(0, 1) += (aPointList[i](0) - fXc)*(aPointList[i](1) - fYc); 00919 mA(0, 2) += (aPointList[i](0) - fXc)*(aPointList[i](2) - fZc); 00920 mA(1, 2) += (aPointList[i](1) - fYc)*(aPointList[i](2) - fZc); 00921 } 00922 mA(1, 0) = mA(0, 1); 00923 mA(2, 0) = mA(0, 2); 00924 mA(2, 1) = mA(1, 2); 00925 00926 // for storing eigenvalues and eigenvectors 00927 VectorXd vEigenValues; 00928 MatrixXd vEigenVectors; 00929 00930 // calculates all eigenvalues and corresponding eigenvectors of matrix mA 00931 mA.getEigenVectors(vEigenVectors, vEigenValues); 00932 00933 // test Eigenvectors 00934 00935 MatrixXd m1, m2, m3; 00936 00937 // eigenvector that corresponds to smallest eigenvalue is normalized normal vector of fitted plane 00938 int iMax; 00939 if (vEigenValues(0) >= vEigenValues(1) && vEigenValues(0) >= vEigenValues(2)) 00940 iMax = 0; 00941 else if (vEigenValues(1) > vEigenValues(0) && vEigenValues(1) >= vEigenValues(2)) 00942 iMax = 1; 00943 else 00944 iMax = 2; 00945 00946 // Geradengleichung: a*x + b*y + c*z +d = 0; 00947 // Berechnung des Normalenvektors 00948 vLineNorm(0) = vEigenVectors(0, iMax); 00949 vLineNorm(1) = vEigenVectors(1, iMax); 00950 vLineNorm(2) = vEigenVectors(2, iMax); 00951 vLineNorm = VEC_Norm(vLineNorm); 00952 00953 vLinePoint(0) = fXc; 00954 vLinePoint(1) = fYc; 00955 vLinePoint(2) = fZc; 00956 } 00957 00958 00959 } //End of the namespace TRTK 00960 00961 #endif 00962
Documentation generated by Doxygen