You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
6.0 KiB
Plaintext
332 lines
6.0 KiB
Plaintext
|
1 month ago
|
/**********************************************************************
|
||
|
|
*
|
||
|
|
* GEOS - Geometry Engine Open Source
|
||
|
|
* http://geos.osgeo.org
|
||
|
|
*
|
||
|
|
* Copyright (C) 2005-2006 Refractions Research Inc.
|
||
|
|
*
|
||
|
|
* This is free software; you can redistribute and/or modify it under
|
||
|
|
* the terms of the GNU Lesser General Public Licence as published
|
||
|
|
* by the Free Software Foundation.
|
||
|
|
* See the COPYING file for more information.
|
||
|
|
*
|
||
|
|
**********************************************************************
|
||
|
|
*
|
||
|
|
* Last port: geom/Envelope.java rev 1.46 (JTS-1.10)
|
||
|
|
*
|
||
|
|
**********************************************************************/
|
||
|
|
|
||
|
|
#ifndef GEOS_GEOM_ENVELOPE_INL
|
||
|
|
#define GEOS_GEOM_ENVELOPE_INL
|
||
|
|
|
||
|
|
#include <algorithm> // std::min, std::max
|
||
|
|
#include <cassert>
|
||
|
|
#include <numeric> // std::signbit
|
||
|
|
#include <geos/geom/Coordinate.h>
|
||
|
|
#include <geos/geom/Envelope.h>
|
||
|
|
|
||
|
|
#if GEOS_DEBUG
|
||
|
|
# include <iostream>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
namespace geos {
|
||
|
|
namespace geom { // geos::geom
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE
|
||
|
|
Envelope::Envelope()
|
||
|
|
{
|
||
|
|
init();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE
|
||
|
|
Envelope::Envelope(double x1, double x2, double y1, double y2)
|
||
|
|
{
|
||
|
|
init(x1, x2, y1, y2);
|
||
|
|
}
|
||
|
|
/*public*/
|
||
|
|
INLINE
|
||
|
|
Envelope::Envelope(const Coordinate& p1, const Coordinate& p2)
|
||
|
|
{
|
||
|
|
init(p1, p2);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE
|
||
|
|
Envelope::Envelope(const Coordinate& p)
|
||
|
|
{
|
||
|
|
init(p);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE
|
||
|
|
Envelope::Envelope(const Envelope& env)
|
||
|
|
:
|
||
|
|
minx(env.minx),
|
||
|
|
maxx(env.maxx),
|
||
|
|
miny(env.miny),
|
||
|
|
maxy(env.maxy)
|
||
|
|
{
|
||
|
|
#if GEOS_DEBUG
|
||
|
|
std::cerr << "Envelope copy" << std::endl;
|
||
|
|
#endif
|
||
|
|
//init(env.minx, env.maxx, env.miny, env.maxy);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE double
|
||
|
|
Envelope::distance(double x0, double y0, double x1, double y1)
|
||
|
|
{
|
||
|
|
double dx = x1 - x0;
|
||
|
|
double dy = y1 - y0;
|
||
|
|
return std::sqrt(dx * dx + dy * dy);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE void
|
||
|
|
Envelope::expandToInclude(const Coordinate& p)
|
||
|
|
{
|
||
|
|
expandToInclude(p.x, p.y);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE void
|
||
|
|
Envelope::expandToInclude(double x, double y)
|
||
|
|
{
|
||
|
|
if(isNull()) {
|
||
|
|
minx = x;
|
||
|
|
maxx = x;
|
||
|
|
miny = y;
|
||
|
|
maxy = y;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if(x < minx) {
|
||
|
|
minx = x;
|
||
|
|
}
|
||
|
|
if(x > maxx) {
|
||
|
|
maxx = x;
|
||
|
|
}
|
||
|
|
if(y < miny) {
|
||
|
|
miny = y;
|
||
|
|
}
|
||
|
|
if(y > maxy) {
|
||
|
|
maxy = y;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE double
|
||
|
|
Envelope::getMaxY() const
|
||
|
|
{
|
||
|
|
return maxy;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE double
|
||
|
|
Envelope::getMaxX() const
|
||
|
|
{
|
||
|
|
return maxx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE double
|
||
|
|
Envelope::getMinY() const
|
||
|
|
{
|
||
|
|
return miny;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE double
|
||
|
|
Envelope::getMinX() const
|
||
|
|
{
|
||
|
|
return minx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE double
|
||
|
|
Envelope::getWidth() const
|
||
|
|
{
|
||
|
|
if(isNull()) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
return maxx - minx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE double
|
||
|
|
Envelope::getHeight() const
|
||
|
|
{
|
||
|
|
if(isNull()) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
return maxy - miny;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE void
|
||
|
|
Envelope::init()
|
||
|
|
{
|
||
|
|
setToNull();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE void
|
||
|
|
Envelope::init(double x1, double x2, double y1, double y2)
|
||
|
|
{
|
||
|
|
if(x1 < x2) {
|
||
|
|
minx = x1;
|
||
|
|
maxx = x2;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
minx = x2;
|
||
|
|
maxx = x1;
|
||
|
|
}
|
||
|
|
if(y1 < y2) {
|
||
|
|
miny = y1;
|
||
|
|
maxy = y2;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
miny = y2;
|
||
|
|
maxy = y1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE void
|
||
|
|
Envelope::init(const Coordinate& p1, const Coordinate& p2)
|
||
|
|
{
|
||
|
|
init(p1.x, p2.x, p1.y, p2.y);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE void
|
||
|
|
Envelope::init(const Coordinate& p)
|
||
|
|
{
|
||
|
|
init(p.x, p.x, p.y, p.y);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::intersects(const Coordinate& other) const
|
||
|
|
{
|
||
|
|
return (other.x <= maxx && other.x >= minx &&
|
||
|
|
other.y <= maxy && other.y >= miny);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::intersects(const Envelope& other) const
|
||
|
|
{
|
||
|
|
return intersects(&other);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::isNull(void) const
|
||
|
|
{
|
||
|
|
return maxx < minx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::intersects(const Envelope* other) const
|
||
|
|
{
|
||
|
|
// Optimized to reduce function calls
|
||
|
|
if(isNull() || other->isNull()) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return !(other->minx > maxx ||
|
||
|
|
other->maxx < minx ||
|
||
|
|
other->miny > maxy ||
|
||
|
|
other->maxy < miny);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::intersects(double x, double y) const
|
||
|
|
{
|
||
|
|
return (x <= maxx && x >= minx && y <= maxy && y >= miny);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::disjoint(const Envelope& other) const
|
||
|
|
{
|
||
|
|
return disjoint(&other);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::disjoint(const Envelope* other) const
|
||
|
|
{
|
||
|
|
if (isNull() || other->isNull()) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return other->minx > maxx ||
|
||
|
|
other->maxx < minx ||
|
||
|
|
other->miny > maxy ||
|
||
|
|
other->maxy < miny;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE bool
|
||
|
|
Envelope::covers(const Coordinate* p) const
|
||
|
|
{
|
||
|
|
return covers(p->x, p->y);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*public*/
|
||
|
|
INLINE void
|
||
|
|
Envelope::setToNull()
|
||
|
|
{
|
||
|
|
minx = 0;
|
||
|
|
maxx = -1;
|
||
|
|
miny = 0;
|
||
|
|
maxy = -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
INLINE double
|
||
|
|
Envelope::distanceSquared(const Envelope& env) const {
|
||
|
|
double dx = std::max(0.0,
|
||
|
|
std::max(maxx, env.maxx) - std::min(minx, env.minx) - (maxx - minx) -
|
||
|
|
(env.maxx - env.minx));
|
||
|
|
double dy = std::max(0.0,
|
||
|
|
std::max(maxy, env.maxy) - std::min(miny, env.miny) - (maxy - miny) -
|
||
|
|
(env.maxy - env.miny));
|
||
|
|
|
||
|
|
return dx * dx + dy * dy;
|
||
|
|
}
|
||
|
|
|
||
|
|
INLINE double
|
||
|
|
Envelope::distance(const Envelope& env) const {
|
||
|
|
return std::sqrt(distanceSquared(env));
|
||
|
|
}
|
||
|
|
|
||
|
|
INLINE double
|
||
|
|
Envelope::distanceToCoordinate(const Coordinate & c, const Coordinate & p0, const Coordinate & p1) {
|
||
|
|
return std::sqrt(distanceSquaredToCoordinate(c, p0, p1));
|
||
|
|
}
|
||
|
|
|
||
|
|
INLINE double
|
||
|
|
Envelope::distanceSquaredToCoordinate(const Coordinate & c, const Coordinate & p0, const Coordinate & p1) {
|
||
|
|
double xa = c.x - p0.x;
|
||
|
|
double xb = c.x - p1.x;
|
||
|
|
double ya = c.y - p0.y;
|
||
|
|
double yb = c.y - p1.y;
|
||
|
|
|
||
|
|
// If sign of a and b are not the same, then Envelope spans c and distance is zero.
|
||
|
|
double dx = (std::signbit(xa) == std::signbit(xb)) * std::min(std::abs(xa), std::abs(xb));
|
||
|
|
double dy = (std::signbit(ya) == std::signbit(yb)) * std::min(std::abs(ya), std::abs(yb));
|
||
|
|
|
||
|
|
return dx*dx + dy*dy;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace geos::geom
|
||
|
|
} // namespace geos
|
||
|
|
|
||
|
|
#endif // GEOS_GEOM_ENVELOPE_INL
|
||
|
|
|