00001 /**************************************************************************** 00002 Copyright (C)2003 David Jung <opensim@pobox.com> 00003 00004 This program/file is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. (http://www.gnu.org) 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 $Id: Line3.cpp 1030 2004-02-11 20:46:17Z jungd $ 00019 $Revision: 1.2 $ 00020 $Date: 2004-02-11 15:46:17 -0500 (Wed, 11 Feb 2004) $ 00021 $Author: jungd $ 00022 00023 ****************************************************************************/ 00024 00025 #include <math.h> 00026 00027 #include <gfx/Line3> 00028 00029 using gfx::Line3; 00030 00031 using base::Point3; 00032 using gfx::Segment3; 00033 00034 00035 Segment3 Line3::shortestSegmentBetween(const Line3& l2) const 00036 { 00037 // minimize the squared dist function 00038 // q(s,t) = | l1(s) - l2(t) |^2 where l1(s) = o+s*d & l2(t) = l2.o+t*l2.d 00039 // which is quadratic with determinant always >= 0 (0 => parallel lines) 00040 // can be written q(s,t) = as^2 + 2bst + ct^2 +2ds +2et + f 00041 // where 00042 const Line3& l1(*this); // alias 00043 Real a = dot(l1.d,l1.d); 00044 Real b = dot(-l1.d,l2.d); 00045 Real c = dot(l2.d,l2.d); 00046 Real d = dot(l1.d,o-l2.o); 00047 Real e = dot(-l2.d,o-l2.o); 00048 // & f = dot(o-l2.o,o-l2.o); 00049 00050 Real det = a*c - b*b; 00051 Real s,t; 00052 if (Math::equals(det,0)) { // parallel 00053 t = 0; s = -d/a; // choose 00054 } 00055 else { // solution for dq = (0,0) 00056 Real acb2 = a*c - b*b; 00057 s = (b*e - c*d) / acb2; 00058 t = (b*d - a*e) / acb2; 00059 } 00060 00061 return Segment3( o+s*l1.d, l2.o+t*l2.d ); 00062 }