207 lines
6.6 KiB
C++
207 lines
6.6 KiB
C++
/**********************************************************************
|
|
*
|
|
* GEOS - Geometry Engine Open Source
|
|
* http://geos.osgeo.org
|
|
*
|
|
* Copyright (C) 2001-2002 Vivid Solutions 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: index/chain/MonotoneChain.java rev. 1.15 (JTS-1.10)
|
|
*
|
|
**********************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include <geos/export.h>
|
|
#include <geos/geom/CoordinateSequence.h> // for inline
|
|
#include <geos/geom/Envelope.h> // for inline
|
|
#include <geos/geom/LineSegment.h> // for inline
|
|
|
|
#include <memory> // for unique_ptr
|
|
|
|
// Forward declarations
|
|
namespace geos {
|
|
namespace geom {
|
|
class LineSegment;
|
|
class CoordinateSequence;
|
|
}
|
|
namespace index {
|
|
namespace chain {
|
|
class MonotoneChainSelectAction;
|
|
class MonotoneChainOverlapAction;
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace geos {
|
|
namespace index { // geos::index
|
|
namespace chain { // geos::index::chain
|
|
|
|
/** \brief
|
|
* Monotone Chains are a way of partitioning the segments of a linestring to
|
|
* allow for fast searching of intersections.
|
|
*
|
|
* They have the following properties:
|
|
*
|
|
* - the segments within a monotone chain never intersect each other
|
|
* - the envelope of any contiguous subset of the segments in a monotone
|
|
* chain is equal to the envelope of the endpoints of the subset.
|
|
*
|
|
* Property 1 means that there is no need to test pairs of segments from
|
|
* within the same monotone chain for intersection.
|
|
* Property 2 allows an efficient binary search to be used to find the
|
|
* intersection points of two monotone chains.
|
|
*
|
|
* For many types of real-world data, these properties eliminate
|
|
* a large number of segment comparisons, producing substantial speed gains.
|
|
*
|
|
* One of the goals of this implementation of MonotoneChains is to be
|
|
* as space and time efficient as possible. One design choice that aids this
|
|
* is that a MonotoneChain is based on a subarray of a list of points.
|
|
* This means that new arrays of points (potentially very large) do not
|
|
* have to be allocated.
|
|
*
|
|
* MonotoneChains support the following kinds of queries:
|
|
*
|
|
* - Envelope select: determine all the segments in the chain which
|
|
* intersect a given envelope
|
|
* - Overlap: determine all the pairs of segments in two chains whose
|
|
* envelopes overlap
|
|
*
|
|
* This implementation of MonotoneChains uses the concept of internal iterators
|
|
* to return the resultsets for the above queries.
|
|
* This has time and space advantages, since it
|
|
* is not necessary to build lists of instantiated objects to represent the segments
|
|
* returned by the query.
|
|
* However, it does mean that the queries are not thread-safe.
|
|
*
|
|
*/
|
|
class GEOS_DLL MonotoneChain {
|
|
public:
|
|
|
|
/// @param pts
|
|
/// Ownership left to caller, this class holds a reference.
|
|
///
|
|
/// @param start
|
|
///
|
|
/// @param end
|
|
///
|
|
/// @param context
|
|
/// Ownership left to caller, this class holds a reference.
|
|
///
|
|
MonotoneChain(const geom::CoordinateSequence& pts,
|
|
std::size_t start, std::size_t end, void* context);
|
|
|
|
~MonotoneChain() = default;
|
|
|
|
/// Returned envelope is owned by this class
|
|
const geom::Envelope& getEnvelope() const;
|
|
const geom::Envelope& getEnvelope(double expansionDistance) const;
|
|
|
|
size_t
|
|
getStartIndex() const
|
|
{
|
|
return start;
|
|
}
|
|
|
|
size_t
|
|
getEndIndex() const
|
|
{
|
|
return end;
|
|
}
|
|
|
|
/** \brief
|
|
* Set given LineSegment with points of the segment starting
|
|
* at the given index.
|
|
*/
|
|
void getLineSegment(std::size_t index, geom::LineSegment& ls) const {
|
|
pts->getAt(index, ls.p0);
|
|
pts->getAt(index + 1, ls.p1);
|
|
}
|
|
|
|
/**
|
|
* Return the subsequence of coordinates forming this chain.
|
|
* Allocates a new CoordinateSequence to hold the Coordinates
|
|
*
|
|
*/
|
|
std::unique_ptr<geom::CoordinateSequence> getCoordinates() const;
|
|
|
|
/**
|
|
* Determine all the line segments in the chain whose envelopes overlap
|
|
* the searchEnvelope, and process them
|
|
*/
|
|
void select(const geom::Envelope& searchEnv,
|
|
MonotoneChainSelectAction& mcs) const;
|
|
|
|
void computeOverlaps(const MonotoneChain* mc,
|
|
MonotoneChainOverlapAction* mco) const;
|
|
|
|
void computeOverlaps(const MonotoneChain* mc, double overlapTolerance,
|
|
MonotoneChainOverlapAction* mco) const;
|
|
|
|
void*
|
|
getContext() const
|
|
{
|
|
return context;
|
|
}
|
|
|
|
private:
|
|
|
|
void computeSelect(const geom::Envelope& searchEnv,
|
|
std::size_t start0,
|
|
std::size_t end0,
|
|
MonotoneChainSelectAction& mcs) const;
|
|
|
|
void computeOverlaps(std::size_t start0, std::size_t end0, const MonotoneChain& mc,
|
|
std::size_t start1, std::size_t end1,
|
|
double overlapTolerance,
|
|
MonotoneChainOverlapAction& mco) const;
|
|
|
|
bool overlaps(std::size_t start0, std::size_t end0,
|
|
const MonotoneChain& mc, std::size_t start1, std::size_t end1,
|
|
double overlapTolerance) const {
|
|
if (overlapTolerance > 0.0) {
|
|
return overlaps(pts->getAt<geom::CoordinateXY>(start0),
|
|
pts->getAt<geom::CoordinateXY>(end0),
|
|
mc.pts->getAt<geom::CoordinateXY>(start1),
|
|
mc.pts->getAt<geom::CoordinateXY>(end1),
|
|
overlapTolerance);
|
|
}
|
|
return geom::Envelope::intersects(pts->getAt<geom::CoordinateXY>(start0),
|
|
pts->getAt<geom::CoordinateXY>(end0),
|
|
mc.pts->getAt<geom::CoordinateXY>(start1),
|
|
mc.pts->getAt<geom::CoordinateXY>(end1));
|
|
}
|
|
|
|
static bool overlaps(const geom::CoordinateXY& p1, const geom::CoordinateXY& p2,
|
|
const geom::CoordinateXY& q1, const geom::CoordinateXY& q2,
|
|
double overlapTolerance);
|
|
|
|
/// Externally owned
|
|
const geom::CoordinateSequence* pts;
|
|
|
|
/// user-defined information
|
|
void* context;
|
|
|
|
/// Index of chain start vertex into the CoordinateSequence, 0 based.
|
|
std::size_t start;
|
|
|
|
/// Index of chain end vertex into the CoordinateSequence, 0 based.
|
|
std::size_t end;
|
|
|
|
/// Owned by this class
|
|
mutable geom::Envelope env;
|
|
|
|
};
|
|
|
|
} // namespace geos::index::chain
|
|
} // namespace geos::index
|
|
} // namespace geos
|
|
|