00001 /********************************************************************* 00002 * 00003 * Software License Agreement (BSD License) 00004 * 00005 * Copyright (c) 2008, Robert Bosch LLC. 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * * Redistributions in binary form must reproduce the above 00015 * copyright notice, this list of conditions and the following 00016 * disclaimer in the documentation and/or other materials provided 00017 * with the distribution. 00018 * * Neither the name of the Robert Bosch nor the names of its 00019 * contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00030 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00032 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00033 * POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 *********************************************************************/ 00036 00037 #include "explore_hrl/Line.h" 00038 00039 #include <iomanip> 00040 //#include <gsl/gsl_fit.h> 00041 //#include <GL/glut.h> 00042 //#include "UnitTest.h" 00043 00044 using namespace std; 00045 00046 namespace geom { 00047 00048 Line::Line():p(0.f,0.f,0.f),d(1.f,0.f,0.f){} 00049 Line::Line(Point p1, Point p2):p(p1){ 00050 d = (p2-p1).normalized(); 00051 } 00052 Line::Line(Point p1, Point p2, bool setLen):p(p1){ 00053 d = (p2-p1).normalized(); 00054 length = (p2-p1).length(); 00055 } 00056 Line::Line(Point _p, float theta):p(_p){ 00057 d = Point(cos(theta),sin(theta),0.f); 00058 } 00059 //Line::Line(const Line& o):beginDist(o.beginDist),endDist(o.endDist),p(o.p),d(o.d){} 00060 00061 Vector Line::getDirection() const{ 00062 return d; 00063 } 00064 00065 Point Line::getPoint() const{ 00066 return p; 00067 } 00068 00069 Point Line::eval(float t) const{ 00070 return p + d*t; 00071 } 00072 00073 Point Line::intersect(const Line& o) const { 00074 float t,s; 00075 return intersect(o, t, s); 00076 } 00077 00078 Point Line::intersect(const Line& o, float& t, float& s) const{ 00079 Vector u = d; 00080 Vector v = o.d; 00081 Vector w = Vector(p - o.p); 00082 Vector vp = perp(v); 00083 Vector up = perp(u); 00084 t = -vp.dot(w) / vp.dot(u); 00085 s = up.dot(w) / up.dot(v); 00086 return eval(t); 00087 } 00088 00089 float Line::distFrom(Point p2) const{ 00090 Vector v = p2-p; 00091 Vector perp = v - d*(d*v); 00092 return perp.length(); 00093 } 00094 00095 bool Line::sameAs(const Line& o, double error) const{ 00096 if(!almostEqual(d,o.d,error) && almostEqual(d,-o.d,error)) 00097 return false; 00098 return(o.distFrom(p) <= error); 00099 } 00100 00101 bool Line::operator<(const Line& o) const{ 00102 if(p==o.p) 00103 return d<o.d; 00104 //else 00105 return p < o.p; 00106 } 00107 00108 void Line::translate(const Point& trans){ 00109 p+=trans; 00110 } 00111 00112 ostream& Line::output(ostream& out) const{ 00113 return out << p << " + t*" << d; 00114 } 00115 00116 //Drawable* Line::getCopy() const{ 00117 // return new Line(*this); 00118 //} 00119 00120 /* 00121 * Finds the best line for the set of pts; 00122 */ 00123 //Line Line::getBestFit(const double* xs, const double* ys, uint size){ 00124 // double A, B, cov00, cov01, cov11, resSq; 00125 // gsl_fit_linear (xs, 1, ys, 1, size, &B, &A, &cov00, &cov01, &cov11, &resSq); 00126 // if(A<=10){ 00127 // return Line(Point(0.f,0*A+B,0.f),Point(16,16*A+B,0.f)); 00128 // } 00129 // else{ 00130 // gsl_fit_linear (ys, 1, xs, 1, size, &B, &A, &cov00, &cov01, &cov11, &resSq); 00131 // return Line(Point(0*A+B,0,0.f),Point(16*A+B,16,0.f)); 00132 // } 00133 //} 00134 //Line Line::getBestFit(const vector<Point>& pts){ 00135 // double* xs = new double[pts.size()]; 00136 // double* ys = new double[pts.size()]; 00137 // for(uint i=0;i<pts.size();i++){ 00138 // xs[i] = pts[i].x(); 00139 // ys[i] = pts[i].y(); 00140 // } 00141 // Line l(Line::getBestFit(xs,ys,pts.size())); 00142 // delete[] xs; 00143 // delete[] ys; 00144 // return l; 00145 //} 00146 //Line Line::getBestFit(const set<Point>& pts){ 00147 // double* xs = new double[pts.size()]; 00148 // double* ys = new double[pts.size()]; 00149 // set<Point>::iterator it = pts.begin(); 00150 // for(int i=0;it!=pts.end();it++,i++){ 00151 // xs[i] = (*it).x(); 00152 // ys[i] = (*it).y(); 00153 // } 00154 // Line l(Line::getBestFit(xs,ys,pts.size())); 00155 // delete[] xs; 00156 // delete[] ys; 00157 // return l; 00158 //} 00159 00160 00161 //void Line::draw() const{ 00162 // glBegin(GL_LINES); 00163 // glColor3f(0.5, 0.5, 0.5); 00164 // Point p = eval(0); 00165 // glVertex2d(p.x,p.y); 00166 // p = eval(length); 00167 // glVertex2d(p.x,p.y); 00168 // glEnd(); 00169 //} 00170 00171 //bool Line::test(std::ostream& out){ 00172 // bool result = true; 00173 // Line l; 00174 // _UNIT_TEST_(l.p == Point(0.f,0.f)); 00175 // _UNIT_TEST_(l.d == Vector(1.f,0.f)); 00176 // _UNIT_TEST_(l.eval(0.f) == Vector(0.f,0.f)); 00177 // _UNIT_TEST_(l.eval(1.f) == Vector(1.f,0.f)); 00178 // _UNIT_TEST_(l.distFrom(Point(35,26)) == 26); 00179 // l = Line(Point(0.f,0.f),Point(1.f,1.f)); 00180 // _UNIT_TEST_(l.p == Point(0.f,0.f)); 00181 // _UNIT_TEST_(l.d.almostEqual(Vector(1.f,1.f).normalize())); 00182 // _UNIT_TEST_(l.eval(0.f) == Point(0.f,0.f)); 00183 // _UNIT_TEST_(l.eval(1.f) == Point(1.f,1.f).normalize()); 00184 // _UNIT_TEST_(Test::doubleEqual(l.distFrom(Point(0,sqrt(2))),1)); 00185 // _UNIT_TEST_(Test::doubleEqual(l.distFrom(Point(0,-sqrt(2))),1)); 00186 // 00187 // _UNIT_TEST_(Line(Point(0,0),Point(0,1)).sameAs(Line(Point(0,0),Point(0,2)))); 00188 // _UNIT_TEST_(Line(Point(0,1),Point(0,2)).sameAs(Line(Point(0,2),Point(0,3)))); 00189 // 00190 // vector<Point> pts; 00191 // pts.push_back(Point(0,0)); 00192 // pts.push_back(Point(10,10)); 00193 // l = Line::getBestFit(pts); 00194 // _UNIT_TEST_(l.sameAs(Line(Point(0,0),Point(10,10)))); 00195 // 00196 // pts[1] = Point(0,10); 00197 // l = Line::getBestFit(pts); 00198 // _UNIT_TEST_(l.sameAs(Line(Point(0,0),Point(0,10)))); 00199 // 00200 // pts.push_back(Point(0,-10)); 00201 // pts.push_back(Point(0,-.1)); 00202 // pts.push_back(Point(0,.1)); 00203 // l = Line::getBestFit(pts); 00204 // _UNIT_TEST_(l.sameAs(Line(Point(0,0),Point(0,10)))); 00205 // return result; 00206 //} 00207 00208 ostream& operator<<(ostream& out, const Line& line){ 00209 return line.output(out); 00210 } 00211 00212 }