GLAMERDOC++
Gravitational Lensing Code Library
geometry.h
1 //
2 // geometry.h
3 // GLAMER
4 //
5 // Created by bmetcalf on 7/24/14.
6 //
7 //
8 
9 #ifndef __GLAMER__geometry__
10 #define __GLAMER__geometry__
11 
12 #include <iostream>
13 #include <array>
14 #include "standard.h"
15 #include "point.h"
16 //
17 // geometry.h
18 // GLAMER
19 //
20 // Created by bmetcalf on 7/23/14.
21 //
22 //
23 namespace Utilities {
24 
26 namespace Geometry{
27 
29 template <typename T = double>
31 
32 public:
33  SphericalPoint(T r,T theta,T phi):
34  r(r),theta(theta),phi(phi){};
35  SphericalPoint():r(0),theta(0),phi(0){};
37  TOspherical(x);
38  }
39 
40  SphericalPoint & operator=(const SphericalPoint &p){
41  if(&p != this){
42  r = p.r;
43  theta = p.theta;
44  phi = p.phi;
45  }
46  return *this;
47  }
48 
49  SphericalPoint & operator=(Point_3d<T> &x){
50  TOspherical(x);
51  return *this;
52  }
53 
54  bool operator==(const SphericalPoint &p) const{
55  if(&p == this) return true;
56  return (r==p.r)*(theta==p.theta)*(phi==p.phi);
57  }
58 
59  SphericalPoint operator*(T a){
60  SphericalPoint<T> p = *this;
61  p.r *= a;
62  return p;
63  }
64 
65  SphericalPoint & operator*=(T a){
66  r *= a;
67  return *this;
68  }
69 
72  return r * p.r * ( cos(theta)*cos(p.theta)*cos(phi-p.phi) + sin(theta)*sin(p.theta) );
73  }
74 
75  T r;
76  T theta;
77  T phi;
78 
80  void TOcartisian(T x[]) const;
82 
83  void cartisianTOspherical(T const x[]);
84  void TOspherical(Point_3d<T> &x);
85 
87  ,T x[]) const;
88  void StereographicProjection(const SphericalPoint &central,Point_2d &x) const;
90 
92  ,T x[]) const;
94  void InverseOrthographicProjection(const SphericalPoint &central,T const x[]);
95  void InverseOrthographicProjection(const SphericalPoint &central,const Point_2d &x);
97 
98 
101  double s1 = sin((theta - p.theta)/2);
102  double s2 = sin((phi - p.phi)/2);
103 
104  return 2*asin(sqrt( s1*s1 + cos(theta)*cos(p.theta)*s2*s2 ) );
105  }
106 
108  Point_3d<T> unitPhi(){return phi_hat();};
110  Point_3d<T> unitTheta(){return theta_hat();};
111 
116 
117  // returns the unit theta vector
118  Point_3d<T> theta_hat() const{
119  return Point_3d<T>(-cos(phi)*sin(theta),-sin(theta)*sin(phi),cos(theta));
120  }
121 
122  // returns the unit phi vector
123  Point_3d<T> phi_hat() const{
124  return Point_3d<T>(-sin(phi),cos(phi),0);
125  }
126 
127 };
128 
129 
178 template <typename T = double>
179 class Quaternion{
180 public:
181  Quaternion(){
182  v[0] = v[1] = v[2] = v[3] = 0;
183  }
184  Quaternion(T s,T x,T y,T z){
185  v[0] = s;
186  v[1] = x;
187  v[2] = y;
188  v[3] = z;
189  }
190  Quaternion(const Quaternion &q){
191  v[0] = q.v[0];
192  v[1] = q.v[1];
193  v[2] = q.v[2];
194  v[3] = q.v[3];
195  }
196  Quaternion(Point_3d<T> p){
197  v[0] = 0;
198  v[1] = p[0];
199  v[2] = p[1];
200  v[3] = p[2];
201  }
202  Quaternion(SphericalPoint<T> sp){
203  sp.TOcartisian(v+1);
204  v[0] = 0;
205  }
206 
207  Quaternion &operator=(const Quaternion &q){
208  v[0] = q.v[0];
209  v[1] = q.v[1];
210  v[2] = q.v[2];
211  v[3] = q.v[3];
212 
213  return *this;
214  }
215 
216  Quaternion operator*(const Quaternion &q) const{
217  return Quaternion(
218  v[0]*q.v[0] - v[1]*q.v[1] - v[2]*q.v[2] - v[3]*q.v[3],
219  v[0]*q.v[1] + v[1]*q.v[0] + v[2]*q.v[3] - v[3]*q.v[2],
220  v[0]*q.v[2] - v[1]*q.v[3] + v[2]*q.v[0] + v[3]*q.v[1],
221  v[0]*q.v[3] + v[1]*q.v[2] - v[2]*q.v[1] + v[3]*q.v[0]);
222  }
223 
225  Quaternion conj() const{
226  return Quaternion(v[0],-v[1],-v[2],-v[3]);
227  }
233  Quaternion inverse() const{
234  return this->conj()/(v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3]);
235  }
236 
238  double norm() const{
239  return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3]);
240  }
241 
243  Quaternion RotateX(T theta){
244  Quaternion R = q_x_rotation(theta);
245  return R*(*this)*R.conj();
246  }
248  Quaternion RotateY(T theta){
249  Quaternion R = q_y_rotation(theta);
250  return R*(*this)*R.conj();
251  }
253  Quaternion RotateZ(T theta){
254  Quaternion R = q_z_rotation(theta);
255  return R*(*this)*R.conj();
256  }
261  Quaternion RotateYZ(T theta,T phi){
262  Quaternion R = q_z_rotation(theta)*q_z_rotation(phi);
263  return R*(*this)*R.conj();
264  }
265 
268  Quaternion Rotate(const Quaternion &R) const{
269  return R*(*this)*R.conj();
270  }
271 
274  void RotInplace(const Quaternion &R){
275  *this = R*(*this)*R.conj();
276  }
277 
278 
280  static Point_3d<T> Rotate(const Point_3d<T> &p
281  ,const Quaternion &R){
282  Quaternion q(p);
283  q.RotInplace(R);
284  return q.to_point_3d();
285  }
286 
288 
289  static SphericalPoint<T> Rotate(const SphericalPoint<T> &p
290  ,const Quaternion &R){
291  Quaternion q(p);
292  q.RotInplace(R);
293  return q.to_SpericalPoint();
294  }
295 
296  Quaternion operator+(const Quaternion &q) const{
297  return Quaternion(v[0] + q.v[0] , v[1] + q.v[1] , v[2] + q.v[2] , v[3] + q.v[3] );
298 
299  }
300  Quaternion operator-(const Quaternion &q) const{
301  return Quaternion(v[0] - q.v[0] , v[1] - q.v[1] , v[2] - q.v[2] , v[3] - q.v[3] );
302  }
303 
305  Quaternion operator/(double s) const{
306  return Quaternion(v[0]/s,v[1]/s,v[2]/s,v[3]/s);
307  }
309  Quaternion operator*(double s) const{
310  return Quaternion(v[0]*s,v[1]*s,v[2]*s,v[3]*s);
311  }
312 
314  Point_3d<T> cross(const Quaternion &q) const{
315  return (*this*q).to_point_3d();
316  }
317 
319  T scalor(const Quaternion &q) const{
320  return v[1]*q.v[1] + v[2]*q.v[2] + v[3]*q.v[3];
321  }
322 
324  Point_3d<T> to_point_3d() const{
325  return Point_3d<T>(v[1],v[2],v[3]);
326  }
327 
329  SphericalPoint<T> to_SpericalPoint() const{
330  SphericalPoint<T> sp;
331  sp.cartisianTOspherical(v+1);
332  return sp;
333  }
334 
335 
337  T v[4];
339  T & operator[](int i){return v[i];}
340  const T &operator[](int i) const{ return v[i]; }
341 
343  static Quaternion q_x_rotation(T theta){
344  return Quaternion(cos(theta/2),sin(theta/2),0,0);
345  }
347  static Quaternion q_y_rotation(T theta){
348  return Quaternion(cos(theta/2),0,-sin(theta/2),0);
349  }
351  static Quaternion q_z_rotation(T theta){
352  return Quaternion(cos(theta/2),0,0,sin(theta/2));
353  }
354 
355 };
356 
358 bool intersect(const PosType a1[],const PosType a2[]
359  ,const PosType b1[],const PosType b2[]);
361 int intersect(const std::vector<Point_2d> &curve);
362 int intersections(const std::vector<Point_2d> &curve,std::vector<Point_2d> &intersections,std::vector<std::pair<int,int> > &segments);
363 
371 int orientation(const PosType p[],const PosType q[],const PosType r[]);
375 bool onSegment(const PosType p[], const PosType q[], const PosType r[]);
376 
378 double AngleBetween2d(double v1[],double v2[]);
379 
380 }
381 }
382 
383 namespace Utilities {
384 namespace Geometry{
385 
387 template <typename T>
389  x[0] = r*cos(theta)*cos(phi);
390  x[1] = r*cos(theta)*sin(phi);
391  x[2] = r*sin(theta);
392 }
393 
395 template <typename T>
397  return Point_3d<T>(r*cos(theta)*cos(phi)
398  ,r*cos(theta)*sin(phi),r*sin(theta) );
399 }
400 
402 template <typename T>
404  r = sqrt( x[0]*x[0] + x[1]*x[1] +x[2]*x[2]);
405  theta = asin(x[2]/r);
406  phi = atan2(x[1],x[0]);
407 }
408 
409 template <typename T>
411  r = sqrt( x[0]*x[0] + x[1]*x[1] +x[2]*x[2]);
412  theta = asin(x[2]/r);
413  phi = atan2(x[1],x[0]);
414 }
415 
416 
422 template <typename T>
424  const SphericalPoint<T> &central
425  ,T x[]
426 ) const{
427  double ct = cos(theta),st = sin(theta);
428  double cosphi = cos(phi - central.phi);
429  double so = sin(central.theta);
430  double co = cos(central.theta);
431 
432  PosType k = 2/( 1 + so*st + co*ct*cosphi );
433 
434  x[0] = k*(ct*sin(phi - central.phi));
435  x[1] = k*(co*st - so*ct*cosphi);
436 }
437 template <typename T>
439  const SphericalPoint<T> &central
440  ,Point_2d &x
441 ) const{
442  double ct = cos(theta),st = sin(theta);
443  double cosphi = cos(phi - central.phi);
444  double so = sin(central.theta);
445  double co = cos(central.theta);
446 
447  PosType k = 2/( 1 + so*st + co*ct*cosphi );
448 
449  x[0] = k*(ct*sin(phi - central.phi));
450  x[1] = k*(co*st - so*ct*cosphi);
451 }
452 
453 template <typename T>
455  const SphericalPoint<T> &central
456 ) const{
457  double ct = cos(theta),st = sin(theta);
458  double cosphi = cos(phi - central.phi);
459  double so = sin(central.theta);
460  double co = cos(central.theta);
461 
462  PosType k = 2/( 1 + so*st + co*ct*cosphi );
463 
464  return Point_2d(k*(ct*sin(phi - central.phi)),k*(co*st - so*ct*cosphi));
465 }
466 
467 
474 template <typename T>
476  const SphericalPoint<T> &central
477  ,T x[]
478 ) const{
479  double ct = cos(theta),st = sin(theta);
480  double cosphi = cos(phi - central.phi);
481  double so = sin(central.theta);
482  double co = cos(central.theta);
483 
484  x[0] = ct*sin(phi - central.phi);
485  x[1] = co*st - so*ct*cosphi;
486 
487  if(st*so + ct*co*cosphi < 0 ){ // point is on the other hemosphere
488  double s = sqrt( x[0]*x[0] + x[1]*x[0] );
489  x[0] /=s;
490  x[1] /=s;
491  }
492 }
493 
494 template <typename T>
496  const SphericalPoint<T> &central
497 ) const{
498  double c = cos(theta);
499  return Point_2d( c*sin(phi - central.phi),
500  cos(central.theta)*sin(theta) - sin(central.theta)*c*cos(phi - central.phi) );
501 }
502 
505 template <typename T>
507  const SphericalPoint<T> &central
508  ,T const x[]
509 ){
510  PosType rho = sqrt(x[0]*x[0] + x[1]*x[1]);
511  PosType c = asin(rho);
512  r=1.0;
513  theta = asin( cos(c)*sin(central.theta) + x[1]*cos(central.theta) );
514  phi = central.phi + atan2(x[0] , cos(central.theta)*cos(c)
515  - x[1]*sin(central.theta) );
516 }
517 
518 template <typename T>
520  const SphericalPoint<T> &central
521  ,const Point_2d &x
522 ){
523  PosType rho = sqrt(x[0]*x[0] + x[1]*x[1]);
524  PosType c = asin(rho);
525  r=1.0;
526  double at=cos(c)*sin(central.theta) + x[1]*cos(central.theta);
527  at = (at > 1) ? 1 : at;
528  at = (at < -1) ? -1 : at;
529  theta = asin( at );
530  phi = central.phi + atan2(x[0] , cos(central.theta)*cos(c)
531  - x[1]*sin(central.theta) );
532 }
533 
534 template <typename T>
536  const SphericalPoint<T> &central
537 ){
538  return atan2( sin(central.theta) * sin(phi - central.phi)
539  , cos(phi - central.phi) );
540 }
541 
542 template <typename T>
544  const SphericalPoint<T> &central
545 ){
546  return atan2( cos(central.theta) * cos(theta) + sin(central.theta) * sin(central.theta)
547  *cos(phi - central.phi)
548  , -sin(phi - central.phi) * sin(phi - central.phi) );
549 }
550 
552 template <typename T>
554  const Point_2d &x
555 ){
556  PosType rho = sqrt(x[0]*x[0] + x[1]*x[1]);
557  if(rho==0) return *this;
558 
559  PosType c = asin(rho);
560  T new_theta = asin( cos(c)*sin(theta) + x[1]*sin(c)*cos(theta)/rho );
561  T new_phi = phi + atan2(x[0]*sin(c),rho*cos(theta)*cos(c)
562  - x[1]*sin(theta)*sin(c) );
563 
564  return SphericalPoint<T>(1,new_theta,new_phi);
565 }
566 
568 template <typename T>
570  ,const SphericalPoint<T> &p2){
571  T x1[3],x2[3];
572 
573  p1.TOcartisian(x1);
574  p2.TOcartisian(x2);
575  return sqrt( (x1[0]-x2[0])*(x1[0]-x2[0]) + (x1[1]-x2[1])*(x1[1]-x2[1])
576  + (x1[2]-x2[2])*(x1[2]-x2[2]) );
577 }
578 
580 template <typename T>
582  ,const SphericalPoint<T> &p2){
583  if(p1 == p2) return 0;
584  double ans = sin(p1.theta)*sin(p2.theta) + cos(p1.theta)*cos(p2.theta)*cos(p1.phi-p2.phi);
585  if(fabs(ans) > 1) return 0;
586  return acos(sin(p1.theta)*sin(p2.theta) + cos(p1.theta)*cos(p2.theta)*cos(p1.phi-p2.phi));
587 }
588 
589 
591 struct CYCLIC{
592  CYCLIC(long n):n(n){}
593 
594  // returns the integer in bounds
595  long operator[](long i){
596  while(i<0) i+=n;
597  return i%n;
598  }
599 
600  long n;
601 };
602 
603 /* \brief finds the edge-wise concave hull of a complex curve
604 
605  The returned curve will consist of segments of the edges of the original curve that form a closed
606  curve that does not cross itself and will enclose all the verticies.
607  */
608 
609 std::vector<Point_2d> DeInterset(const std::vector<Point_2d> &points);
610 }
611 }
612 
613 template <typename T>
614 std::ostream &operator<<(std::ostream &os, Utilities::Geometry::SphericalPoint<T> const &p){
615  return os << "r: " << p.r << " theta: " << p.theta << " phi: " << p.phi;
616 }
617 
618 
619 #endif /* defined(__GLAMER__geometry__) */
Utilities::Geometry::SphericalPoint::OrthographicProjection
Point_2d OrthographicProjection(const SphericalPoint &central) const
Definition: geometry.h:495
Utilities::Geometry::CYCLIC
used so that an index will not go out of bounds, ie. CYCLIC[0]=0, CYCLIC[n]=0, CYCLIC[-1]=n-1,...
Definition: geometry.h:591
Point_2d
Class for representing points or vectors in 2 dimensions. Not that the dereferencing operator is over...
Definition: point.h:48
Utilities::Geometry::SphericalPoint::StereographicProjection
void StereographicProjection(const SphericalPoint &central, Point_2d &x) const
Definition: geometry.h:438
Utilities::Geometry::SphericalPoint::StereographicProjection
void StereographicProjection(const SphericalPoint &central, T x[]) const
Calculates the stereographic projection of the point onto a plane.
Definition: geometry.h:423
Utilities::Geometry::SphericalPoint::TOcartisian
void TOcartisian(T x[]) const
output Cartesian coordinates of the point
Definition: geometry.h:388
Utilities::Geometry::SphericalPoint::angular_separation
T angular_separation(SphericalPoint &p)
angle between points. This uses the haversine formula that is more stable for small angles than the m...
Definition: geometry.h:100
Utilities::Geometry::SphericalPoint::InverseOrthographicProjection
SphericalPoint< T > InverseOrthographicProjection(const Point_2d &x)
Definition: geometry.h:553
standard.h
Utilities::Geometry::SphericalPoint
represents a point in spherical coordinates, theta = 0 is equator
Definition: geometry.h:30
Utilities::Geometry::SphericalPoint::StereographicProjection
Point_2d StereographicProjection(const SphericalPoint &central) const
Definition: geometry.h:454
Utilities::Geometry::SphericalPoint::InverseOrthographicProjection
void InverseOrthographicProjection(const SphericalPoint &central, const Point_2d &x)
Definition: geometry.h:519
Utilities::Geometry::SphericalPoint::InverseOrthographicProjection
void InverseOrthographicProjection(const SphericalPoint &central, T const x[])
Convert from an orthographic projection of the plane onto the unit sphere.
Definition: geometry.h:506
Utilities::Geometry::Seporation
T Seporation(const SphericalPoint< T > &p1, const SphericalPoint< T > &p2)
3 dimensional distance between points
Definition: geometry.h:569
Utilities::Geometry::AngleSeporation
T AngleSeporation(const SphericalPoint< T > &p1, const SphericalPoint< T > &p2)
Angular seporation between points.
Definition: geometry.h:581
Utilities::Geometry::SphericalPoint::unitPhi
Point_3d< T > unitPhi()
unit vector in phi direction
Definition: geometry.h:108
Utilities::Geometry::SphericalPoint::OrthographicAnglePhi
T OrthographicAnglePhi(const SphericalPoint &central)
the angle between the orthographic x-axis and the constant Phi curve
Definition: geometry.h:543
Utilities::Geometry::SphericalPoint::unitTheta
Point_3d< T > unitTheta()
unit vector in theta direction
Definition: geometry.h:110
Utilities::Geometry::SphericalPoint::cartisianTOspherical
void cartisianTOspherical(T const x[])
set the spherical coordinates of the point from the cartisian coordinates
Definition: geometry.h:403
Utilities::Geometry::SphericalPoint::TOcartisian
Point_3d< T > TOcartisian() const
output cartisian coordinates of the point
Definition: geometry.h:396
Utilities::Geometry::SphericalPoint::OrthographicProjection
void OrthographicProjection(const SphericalPoint &central, T x[]) const
Calculates the orthographic projection of the point onto a plane.
Definition: geometry.h:475
Point_3d
Class for representing points or vectors in 3 dimensions. Not that the dereferencing operator is over...
Definition: point.h:932
Utilities::Geometry::SphericalPoint::operator*
T operator*(const SphericalPoint< T > &p)
dot product
Definition: geometry.h:71
Utilities::Geometry::SphericalPoint::OrthographicAngleTheta
T OrthographicAngleTheta(const SphericalPoint &central)
the angle between the orthographic x-axis and the constant theta curve
Definition: geometry.h:535
Utilities
Definition: utilities.h:48