Loading...
Searching...
No Matches
GeoFrame.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31#ifndef GEOFRAME_H_
32#define GEOFRAME_H_
33
34#include "drain/StringTools.h"
35#include "drain/util/BoundingBox.h"
36#include "drain/util/Proj6.h" // for geographical projection of radar data bins
37#include "drain/util/Units.h"
38#include "Geometry.h"
39
40namespace drain
41{
42
43namespace image
44{
45
46class GeoInfo {
47
48public:
49 // TODO: CartesianODIM compatibility
50};
51
53
56class GeoFrame { // See also
57
58public:
59
61 GeoFrame();
62
64 GeoFrame(unsigned int width, unsigned int height);
65
66 virtual inline
67 ~GeoFrame(){
68 };
69
70 void reset();
71
73
76 inline
77 bool projectionIsSet() const {
78 return projGeo2Native.isSet();
79 };
80
82 inline
83 bool geometryIsSet() const {
84 return ((frame.width > 0) && (frame.height > 0));
85 };
86
88
92 inline
93 bool bboxIsSet() const {
94 return (bBoxD.getArea() > 0.0);
95 };
96
98
102 inline
103 bool isDefined() const {
104 return geometryIsSet() && projectionIsSet() && bboxIsSet();
105 };
106
108 inline
109 void setGeometry(const Frame2D<int> & frame){
110 setGeometry(frame.width, frame.height);
111 }
112
114 virtual
115 void setGeometry(unsigned int width, unsigned int height);
116
118 inline
119 const Frame2D<int> & getGeometry() const { return frame; };
120
122 inline
123 int getFrameWidth() const {return frame.width; };
124
126 inline
127 int getFrameHeight() const {return frame.height; };
128
129
130
132
138 void setBoundingBox(double lonLL, double latLL, double lonUR, double latUR);
139
141 inline
143 setBoundingBox(bbox.lowerLeft.x, bbox.lowerLeft.y, bbox.upperRight.x, bbox.upperRight.y);
144 }
145
146
148 //inline
149 void setBoundingBoxD(double lonLL, double latLL, double lonUR, double latUR);
150 // { setBoundingBoxR(DEG2RAD*lonLL, DEG2RAD*latLL, DEG2RAD*lonUR, DEG2RAD*latUR);}
151
153 inline
155 setBoundingBoxD(bboxD.lowerLeft.x, bboxD.lowerLeft.y, bboxD.upperRight.x, bboxD.upperRight.y);
156 }
157
158
160 inline
161 void setBoundingBoxR(double lonLL, double latLL, double lonUR, double latUR){
162 setBoundingBoxD(RAD2DEG*lonLL, RAD2DEG*latLL, RAD2DEG*lonUR, RAD2DEG*latUR);
163 }
164
166 inline
168 setBoundingBoxR(bboxR.lowerLeft.x, bboxR.lowerLeft.y, bboxR.upperRight.x, bboxR.upperRight.y);
169 }
170
171
173 void setBoundingBoxNat(double xLL, double yLL, double xUR, double yUR);
174
176 inline
177 /*
178 void setBoundingBoxNat(const drain::Rectangle<double> & bboxM) {
179 setBoundingBoxNat(bboxM.lowerLeft.x, bboxM.lowerLeft.y, bboxM.upperRight.x, bboxM.upperRight.y);
180 }*/
182 setBoundingBoxNat(bboxM[0], bboxM[1], bboxM[2], bboxM[3]);
183 }
184
185protected:
186
188 void updateBoundingBoxR(); //double lonLL, double latLL, double lonUR, double latUR);
189
191 // void updateBoundingBoxD(); //double lonLL, double latLL, double lonUR, double latUR);
192
194 void updateBoundingBoxNat(); // double lonLL, double latLL, double lonUR, double latUR);
195
196
198 void updateScaling();
199
200public:
201
202
203
205 inline
207
209 inline
211
213 inline
215
216 void getCenterPixel(drain::Rectangle<double> & pixelD) const;
217
219 inline
220 double getXScale() const {
221 return xScale;
222 }
223
225 inline
226 double getYScale() const {
227 return yScale;
228 }
229
230
231
233 /*
234 * \par bboxM - bounding box (xLowerLeft, yLowerLeft, xUpperRight, yUpperRight).
235 */
236 inline
238 cropWithM(bboxM.lowerLeft.x, bboxM.lowerLeft.y, bboxM.upperRight.x, bboxM.upperRight.y);
239 }
240
242 void cropWithM(double xLL, double yLL, double xUR, double yUR);
243
244
246 virtual inline
247 void deg2pix(double lon, double lat, int & i, int & j) const {
248 projGeo2Native.projectFwd(lon, lat, lon, lat); // PROJ6-CRS uses degrees
249 // ...Now (lon,lat) are metric
250 // projGeo2Native.projectFwd(lon*DEG2RAD, lat*DEG2RAD, lon, lat); // PROJ6-CRS uses degrees
251 m2pix(lon, lat, i,j);
252 }
253
255 inline
256 void deg2pix(const drain::Point2D<double> & loc, drain::Point2D<int> & pix) const {
257 deg2pix(loc.x, loc.y, pix.x, pix.y);
258 }
259
261
263 virtual inline
264 void deg2m(double lon, double lat, double &x, double &y) const {
265 projGeo2Native.projectFwd(lon, lat, x, y); // PROJ6-CRS uses degrees
266 }
267
269
271 inline
272 void deg2m(const drain::Point2D<double> & pDeg, drain::Point2D<double> & pMet) const {
273 deg2m(pDeg.x, pDeg.y, pMet.x, pMet.y);
274 }
275
277 virtual inline
278 void pix2deg(int i, int j, double & lon, double & lat) const {
279 pix2m(i,j, lon,lat); //pix2m(i,j, x,y);
280 projGeo2Native.projectInv(lon,lat, lon,lat);
281 // lon *= RAD2DEG; // PROJ6-CRS uses degrees
282 // lat *= RAD2DEG; // PROJ6-CRS uses degrees
283 }
284
286 virtual inline
287 void pix2rad(int i, int j, double & lon, double & lat) const {
288 pix2m(i,j, lon,lat);
289 projGeo2Native.projectInv(lon,lat, lon,lat);
290 // PROJ6-CRS uses degrees:
291 lon *= DEG2RAD;
292 lat *= DEG2RAD;
293 }
294
295
297 inline
298 void pix2deg(const drain::Point2D<int> & pix, drain::Point2D<double> & loc) const {
299 pix2deg(pix.x,pix.y, loc.x,loc.y);
300 }
301
303 virtual inline
304 void pix2LLdeg(int i,int j, double & lon, double & lat) const {
305 double x, y; // metric
306 pix2LLm(i,j, x,y);
307 projGeo2Native.projectInv(x,y, lon,lat);
308 // lon *= RAD2DEG; // PROJ6-CRS uses degrees
309 // lat *= RAD2DEG; // PROJ6-CRS uses degrees
310 }
311
313
315 virtual inline
316 void m2deg(double x, double y, double & lon, double & lat) const {
317 projGeo2Native.projectInv(x,y, lon,lat);
318 // lon *= RAD2DEG; // PROJ6-CRS uses degrees
319 // lat *= RAD2DEG; // PROJ6-CRS uses degrees
320 }
321
323
325 virtual inline
326 void m2deg(const drain::Point2D<double> & pMetric, drain::Point2D<double> & pDeg) const {
327 projGeo2Native.projectInv(pMetric.x, pMetric.y, pDeg.x, pDeg.y); // lon, lat);
328 //pDeg.x *= RAD2DEG; // PROJ6-CRS uses degrees
329 //pDeg.y *= RAD2DEG; // PROJ6-CRS uses degrees
330 }
331
332 /* UNTESTED
333 inline virtual
334 void LLdeg2m(const double & lon, const double & lat, double & x, double & y) const {
335 projGeo2Native.projectFwd(lon,lat, x,y);
336 }
337 */
338
339
341
348 inline virtual
349 void m2pix(double x, double y, int & i, int & j) const {
350 // i = static_cast<int>(0.5+ (x - bBoxNative.lowerLeft.x) / xScale); // xOffset
351 // j = frameHeight-1 - static_cast<int>(0.5+ (y - bBoxNative.lowerLeft.y) / yScale);
352 // j = frameHeight-1 - static_cast<int>(0.5+ (y - bBoxNative.lowerLeft.y) / yScale);
353 i = ::lround((x - bBoxNative.lowerLeft.x) / xScale); // xOffset
354 j = frame.height-1 - ::lround((y - bBoxNative.lowerLeft.y) / yScale);
355 }
356
357 inline // virtual
358 void m2pix(const drain::Point2D<double> & pMetric, drain::Point2D<int> & pImage) const {
359 // pImage.x = ::lround( (pMetric.x - bBoxNative.lowerLeft.x) / xScale); // xOffset
360 // pImage.y = frame.height-1 - ::lround((pMetric.y - bBoxNative.lowerLeft.y) / yScale);
361 m2pix(pMetric.x, pMetric.y, pImage.x, pImage.y);
362 }
363
364
366
376 virtual inline
377 void pix2m(int i, int j, double & x, double & y) const {
378 x = (static_cast<double>(i)+0.5)*xScale + bBoxNative.lowerLeft.x;
379 y = (static_cast<double>(frame.height-1 - j)+0.5)*yScale + bBoxNative.lowerLeft.y;
380 }
381
383
386 virtual inline
387 void pix2m(const drain::Point2D<int> & pImage, drain::Point2D<double> & pMetric) const {
388 pMetric.x = (static_cast<double>(pImage.x)+0.5)*xScale + bBoxNative.lowerLeft.x;
389 pMetric.y = (static_cast<double>(frame.height-1 - pImage.y)+0.5)*yScale + bBoxNative.lowerLeft.y;
390 }
391
393
401 virtual inline
402 void pix2LLm(int i, int j, double & x, double & y) const {
403 x = (static_cast<double>(i))*xScale + bBoxNative.lowerLeft.x;
404 y = (static_cast<double>(frame.height-1 - j))*yScale + bBoxNative.lowerLeft.y;
405 }
406
407
408 inline
409 void setProjection(const Projector & proj){
410 if (proj.getEPSG() > 0){
411 projGeo2Native.setProjectionDst(proj.getEPSG());
412 }
413 else {
414 projGeo2Native.setProjectionDst(proj.getProjDef()); // variant?
415 }
417 }
418
420 inline
421 void setProjection(const std::string & projDef){
424 }
425
427 inline
428 void setProjectionEPSG(int epsg){
430 //projGeo2Native.dst.setProjection(epsg);
431 //projGeo2Native.setDirectMapping(true); // was missing?
433 }
434
435
437 inline
438 const Proj6 & getProj() const {
439 return projGeo2Native;
440 };
441
442 inline
443 int getEPSG() const {
444 return projGeo2Native.getDst().getEPSG();
445 };
446
448 inline
449 const std::string & getProjStr() const {
450 return projGeo2Native.getProjStrDst();
451 };
452
454 // Consider: rename src/input projection coord system
455 inline
456 const std::string & getInputProjStr() const {
458 };
459
460
462 inline
463 //const drain::Rectangle<double> & getDataBBoxD() const { return dataBBoxD; };
465
467 inline
468 //const drain::Rectangle<double> & getDataOverlapD() const { return dataOverlapD; };
470
472
475 void updateDataExtentDeg(const drain::Rectangle<double> &inputBBoxDeg);
476
480 void updateDataExtentNat(const drain::Rectangle<double> &inputBBoxNat);
481
482
483 inline
484 bool isLongLat() const {
485 return projGeo2Native.isLongLat();
486 }
487
489
492 template <typename BB>
493 drain::Unit convert(const std::string & bboxStr, BB & bbox);
494
495 // Todo: templatize to support bb[0...3]
496 void convert(const std::vector<double> &bb, drain::Unit unit,
498
499 // Todo: templatize to support bb[0...3]
500 drain::Unit convert(const std::string & bbox,
502
503
504 //std::ostream & toOStr(std::ostream & ostr) const ;
505 virtual
506 std::ostream & toStream(std::ostream & ostr) const;
507
508
509
510protected:
511
514
516 void updateProjection();
517
518
519 // drain::image::AreaGeometry frameGeometry; would be fine, but unsigned caused conversion/cast underflows
520 Frame2D<int> frame;
521 // int frameWidth;
522 // int frameHeight;
523
526
529
532
533 // experimental
536
537 // experimental
540
541 // ... needed in mapping...
542 double xScale = 0.0;
543 double yScale = 0.0;
544
545};
546
547
549
554template <typename BB>
555drain::Unit GeoFrame::convert(const std::string & bboxStr, BB & bbox){
556
557 drain::StringTools::split(bboxStr, bbox, ',');
558
559 drain::Unit unit = drain::Units::extract<drain::Unit>(bboxStr);
560 if (unit == drain::Unit::UNDEFINED){
561 if (BBox::isMetric({bbox[0], bbox[1]}) && BBox::isMetric({bbox[2], bbox[3]})){
562 // TODO: add numeric support to guess...
563
564 };
565 unit = drain::Unit::PIXEL;
566 }
567
568 return unit;
569}
570
571
572inline
573std::ostream & operator<<(std::ostream & ostr, const GeoFrame & frame){
574 frame.GeoFrame::toStream(ostr);
575 ostr << '\n';
576 return ostr;
577}
578
579
580} // ::image
581} // ::drain
582
583#endif /*COMPOSITOR_R_H_*/
584
585// Drain
bool isMetric() const
Check if this Bounding Box has metric coordinates, instead of degrees.
Definition BoundingBox.h:94
Something that has width and height.
Definition Frame.h:53
Definition Proj6.h:61
bool isLongLat() const
Check if destination projection is longitude-latitude degrees.
Definition Proj6.h:259
const std::string & getProjStrSrc() const
Returns the projection std::string applied by the last setProjection call.
Definition Proj6.h:165
void projectFwd(double &x, double &y) const
Forward projection (in-place)
Definition Proj6.h:190
void setProjectionDst(const T &...args)
Sets destination projection.
Definition Proj6.h:131
Definition Projector.h:52
static void split(const std::string &s, T &sequence, const C &separators, const std::string &trimChars=" \t\n")
Splits and trims a given std::string to a std Sequence.
Definition StringTools.h:516
Tuple of N elements of type T.
Definition UniTuple.h:65
Array with georeferencing support.
Definition GeoFrame.h:56
drain::Unit convert(const std::string &bboxStr, BB &bbox)
Split bbox string to numeric bbox, deriving the unit from the end of the string or numeric scale.
Definition GeoFrame.h:555
drain::Rectangle< double > bBoxR
Geographical scope in Radians.
Definition GeoFrame.h:525
const std::string & getProjStr() const
Returns the projection of the composite image as a proj4 std::string.
Definition GeoFrame.h:449
void setBoundingBox(const drain::Rectangle< double > &bbox)
Sets bounding box in degrees in the target coordinate system.
Definition GeoFrame.h:142
virtual void pix2m(const drain::Point2D< int > &pImage, drain::Point2D< double > &pMetric) const
Scales image coordinates (i,j) to map coordinates (x,y) in the center of the pixel.
Definition GeoFrame.h:387
virtual void m2pix(double x, double y, int &i, int &j) const
Scales geographic map coordinates to image coordinates.
Definition GeoFrame.h:349
GeoFrame()
Default constructor.
Definition GeoFrame.cpp:49
const drain::Rectangle< double > & getDataOverlapBBoxNat() const
Return the common overlapping geographical area (intersection) implied by input data.
Definition GeoFrame.h:469
const drain::Rectangle< double > & getBoundingBoxRad() const
Returns the geographical scope in Radians.
Definition GeoFrame.h:214
void setProjectionEPSG(int epsg)
Sets the projection of the image as a EPSG code.
Definition GeoFrame.h:428
void updateScaling()
Geometric scaling.
Definition GeoFrame.cpp:320
virtual void pix2rad(int i, int j, double &lon, double &lat) const
Calculates the geographic coordinates (lon,lat) [rad] of the center of a pixel at (i,...
Definition GeoFrame.h:287
virtual void m2deg(const drain::Point2D< double > &pMetric, drain::Point2D< double > &pDeg) const
Convert metric coordinates to degrees.
Definition GeoFrame.h:326
void updateProjection()
Updates bboxes, if needed.
Definition GeoFrame.cpp:278
const Proj6 & getProj() const
Returns the projection of the composite image as a proj4 std::string.
Definition GeoFrame.h:438
void pix2deg(const drain::Point2D< int > &pix, drain::Point2D< double > &loc) const
Calculates the geographic coordinates of the center of a pixel at (i,j).
Definition GeoFrame.h:298
void updateDataExtentNat(const drain::Rectangle< double > &inputBBoxNat)
Definition GeoFrame.cpp:407
void setBoundingBoxR(double lonLL, double latLL, double lonUR, double latUR)
Sets bounding box in radians in the target coordinate system.
Definition GeoFrame.h:161
const drain::Rectangle< double > & getDataBBoxNat() const
Return the actual geographical boundingBox suggested by implied by input data.
Definition GeoFrame.h:464
void updateBoundingBoxR()
Proj 6 NEW: Given BBox in geo coords [deg], adjust geo coords [rad].
Definition GeoFrame.cpp:228
const drain::Rectangle< double > & getBoundingBoxNat() const
Returns the geographical scope in Meters.
Definition GeoFrame.h:210
bool bboxIsSet() const
Returns true, if the bounding box (geographical extent) has been set.
Definition GeoFrame.h:93
int getFrameHeight() const
Return the nominal height, not the height of the memory array which does not have to be allocated.
Definition GeoFrame.h:127
void updateDataExtentDeg(const drain::Rectangle< double > &inputBBoxDeg)
Extend to include this input.
Definition GeoFrame.cpp:393
virtual void pix2LLdeg(int i, int j, double &lon, double &lat) const
Calculates the geographic coordinates of the lower left corner of a pixel at (i,j).
Definition GeoFrame.h:304
void setGeometry(const Frame2D< int > &frame)
This does NOT allocate memory.
Definition GeoFrame.h:109
drain::Rectangle< double > dataBBoxNat
For deriving extent (~union) of input data.
Definition GeoFrame.h:535
bool geometryIsSet() const
Return true, if array area is greater than zero.
Definition GeoFrame.h:83
bool projectionIsSet() const
Returns true, if the geographical extent has been set.
Definition GeoFrame.h:77
void setBoundingBox(double lonLL, double latLL, double lonUR, double latUR)
Sets bounding box in degrees OR in metres in the target coordinate system.
Definition GeoFrame.cpp:91
virtual void pix2LLm(int i, int j, double &x, double &y) const
Scales image coordinates (i,j) to map coordinates (x,y) of the lower left corner of the pixel.
Definition GeoFrame.h:402
drain::Rectangle< double > bBoxNative
Geographical scope in meters, or degrees in case of long/lat.
Definition GeoFrame.h:531
virtual void pix2m(int i, int j, double &x, double &y) const
Scales image coordinates (i,j) to map coordinates (x,y) in the center of the pixel.
Definition GeoFrame.h:377
const Frame2D< int > & getGeometry() const
Return frame geometry - the nominal width and height.
Definition GeoFrame.h:119
virtual void deg2m(double lon, double lat, double &x, double &y) const
Convert degrees to native (often metric) coordinates.
Definition GeoFrame.h:264
void setBoundingBoxNat(const drain::UniTuple< double, 4 > &bboxM)
Sets bounding box in meters in the target coordinate system.
Definition GeoFrame.h:181
void setBoundingBoxR(const drain::Rectangle< double > &bboxR)
Sets bounding box in radians in the target coordinate system.
Definition GeoFrame.h:167
virtual void m2deg(double x, double y, double &lon, double &lat) const
Convert metric coordinates to degrees.
Definition GeoFrame.h:316
bool isDefined() const
Returns true, if the projection, array area and geographical extent bounding box has been set.
Definition GeoFrame.h:103
virtual void deg2pix(double lon, double lat, int &i, int &j) const
Projects geographic coordinates to image coordinates.
Definition GeoFrame.h:247
const std::string & getInputProjStr() const
Returns the source projection (should be radian array, lon & lat).
Definition GeoFrame.h:456
void setBoundingBoxNat(double xLL, double yLL, double xUR, double yUR)
Sets bounding box in meters in the target coordinate system.
Definition GeoFrame.cpp:152
drain::Rectangle< double > dataOverlapBBoxNat
For deriving common extent (~intersection) of input data.
Definition GeoFrame.h:539
virtual void pix2deg(int i, int j, double &lon, double &lat) const
Calculates the geographic coordinates of the center of a pixel at (i,j).
Definition GeoFrame.h:278
const drain::Rectangle< double > & getBoundingBoxDeg() const
Returns the geographical scope in Degrees.
Definition GeoFrame.h:206
void setProjection(const std::string &projDef)
Sets the projection of the image as a Proj string.
Definition GeoFrame.h:421
double getYScale() const
Return vertical resolution of a pixel in meters (if metric) or degrees (if unprojected,...
Definition GeoFrame.h:226
drain::Proj6 projGeo2Native
Radial to metric.
Definition GeoFrame.h:513
void deg2pix(const drain::Point2D< double > &loc, drain::Point2D< int > &pix) const
Project geographic coordinates (degrees) to image coordinates (pixels).
Definition GeoFrame.h:256
void setBoundingBoxD(const drain::Rectangle< double > &bboxD)
Sets bounding box in degrees in the target coordinate system.
Definition GeoFrame.h:154
void cropWithM(drain::Rectangle< double > &bboxM)
Crops the initial bounding box with a given bounding box.
Definition GeoFrame.h:237
void updateBoundingBoxNat()
Given BBox in geo coords [rad], adjust geo coords [deg].
Definition GeoFrame.cpp:236
double getXScale() const
Return horizontal resolution of a pixel in meters (if metric) or degrees (if unprojected,...
Definition GeoFrame.h:220
void deg2m(const drain::Point2D< double > &pDeg, drain::Point2D< double > &pMet) const
Convert degrees to native (often metric) coordinates.
Definition GeoFrame.h:272
void setBoundingBoxD(double lonLL, double latLL, double lonUR, double latUR)
Sets bounding box in degrees in the target coordinate system.
Definition GeoFrame.cpp:132
drain::Rectangle< double > bBoxD
Geographical scope in Degrees.
Definition GeoFrame.h:528
int getFrameWidth() const
Return the nominal width, not the width of the memory array which does not have to be allocated.
Definition GeoFrame.h:123
Definition GeoFrame.h:46
Definition Data.h:1473
Definition Point.h:48
Rectange defined through lower left and upper right coordinates.
Definition Rectangle.h:65