GEOS  3.14.0dev
Envelope.h
1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2006 Refractions Research Inc.
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU Lesser General Public Licence as published
10  * by the Free Software Foundation.
11  * See the COPYING file for more information.
12  *
13  **********************************************************************
14  *
15  * Last port: geom/Envelope.java rev 1.46 (JTS-1.10)
16  *
17  **********************************************************************/
18 
19 #pragma once
20 
21 
22 #include <geos/export.h>
23 #include <geos/geom/Coordinate.h>
24 
25 #include <string>
26 #include <vector>
27 #include <ostream> // for operator<<
28 #include <memory>
29 #include <cassert>
30 #include <algorithm>
31 
32 namespace geos {
33 namespace geom { // geos::geom
34 
35 class Envelope;
36 
38 GEOS_DLL std::ostream& operator<< (std::ostream& os, const Envelope& o);
39 
40 class Coordinate;
41 
59 class GEOS_DLL Envelope {
60 
61 public:
62 
63  friend std::ostream& operator<< (std::ostream& os, const Envelope& o);
64 
65  typedef std::unique_ptr<Envelope> Ptr;
66 
71  : minx(DoubleNotANumber)
72  , maxx(DoubleNotANumber)
73  , miny(DoubleNotANumber)
74  , maxy(DoubleNotANumber)
75  {};
76 
85  Envelope(double x1, double x2, double y1, double y2)
86  {
87  init(x1, x2, y1, y2);
88  }
89 
96  Envelope(const CoordinateXY& p1, const CoordinateXY& p2)
97  {
98  init(p1, p2);
99  }
100 
106  explicit Envelope(const CoordinateXY& p)
107  : minx(p.x)
108  , maxx(p.x)
109  , miny(p.y)
110  , maxy(p.y)
111  {
112  }
113 
118  explicit Envelope(const std::string& str);
119 
129  static bool intersects(const CoordinateXY& p1, const CoordinateXY& p2,
130  const CoordinateXY& q);
131 
143  static bool intersects(
144  const CoordinateXY& p1, const CoordinateXY& p2,
145  const CoordinateXY& q1, const CoordinateXY& q2)
146  {
147  double minq = std::min(q1.x, q2.x);
148  double maxq = std::max(q1.x, q2.x);
149  double minp = std::min(p1.x, p2.x);
150  double maxp = std::max(p1.x, p2.x);
151  if(minp > maxq) {
152  return false;
153  }
154  if(maxp < minq) {
155  return false;
156  }
157  minq = std::min(q1.y, q2.y);
158  maxq = std::max(q1.y, q2.y);
159  minp = std::min(p1.y, p2.y);
160  maxp = std::max(p1.y, p2.y);
161  if(minp > maxq) {
162  return false;
163  }
164  if(maxp < minq) {
165  return false;
166  }
167  return true;
168  }
169 
178  bool intersects(const CoordinateXY& a, const CoordinateXY& b) const;
179 
183  void init()
184  {
185  setToNull();
186  };
187 
196  void init(double x1, double x2, double y1, double y2)
197  {
198  if(x1 < x2) {
199  minx = x1;
200  maxx = x2;
201  }
202  else {
203  minx = x2;
204  maxx = x1;
205  }
206  if(y1 < y2) {
207  miny = y1;
208  maxy = y2;
209  }
210  else {
211  miny = y2;
212  maxy = y1;
213  }
214  };
215 
222  void init(const CoordinateXY& p1, const CoordinateXY& p2)
223  {
224  init(p1.x, p2.x, p1.y, p2.y);
225  };
226 
232  void init(const CoordinateXY& p)
233  {
234  init(p.x, p.x, p.y, p.y);
235  };
236 
241  void setToNull()
242  {
243  minx = maxx = miny = maxy = DoubleNotANumber;
244  };
245 
252  bool isNull(void) const
253  {
254  return std::isnan(maxx);
255  };
256 
262  double getWidth() const
263  {
264  if(isNull()) {
265  return 0;
266  }
267  return maxx - minx;
268  }
269 
275  double getHeight() const
276  {
277  if(isNull()) {
278  return 0;
279  }
280  return maxy - miny;
281  }
282 
289  double
290  getArea() const
291  {
292  return getWidth() * getHeight();
293  }
294 
298  bool
299  isFinite() const
300  {
301  return std::isfinite(getArea());
302  }
303 
308  double getMaxY() const
309  {
310  assert(!isNull());
311  return maxy;
312  };
313 
318  double getMaxX() const
319  {
320  assert(!isNull());
321  return maxx;
322  };
323 
328  double getMinY() const
329  {
330  assert(!isNull());
331  return miny;
332  };
333 
338  double getMinX() const
339  {
340  assert(!isNull());
341  return minx;
342  };
343 
349  double getDiameter() const
350  {
351  if (isNull()) {
352  return 0.0;
353  }
354  double w = getWidth();
355  double h = getHeight();
356  return std::sqrt(w*w + h*h);
357  }
358 
366  bool centre(CoordinateXY& centre) const;
367 
377  bool intersection(const Envelope& env, Envelope& result) const;
378 
385  void translate(double transX, double transY);
386 
394  void expandBy(double deltaX, double deltaY);
395 
403  void
404  expandBy(double p_distance)
405  {
406  expandBy(p_distance, p_distance);
407  };
408 
415  void expandToInclude(const CoordinateXY& p)
416  {
417  expandToInclude(p.x, p.y);
418  };
419 
430  void expandToInclude(double x, double y)
431  {
432  if(isNull()) {
433  minx = x;
434  maxx = x;
435  miny = y;
436  maxy = y;
437  }
438  else {
439  if(x < minx) {
440  minx = x;
441  }
442  if(x > maxx) {
443  maxx = x;
444  }
445  if(y < miny) {
446  miny = y;
447  }
448  if(y > maxy) {
449  maxy = y;
450  }
451  }
452  };
453 
461  void expandToInclude(const Envelope* other)
462  {
463  if(isNull()) {
464  minx = other->minx;
465  maxx = other->maxx;
466  miny = other->miny;
467  maxy = other->maxy;
468  }
469  else {
470  if(std::isless(other->minx, minx)) {
471  minx = other->minx;
472  }
473  if(std::isgreater(other->maxx, maxx)) {
474  maxx = other->maxx;
475  }
476  if(std::isless(other->miny, miny)) {
477  miny = other->miny;
478  }
479  if(std::isgreater(other->maxy, maxy)) {
480  maxy = other->maxy;
481  }
482  }
483  };
484 
485  void expandToInclude(const Envelope& other)
486  {
487  return expandToInclude(&other);
488  };
489 
502  bool
503  contains(const Envelope& other) const
504  {
505  return covers(other);
506  }
507 
508  bool
509  contains(const Envelope* other) const
510  {
511  return contains(*other);
512  }
513 
521  bool
522  contains(const CoordinateXY& p) const
523  {
524  return covers(p.x, p.y);
525  }
526 
537  bool
538  contains(double x, double y) const
539  {
540  return covers(x, y);
541  }
542 
549  bool intersects(const CoordinateXY& other) const
550  {
551  return (std::islessequal(other.x, maxx) && std::isgreaterequal(other.x, minx) &&
552  std::islessequal(other.y, maxy) && std::isgreaterequal(other.y, miny));
553  }
554 
562  bool intersects(double x, double y) const
563  {
564  return std::islessequal(x, maxx) &&
565  std::isgreaterequal(x, minx) &&
566  std::islessequal(y, maxy) &&
567  std::isgreaterequal(y, miny);
568  }
569 
576  bool intersects(const Envelope* other) const
577  {
578  return std::islessequal(other->minx, maxx) &&
579  std::isgreaterequal(other->maxx, minx) &&
580  std::islessequal(other->miny, maxy) &&
581  std::isgreaterequal(other->maxy, miny);
582  }
583 
584  bool intersects(const Envelope& other) const
585  {
586  return intersects(&other);
587  }
588 
596  bool disjoint(const Envelope& other) const
597  {
598  return !intersects(other);
599  }
600 
601  bool disjoint(const Envelope* other) const
602  {
603  return !intersects(other);
604  }
605 
613  bool covers(double x, double y) const {
614  return std::isgreaterequal(x, minx) &&
615  std::islessequal(x, maxx) &&
616  std::isgreaterequal(y, miny) &&
617  std::islessequal(y, maxy);
618  }
619 
626  bool covers(const CoordinateXY* p) const
627  {
628  return covers(p->x, p->y);
629  }
630 
637  bool covers(const Envelope& other) const;
638 
639  bool
640  covers(const Envelope* other) const
641  {
642  return covers(*other);
643  }
644 
645 
652  bool equals(const Envelope* other) const;
653 
659  bool isfinite() const;
660 
666  std::string toString() const;
667 
674  double distance(const Envelope& env) const
675  {
676  return std::sqrt(distanceSquared(env));
677  }
678 
682  double maxDistance(const Envelope& other) const
683  {
684  Coordinate p(std::min(minx, other.minx), std::min(miny, other.miny));
685  Coordinate q(std::max(maxx, other.maxx), std::max(maxy, other.maxy));
686  return p.distance(q);
687  }
688 
695  double distanceSquared(const Envelope& env) const
696  {
697  double dx = std::max(0.0,
698  std::max(maxx, env.maxx) - std::min(minx, env.minx) - (maxx - minx) -
699  (env.maxx - env.minx));
700  double dy = std::max(0.0,
701  std::max(maxy, env.maxy) - std::min(miny, env.miny) - (maxy - miny) -
702  (env.maxy - env.miny));
703 
704  return dx * dx + dy * dy;
705  };
706 
716  static double distanceToCoordinate(
717  const CoordinateXY& c,
718  const CoordinateXY& p0,
719  const CoordinateXY& p1)
720  {
721  return std::sqrt(distanceSquaredToCoordinate(c, p0, p1));
722  };
723 
734  const CoordinateXY& c,
735  const CoordinateXY& p0,
736  const CoordinateXY& p1)
737  {
738  double xa = c.x - p0.x;
739  double xb = c.x - p1.x;
740  double ya = c.y - p0.y;
741  double yb = c.y - p1.y;
742 
743  // If sign of a and b are not the same, then Envelope spans c and distance is zero.
744  double dx = (std::signbit(xa) == std::signbit(xb)) * std::min(std::abs(xa), std::abs(xb));
745  double dy = (std::signbit(ya) == std::signbit(yb)) * std::min(std::abs(ya), std::abs(yb));
746 
747  return dx*dx + dy*dy;
748  }
749 
750  std::size_t hashCode() const
751  {
752  auto hash = std::hash<double>{};
753 
754  //Algorithm from Effective Java by Joshua Bloch [Jon Aquino]
755  std::size_t result = 17;
756  result = 37 * result + hash(minx);
757  result = 37 * result + hash(maxx);
758  result = 37 * result + hash(miny);
759  result = 37 * result + hash(maxy);
760  return result;
761  }
762 
763  struct GEOS_DLL HashCode
764  {
765  std::size_t operator()(const Envelope& e) const
766  {
767  return e.hashCode();
768  };
769  };
770 
772  // GEOS_DLL bool operator==(const Envelope& a, const Envelope& b);
773  GEOS_DLL friend bool
774  operator==(const Envelope& a, const Envelope& b)
775  {
776  return a.equals(&b);
777  }
778 
779  // GEOS_DLL bool operator!=(const Envelope& a, const Envelope& b);
780  GEOS_DLL friend bool
781  operator!=(const Envelope& a, const Envelope& b)
782  {
783  return !(a == b);
784  }
785 
788  GEOS_DLL friend bool
789  operator< (const Envelope& a, const Envelope& b);
790 
791 private:
792 
799  static std::vector<std::string> split(const std::string& str,
800  const std::string& delimiters = " ");
801 
802  static double distance(double x0, double y0, double x1, double y1)
803  {
804  double dx = x1 - x0;
805  double dy = y1 - y0;
806  return std::sqrt(dx * dx + dy * dy);
807  }
808 
810  double minx;
811 
813  double maxx;
814 
816  double miny;
817 
819  double maxy;
820 };
821 
822 
823 
824 
825 } // namespace geos::geom
826 } // namespace geos
Coordinate is the lightweight class used to store coordinates.
Definition: Coordinate.h:217
An Envelope defines a rectangulare region of the 2D coordinate plane.
Definition: Envelope.h:59
double getMinX() const
Returns the Envelope minimum x-value. Null envelopes do not have maximum values.
Definition: Envelope.h:338
void expandToInclude(const CoordinateXY &p)
Enlarges the boundary of the Envelope so that it contains p. Does nothing if p is already on or withi...
Definition: Envelope.h:415
bool contains(const CoordinateXY &p) const
Returns true if the given point lies in or on the envelope.
Definition: Envelope.h:522
bool intersection(const Envelope &env, Envelope &result) const
Computes the intersection of two Envelopes.
double distanceSquared(const Envelope &env) const
Computes the square of the distance between this and another Envelope.
Definition: Envelope.h:695
bool contains(const Envelope &other) const
Tests if the Envelope other lies wholly inside this Envelope (inclusive of the boundary).
Definition: Envelope.h:503
void expandToInclude(double x, double y)
Enlarges the boundary of the Envelope so that it contains (x,y).
Definition: Envelope.h:430
bool intersects(double x, double y) const
Check if the point (x, y) intersects (lies inside) the region of this Envelope.
Definition: Envelope.h:562
bool isfinite() const
double getDiameter() const
Definition: Envelope.h:349
bool equals(const Envelope *other) const
Returns true if the Envelope other spatially equals this Envelope.
void setToNull()
Makes this Envelope a "null" envelope, that is, the envelope of the empty geometry.
Definition: Envelope.h:241
bool covers(double x, double y) const
Tests if the given point lies in or on the envelope.
Definition: Envelope.h:613
bool centre(CoordinateXY &centre) const
Computes the coordinate of the centre of this envelope (as long as it is non-null).
double distance(const Envelope &env) const
Computes the distance between this and another Envelope.
Definition: Envelope.h:674
static double distanceToCoordinate(const CoordinateXY &c, const CoordinateXY &p0, const CoordinateXY &p1)
Computes the distance between one Coordinate and an Envelope defined by two other Coordinates....
Definition: Envelope.h:716
double getArea() const
Gets the area of this envelope.
Definition: Envelope.h:290
void init(const CoordinateXY &p1, const CoordinateXY &p2)
Initialize an Envelope to a region defined by two Coordinates.
Definition: Envelope.h:222
void expandBy(double deltaX, double deltaY)
Expands this envelope by a given distance in all directions. Both positive and negative distances are...
void init(double x1, double x2, double y1, double y2)
Initialize an Envelope for a region defined by maximum and minimum values.
Definition: Envelope.h:196
static bool intersects(const CoordinateXY &p1, const CoordinateXY &p2, const CoordinateXY &q)
Test the point q to see whether it intersects the Envelope defined by p1-p2.
bool contains(double x, double y) const
Returns true if the given point lies in or on the envelope.
Definition: Envelope.h:538
double getHeight() const
Returns the difference between the maximum and minimum y values.
Definition: Envelope.h:275
Envelope()
Creates a null Envelope.
Definition: Envelope.h:70
Envelope(const std::string &str)
Create an Envelope from an Envelope string representation produced by Envelope::toString()
bool isFinite() const
Returns true if this Envelope covers a finite region.
Definition: Envelope.h:299
double getWidth() const
Returns the difference between the maximum and minimum x values.
Definition: Envelope.h:262
double getMaxX() const
Returns the Envelope maximum x-value. Null envelopes do not have maximum values.
Definition: Envelope.h:318
bool intersects(const CoordinateXY &a, const CoordinateXY &b) const
Check if the extent defined by two extremal points intersects the extent of this Envelope.
double getMaxY() const
Returns the Envelope maximum y-value. Null envelopes do not have maximum values.
Definition: Envelope.h:308
bool isNull(void) const
Returns true if this Envelope is a "null" envelope.
Definition: Envelope.h:252
void init(const CoordinateXY &p)
Initialize an Envelope to a region defined by a single Coordinate.
Definition: Envelope.h:232
void expandBy(double p_distance)
Expands this envelope by a given distance in all directions.
Definition: Envelope.h:404
bool covers(const CoordinateXY *p) const
Tests if the given point lies in or on the envelope.
Definition: Envelope.h:626
void expandToInclude(const Envelope *other)
Enlarges the boundary of the Envelope so that it contains other.
Definition: Envelope.h:461
static bool intersects(const CoordinateXY &p1, const CoordinateXY &p2, const CoordinateXY &q1, const CoordinateXY &q2)
Test the envelope defined by p1-p2 for intersection with the envelope defined by q1-q2.
Definition: Envelope.h:143
Envelope(const CoordinateXY &p)
Creates an Envelope for a region defined by a single Coordinate.
Definition: Envelope.h:106
bool disjoint(const Envelope &other) const
Definition: Envelope.h:596
void init()
Initialize to a null Envelope.
Definition: Envelope.h:183
friend bool operator==(const Envelope &a, const Envelope &b)
Checks if two Envelopes are equal (2D only check)
Definition: Envelope.h:774
Envelope(const CoordinateXY &p1, const CoordinateXY &p2)
Creates an Envelope for a region defined by two Coordinates.
Definition: Envelope.h:96
std::string toString() const
Returns a string of the form Env[minx:maxx,miny:maxy].
bool intersects(const Envelope *other) const
Check if the region defined by other Envelope intersects the region of this Envelope.
Definition: Envelope.h:576
bool intersects(const CoordinateXY &other) const
Check if the point p intersects (lies inside) the region of this Envelope.
Definition: Envelope.h:549
static double distanceSquaredToCoordinate(const CoordinateXY &c, const CoordinateXY &p0, const CoordinateXY &p1)
Computes the squared distance between one Coordinate and an Envelope defined by two other Coordinates...
Definition: Envelope.h:733
void translate(double transX, double transY)
Translates this envelope by given amounts in the X and Y direction.
bool covers(const Envelope &other) const
Tests if the Envelope other lies wholly inside this Envelope (inclusive of the boundary).
double getMinY() const
Returns the Envelope minimum y-value. Null envelopes do not have maximum values.
Definition: Envelope.h:328
Envelope(double x1, double x2, double y1, double y2)
Creates an Envelope for a region defined by maximum and minimum values.
Definition: Envelope.h:85
double maxDistance(const Envelope &other) const
Computes the maximum distance between points in this and another Envelope.
Definition: Envelope.h:682
bool operator<(const CoordinateXY &a, const CoordinateXY &b)
Strict weak ordering operator for Coordinate.
Definition: Coordinate.h:458
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25