Main Page   Namespace List   Class Hierarchy   Compound List   File List   Header Files   Sources   Namespace Members   Compound Members   File Members  

angle_constraint.cpp

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 

Generated at Sun Jul 14 20:38:06 2002 for Mapper by doxygen 1.0.0 written by Dimitri van Heesch, © 1997-1999