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
00027
00028
00029
00030
00031
00032
00033 #ifndef _GOPOINT_H
00034 #define _GOPOINT_H
00035
00036
00037 #include "Array.h"
00038 #include "errormacros.h"
00039 #include <algorithm>
00040 #include <math.h>
00041
00042 namespace Go {
00045
00046
00047
00056 class Point
00057 {
00058 private:
00059 double* pstart_;
00060 int n_;
00061 bool owns_;
00062
00063 public:
00068 Point()
00069 : pstart_(0), n_(0), owns_(true)
00070 {}
00074 explicit Point(int dim)
00075 : pstart_(new double[dim]), n_(dim), owns_(true)
00076 {}
00079 Point(double x, double y)
00080 : pstart_(new double[2]), n_(2), owns_(true)
00081 {
00082 pstart_[0] = x;
00083 pstart_[1] = y;
00084 }
00087 Point(double x, double y, double z)
00088 : pstart_(new double[3]), n_(3), owns_(true)
00089 {
00090 pstart_[0] = x;
00091 pstart_[1] = y;
00092 pstart_[2] = z;
00093 }
00094
00097
00098
00099
00100 template <typename T, int Dim>
00101 explicit Point(const Array<T, Dim>& v)
00102 : pstart_(0), n_(Dim), owns_(true)
00103 {
00104 pstart_ = new double[n_];
00105 std::copy(v.begin(), v.end(), pstart_);
00106 }
00107
00108
00110 template <typename RandomAccessIterator>
00111 Point(RandomAccessIterator first, RandomAccessIterator last)
00112 : pstart_(0), n_(last - first), owns_(true)
00113 {
00114 pstart_ = new double[n_];
00115 std::copy(first, last, pstart_);
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00147 Point(double* begin, double* end, bool own)
00148 : pstart_(0), n_(end-begin), owns_(own)
00149 {
00150 if (owns_) {
00151 pstart_ = new double[n_];
00152 std::copy(begin, end, pstart_);
00153 } else {
00154 pstart_ = begin;
00155 }
00156 }
00157
00159 Point(const Point& v)
00160 : pstart_(0), n_(v.n_), owns_(true)
00161 {
00162 pstart_ = new double[n_];
00163 std::copy(v.pstart_, v.pstart_ + n_, pstart_);
00164 }
00165
00167 Point& operator = (const Point &v)
00168 {
00169 Point temp(v);
00170 swap(temp);
00171 return *this;
00172 }
00173
00175 ~Point()
00176 {
00177 if (owns_) delete [] pstart_;
00178 }
00179
00181 void swap(Point& other)
00182 {
00183 std::swap(pstart_, other.pstart_);
00184 std::swap(n_, other.n_);
00185 std::swap(owns_, other.owns_);
00186 }
00187
00191 void read(std::istream& is);
00192
00197 void write(std::ostream& os) const;
00198
00199
00201 const double& operator [] (int i) const { return pstart_[i]; }
00203 double& operator [] (int i) { return pstart_[i]; }
00205 const double* begin() const { return pstart_; }
00207 double* begin() { return pstart_; }
00209 const double* end() const { return pstart_ + n_; }
00211 double* end() { return pstart_ + n_; }
00213 int size() const { return n_; }
00215 int dimension() const { return n_; }
00216
00218 void resize(int d)
00219 {
00220 if (n_ < d) {
00221 Point temp(d);
00222 swap(temp);
00223 } else {
00224 n_ = d;
00225 }
00226 }
00227
00229 void setValue(double x, double y)
00230 {
00231 resize(2);
00232 pstart_[0] = x;
00233 pstart_[1] = y;
00234 }
00236 void setValue(double x, double y, double z)
00237 {
00238 resize(3);
00239 pstart_[0] = x;
00240 pstart_[1] = y;
00241 pstart_[2] = z;
00242 }
00246 void setValue(const double* array)
00247 {
00248 for (int i = 0; i < n_; ++i) {
00249 pstart_[i] = array[i];
00250 }
00251 }
00255 void setValue(double val)
00256 {
00257 for (int i = 0; i < n_; ++i) {
00258 pstart_[i] = val;
00259 }
00260 }
00261
00262 void resetValue(int idx, double val)
00263 {
00264 DEBUG_ERROR_IF(idx < 0 || idx >= n_,
00265 "Dimension mismatch.");
00266 pstart_[idx] = val;
00267 }
00268
00271 double length2() const
00272 {
00273 double l2 = 0;
00274 for (int i = 0; i < n_; ++i)
00275 l2 += pstart_[i]*pstart_[i];
00276 return l2;
00277 }
00280 double length() const
00281 {
00282 return sqrt(length2());
00283 }
00286 double lengthInf() const
00287 {
00288 double linf = 0;
00289 for (int i = 0; i < n_; ++i) {
00290 linf = std::max(linf, fabs(pstart_[i]));
00291 }
00292 return linf;
00293 }
00297 double dist2(const Point &v) const
00298 {
00299 double l2 = 0;
00300 double d;
00301 for (int i = 0; i < n_; ++i) {
00302 d = pstart_[i] - v.pstart_[i];
00303 l2 += d*d;
00304 }
00305 return l2;
00306 }
00310 double dist(const Point &v) const
00311 {
00312 return sqrt(dist2(v));
00313 }
00317 double distInf(const Point &v) const
00318 {
00319 double linf = 0;
00320 double d;
00321 for (int i = 0; i < n_; ++i) {
00322 d = pstart_[i] - v.pstart_[i];
00323 linf = std::max(linf, fabs(d));
00324 }
00325 return linf;
00326 }
00329 void normalize()
00330 {
00331 double tl = length();
00332 DEBUG_ERROR_IF(tl == 0.0, "Cannot normalize vector of zero length");
00333 (*this) /= tl;
00334 }
00335
00336 double normalize_checked()
00337 {
00338 double tl = length();
00339 if (tl<1.0e-12)
00340 return 0;
00341
00342 (*this) /= tl;
00343 return tl;
00344 }
00345
00347 Point operator + (const Point &v) const
00348 {
00349 Point res(*this);
00350 res += v;
00351 return res;
00352 }
00354 void operator +=(const Point &v)
00355 {
00356 DEBUG_ERROR_IF(n_!=v.n_,
00357 "Dimension mismatch.");
00358 for (int i = 0; i < n_; ++i)
00359 pstart_[i] += v.pstart_[i];
00360 }
00361
00363 Point operator - (const Point &v) const
00364 {
00365 Point res(*this);
00366 res -= v;
00367 return res;
00368 }
00370 void operator -=(const Point &v)
00371 {
00372 DEBUG_ERROR_IF(n_!=v.n_,
00373 "Dimension mismatch.");
00374 for (int i = 0; i < n_; ++i)
00375 pstart_[i] -= v.pstart_[i];
00376 }
00378 Point operator * (double d) const
00379 {
00380 Point res(*this);
00381 res *= d;
00382 return res;
00383 }
00385 void operator *=(double d)
00386 {
00387 for (int i = 0; i < n_; ++i)
00388 pstart_[i] *= d;
00389 }
00390
00392 Point operator / (double d) const
00393 {
00394 Point res(*this);
00395 res /= d;
00396 return res;
00397 }
00399 void operator /=(double d)
00400 {
00401 for (int i = 0; i < n_; ++i)
00402 pstart_[i] /= d;
00403 }
00404
00406 Point operator - () const
00407 {
00408 Point res(*this);
00409 for (int i = 0; i < n_; ++i)
00410 res.pstart_[i] = - pstart_[i];
00411 return res;
00412 }
00413
00416 double operator * (const Point &v) const
00417 {
00418 DEBUG_ERROR_IF(n_!=v.n_,
00419 "Dimension mismatch.");
00420 double res = 0;
00421 for (int i = 0; i < n_; ++i)
00422 res += pstart_[i]*v.pstart_[i];
00423 return res;
00424 }
00425
00428 Point operator % (const Point &v) const
00429 {
00430 DEBUG_ERROR_IF(n_ != 3 || v.n_ != 3,
00431 "Dimension mismatch.");
00432 return Point(pstart_[1]*v.pstart_[2] - pstart_[2]*v.pstart_[1],
00433 pstart_[2]*v.pstart_[0] - pstart_[0]*v.pstart_[2],
00434 pstart_[0]*v.pstart_[1] - pstart_[1]*v.pstart_[0]);
00435 }
00436
00439 Point cross(const Point &v) const
00440 {
00441 return operator%(v);
00442 }
00443
00445 void setToCrossProd(const Point &u, const Point &v)
00446 {
00447 DEBUG_ERROR_IF(u.n_!=v.n_,
00448 "Dimension mismatch.");
00449 DEBUG_ERROR_IF(u.n_!=3,
00450 "Dimension must be 3.");
00451
00452 bool have_already = owns_ && (n_ >= v.n_);
00453 if (!have_already) {
00454 Point temp(3);
00455 swap(temp);
00456 } else {
00457 n_ = 3;
00458 }
00459 pstart_[0]=u.pstart_[1]*v.pstart_[2] - u.pstart_[2]*v.pstart_[1];
00460 pstart_[1]=u.pstart_[2]*v.pstart_[0] - u.pstart_[0]*v.pstart_[2];
00461 pstart_[2]=u.pstart_[0]*v.pstart_[1] - u.pstart_[1]*v.pstart_[0];
00462 }
00463
00466 double cosAngle(const Point& v) const
00467 {
00468 double tl1 = length();
00469 double tl2 = v.length();
00470
00471 if (tl1*tl2 == 0.0)
00472 {
00473
00474 return 0.0;
00475 }
00476 double res = ((*this)*v)/(tl1*tl2);
00477 res = std::min(1.0, std::max(-1.0, res));
00478 return res;
00479 }
00480
00483 double angle(const Point& v) const
00484 {
00485 return acos(cosAngle(v));
00486 }
00487
00490 double angle_smallest(const Point& v) const
00491 {
00492 double tl1 = length();
00493 double tl2 = v.length();
00494
00495 double tcos = fabs(((*this)*v)/(tl1*tl2));
00496 tcos = std::min(1.0, tcos);
00497 return acos(tcos);
00498 }
00499
00500 };
00501
00503 inline Point operator * (double d, const Point& p)
00504 { return p*d; }
00505
00507 inline std::istream& operator>>(std::istream& is, Go::Point& v)
00508 { v.read(is); return is; }
00509
00511 inline std::ostream& operator<<(std::ostream& os, const Go::Point& v)
00512 { v.write(os); return os; }
00513
00514
00515 inline bool operator<(const Point& p1, const Point& p2)
00516 {
00517 const int dim = p1.dimension();
00518 DEBUG_ERROR_IF(p2.dimension() != dim, "Dimension Mismatch");
00519 for (int i = dim-1; i >= 0; --i) {
00520 if (p1[i] > p2[i]) return false;
00521 if (p1[i] < p2[i]) return true;
00522 }
00523 return false;
00524 }
00525
00527 }
00528
00529
00530
00531 #endif // _GOPOINT_H
00532
00533
00534
00535
00536
00537