Files Classes Functions Hierarchy
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
1.5.8