Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/WaypointPathRep.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2002 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: WaypointPathRep.cpp 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.5 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <base/WaypointPathRep>
00026 
00027 #include <base/Serializer>
00028 
00029 using base::WaypointPathRep;
00030 
00031 
00032 
00033 
00034 base::Point3 WaypointPathRep::position(Real s) const
00035 {
00036   if (flags & ConstPos) 
00037     return points[0];
00038 
00039   Int i=findIndex(s);
00040   if (equals(s,si[i])) // fast path if s corresponds to a waypoint
00041     return points[i];
00042 
00043   Vector3 v( points[i+1] - points[i] );
00044   Real ts( si[i+1] - si[i] ); // change in s between points[i] to points[i+1]
00045 
00046   Real ds = s-si[i]; 
00047   Vector3 dv( (ds/ts)*v );
00048 
00049   return points[i] + dv;
00050 }
00051 
00052 
00053 base::Orient WaypointPathRep::orientation(Real s) const
00054 {
00055   if (flags & ConstOrient)
00056     return orients[0];
00057 
00058   Int i=findIndex(s);
00059   if (Math::equals(s,si[i])) // fast path if s corresponds to a waypoint
00060     return orients[i];
00061 
00062   // analogous to position, but using Quat4::interpolate()
00063   Quat4 q1( orients[i].getQuat4() );
00064   Quat4 q2( orients[i+1].getQuat4() );
00065   Real ts( si[i+1] - si[i] );
00066 
00067   Real ds = s-si[i];
00068   Quat4 q( Quat4::interpolate(q1,q2,ds/ts) );
00069 
00070   return Orient(q);
00071 }
00072 
00073 
00074 Real WaypointPathRep::distinguishedValue(Int i) const
00075 {
00076   if ((flags & ConstPos) && (flags && ConstOrient)) {
00077     Math::bound<Int>(i,0,1); 
00078     return (i==0)?0.0:1.0;
00079   }
00080   
00081   Math::bound<Int>(i,0,si.size()-1); 
00082   return si[i];
00083 }
00084 
00085 
00086 Int WaypointPathRep::numDistinguishedValues() const
00087 {
00088   if ((flags & ConstPos) && (flags && ConstOrient))
00089     return 2;
00090 
00091   return si.size();
00092 }
00093 
00094 
00095 
00096 
00097 void WaypointPathRep::computeSis()
00098 {
00099   if (points.size() < 2)  flags |= ConstPos;
00100   if (orients.size() < 2) flags |= ConstOrient;
00101 
00102   // ensure at least one point
00103   if (points.size() == 0) points.at(0) = Point3();
00104   if (orients.size() == 0) orients.at(0) = Orient();
00105 
00106   // if not const position, s's range maps to spatial path length
00107   if (!(flags & ConstPos)) {
00108 
00109     // scan path and assign the incremental path length to si[]
00110     //  (it will be divided by the total path length next)
00111     Real pathLength = 0;
00112     Int i=1;
00113     si.resize(points.size());
00114     si[0] = 0;
00115     while (i<points.size()) {
00116       pathLength += (points[i] - points[i-1]).length();
00117       si[i] = pathLength;
00118       i++;
00119     }
00120 
00121     if (pathLength > 0)
00122       for(Int i=0; i<points.size(); i++) 
00123         si[i] /= pathLength;
00124 
00125   }
00126   else if (!(flags & ConstOrient)) {
00127     // if position is constant, but orientation is not, s's range maps to angular path length
00128     
00129     Real pathLength = 0;
00130     Int i=1;
00131     si.resize(orients.size());
00132     si[0]=0;
00133     while (i<orients.size()) {
00134       // we calculate the angle between two Quats in a round about way - there
00135       //  is probably a better one
00136       // transform a unit x-axis vector by each Quat and then use the dot product to get
00137       // and angle between them
00138       Quat4 from(orients[i-1].getQuat4());
00139       Quat4 to(orients[i].getQuat4()); 
00140       pathLength += Quat4::angleBetween(from,to);
00141       si[i] = pathLength;
00142       i++;
00143     }
00144 
00145     if (pathLength > 0)
00146       for(Int i=0; i<orients.size(); i++)
00147         si[i] /= pathLength;
00148   }
00149 
00150   // if both position & orientation are constant, ti is not used and all position
00151   //  and orientation queries will return the same point
00152 
00153 }
00154 
00155 
00156 Int  WaypointPathRep::findIndex(Real s) const
00157 {
00158   // common end cases
00159   if ((si[0] <= s) && (s <= si[1])) return 0;
00160   if ((si[si.size()-2] <= s) && (s <= si[si.size()-1])) return si.size()-2;
00161   
00162   if (si.size()>4) {
00163     // binary search
00164     Int high, i, low;
00165     for(low=1, high=si.size()-1; high-low > 1;) {
00166       i = (high+low)/2;
00167       if (s <= si[i]) high=i; else low=i;
00168     }
00169     if ((si[i]<=s) && (s<=si[i+1])) return i; else return i-1;
00170   }
00171   else {
00172     // linear search
00173     Int i;
00174     for(i=0; i<si.size(); i++)
00175       if (si[i] > s) break;
00176     return i-1;
00177   }
00178 }
00179 
00180 
00181 
00182 void WaypointPathRep::translate(const Vector3& t)
00183 {
00184   for(Int i=0; i<points.size(); i++)
00185     points[i] += t;
00186 }
00187 
00188 
00189 void WaypointPathRep::rotate(const Quat4& r)
00190 {
00191   for(Int i=0; i<points.size(); i++) {
00192     r.rotatePoint(points[i]);
00193     Quat4 q(orients[i].getQuat4());
00194     orients[i] = r*q;
00195   }
00196 }
00197 
00198 
00199 void WaypointPathRep::transform(const Matrix4& m)
00200 {
00201   for(Int i=0; i<points.size(); i++) {
00202     Point4 p(points[i]);
00203     p = m*p;
00204     points[i] = Point3(p.x,p.y,p.z);
00205 
00206     Quat4 r;
00207     r.setRotation(m);
00208     Quat4 q(orients[i].getQuat4());
00209     orients[i] = r*q;
00210   }  
00211 }
00212 
00213 
00214 void WaypointPathRep::scalePosition(Real s)
00215 {
00216   for(Int i=0; i<points.size(); i++) {
00217     points[i] *= s;
00218   }
00219 }
00220 
00221 
00222 void WaypointPathRep::serialize(Serializer& s)
00223 {
00224   s(flags,"flags");
00225   s(points,"points");
00226   s(orients,"orients");
00227   s(si,"si");
00228 }

Generated on Thu Jul 29 15:56:17 2004 for OpenSim by doxygen 1.3.6