proj home

Files   Classes   Functions   Hierarchy  

arc.cpp

Go to the documentation of this file.
00001 #include <fstream>
00002 using namespace std;
00003 
00004 #include <arcsdef.h>
00005 
00006 #include <arc.h>
00007 
00008 double arc::zero = 1e-12;
00009 
00010 arc::arc()
00011   : radius(0.0), phi0(0.0), phi1(0.0)
00012 {
00013 }
00014 
00015 boolc arc::valid() const
00016 {
00017   
00018   if ((p0==p1)==true)
00019   {
00020     cout << "error:  " << *this << " has p0 and p1 equal.";
00021     cout << endl;
00022     return false;
00023   }
00024 
00025   if (isStraightLine())
00026     return true;
00027 
00028 /*
00029   if ( ((p0-p1).dot() <= radius*radius*4.0) == false )
00030   {
00031     cout << *this << " failed radius condition." << endl;
00032     assert(false);
00033     return false;
00034   }
00035 */
00036   
00037   return true;
00038 }
00039 
00040 
00041 boolc arc::isAntiClockwise2() const
00042 {
00043   assert(isStraightLine()==false);
00044 
00045   double dphi = phi1-phi0;
00046   if (dphi<0.0)
00047     dphi += 2.0*PI;
00048 
00049   if (dphi<=PI)
00050     return true;
00051 
00052   return false;
00053 }
00054 
00055 void arc::calculateCenter() 
00056 {
00057   assert(valid());
00058   assert(isStraightLine()==false);
00059 
00060   pt2 p2((p0+p1)*0.5);
00061   pt2 q(p1-p0);
00062   if (radius<0.0)
00063     q *= -1.0; 
00064   pt2 Dq(-q.y,q.x);
00065   Dq.normalize();
00066   doublec w = q.distance() * 0.5;
00067 //cout << "w=" << w << endl;
00068   doublec h = sqrt(radius*radius-w*w);
00069 //cout << "h=" << h << endl;
00070 
00071 
00072 
00073   center = p2 + Dq*h;
00074 
00075 /*
00076 cout << SHOW(p0) << " " << SHOW(p1) << " " << SHOW(center) <<  endl;
00077 cout << SHOW(h) << " " << SHOW(q) << " " << SHOW(Dq) << endl;
00078 */
00079 }
00080 
00081 ostream & operator << (ostream & os, arc const & a)
00082 {
00083   return os << (string)a;
00084 }
00085 
00086 arc::operator string() const
00087 {
00088   stringstream ss;
00089   ss << p0 << " " << p1 << " " << radius; 
00090   return ss.str();
00091 }
00092 
00093 
00094 void arc::constructRadiusTwoPoints
00095 (
00096   doublec radius_,
00097   pt2c & p0_,
00098   pt2c & p1_
00099 )
00100 {
00101   radius = radius_;
00102   p0 = p0_;
00103   p1 = p1_;
00104 
00105   if (isStraightLine()==true)
00106     return;
00107 
00108   calculateCenter();
00109 
00110   pt2 g0(p0-center);
00111   //g0.normalize();
00112   phi0 = atan2(g0.y,g0.x);
00113   angleAdjusted(phi0);
00114   pt2 g1(p1-center);
00115   //g1.normalize();
00116   phi1 = atan2(g1.y,g1.x);
00117   angleAdjusted(phi1);
00118 
00119 /*
00120 cout << SHOW(g0) << " " << SHOW(phi0*180./PI) << endl;
00121 cout << SHOW(g1) << " " << SHOW(phi1*180./PI) << endl;
00122 cout << SHOW(phi1-phi0) << " " << SHOW(length()) << endl;
00123 */
00124   
00125 }
00126 
00127 void arc::constructPhi0TwoPoints
00128 (
00129   doublec phi0_,
00130   pt2c & p0_,
00131   pt2c & p1_
00132 )
00133 {
00134   p0 = p0_;
00135   p1 = p1_;
00136   phi0 = phi0_;
00137 /*
00138 cout << endl << endl;
00139 
00140 cout << SHOW(phi0*180.0/PI) << endl; 
00141 cout << SHOW(p0) << endl;
00142 cout << SHOW(p1) << endl;
00143 */
00144 
00145   pt2c f(cos(phi0),sin(phi0));
00146   pt2c dp(p0-p1);
00147 
00148   doublec fdotdp(f.dot(dp));
00149   if ( abs(fdotdp)<zero)
00150   {
00151     radius=0.0;
00152     return;
00153   }
00154   
00155 
00156 if ( fdotdp< 0.0 )
00157 {
00158 #ifndef NDEBUG
00159 cout << "error:  wrong initial angle" << endl;
00160 #endif
00161   constructPhi0TwoPoints(phi0+PI,p0,p1);
00162   return;
00163 }
00164 
00165   radius = dp.dot() / fdotdp * 0.5;
00166 //cout << SHOW(radius) << endl;
00167 
00168 #ifndef NDEBUG
00169 if (radius<0.0)
00170   cout << "error: the radius should be positive." << endl;
00171 #endif
00172   //center = p0 - f * abs(radius);
00173   center = p0 - f * radius;
00174 
00175 
00176 
00177 
00178 
00179 /*
00180   pt2 c0 = p0 - f * radius;
00181   center = c0;
00182 
00183 
00184 cout << SHOW(c0) << endl;
00185 cout << SHOW(c0 + f * radius) << endl;
00186 cout << SHOW(c0 - f * radius) << endl;
00187 cout << SHOW( (p0-c0).distance() ) << endl;
00188 cout << SHOW( (p1-c0).distance() ) << endl;
00189 */
00190 
00191 
00192   pt2 p4(p1-center);
00193   p4 *= 1.0 / radius;
00194   phi1 = atan2(p4.y,p4.x);
00195 
00196   if (isAntiClockwise2()==false)
00197   {
00198 
00199     if (radius<0)
00200     {
00201 #ifndef NDEBUG
00202 cout << "error:  radius already -ve, this message should not appear" << endl;
00203 #endif
00204     }
00205     else
00206       radius *= -1;
00207   }
00208 
00209 /*
00210 
00211 cout << "Verify by finding p2 from phi1." << endl;
00212   pt2 p5(cos(phi1),sin(phi1));
00213   p5 *= radius;
00214   p5 += center;
00215 
00216 
00217 cout << SHOW(p4) << endl;
00218 cout << SHOW(p4.dot()) << endl;
00219 cout << SHOW(phi1*180.0/PI) << endl;
00220 cout << SHOW(p5) << endl;
00221 */
00222 
00223 
00224 }
00225 
00226  
00227 arc::arc
00228 (
00229   doublec radius_,
00230   pt2c & p0_,
00231   pt2c & p1_
00232 )
00233 {
00234   constructRadiusTwoPoints(radius_,p0_,p1_);
00235 }
00236 
00237 doublec arc::length() const
00238 {
00239   assert(valid()==true);
00240 
00241   if (isStraightLine())
00242     return (p1-p0).distance();
00243 
00244 
00245   // Interpret the arc as convex between points p0 and p1.
00246   //  Find the acute angle between the points p0 and p1.
00247   double dphi = abs(phi1-phi0);
00248   if (dphi>PI)
00249     dphi = 2.0*PI - dphi;
00250 
00251   return abs(dphi*radius);
00252 }
00253 
00254 
00255 void arc::arcreader
00256 (
00257   vector<arc> & v, 
00258   string const & filename
00259 )
00260 {
00261   v.clear();
00262 
00263   ifstream targ(filename.c_str());
00264 
00265   assert(targ.good()==true);
00266   if (targ.good()==false)
00267     return;
00268   
00269   vector< pt2 > pts;
00270 
00271   pt2 p;
00272   uint k;
00273   targ >> k;
00274   for ( uint i=0; i<k; ++i)
00275   {
00276     targ >> p;
00277     pts.push_back(p);
00278   }
00279 
00280   uint a;
00281   uint b;
00282   double radius;
00283 
00284   targ >> k;
00285 
00286   for ( uint i=0; i<k; ++i)
00287   {
00288     targ >> a;
00289     targ >> b;
00290     targ >> radius;
00291 
00292     assert(a<pts.size());
00293     assert(b<pts.size());
00294 
00295     v.push_back( arc(radius,pts[a],pts[b]) );
00296   }
00297 }
00298 
00299 
00300 void arc::print() const
00301 {
00302   cout << SHOW(radius) << endl;
00303   cout << SHOW(p0) << endl;
00304   cout << SHOW(p1) << endl;
00305   
00306   cout << SHOW(center) << endl;
00307   cout << SHOW(phi0*180.0/PI) << endl;
00308   cout << SHOW(phi1*180.0/PI) << endl;
00309   cout << SHOW(isAntiClockwise()) << endl;
00310   cout << SHOW(isAntiClockwise2()) << endl;
00311   cout << SHOW(center+pt2(cos(phi0),sin(phi0))*abs(radius) ) << endl;
00312   cout << SHOW(center+pt2(cos(phi1),sin(phi1))*abs(radius) ) << endl;
00313   cout << endl;
00314 }
00315 
00316 
00317 /*
00318 Note that this test first has to find out its
00319  orientation
00320 
00321 
00322 */
00323 void arc::distance( double & val, pt2c & p ) const
00324 {
00325   pt2 p3(p-center);
00326 
00327   if (isAntiClockwise())
00328   {
00329     {
00330       pt2 z(center-p0);
00331       z.rotate90();
00332       if (z.dot(p3)>0.0)
00333       {
00334 //cout << "greater than p0 arm." << endl;
00335         // Take the distance from the endpoint.
00336         val = (p-p0).distance();
00337         return;
00338       }
00339     }
00340     {
00341       pt2 z(p1-center);
00342       z.rotate90();
00343       if (z.dot(p3)>0.0)
00344       {
00345 //cout << "greater than p1 arm." << endl;
00346         // Take the distance from the endpoint.
00347         val = (p-p1).distance();
00348         return;
00349       }
00350     }
00351   }
00352   else
00353   {
00354     {
00355       pt2 z(center-p1);
00356       z.rotate90();
00357       if (z.dot(p3)>0.0)
00358       {
00359         val = (p-p1).distance();
00360         return;
00361       }
00362     }
00363     {
00364       pt2 z(p0-center);
00365       z.rotate90();
00366       if (z.dot(p3)>0.0)
00367       {
00368         val = (p-p0).distance();
00369         return;
00370       }
00371     }
00372   }
00373 
00374   val = abs(p3.distance() - radius);
00375   return;
00376   
00377 } 
00378 
00379 void arc::distanceSquared( double & val, pt2c & p ) const
00380 {
00381   pt2 p3(p-center);
00382 
00383   if (isAntiClockwise())
00384   {
00385     {
00386       pt2 z(center-p0);
00387       z.rotate90();
00388       if (z.dot(p3)>0.0)
00389       {
00390         //val = (p-p0).distanceSquared();
00391         val = (p-p0).dot();
00392         return;
00393       }
00394     }
00395     {
00396       pt2 z(p1-center);
00397       z.rotate90();
00398       if (z.dot(p3)>0.0)
00399       {
00400         //val = (p-p1).distanceSquared();
00401         val = (p-p1).dot();
00402         return;
00403       }
00404     }
00405   }
00406   else
00407   {
00408     {
00409       pt2 z(center-p1);
00410       z.rotate90();
00411       if (z.dot(p3)>0.0)
00412       {
00413         //val = (p-p1).distanceSquared();
00414         val = (p-p1).dot();
00415         return;
00416       }
00417     }
00418     {
00419       pt2 z(p0-center);
00420       z.rotate90();
00421       if (z.dot(p3)>0.0)
00422       {
00423         //val = (p-p0).distanceSquared();
00424         val = (p-p0).dot();
00425         return;
00426       }
00427     }
00428   }
00429 
00430   //val = abs(p3.distanceSquared() - radius*radius);
00431   val = abs(p3.dot() - radius*radius);
00432 } 
00433 
00434 void arc::angleAdjusted(double & angle) const
00435 { 
00436   if (angle<0.0) angle += PI*2.0; 
00437   if (angle>PI*2.0) angle -= PI*2.0;
00438   
00439   assert(angle>=0.0);
00440   assert(angle<=PI*2.0); 
00441 }
00442 
00443 
00444 
00445 

Generated on Fri Mar 4 00:49:25 2011 for Chelton Evans Source by  doxygen 1.5.8