00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef WFMATH_STREAM_H
00027 #define WFMATH_STREAM_H
00028
00029 #include <wfmath/vector.h>
00030 #include <wfmath/rotmatrix.h>
00031 #include <wfmath/quaternion.h>
00032 #include <wfmath/point.h>
00033 #include <wfmath/axisbox.h>
00034 #include <wfmath/ball.h>
00035 #include <wfmath/segment.h>
00036 #include <wfmath/rotbox.h>
00037 #include <wfmath/polygon.h>
00038 #include <wfmath/error.h>
00039 #include <string>
00040 #include <iostream>
00041 #include <list>
00042
00043 namespace WFMath {
00044
00045
00046
00047 namespace _IOWrapper {
00048
00049
00050
00051 class BaseRead {
00052 public:
00053 virtual ~BaseRead() {}
00054
00055 virtual void read(std::istream& is) = 0;
00056 };
00057
00058 class BaseWrite {
00059 public:
00060 virtual ~BaseWrite() {}
00061
00062 virtual void write(std::ostream& os) const = 0;
00063 };
00064
00065 template<class C>
00066 class ImplRead : public BaseRead {
00067 public:
00068 ImplRead(C& c) : m_data(c) {}
00069 virtual ~ImplRead() {}
00070
00071 virtual void read(std::istream& is) {is >> m_data;}
00072
00073 private:
00074 C &m_data;
00075 };
00076
00077 template<class C>
00078 class ImplWrite : public BaseWrite {
00079 public:
00080 ImplWrite(const C& c) : m_data(c) {}
00081 virtual ~ImplWrite() {}
00082
00083 virtual void write(std::ostream& os) const {os << m_data;}
00084
00085 private:
00086 const C &m_data;
00087 };
00088
00089 std::string ToStringImpl(const BaseWrite& b, int precision);
00090 void FromStringImpl(BaseRead& b, const std::string& s, int precision);
00091 }
00092
00094
00097 template<class C>
00098 inline std::string ToString(const C& c, unsigned int precision = 6)
00099 {
00100 return _IOWrapper::ToStringImpl(_IOWrapper::ImplWrite<C>(c), 6);
00101 }
00102
00104
00107 template<class C>
00108 inline void FromString(C& c, const std::string& s, unsigned int precision = 6)
00109 {
00110 _IOWrapper::ImplRead<C> i(c);
00111 _IOWrapper::FromStringImpl(i, s, 6);
00112 }
00113
00114 void _ReadCoordList(std::istream& is, CoordType* d, const int num);
00115 void _WriteCoordList(std::ostream& os, const CoordType* d, const int num);
00116 CoordType _GetEpsilon(std::istream& is);
00117
00118 template<const int dim>
00119 inline std::ostream& operator<<(std::ostream& os, const Vector<dim>& v)
00120 {
00121 _WriteCoordList(os, v.m_elem, dim);
00122 return os;
00123 }
00124
00125 template<const int dim>
00126 inline std::istream& operator>>(std::istream& is, Vector<dim>& v)
00127 {
00128 _ReadCoordList(is, v.m_elem, dim);
00129 v.m_valid = true;
00130 return is;
00131 }
00132
00133 template<const int dim>
00134 inline std::ostream& operator<<(std::ostream& os, const RotMatrix<dim>& m)
00135 {
00136 os << '(';
00137
00138 for(int i = 0; i < dim; ++i) {
00139 _WriteCoordList(os, m.m_elem[i], dim);
00140 os << (i < (dim - 1) ? ',' : ')');
00141 }
00142
00143 return os;
00144 }
00145
00146 template<const int dim>
00147 inline std::istream& operator>>(std::istream& is, RotMatrix<dim>& m)
00148 {
00149 CoordType d[dim*dim];
00150 char next;
00151
00152 is >> next;
00153 if(next != '(')
00154 throw ParseError();
00155
00156 for(int i = 0; i < dim; ++i) {
00157 _ReadCoordList(is, d + i * dim, dim);
00158 is >> next;
00159 char want = (i == dim - 1) ? ')' : ',';
00160 if(next != want)
00161 throw ParseError();
00162 }
00163
00164 if(!m._setVals(d, FloatMax(WFMATH_EPSILON, _GetEpsilon(is))))
00165 throw ParseError();
00166
00167 return is;
00168 }
00169
00170 template<const int dim>
00171 inline std::ostream& operator<<(std::ostream& os, const Point<dim>& p)
00172 {
00173 _WriteCoordList(os, p.m_elem, dim);
00174 return os;
00175 }
00176
00177 template<const int dim>
00178 inline std::istream& operator>>(std::istream& is, Point<dim>& p)
00179 {
00180 _ReadCoordList(is, p.m_elem, dim);
00181 p.m_valid = true;
00182 return is;
00183 }
00184
00185 template<const int dim>
00186 inline std::ostream& operator<<(std::ostream& os, const AxisBox<dim>& a)
00187 {
00188 return os << "AxisBox: m_low = " << a.m_low << ", m_high = " << a.m_high;
00189 }
00190
00191 template<const int dim>
00192 inline std::istream& operator>>(std::istream& is, AxisBox<dim>& a)
00193 {
00194 char next;
00195
00196 do {
00197 is >> next;
00198 } while(next != '=');
00199
00200 is >> a.m_low;
00201
00202 do {
00203 is >> next;
00204 } while(next != '=');
00205
00206 is >> a.m_high;
00207
00208 return is;
00209 }
00210
00211 template<const int dim>
00212 inline std::ostream& operator<<(std::ostream& os, const Ball<dim>& b)
00213 {
00214 return os << "Ball: m_center = " << b.m_center <<
00215 + ", m_radius = " << b.m_radius;
00216 }
00217
00218 template<const int dim>
00219 inline std::istream& operator>>(std::istream& is, Ball<dim>& b)
00220 {
00221 char next;
00222
00223 do {
00224 is >> next;
00225 } while(next != '=');
00226
00227 is >> b.m_center;
00228
00229 do {
00230 is >> next;
00231 } while(next != '=');
00232
00233 is >> b.m_radius;
00234
00235 return is;
00236 }
00237
00238 template<const int dim>
00239 inline std::ostream& operator<<(std::ostream& os, const Segment<dim>& s)
00240 {
00241 return os << "Segment: m_p1 = " << s.m_p1 << ", m_p2 = " << s.m_p2;
00242 }
00243
00244 template<const int dim>
00245 inline std::istream& operator>>(std::istream& is, Segment<dim>& s)
00246 {
00247 char next;
00248
00249 do {
00250 is >> next;
00251 } while(next != '=');
00252
00253 is >> s.m_p1;
00254
00255 do {
00256 is >> next;
00257 } while(next != '=');
00258
00259 is >> s.m_p2;
00260
00261 return is;
00262 }
00263
00264 template<const int dim>
00265 inline std::ostream& operator<<(std::ostream& os, const RotBox<dim>& r)
00266 {
00267 return os << "RotBox: m_corner0 = " << r.m_corner0
00268 << ", m_size = " << r.m_size
00269 << ", m_orient = " << r.m_orient;
00270 }
00271
00272 template<const int dim>
00273 inline std::istream& operator>>(std::istream& is, RotBox<dim>& r)
00274 {
00275 char next;
00276
00277 do {
00278 is >> next;
00279 } while(next != '=');
00280
00281 is >> r.m_corner0;
00282
00283 do {
00284 is >> next;
00285 } while(next != '=');
00286
00287 is >> r.m_size;
00288
00289 do {
00290 is >> next;
00291 } while(next != '=');
00292
00293 is >> r.m_orient;
00294
00295 return is;
00296 }
00297
00298 template<> std::ostream& operator<<(std::ostream& os, const Polygon<2>& r);
00299 template<> std::istream& operator>>(std::istream& is, Polygon<2>& r);
00300
00301 template<const int dim>
00302 inline std::ostream& operator<<(std::ostream& os, const Polygon<dim>& r)
00303 {
00304 int size = r.m_poly.numCorners();
00305
00306 if(size == 0) {
00307 os << "<empty>";
00308 return os;
00309 }
00310
00311 os << "Polygon: (";
00312
00313 for(int i = 0; i < size; ++i)
00314 os << r.getCorner(i) << (i < (dim - 1) ? ',' : ')');
00315
00316 return os;
00317 }
00318
00319
00320
00321 template<const int dim> struct _PolyReader
00322 {
00323 Point<dim> pd;
00324 Point<2> p2;
00325 };
00326
00327 template<const int dim>
00328 std::istream& operator>>(std::istream& is, Polygon<dim>& r)
00329 {
00330 char next;
00331 _PolyReader<dim> read;
00332 std::list<_PolyReader<dim> > read_list;
00333
00334
00335
00336 do {
00337 is >> next;
00338 if(next == '<') {
00339 do {
00340 is >> next;
00341 } while(next != '>');
00342 return is;
00343 }
00344 } while(next != '(');
00345
00346 while(true) {
00347 is >> read.pd;
00348 read_list.push_back(read);
00349 is >> next;
00350 if(next == ')')
00351 break;
00352 if(next != ',')
00353 throw ParseError();
00354 }
00355
00356
00357
00358
00359
00360
00361 typename std::list<_PolyReader<dim> >::iterator i, end = read_list.end();
00362 bool succ;
00363
00364 int str_prec = is.precision();
00365 double str_eps = 1;
00366 while(--str_prec > 0)
00367 str_eps /= 10;
00368 double epsilon = FloatMax(str_eps, WFMATH_EPSILON);
00369
00370 r.m_orient = _Poly2Orient<dim>();
00371
00372 if(read_list.size() < 3) {
00373 for(i = read_list.begin(); i != end; ++i) {
00374 succ = r.m_orient.expand(i->pd, i->p2, epsilon);
00375 assert(succ);
00376 }
00377 }
00378 else {
00379 typename std::list<_PolyReader<dim> >::iterator p1 = end, p2 = end, p3 = end, j;
00380 CoordType dist = -1;
00381
00382 for(i = read_list.begin(); i != end; ++i) {
00383 for(j = i, ++j; j != end; ++j) {
00384 CoordType new_dist = SloppyDistance(i->pd, j->pd);
00385 if(new_dist > dist) {
00386 p1 = i;
00387 p2 = j;
00388 dist = new_dist;
00389 }
00390 }
00391 }
00392
00393 assert(p1 != end);
00394 assert(p2 != end);
00395
00396 dist = -1;
00397
00398 for(i = read_list.begin(); i != end; ++i) {
00399
00400 if(i == p1 || i == p2)
00401 continue;
00402 CoordType new_dist = FloatMin(SloppyDistance(i->pd, p1->pd),
00403 SloppyDistance(i->pd, p2->pd));
00404 if(new_dist > dist) {
00405 p3 = i;
00406 dist = new_dist;
00407 }
00408 }
00409
00410 assert(p3 != end);
00411
00412
00413
00414 succ = r.m_orient.expand(p1->pd, p1->p2, epsilon);
00415 assert(succ);
00416 succ = r.m_orient.expand(p2->pd, p2->p2, epsilon);
00417 assert(succ);
00418 succ = r.m_orient.expand(p3->pd, p3->p2, epsilon);
00419 assert(succ);
00420
00421
00422
00423 for(i = read_list.begin(); i != end; ++i) {
00424 if(i == p1 || i == p2 || i == p3)
00425 continue;
00426 succ = r.m_orient.expand(i->pd, i->p2, epsilon);
00427 if(!succ) {
00428 r.clear();
00429 throw ParseError();
00430 }
00431 }
00432 }
00433
00434
00435
00436 r.m_poly.resize(read_list.size());
00437
00438 int pnum;
00439 for(i = read_list.begin(), pnum = 0; i != end; ++i, ++pnum)
00440 r.m_poly[pnum] = i->p2;
00441
00442 return is;
00443 }
00444
00445 }
00446
00447 #endif // WFMATH_STREAM_H