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