00001 //$Header: /home/ben/Mapper/c++/RCS/angle_constraint.cpp,v 6.4 2002/07/02 13:14:38 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 "angle_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 angle_constraint::angle_constraint(
00041 const double u,
00042 const double a
00043 )
00044 :
00045 constraint( u ),
00046 wanted_angle_( a )
00047 {
00048 {//preconditions:
00049 assert( 0.0 < u );
00050 };
00051 this->points_.reserve( 3 );
00052 const vector< vector2* > zero( 3U, 0 );
00053 this->points_ = zero;
00054 {//postconditions:
00055 assert( this->uncertainty() == u );
00056 assert( this->wanted_angle() == a );
00057 assert( this->points().size() == 3 );
00058 };
00059 }
00060
00061
00062
00063 angle_constraint::~angle_constraint(void)
00064 {
00065 if( this->points_[0] ) unassoc( *this );
00066 }
00067
00068
00069 namespace {
00070
00071 static double normalised_angle(
00072 double a
00073 )
00074 {
00075 while( pi < a ) a -= 2.0*pi;
00076 while( a < -pi ) a += 2.0*pi;
00077 assert( -pi <= a && a <= pi );
00078 return a;
00079 }
00080
00081
00082
00083 static void gradients(
00084 const double r2,
00085 const vector2 &v,
00086 const double deda,
00087 vector2 &dedp //output
00088 )
00089 {
00090 vector2 dadp;
00091 if( 0.0 < r2 )
00092 dadp = vector2( -v.y/r2, v.x/r2 );
00093 else
00094 //special case
00095 dadp = vector2( 0, 0 );
00096 ;
00097 dedp = deda * dadp;
00098 };
00099
00100 }
00101
00102
00103
00104 void angle_constraint::energy(
00105 const double /*tol*/,
00106 const vector< vector2 > &p,
00107 double &e, //output
00108 vector< vector2 > &dedp //output
00109 ) const
00110 {
00111 //tol is a dimensionless calculation tolerance.
00112 //Calculate a dimensionless measure of the potential energy (e)
00113 //of the constraint,
00114 //if this->(*point)[i] had position (x[i], y[i]),
00115 //and the rates of change of that energy (dedx, dedy)
00116 //with respect to the point positions.
00117 //Larger values indicate the constraint is less well satisfied.
00118 //Conventionally, 0 is defined as the minimum possible energy,
00119 //And energy <= 1 indicates that the constraint is satisifed
00120 //to within the uncertainty of the constraint.
00121 {//precondition:
00122 assert( p.size() == 3 );
00123 //assert( 0 < tol && tol < 1 );
00124 };
00125 const vector2 v1( p[1] - p[0] );
00126 const vector2 v2( p[2] - p[0] );
00127 const double r12 = v1 * v1;
00128 const double r22 = v2 * v2;
00129 const double a1 = atan2( v1.y, v1.x );
00130 const double a2 = atan2( v2.y, v2.x );
00131 const double a = a2 - a1;
00132 double ae = normalised_angle( a - this->wanted_angle() );
00133 //calculate energy
00134 const double aeu = ae/this->uncertainty();
00135 e = aeu*aeu;
00136 {//calculate gradients
00137 const double w = 2.0*aeu/this->uncertainty();
00138 const double deda1 = -w;
00139 const double deda2 = w;
00140 {//ensure the output vector has the correct dimension
00141 static const vector< vector2 > empty3( 3 );
00142 dedp = empty3;
00143 };
00144 gradients( r12, v1, deda1, dedp[1] );
00145 gradients( r22, v2, deda2, dedp[2] );
00146 dedp[0] = -(dedp[1] + dedp[2]);
00147 };
00148 {//postconditions:
00149 assert( dedp.size() == 3 );
00150 };
00151 }
00152
00153
00154