00001 //$Header: /home/ben/Mapper/c++/RCS/distance_constraint.cpp,v 6.4 2002/07/07 18:23:13 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
00029 #include <cassert>
00030 #include <cmath>
00031
00032 #include "distance_constraint.h"
00033 #include "vector2.h"
00034
00035
00036
00037 distance_constraint::distance_constraint(
00038 const double u,
00039 const double d
00040 )
00041 :
00042 constraint( u ),
00043 wanted_distance_( d )
00044 {
00045 {//preconditions:
00046 assert( 0.0 < u );
00047 assert( 0.0 <= d );
00048 };
00049 this->points_.reserve( 2 );
00050 static const vector< vector2* > zero( 2U, 0 );
00051 this->points_ = zero;
00052 {//postconditions:
00053 assert( this->uncertainty() == u );
00054 assert( this->wanted_distance() == d );
00055 assert( this->points().size() == 2 );
00056 assert( this->points()[0] == 0 );
00057 assert( this->points()[1] == 0 );
00058 };
00059 }
00060
00061
00062
00063 distance_constraint::~distance_constraint(void)
00064 {
00065 if( this->points_[0] ) unassoc( *this );
00066 }
00067
00068
00069
00070 void distance_constraint::energy(
00071 const double /*tol*/,
00072 const vector< vector2 > &p,
00073 double &e, //output
00074 vector< vector2 > &dedp //output
00075 ) const
00076 {
00077 //tol is a dimensionless calculation tolerance.
00078 //Calculate a dimensionless measure of the potential energy (e)
00079 //of the constraint,
00080 //if this->(*point)[i] had position p[i],
00081 //and the rates of change of that energy dedp
00082 //with respect to the point positions.
00083 //Larger values indicate the constraint is less well satisfied.
00084 //Conventionally, 0 is defined as the minimum possible energy,
00085 //And energy <= 1 indicates that the constraint is satisifed
00086 //to within the uncertainty of the constraint.
00087 {//precondition:
00088 assert( p.size() == 2 );
00089 //assert( 0 < tol && tol < 1 );
00090 };
00091 const vector2 v( p[1] - p[0] );
00092 const double r2 = v * v;
00093 const double r = sqrt( r2 );
00094 const double re = (r - this->wanted_distance())/this->uncertainty();
00095 e = re*re;
00096 {//ensure the output vector haathe correct dimension
00097 static const vector< vector2 > empty2( 2 );
00098 dedp = empty2;
00099 };
00100 if( 0.0 < r2 ){
00101 const vector2 grad( v * (2.0*re/(this->uncertainty() * r2)) );
00102 dedp[1] = grad;
00103 dedp[0] = -grad;
00104 }else{ //special case: coincident points (local maximum)
00105 dedp[0] = vector2( 0, 0 );
00106 dedp[1] = vector2( 0, 0 );
00107 };
00108 {//postconditions:
00109 assert( dedp.size() == 2 );
00110 };
00111 }
00112
00113
00114
00115 void distance_constraint::wanted_distance(
00116 const double d
00117 )
00118 {
00119 {//preconditions:
00120 assert( 0.0 <= d );
00121 };
00122 this->wanted_distance_ = d;
00123 {//postconditions:
00124 assert( this->wanted_distance() == d );
00125 };
00126 }