atlas
Geometry.h
1 /*
2  * (C) Copyright 2013 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation
8  * nor does it submit to any jurisdiction.
9  */
10 
11 #pragma once
12 
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 
17 #include "atlas/runtime/Exception.h"
18 #include "atlas/util/Earth.h"
19 #include "atlas/util/Object.h"
20 #include "atlas/util/ObjectHandle.h"
21 #include "atlas/util/Point.h"
22 
23 namespace atlas {
24 namespace geometry {
25 
26 //------------------------------------------------------------------------------------------------------
27 
28 namespace detail {
29 
30 class GeometryBase : public util::Object {
31 public:
32  virtual ~GeometryBase() = default;
33  virtual void lonlat2xyz( const Point2&, Point3& ) const = 0;
34  virtual void xyz2lonlat( const Point3&, Point2& ) const = 0;
35  virtual double distance( const Point2& p1, const Point2& p2 ) const = 0;
36  virtual double distance( const Point3& p1, const Point3& p2 ) const = 0;
37  virtual double radius() const = 0;
38  virtual double area() const = 0;
39 
40  Point3 xyz( const Point2& lonlat ) const {
41  Point3 xyz;
42  lonlat2xyz( lonlat, xyz );
43  return xyz;
44  }
45  Point2 lonlat( const Point3& xyz ) const {
46  Point2 lonlat;
47  xyz2lonlat( xyz, lonlat );
48  return lonlat;
49  }
50 };
51 
52 //------------------------------------------------------------------------------------------------------
53 
54 template <typename SphereT>
55 class GeometrySphereT : public GeometryBase {
56 public:
57  void lonlat2xyz( const Point2& lonlat, Point3& xyz ) const override {
58  SphereT::convertSphericalToCartesian( lonlat, xyz );
59  }
60  void xyz2lonlat( const Point3& xyz, Point2& lonlat ) const override {
61  SphereT::convertCartesianToSpherical( xyz, lonlat );
62  }
63  double distance( const Point2& p1, const Point2& p2 ) const override { return SphereT::distance( p1, p2 ); }
64  double distance( const Point3& p1, const Point3& p2 ) const override { return SphereT::distance( p1, p2 ); }
65  double radius() const override { return SphereT::radius(); }
66  double area() const override { return SphereT::area(); }
67 };
68 
69 class GeometrySphere : public GeometryBase {
70  using Sphere = eckit::geometry::Sphere;
71 
72 public:
73  GeometrySphere( double radius ) : radius_( radius ) {}
74  void lonlat2xyz( const Point2& lonlat, Point3& xyz ) const override {
75  Sphere::convertSphericalToCartesian( radius_, lonlat, xyz );
76  }
77  void xyz2lonlat( const Point3& xyz, Point2& lonlat ) const override {
78  Sphere::convertCartesianToSpherical( radius_, xyz, lonlat );
79  }
80  double distance( const Point2& p1, const Point2& p2 ) const override { return Sphere::distance( radius_, p1, p2 ); }
81  double distance( const Point3& p1, const Point3& p2 ) const override { return Sphere::distance( radius_, p1, p2 ); }
82  double radius() const override { return radius_; }
83  double area() const override { return Sphere::area( radius_ ); }
84 
85 private:
86  double radius_;
87 };
88 
89 } // namespace detail
90 } // namespace geometry
91 
92 //------------------------------------------------------------------------------------------------------
93 
94 class Geometry : public util::ObjectHandle<geometry::detail::GeometryBase> {
95 public:
96  using Handle::Handle;
97 
99  Geometry( const std::string& name ) : Handle( build( name ) ) {}
100  Geometry( const char* name ) : Handle( build( name ) ) {}
101  Geometry( double radius ) : Handle( build<geometry::detail::GeometrySphere>( radius ) ) {}
102 
103  template <typename SphereT>
104  Geometry( const SphereT& ) : Handle( build<SphereT>() ) {}
105 
106  Point3 xyz( const Point2& lonlat ) const { return get()->xyz( lonlat ); }
107  Point2 lonlat( const Point3& xyz ) const { return get()->lonlat( xyz ); }
108  void xyz2lonlat( const Point3& xyz, Point2& lonlat ) const { get()->xyz2lonlat( xyz, lonlat ); }
109  void lonlat2xyz( const Point2& lonlat, Point3& xyz ) const { get()->lonlat2xyz( lonlat, xyz ); }
110  double distance( const Point2& p1, const Point2& p2 ) const { return get()->distance( p1, p2 ); }
111  double distance( const Point3& p1, const Point3& p2 ) const { return get()->distance( p1, p2 ); }
112  double radius() const { return get()->radius(); }
113  double area() const { return get()->area(); }
114 
115 protected:
116  template <typename GeometryT, typename... Args>
117  static Implementation* build( Args... args ) {
118  return new GeometryT( args... );
119  }
120 
121  static Implementation* build( const std::string& name ) {
122  // Factory without self registration
123  if ( name == "Earth" ) {
124  return build<geometry::detail::GeometrySphereT<util::Earth>>();
125  }
126  else if ( name == "UnitSphere" ) {
127  return build<geometry::detail::GeometrySphereT<eckit::geometry::UnitSphere>>();
128  }
129  else {
130  ATLAS_THROW_EXCEPTION( "name " << name << " is not a valid key for a Geometry" );
131  }
132  }
133 };
134 
135 //------------------------------------------------------------------------------------------------------
136 
137 namespace geometry {
138 using Earth = Geometry; // Sphere with util::Earth radius by default
139 class UnitSphere : public Geometry {
140 public:
141  UnitSphere() : Geometry( /*radius*/ 1. ) {}
142 };
143 
144 } // namespace geometry
145 
146 
147 // ------------------------------------------------------------------
148 // C wrapper interfaces to C++ routines
149 
150 extern "C" {
151 Geometry::Implementation* atlas__Geometry__new_name( const char* name );
152 Geometry::Implementation* atlas__Geometry__new_radius( const double radius );
153 void atlas__Geometry__delete( Geometry::Implementation* This );
154 void atlas__Geometry__xyz2lonlat( Geometry::Implementation* This, const double x, const double y, const double z,
155  double& lon, double& lat );
156 void atlas__Geometry__lonlat2xyz( Geometry::Implementation* This, const double lon, const double lat, double& x,
157  double& y, double& z );
158 double atlas__Geometry__distance_lonlat( Geometry::Implementation* This, const double lon1, const double lat1,
159  const double lon2, const double lat2 );
160 double atlas__Geometry__distance_xyz( Geometry::Implementation* This, const double x1, const double y1, const double z1,
161  const double x2, const double y2, const double z2 );
162 double atlas__Geometry__radius( Geometry::Implementation* This );
163 double atlas__Geometry__area( Geometry::Implementation* This );
164 }
165 
166 //------------------------------------------------------------------------------------------------------
167 
168 } // namespace atlas
Definition: Geometry.h:94
This file contains classes and functions working on points.
Definition: Geometry.h:30
Definition: Object.h:18
Definition: Geometry.h:139
Contains all atlas classes and methods.
Definition: atlas-grids.cc:33
Definition: ObjectHandle.h:64