GEOS  3.13.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 
58 class GEOS_DLL Envelope {
59 
60 public:
61 
62  friend std::ostream& operator<< (std::ostream& os, const Envelope& o);
63 
64  typedef std::unique_ptr<Envelope> Ptr;
65 
70  : minx(DoubleNotANumber)
71  , maxx(DoubleNotANumber)
72  , miny(DoubleNotANumber)
73  , maxy(DoubleNotANumber)
74  {};
75 
84  Envelope(double x1, double x2, double y1, double y2)
85  {
86  init(x1, x2, y1, y2);
87  }
88 
95  Envelope(const CoordinateXY& p1, const CoordinateXY& p2)
96  {
97  init(p1, p2);
98  }
99 
105  explicit Envelope(const CoordinateXY& p)
106  : minx(p.x)
107  , maxx(p.x)
108  , miny(p.y)
109  , maxy(p.y)
110  {
111  }
112 
117  explicit Envelope(const std::string& str);
118 
128  static bool intersects(const CoordinateXY& p1, const CoordinateXY& p2,
129  const CoordinateXY& q);
130 
142  static bool intersects(
143  const CoordinateXY& p1, const CoordinateXY& p2,
144  const CoordinateXY& q1, const CoordinateXY& q2)
145  {
146  double minq = std::min(q1.x, q2.x);
147  double maxq = std::max(q1.x, q2.x);
148  double minp = std::min(p1.x, p2.x);
149  double maxp = std::max(p1.x, p2.x);
150  if(minp > maxq) {
151  return false;
152  }
153  if(maxp < minq) {
154  return false;
155  }
156  minq = std::min(q1.y, q2.y);
157  maxq = std::max(q1.y, q2.y);
158  minp = std::min(p1.y, p2.y);
159  maxp = std::max(p1.y, p2.y);
160  if(minp > maxq) {
161  return false;
162  }
163  if(maxp < minq) {
164  return false;
165  }
166  return true;
167  }
168 
177  bool intersects(const CoordinateXY& a, const CoordinateXY& b) const;
178 
182  void init()
183  {
184  setToNull();
185  };
186 
195  void init(double x1, double x2, double y1, double y2)
196  {
197  if(x1 < x2) {
198  minx = x1;
199  maxx = x2;
200  }
201  else {
202  minx = x2;
203  maxx = x1;
204  }
205  if(y1 < y2) {
206  miny = y1;
207  maxy = y2;
208  }
209  else {
210  miny = y2;
211  maxy = y1;
212  }
213  };
214 
221  void init(const CoordinateXY& p1, const CoordinateXY& p2)
222  {
223  init(p1.x, p2.x, p1.y, p2.y);
224  };
225 
231  void init(const CoordinateXY& p)
232  {
233  init(p.x, p.x, p.y, p.y);
234  };
235 
240  void setToNull()
241  {
242  minx = maxx = miny = maxy = DoubleNotANumber;
243  };
244 
251  bool isNull(void) const
252  {
253  return std::isnan(maxx);
254  };
255 
261  double getWidth() const
262  {
263  if(isNull()) {
264  return 0;
265  }
266  return maxx - minx;
267  }
268 
274  double getHeight() const
275  {
276  if(isNull()) {
277  return 0;
278  }
279  return maxy - miny;
280  }
281 
288  double
289  getArea() const
290  {
291  return getWidth() * getHeight();
292  }
293 
297  bool
298  isFinite() const
299  {
300  return std::isfinite(getArea());
301  }
302 
307  double getMaxY() const
308  {
309  assert(!isNull());
310  return maxy;
311  };
312 
317  double getMaxX() const
318  {
319  assert(!isNull());
320  return maxx;
321  };
322 
327  double getMinY() const
328  {
329  assert(!isNull());
330  return miny;
331  };
332 
337  double getMinX() const
338  {
339  assert(!isNull());
340  return minx;
341  };
342 
348  double getDiameter() const
349  {
350  if (isNull()) {
351  return 0.0;
352  }
353  double w = getWidth();
354  double h = getHeight();
355  return std::sqrt(w*w + h*h);
356  }
357 
365  bool centre(CoordinateXY& centre) const;
366 
376  bool intersection(const Envelope& env, Envelope& result) const;
377 
384  void translate(double transX, double transY);
385 
393  void expandBy(double deltaX, double deltaY);
394 
402  void
403  expandBy(double p_distance)
404  {
405  expandBy(p_distance, p_distance);
406  };
407 
414  void expandToInclude(const CoordinateXY& p)
415  {
416  expandToInclude(p.x, p.y);
417  };
418 
429  void expandToInclude(double x, double y)
430  {
431  if(isNull()) {
432  minx = x;
433  maxx = x;
434  miny = y;
435  maxy = y;
436  }
437  else {
438  if(x < minx) {
439  minx = x;
440  }
441  if(x > maxx) {
442  maxx = x;
443  }
444  if(y < miny) {
445  miny = y;
446  }
447  if(y > maxy) {
448  maxy = y;
449  }
450  }
451  };
452 
460  void expandToInclude(const Envelope* other)
461  {
462  if(isNull()) {
463  minx = other->minx;
464  maxx = other->maxx;
465  miny = other->miny;
466  maxy = other->maxy;
467  }
468  else {
469  if(std::isless(other->minx, minx)) {
470  minx = other->minx;
471  }
472  if(std::isgreater(other->maxx, maxx)) {
473  maxx = other->maxx;
474  }
475  if(std::isless(other->miny, miny)) {
476  miny = other->miny;
477  }
478  if(std::isgreater(other->maxy, maxy)) {
479  maxy = other->maxy;
480  }
481  }
482  };
483 
484  void expandToInclude(const Envelope& other)
485  {
486  return expandToInclude(&other);
487  };
488 
501  bool
502  contains(const Envelope& other) const
503  {
504  return covers(other);
505  }
506 
507  bool
508  contains(const Envelope* other) const
509  {
510  return contains(*other);
511  }
512 
520  bool
521  contains(const CoordinateXY& p) const
522  {
523  return covers(p.x, p.y);
524  }
525 
536  bool
537  contains(double x, double y) const
538  {
539  return covers(x, y);
540  }
541 
548  bool intersects(const CoordinateXY& other) const
549  {
550  return (std::islessequal(other.x, maxx) && std::isgreaterequal(other.x, minx) &&
551  std::islessequal(other.y, maxy) && std::isgreaterequal(other.y, miny));
552  }
553 
561  bool intersects(double x, double y) const
562  {
563  return std::islessequal(x, maxx) &&
564  std::isgreaterequal(x, minx) &&
565  std::islessequal(y, maxy) &&
566  std::isgreaterequal(y, miny);
567  }
568 
575  bool intersects(const Envelope* other) const
576  {
577  return std::islessequal(other->minx, maxx) &&
578  std::isgreaterequal(other->maxx, minx) &&
579  std::islessequal(other->miny, maxy) &&
580  std::isgreaterequal(other->maxy, miny);
581  }
582 
583  bool intersects(const Envelope& other) const
584  {
585  return intersects(&other);
586  }
587 
595  bool disjoint(const Envelope& other) const
596  {
597  return !intersects(other);
598  }
599 
600  bool disjoint(const Envelope* other) const
601  {
602  return !intersects(other);
603  }
604 
612  bool covers(double x, double y) const {
613  return std::isgreaterequal(x, minx) &&
614  std::islessequal(x, maxx) &&
615  std::isgreaterequal(y, miny) &&
616  std::islessequal(y, maxy);
617  }
618 
625  bool covers(const CoordinateXY* p) const
626  {
627  return covers(p->x, p->y);
628  }
629 
636  bool covers(const Envelope& other) const;
637 
638  bool
639  covers(const Envelope* other) const
640  {
641  return covers(*other);
642  }
643 
644 
651  bool equals(const Envelope* other) const;
652 
658  bool isfinite() const;
659 
665  std::string toString() const;
666 
673  double distance(const Envelope& env) const
674  {
675  return std::sqrt(distanceSquared(env));
676  }
677 
681  double maxDistance(const Envelope& other) const
682  {
683  Coordinate p(std::min(minx, other.minx), std::min(miny, other.miny));
684  Coordinate q(std::max(maxx, other.maxx), std::max(maxy, other.maxy));
685  return p.distance(q);
686  }
687 
694  double distanceSquared(const Envelope& env) const
695  {
696  double dx = std::max(0.0,
697  std::max(maxx, env.maxx) - std::min(minx, env.minx) - (maxx - minx) -
698  (env.maxx - env.minx));
699  double dy = std::max(0.0,
700  std::max(maxy, env.maxy) - std::min(miny, env.miny) - (maxy - miny) -
701  (env.maxy - env.miny));
702 
703  return dx * dx + dy * dy;
704  };
705 
715  static double distanceToCoordinate(
716  const CoordinateXY& c,
717  const CoordinateXY& p0,
718  const CoordinateXY& p1)
719  {
720  return std::sqrt(distanceSquaredToCoordinate(c, p0, p1));
721  };
722 
733  const CoordinateXY& c,
734  const CoordinateXY& p0,
735  const CoordinateXY& p1)
736  {
737  double xa = c.x - p0.x;
738  double xb = c.x - p1.x;
739  double ya = c.y - p0.y;
740  double yb = c.y - p1.y;
741 
742  // If sign of a and b are not the same, then Envelope spans c and distance is zero.
743  double dx = (std::signbit(xa) == std::signbit(xb)) * std::min(std::abs(xa), std::abs(xb));
744  double dy = (std::signbit(ya) == std::signbit(yb)) * std::min(std::abs(ya), std::abs(yb));
745 
746  return dx*dx + dy*dy;
747  }
748 
749  std::size_t hashCode() const
750  {
751  auto hash = std::hash<double>{};
752 
753  //Algorithm from Effective Java by Joshua Bloch [Jon Aquino]
754  std::size_t result = 17;
755  result = 37 * result + hash(minx);
756  result = 37 * result + hash(maxx);
757  result = 37 * result + hash(miny);
758  result = 37 * result + hash(maxy);
759  return result;
760  }
761 
762  struct GEOS_DLL HashCode
763  {
764  std::size_t operator()(const Envelope& e) const
765  {
766  return e.hashCode();
767  };
768  };
769 
771  // GEOS_DLL bool operator==(const Envelope& a, const Envelope& b);
772  GEOS_DLL friend bool
773  operator==(const Envelope& a, const Envelope& b)
774  {
775  return a.equals(&b);
776  }
777 
778  // GEOS_DLL bool operator!=(const Envelope& a, const Envelope& b);
779  GEOS_DLL friend bool
780  operator!=(const Envelope& a, const Envelope& b)
781  {
782  return !(a == b);
783  }
784 
787  GEOS_DLL friend bool
788  operator< (const Envelope& a, const Envelope& b);
789 
790 private:
791 
798  static std::vector<std::string> split(const std::string& str,
799  const std::string& delimiters = " ");
800 
801  static double distance(double x0, double y0, double x1, double y1)
802  {
803  double dx = x1 - x0;
804  double dy = y1 - y0;
805  return std::sqrt(dx * dx + dy * dy);
806  }
807 
809  double minx;
810 
812  double maxx;
813 
815  double miny;
816 
818  double maxy;
819 };
820 
821 
822 
823 
824 } // namespace geos::geom
825 } // namespace geos
Coordinate is the lightweight class used to store coordinates.
Definition: Coordinate.h:216
An Envelope defines a rectangulare region of the 2D coordinate plane.
Definition: Envelope.h:58
double getMinX() const
Returns the Envelope minimum x-value. min x > max x indicates that this is a null Envelope.
Definition: Envelope.h:337
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:414
bool contains(const CoordinateXY &p) const
Returns true if the given point lies in or on the envelope.
Definition: Envelope.h:521
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:694
bool contains(const Envelope &other) const
Tests if the Envelope other lies wholly inside this Envelope (inclusive of the boundary).
Definition: Envelope.h:502
void expandToInclude(double x, double y)
Enlarges the boundary of the Envelope so that it contains (x,y).
Definition: Envelope.h:429
bool intersects(double x, double y) const
Check if the point (x, y) intersects (lies inside) the region of this Envelope.
Definition: Envelope.h:561
bool isfinite() const
double getDiameter() const
Definition: Envelope.h:348
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:240
bool covers(double x, double y) const
Tests if the given point lies in or on the envelope.
Definition: Envelope.h:612
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:673
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:715
double getArea() const
Gets the area of this envelope.
Definition: Envelope.h:289
void init(const CoordinateXY &p1, const CoordinateXY &p2)
Initialize an Envelope to a region defined by two Coordinates.
Definition: Envelope.h:221
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:195
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:537
double getHeight() const
Returns the difference between the maximum and minimum y values.
Definition: Envelope.h:274
Envelope()
Creates a null Envelope.
Definition: Envelope.h:69
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:298
double getWidth() const
Returns the difference between the maximum and minimum x values.
Definition: Envelope.h:261
double getMaxX() const
Returns the Envelope maximum x-value. min x > max x indicates that this is a null Envelope.
Definition: Envelope.h:317
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. min y > max y indicates that this is a null Envelope.
Definition: Envelope.h:307
bool isNull(void) const
Returns true if this Envelope is a "null" envelope.
Definition: Envelope.h:251
void init(const CoordinateXY &p)
Initialize an Envelope to a region defined by a single Coordinate.
Definition: Envelope.h:231
void expandBy(double p_distance)
Expands this envelope by a given distance in all directions.
Definition: Envelope.h:403
bool covers(const CoordinateXY *p) const
Tests if the given point lies in or on the envelope.
Definition: Envelope.h:625
void expandToInclude(const Envelope *other)
Enlarges the boundary of the Envelope so that it contains other.
Definition: Envelope.h:460
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:142
Envelope(const CoordinateXY &p)
Creates an Envelope for a region defined by a single Coordinate.
Definition: Envelope.h:105
bool disjoint(const Envelope &other) const
Definition: Envelope.h:595
void init()
Initialize to a null Envelope.
Definition: Envelope.h:182
friend bool operator==(const Envelope &a, const Envelope &b)
Checks if two Envelopes are equal (2D only check)
Definition: Envelope.h:773
Envelope(const CoordinateXY &p1, const CoordinateXY &p2)
Creates an Envelope for a region defined by two Coordinates.
Definition: Envelope.h:95
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:575
bool intersects(const CoordinateXY &other) const
Check if the point p intersects (lies inside) the region of this Envelope.
Definition: Envelope.h:548
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:732
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. min y > max y indicates that this is a null Envelope.
Definition: Envelope.h:327
Envelope(double x1, double x2, double y1, double y2)
Creates an Envelope for a region defined by maximum and minimum values.
Definition: Envelope.h:84
double maxDistance(const Envelope &other) const
Computes the maximum distance between points in this and another Envelope.
Definition: Envelope.h:681
bool operator<(const CoordinateXY &a, const CoordinateXY &b)
Strict weak ordering operator for Coordinate.
Definition: Coordinate.h:453
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25