GEOS 3.15.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
32namespace geos {
33namespace geom { // geos::geom
34
35class Envelope;
36
38GEOS_DLL std::ostream& operator<< (std::ostream& os, const Envelope& o);
39
40class Coordinate;
41
59class GEOS_DLL Envelope {
60
61public:
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
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
301 double
303 {
304 return 2*getWidth() + 2*getHeight();
305 }
306
310 bool
311 isFinite() const
312 {
313 return std::isfinite(getArea());
314 }
315
320 double getMaxY() const
321 {
322 assert(!isNull());
323 return maxy;
324 };
325
330 double getMaxX() const
331 {
332 assert(!isNull());
333 return maxx;
334 };
335
340 double getMinY() const
341 {
342 assert(!isNull());
343 return miny;
344 };
345
350 double getMinX() const
351 {
352 assert(!isNull());
353 return minx;
354 };
355
361 double getDiameter() const
362 {
363 if (isNull()) {
364 return 0.0;
365 }
366 double w = getWidth();
367 double h = getHeight();
368 return std::sqrt(w*w + h*h);
369 }
370
378 bool centre(CoordinateXY& centre) const;
379
389 bool intersection(const Envelope& env, Envelope& result) const;
390
399 Envelope intersection(const Envelope& env) const;
400
407 void translate(double transX, double transY);
408
416 void expandBy(double deltaX, double deltaY);
417
425 void
426 expandBy(double p_distance)
427 {
428 expandBy(p_distance, p_distance);
429 };
430
437 void expandToInclude(const CoordinateXY& p)
438 {
439 expandToInclude(p.x, p.y);
440 };
441
452 void expandToInclude(double x, double y)
453 {
454 if(isNull()) {
455 minx = x;
456 maxx = x;
457 miny = y;
458 maxy = y;
459 }
460 else {
461 if(x < minx) {
462 minx = x;
463 }
464 if(x > maxx) {
465 maxx = x;
466 }
467 if(y < miny) {
468 miny = y;
469 }
470 if(y > maxy) {
471 maxy = y;
472 }
473 }
474 };
475
483 void expandToInclude(const Envelope* other)
484 {
485 if(isNull()) {
486 minx = other->minx;
487 maxx = other->maxx;
488 miny = other->miny;
489 maxy = other->maxy;
490 }
491 else {
492 if(std::isless(other->minx, minx)) {
493 minx = other->minx;
494 }
495 if(std::isgreater(other->maxx, maxx)) {
496 maxx = other->maxx;
497 }
498 if(std::isless(other->miny, miny)) {
499 miny = other->miny;
500 }
501 if(std::isgreater(other->maxy, maxy)) {
502 maxy = other->maxy;
503 }
504 }
505 };
506
507 void expandToInclude(const Envelope& other)
508 {
509 return expandToInclude(&other);
510 };
511
524 bool
525 contains(const Envelope& other) const
526 {
527 return covers(other);
528 }
529
530 bool
531 contains(const Envelope* other) const
532 {
533 return contains(*other);
534 }
535
543 bool
544 contains(const CoordinateXY& p) const
545 {
546 return covers(p.x, p.y);
547 }
548
559 bool
560 contains(double x, double y) const
561 {
562 return covers(x, y);
563 }
564
571 bool
572 containsProperly(const CoordinateXY& p) const
573 {
574 return std::isless(p.x, maxx) && std::isgreater(p.x, minx) &&
575 std::isless(p.y, maxy) && std::isgreater(p.y, miny);
576 }
577
584 bool intersects(const CoordinateXY& other) const
585 {
586 return (std::islessequal(other.x, maxx) && std::isgreaterequal(other.x, minx) &&
587 std::islessequal(other.y, maxy) && std::isgreaterequal(other.y, miny));
588 }
589
597 bool intersects(double x, double y) const
598 {
599 return std::islessequal(x, maxx) &&
600 std::isgreaterequal(x, minx) &&
601 std::islessequal(y, maxy) &&
602 std::isgreaterequal(y, miny);
603 }
604
611 bool intersects(const Envelope* other) const
612 {
613 return std::islessequal(other->minx, maxx) &&
614 std::isgreaterequal(other->maxx, minx) &&
615 std::islessequal(other->miny, maxy) &&
616 std::isgreaterequal(other->maxy, miny);
617 }
618
619 bool intersects(const Envelope& other) const
620 {
621 return intersects(&other);
622 }
623
631 bool disjoint(const Envelope& other) const
632 {
633 return !intersects(other);
634 }
635
636 bool disjoint(const Envelope* other) const
637 {
638 return !intersects(other);
639 }
640
648 bool covers(double x, double y) const {
649 return std::isgreaterequal(x, minx) &&
650 std::islessequal(x, maxx) &&
651 std::isgreaterequal(y, miny) &&
652 std::islessequal(y, maxy);
653 }
654
661 bool covers(const CoordinateXY* p) const
662 {
663 return covers(p->x, p->y);
664 }
665
672 bool covers(const Envelope& other) const;
673
674 bool
675 covers(const Envelope* other) const
676 {
677 return covers(*other);
678 }
679
680
687 bool equals(const Envelope* other) const;
688
694 bool isfinite() const;
695
701 std::string toString() const;
702
709 double distance(const Envelope& env) const
710 {
711 return std::sqrt(distanceSquared(env));
712 }
713
717 double maxDistance(const Envelope& other) const
718 {
719 Coordinate p(std::min(minx, other.minx), std::min(miny, other.miny));
720 Coordinate q(std::max(maxx, other.maxx), std::max(maxy, other.maxy));
721 return p.distance(q);
722 }
723
730 double distanceSquared(const Envelope& env) const
731 {
732 double dx = std::max(0.0,
733 std::max(maxx, env.maxx) - std::min(minx, env.minx) - (maxx - minx) -
734 (env.maxx - env.minx));
735 double dy = std::max(0.0,
736 std::max(maxy, env.maxy) - std::min(miny, env.miny) - (maxy - miny) -
737 (env.maxy - env.miny));
738
739 return dx * dx + dy * dy;
740 };
741
751 static double distanceToCoordinate(
752 const CoordinateXY& c,
753 const CoordinateXY& p0,
754 const CoordinateXY& p1)
755 {
756 return std::sqrt(distanceSquaredToCoordinate(c, p0, p1));
757 };
758
769 const CoordinateXY& c,
770 const CoordinateXY& p0,
771 const CoordinateXY& p1)
772 {
773 double xa = c.x - p0.x;
774 double xb = c.x - p1.x;
775 double ya = c.y - p0.y;
776 double yb = c.y - p1.y;
777
778 // If sign of a and b are not the same, then Envelope spans c and distance is zero.
779 double dx = (std::signbit(xa) == std::signbit(xb)) * std::min(std::abs(xa), std::abs(xb));
780 double dy = (std::signbit(ya) == std::signbit(yb)) * std::min(std::abs(ya), std::abs(yb));
781
782 return dx*dx + dy*dy;
783 }
784
785 std::size_t hashCode() const
786 {
787 auto hash = std::hash<double>{};
788
789 //Algorithm from Effective Java by Joshua Bloch [Jon Aquino]
790 std::size_t result = 17;
791 result = 37 * result + hash(minx);
792 result = 37 * result + hash(maxx);
793 result = 37 * result + hash(miny);
794 result = 37 * result + hash(maxy);
795 return result;
796 }
797
798 struct GEOS_DLL HashCode
799 {
800 std::size_t operator()(const Envelope& e) const
801 {
802 return e.hashCode();
803 };
804 };
805
807 // GEOS_DLL bool operator==(const Envelope& a, const Envelope& b);
808 GEOS_DLL friend bool
809 operator==(const Envelope& a, const Envelope& b)
810 {
811 return a.equals(&b);
812 }
813
814 // GEOS_DLL bool operator!=(const Envelope& a, const Envelope& b);
815 GEOS_DLL friend bool
816 operator!=(const Envelope& a, const Envelope& b)
817 {
818 return !(a == b);
819 }
820
823 GEOS_DLL friend bool
824 operator< (const Envelope& a, const Envelope& b);
825
826private:
827
834 static std::vector<std::string> split(const std::string& str,
835 const std::string& delimiters = " ");
836
837 static double distance(double x0, double y0, double x1, double y1)
838 {
839 double dx = x1 - x0;
840 double dy = y1 - y0;
841 return std::sqrt(dx * dx + dy * dy);
842 }
843
845 double minx;
846
848 double maxx;
849
851 double miny;
852
854 double maxy;
855};
856
857
858
859
860} // namespace geos::geom
861} // 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:350
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:437
bool contains(const CoordinateXY &p) const
Returns true if the given point lies in or on the envelope.
Definition Envelope.h:544
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:730
bool contains(const Envelope &other) const
Tests if the Envelope other lies wholly inside this Envelope (inclusive of the boundary).
Definition Envelope.h:525
void expandToInclude(double x, double y)
Enlarges the boundary of the Envelope so that it contains (x,y).
Definition Envelope.h:452
bool intersects(double x, double y) const
Check if the point (x, y) intersects (lies inside) the region of this Envelope.
Definition Envelope.h:597
bool isfinite() const
double getDiameter() const
Definition Envelope.h:361
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:648
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:709
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:751
double getArea() const
Gets the area of this envelope.
Definition Envelope.h:290
double getPerimeter() const
Gets the perimeter of this envelope.
Definition Envelope.h:302
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:560
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:311
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:330
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:320
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:426
bool covers(const CoordinateXY *p) const
Tests if the given point lies in or on the envelope.
Definition Envelope.h:661
void expandToInclude(const Envelope *other)
Enlarges the boundary of the Envelope so that it contains other.
Definition Envelope.h:483
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
Envelope intersection(const Envelope &env) const
Computes the intersection of two Envelopes.
bool disjoint(const Envelope &other) const
Definition Envelope.h:631
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:809
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:611
bool intersects(const CoordinateXY &other) const
Check if the point p intersects (lies inside) the region of this Envelope.
Definition Envelope.h:584
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:768
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:340
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
bool containsProperly(const CoordinateXY &p) const
Check if the point p lies in the interior of this Envelope.
Definition Envelope.h:572
double maxDistance(const Envelope &other) const
Computes the maximum distance between points in this and another Envelope.
Definition Envelope.h:717
Basic namespace for all GEOS functionalities.
Definition geos.h:38