00001 //$Header: /home/ben/Mapper/c++/RCS/bearing_constraint.cpp,v 6.2 2002/06/14 22:28:47 ben Exp $
00002 // Copyright Benedict Adamson 2002.
00003 // This file is part of Mapper.
00004
00005 // Mapper is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009
00010 // Mapper is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 // GNU General Public License for more details.
00014
00015 // You should have received a copy of the GNU General Public License
00016 // along with Mapper; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018
00027 #include "bearing_constraint.h"
00028
00029
00030
00031 #include <cmath>
00032 #include "vector2.h"
00033
00034
00035
00036 static const double pi = M_PI;
00037
00038
00039
00040 bearing_constraint::bearing_constraint(
00041 const double u,
00042 const double b
00043 )
00044 :
00045 constraint( u ),
00046 wanted_bearing_( b )
00047 {
00048 this->points_.reserve( 2 );
00049 const vector< vector2* > zero( 2U, 0 );
00050 this->points_ = zero;
00051 {//postconditions:
00052 assert( this->uncertainty() == u );
00053 assert( this->wanted_bearing() == b );
00054 assert( this->points().size() == 2 );
00055 };
00056 }
00057
00058
00059
00060 bearing_constraint::~bearing_constraint(void)
00061 {
00062 if( this->points_[0] ) unassoc( *this );
00063 }
00064
00065
00066
00067 void bearing_constraint::energy(
00068 const double /*tol*/,
00069 const vector< vector2 > &p,
00070 double &e, //output
00071 vector< vector2 > &dedp //output
00072 ) const
00073 {
00074 //tol is a dimensionless calculation tolerance.
00075 //Calculate a dimensionless measure of the potential energy (e)
00076 //of the constraint,
00077 //if this->(*point)[i] had position (x[i], y[i]),
00078 //and the rates of change of that energy (dedx, dedy)
00079 //with respect to the point positions.
00080 //Larger values indicate the constraint is less well satisfied.
00081 //Conventionally, 0 is defined as the minimum possible energy,
00082 //And energy <= 1 indicates that the constraint is satisifed
00083 //to within the uncertainty of the constraint.
00084 {//precondition:
00085 assert( p.size() == 2 );
00086 //assert( 0 < tol && tol < 1 );
00087 };
00088 {//ensure returned gradient vector has the correct dimension
00089 static const vector< vector2 > empty( 2 );
00090 dedp = empty;
00091 };
00092 const vector2 v( p[1] - p[0] );
00093 const double r2 = v*v;
00094 if( 0.0 < r2 ){
00095 //calculate angles
00096 const double a = atan2( v.x, v.y );
00097 double da = a - this->wanted_bearing();
00098 while( pi < da ) da -= 2.0*pi;
00099 while( da < -pi ) da += 2.0*pi;
00100 assert( -pi <= da && da <= pi );
00101 //calculate energy
00102 const double ae = da / this->uncertainty();
00103 e = ae*ae;
00104 {//calculate gradients
00105 const vector2 grad(
00106 vector2( -v.y, v.x ) * 2.0*ae/
00107 (r2 * this->uncertainty())
00108 );
00109 dedp[0] = grad;
00110 dedp[1] = -grad;
00111 };
00112 }else{
00113 e = 0.0;
00114 dedp[0] = vector2( 0, 0 );
00115 dedp[1] = vector2( 0, 0 );
00116 };
00117 {//postconditions:
00118 assert( dedp.size() == 2 );
00119 };
00120 }
00121
00122
00123
00124 void bearing_constraint::wanted_bearing(
00125 const double d
00126 )
00127 {
00128 {//preconditions:
00129 assert( 0.0 <= d );
00130 };
00131 this->wanted_bearing_ = d;
00132 {//postconditions:
00133 assert( this->wanted_bearing() == d );
00134 };
00135 }