Projector.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 #ifndef DRAIN_PROJECTOR_H_
32 #define DRAIN_PROJECTOR_H_
33 
34 #include <cstddef>
35 #include <iostream>
36 #include <set>
37 #include <stdexcept>
38 #include <string>
39 
40 #include <proj.h>
41 
42 // #include "Dictionary.h"
43 #include "EnumFlags.h"
44 // #include "Point.h"
45 
46 
47 namespace drain
48 {
49 
50 class Proj6;
51 
52 
53 // Helper class for containing a single (one-way) Proj object and its
54 class Projector {
55 
56  friend class Proj6;
57 
58  static const SprinterLayout projDefLayout; // space-separated, =, no hypens (" ","","=", "","");
59 
60 
61 public:
62 
63  static const std::string proj4version;
64 
66 
67  //typedef enum {PROJ4, PROJ6, CRS} version;
68  typedef enum {
69  ACCEPT_CRS, // Do not touch
70  REMOVE_CRS, // Delete "+type=crs" from projDef, warn if EPSG:<code> syntax used
71  FORCE_CRS // Add "+type=crs"
72  } CRS_mode;
73 
74 
76  typedef enum {
77  ORIG, // Supplied by user
78  MODIFIED, // EPSG-converted and filtered
79  // FINAL, //
80  PROJ4, // Final, formulated by projlib
81  PROJ5, // Final, formulated by projlib
82  SIMPLE // Final, simplified for backward compatibility: "+type=crs" and "+init=epsg:..." pruned.
84 
85 
86  inline // NEW 2024: proj_context_create()
87  Projector(const std::string & projDef = "", CRS_mode crs=ACCEPT_CRS) : pjContext(proj_context_create()), pj(nullptr), epsg(0){
88  if (projDef.empty()){
89  projDefs = {{ORIG,""}, {MODIFIED,""}, {PROJ4,""}, {PROJ5,""}, {SIMPLE,""}};
90  }
91  else {
92  setProjection(projDef, crs);
93  }
94  }
95 
96  inline
97  Projector(PJ_CONTEXT *pjContext, const std::string & projDef = "", CRS_mode crs=ACCEPT_CRS) : pjContext(pjContext), pj(nullptr), epsg(0){
98 
99  if (projDef.empty()){
100  // CONSIDER projeDef.empty() check in setProjection(projDef, crs); ?
101  projDefs = {{ORIG,""}, {MODIFIED,""}, {PROJ4,""}, {PROJ5,""}, {SIMPLE,""}};
102  }
103  else {
104  setProjection(projDef, crs);
105  }
106 
107  }
108 
109  // Moved to .cpp for version 6/7/8 problems (context_clone)
110  Projector(const Projector & pr);
111 
112 
113  virtual inline
114  ~Projector(){
115  proj_destroy(pj);
116  proj_context_destroy(pjContext); // NEW 2024
117  }
118 
119 
120  static
121  int extractEPSG(const std::string & projDef);
122 
123 
124  const std::string & getProjDef(PROJDEF_variant v = SIMPLE) const { // For external objects, excluding +init=epsg and +type=crs
125  return projDefs[v];
126  }
127 
128 
129 
131  void clear(){
132  projDefs = {{ORIG,""}, {MODIFIED,""}, {PROJ4,""}, {PROJ5,""}, {SIMPLE,""}};
133  pjContext = nullptr; // TODO: flag for own CTX => destroy at end
134  proj_destroy(pj);
135  pj = nullptr;
136  projDefDict.clear();
137  epsg = 0;
138  }
139 
141 
144  void setProjection(const std::string &str, CRS_mode crs=FORCE_CRS);
145 
147 
150  void setProjection(int epsg, CRS_mode crs=FORCE_CRS);
151 
152  // protect
153  void createProjection(CRS_mode crs);
154 
156  inline
157  bool isSet() const {
158  return (pj != nullptr);
159  }
160 
161  // NOTE: compliancy problems Proj.4...6...
162  inline
163  bool isLongLat() const {
164  // TODO: what if not defined.
165  return isLongLat(pj);
166  }
167 
168  inline
169  int getEPSG() const {
170  return epsg;
171  }
172 
173 
174 
176  //static
177  // int filterProjStr(const std::string & src, std::ostream & ostr, CRS_mode crs=ACCEPT_CRS);
178 
179 
180  inline
181  void info(std::ostream & ostr = std::cout, int wkt = -1){
182 
183  for (const auto & entry: projDefs){
184  ostr << entry.first << ": '" << entry.second << "'\n";
185  }
186  info(pj, ostr, wkt);
187  }
188 
189  inline
190  std::string getErrorString() const {
191  int err = proj_context_errno(pjContext);
192  return proj_errno_string(err);
193  //return "Not Impl."; //std::string(pj_strerrno(*pj_get_errno_ref()));
194  };
195 
196 // To be protected?
197 
199  void info(PJ *pj, std::ostream & ostr = std::cout, int wkt = -1);
200 
201 protected:
202 
204  PJ_CONTEXT *pjContext;
205 
207  PJ *pj;
208 
211 
213  int epsg = 0;
214 
215  mutable
216  std::map<PROJDEF_variant,std::string> projDefs;
217 
218  void storeProjDef(const std::string & str);
219 
220  static
221  void getProjDefStr(const ProjDef & dict, std::stringstream & sstr, const std::set<std::string> & excludeKeys = {"+type"});
222 
223  // static
224  // int extractEPSGold(const ProjDef & projDefDict);
225 
227 
231  // PJ * getProjection(const std::string & projStr, CRS_mode crs=ACCEPT_CRS) const;
232 
233  static
234  bool isLongLat(const PJ *prj);
235 
236 
237 };
238 
239 template <>
241 
242 DRAIN_ENUM_OSTREAM(Projector::PROJDEF_variant);
243 
244 
245 } // drain
246 
247 
248 #endif /*PROJ4_H_*/
249 
Definition: Proj6.h:66
Definition: Projector.h:54
void info(std::ostream &ostr=std::cout, int wkt=-1)
Prunes "+init=epsg:<...>" and optionally "+type=crs" codes.
Definition: Projector.h:181
bool isSet() const
Returns true, if PJ object has been set.
Definition: Projector.h:157
PJ_CONTEXT * pjContext
Metadata for PROJ (introduced in latest versions, currently not used by Drain & Rack )
Definition: Projector.h:204
PROJDEF_variant
Each projector has three (3) versions of project definition.
Definition: Projector.h:76
ProjDef projDefDict
Secondary description of state.
Definition: Projector.h:210
PJ * pj
Essential member: the pointer to a PJ object. This is the primary description of state.
Definition: Projector.h:207
void setProjection(const std::string &str, CRS_mode crs=FORCE_CRS)
Sets projection defined as Proj string.
Definition: Projector.cpp:97
void clear()
Deletes projection object and clears all the metadata.
Definition: Projector.h:131
Definition: DataSelector.cpp:1277
Wrapper for unique (static) dictionary of enum values.
Definition: EnumFlags.h:66
Definition: Sprinter.h:137