// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_line #define tools_line namespace tools { // Parametric description: // l(t) = pos + t * dir template class line { protected: typedef typename VEC3::elem_t T; public: line(){} line(const VEC3& a_p0,const VEC3& a_p1) { // Construct a line from two points lying on the line. If you // want to construct a line from a position and a direction, use // line(p, p + d). // line is directed from p0 to p1. m_pos = a_p0; //m_dir = a_p1-a_p0; m_dir = a_p0; m_dir.multiply(-1); m_dir.add(a_p1); m_dir.normalize(); } line(const T& a_0_x,const T& a_0_y,const T& a_0_z, const T& a_1_x,const T& a_1_y,const T& a_1_z) { m_pos.set_value(a_0_x,a_0_y,a_0_z); m_dir.set_value(a_1_x-a_0_x,a_1_y-a_0_y,a_1_z-a_0_z); m_dir.normalize(); } virtual ~line() {} public: line(const line& a_from) :m_pos(a_from.m_pos) ,m_dir(a_from.m_dir) {} line& operator=(const line& a_from) { m_pos = a_from.m_pos; m_dir = a_from.m_dir; return *this; } public: void set_value(const VEC3& a_p0,const VEC3& a_p1) { m_pos = a_p0; m_dir = a_p0; m_dir.multiply(-1); m_dir.add(a_p1); m_dir.normalize(); } void set_value(const T& a_0_x,const T& a_0_y,const T& a_0_z, const T& a_1_x,const T& a_1_y,const T& a_1_z) { m_pos.set_value(a_0_x,a_0_y,a_0_z); m_dir.set_value(a_1_x-a_0_x,a_1_y-a_0_y,a_1_z-a_0_z); m_dir.normalize(); } const VEC3& position() const {return m_pos;} const VEC3& direction() const {return m_dir;} /* not tested : void closest_point(const VEC3& a_point,VEC& a_out) const { //from coin3d/SbLine.cpp. // // a_out // m_pos x-----x-------> m_dir // \ | // \ | // \ | // \ | // \| // x a_point a_out = m_pos + m_dir * ((a_point - m_pos).dot(m_dir)); } bool closest_points(const line& a_line,VEC3& a_on_this,VEC3& a_on_line) const { //from coin3d/SbLine.cpp. //WARNING : if ret false, a_on_this, a_on_line not set. // Check if the lines are parallel. // FIXME: should probably use equals() here. if(a_line.m_dir == m_dir) return false; if(a_line.m_dir == T(-1)*m_dir) return false; VEC3 P0 = m_pos; VEC3 P1 = a_line.m_pos; VEC3 D0 = m_dir; VEC3 D1 = a_line.m_dir; VEC3 D0N = D0; T c[3], d[3]; for(unsigned int i=0;i<3;i++) { d[i] = D1[i] - D0N[i]*(D0[0]*D1[0] + D0[1]*D1[1] + D0[2]*D1[2]); c[i] = P1[i] - P0[i] + D0N[i]*(D0[0]*P0[0] + D0[1]*P0[1] + D0[2]*P0[2]); } T den = d[0]*d[0]+d[1]*d[1]+d[2]*d[2]; if(den==T()) return false; T t = -(c[0]*d[0]+c[1]*d[1]+c[2]*d[2]) / den; a_on_line = a_line.m_pos + a_line.m_dir * t; closest_point(a_on_line,a_on_this); return true; } bool intersect(const line& a_line,VEC3& a_out,const T& a_prec) const { VEC3 p,q; if(!closest_points(a_line,p,q)) return false; if((q-p).length()>a_prec) return false; a_out = p; return true; } */ protected: VEC3 m_pos; VEC3 m_dir; //normalized. }; } #endif