00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "PotentialFunctions.h"
00010 #include "PfieldDatatypes.h"
00011 #include "PfieldGeometry.h"
00012
00013
00014
00015 double PotentialfieldFunction::computeValue(double x, bool smooth)
00016 {
00017 if(x >= range)
00018 {
00019 return 0.0;
00020 }
00021 else if(smooth && (x > smoothingAtBorderPosition))
00022 {
00023 return computeSmoothedValue(smoothingAtBorderPosition, f(smoothingAtBorderPosition),
00024 d(smoothingAtBorderPosition), range, 0.0, gradientAtBorder, x);
00025 }
00026 else if(smooth && (x < smoothingAtObjectPosition))
00027 {
00028 return computeSmoothedValue(0.0, atZero, gradientAtObject,
00029 smoothingAtObjectPosition, f(smoothingAtObjectPosition),
00030 d(smoothingAtObjectPosition), x);
00031 }
00032 else
00033 {
00034 return f(x);
00035 }
00036 }
00037
00038
00039 double PotentialfieldFunction::computeDerivativeValue(double x, bool smooth)
00040 {
00041 if(x >= range)
00042 {
00043 return 0.0;
00044 }
00045 else if(smooth && (x > smoothingAtBorderPosition))
00046 {
00047 return computeSmoothedValue(smoothingAtBorderPosition, d(smoothingAtBorderPosition),
00048 dd(smoothingAtBorderPosition), range, 0.0, 0.0, x);
00049 }
00050 else if(smooth && (x < smoothingAtObjectPosition))
00051 {
00052 return computeSmoothedValue(0.0, atZero, 0.0,
00053 smoothingAtObjectPosition, d(smoothingAtObjectPosition),
00054 dd(smoothingAtObjectPosition), x);
00055 }
00056 else
00057 {
00058 return d(x);
00059 }
00060 }
00061
00062
00063 double PotentialfieldFunction::computeSmoothedValue
00064 (double x1, double fx1, double dx1,
00065 double x2, double fx2, double dx2, double x)
00066 {
00067 double denominator(x2*x2*x2 + 3*x1*x2*(x1-x2) - x1*x1*x1);
00068 double a(dx2*(x2-x1) + dx1*(x2-x1) - 2*fx2 + 2*fx1);
00069 a /= denominator;
00070 double b((dx2 - dx1 - 3*a*(x2*x2-x1*x1))/(2*(x2-x1)));
00071 double c(dx1 - 3*a*x1*x1 - 2*b*x1);
00072 double d(fx1 - a*x1*x1*x1 - b*x1*x1 - c*x1);
00073 return (a*x*x*x + b*x*x + c*x +d);
00074 }
00075
00076
00077 double computeChargeForPointfield(const PfPose& objectPose, const PfPose& testedPose,
00078 PotentialfieldFunction* function)
00079 {
00080 double x = objectPose.pos.distanceTo(testedPose.pos);
00081 return function->computeValue(x);
00082 }
00083
00084
00085 double computeChargeForShapefield(const PfPose& objectPose, const PfPose& testedPose,
00086 PotentialfieldFunction* function,
00087 PfieldGeometricObject* geometry)
00088 {
00089 PfVec dummy;
00090 double x = geometry->distanceTo(objectPose, testedPose.pos, dummy);
00091 if(x == 0.0)
00092 {
00093 return function->computeValue(x, false);
00094 }
00095 else
00096 {
00097 return function->computeValue(x);
00098 }
00099 }
00100
00101
00102 double computeChargeForSectorfield(const PfPose& objectPose, const PfPose& testedPose,
00103 PotentialfieldFunction* function,
00104 const Sector& sector)
00105 {
00106 double dist = objectPose.pos.distanceTo(testedPose.pos);
00107 if((dist > function->getRange()) ||
00108 !sector.pointInside(objectPose, testedPose.pos))
00109 {
00110 return 0.0;
00111 }
00112 double distValue = function->computeValue(dist);
00113 double x = fabs(objectPose.getAngleTo(testedPose.pos));
00114 sector.crossFunction->setParameters(distValue, sector.openingAngle/2.0);
00115 return sector.crossFunction->computeValue(x);
00116 }
00117
00118
00119 PfVec computeGradientForPointfield(const PfPose& objectPose, const PfPose& testedPose,
00120 PotentialfieldFunction* function)
00121 {
00122 PfVec vecToObject = (objectPose.pos - testedPose.pos);
00123 double x = vecToObject.length();
00124 vecToObject.normalize();
00125 PfVec result(0.0,0.0);
00126 double gradient = function->computeDerivativeValue(x);
00127 result = (vecToObject * gradient);
00128 return result;
00129 }
00130
00131
00132 PfVec computeGradientForShapefield(const PfPose& objectPose, const PfPose& testedPose,
00133 PotentialfieldFunction* function,
00134 PfieldGeometricObject* geometry,
00135 ObjectType objectType)
00136 {
00137 PfVec nextObjectPosition;
00138 double x = geometry->distanceTo(objectPose, testedPose.pos, nextObjectPosition);
00139 PfVec result(0.0,0.0);
00140 PfVec vecToObject;
00141 double gradient;
00142 if(x == 0.0)
00143 {
00144 if(objectType == ATTRACTIVE)
00145 {
00146 return result;
00147 }
00148 else
00149 {
00150 vecToObject = (testedPose.pos - nextObjectPosition);
00151 gradient = function->computeDerivativeValue(x, false);
00152 }
00153 }
00154 else
00155 {
00156 vecToObject = (nextObjectPosition - testedPose.pos);
00157 gradient = function->computeDerivativeValue(x);
00158 }
00159 vecToObject.normalize();
00160 result = (vecToObject * gradient);
00161 return result;
00162 }
00163
00164
00165 PfVec computeGradientForSectorfield(const PfPose& objectPose, const PfPose& testedPose,
00166 PotentialfieldFunction* function,
00167 const Sector& sector)
00168 {
00169 PfVec result(0.0,0.0);
00170 double dist = objectPose.pos.distanceTo(testedPose.pos);
00171 if((dist > function->getRange()) ||
00172 !sector.pointInside(objectPose, testedPose.pos))
00173 {
00174 return result;
00175 }
00176 PfVec vecToObject = (objectPose.pos - testedPose.pos);
00177 vecToObject.normalize();
00178 double gradient = function->computeDerivativeValue(dist);
00179 PfVec gradientToOrigin(vecToObject * gradient);
00180
00181 PfVec centerOfSector(1.0,0.0);
00182 centerOfSector.rotate(objectPose.rotation);
00183 PfVec vecToCenter = (objectPose.pos - testedPose.pos + (centerOfSector*dist));
00184 if(vecToCenter.length() == 0.0)
00185 {
00186 return gradientToOrigin;
00187 }
00188 vecToCenter.normalize();
00189 double x = fabs(objectPose.getAngleTo(testedPose.pos))*dist;
00190 double distValue = function->computeValue(dist);
00191 double range = (sector.openingAngle/2.0)*dist;
00192 sector.crossFunction->setParameters(distValue, range);
00193 double cgradient(sector.crossFunction->computeDerivativeValue(x));
00194 result = (gradientToOrigin + (vecToCenter*cgradient));
00195 return result;
00196 }