168 lines
5.5 KiB
C++
168 lines
5.5 KiB
C++
/**********************************************************************
|
|
*
|
|
* GEOS - Geometry Engine Open Source
|
|
* http://geos.osgeo.org
|
|
*
|
|
* Copyright (C) 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: noding/snapround/SnapRoundingNoder.java r320 (JTS-1.12)
|
|
*
|
|
**********************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include <geos/export.h>
|
|
|
|
#include <geos/geom/Coordinate.h>
|
|
#include <geos/geom/Envelope.h>
|
|
#include <geos/noding/snapround/HotPixelIndex.h>
|
|
#include <geos/noding/Noder.h>
|
|
|
|
|
|
// Forward declarations
|
|
namespace geos {
|
|
namespace geom {
|
|
class Envelope;
|
|
class PrecisionModel;
|
|
}
|
|
namespace noding {
|
|
class NodedSegmentString;
|
|
}
|
|
}
|
|
|
|
namespace geos {
|
|
namespace noding { // geos::noding
|
|
namespace snapround { // geos::noding::snapround
|
|
|
|
/**
|
|
* Uses Snap Rounding to compute a rounded,
|
|
* fully noded arrangement from a set of {@link noding::SegmentString}s,
|
|
* in a performant way, and avoiding unnecessary noding.
|
|
*
|
|
* Implements the Snap Rounding technique described in
|
|
* the papers by Hobby, Guibas & Marimont, and Goodrich et al.
|
|
* Snap Rounding enforces that all output vertices lie on a uniform grid,
|
|
* which is determined by the provided {@link geom::PrecisionModel}.
|
|
*
|
|
* Input vertices do not have to be rounded to the grid beforehand;
|
|
* this is done during the snap-rounding process.
|
|
* In fact, rounding cannot be done a priori,
|
|
* since rounding vertices by themselves can distort the rounded topology
|
|
* of the arrangement (i.e. by moving segments away from hot pixels
|
|
* that would otherwise intersect them, or by moving vertices
|
|
* across segments).
|
|
*
|
|
* To minimize the number of introduced nodes,
|
|
* the Snap-Rounding Noder avoids creating nodes
|
|
* at edge vertices if there is no intersection or snap at that location.
|
|
* However, if two different input edges contain identical segments,
|
|
* each of the segment vertices will be noded.
|
|
* This still provides fully-noded output.
|
|
* This is the same behaviour provided by other noders,
|
|
* such as {@link noding::MCIndexNoder} and {@link noding::snap::SnappingNoder}.
|
|
*/
|
|
class GEOS_DLL SnapRoundingNoder : public Noder {
|
|
|
|
private:
|
|
/**
|
|
* The division factor used to determine
|
|
* nearness distance tolerance for interior intersection detection.
|
|
*/
|
|
static constexpr int INTERSECTION_NEARNESS_FACTOR = 100;
|
|
|
|
// Members
|
|
const geom::PrecisionModel* pm;
|
|
noding::snapround::HotPixelIndex pixelIndex;
|
|
std::vector<SegmentString*> snappedResult;
|
|
|
|
// Methods
|
|
void snapRound(std::vector<SegmentString*>& inputSegStrings, std::vector<SegmentString*>& resultNodedSegments);
|
|
|
|
/**
|
|
* Creates HotPixels for each vertex in the input segStrings.
|
|
* The HotPixels are not marked as nodes, since they will
|
|
* only be nodes in the final line arrangement
|
|
* if they interact with other segments (or they are already
|
|
* created as intersection nodes).
|
|
*/
|
|
void addVertexPixels(std::vector<SegmentString*>& segStrings);
|
|
|
|
/**
|
|
* Detects interior intersections in the collection of {@link SegmentString}s,
|
|
* and adds nodes for them to the segment strings.
|
|
* Also creates HotPixel nodes for the intersection points.
|
|
*/
|
|
void addIntersectionPixels(std::vector<SegmentString*>& segStrings);
|
|
|
|
/**
|
|
* Gets a list of the rounded coordinates.
|
|
* Duplicate (collapsed) coordinates are removed.
|
|
*
|
|
* @param pts the coordinates to round
|
|
* @return array of rounded coordinates
|
|
*/
|
|
std::unique_ptr<geom::CoordinateSequence> round(const geom::CoordinateSequence& pts) const;
|
|
|
|
/**
|
|
* Computes new segment strings which are rounded and contain
|
|
* intersections added as a result of snapping segments to snap points (hot pixels).
|
|
*
|
|
* @param segStrings segments to snap
|
|
* @return the snapped segment strings
|
|
*/
|
|
void computeSnaps(const std::vector<SegmentString*>& segStrings, std::vector<SegmentString*>& snapped);
|
|
NodedSegmentString* computeSegmentSnaps(NodedSegmentString* ss);
|
|
|
|
/**
|
|
* Snaps a segment in a segmentString to HotPixels that it intersects.
|
|
*
|
|
* @param p0 the segment start coordinate
|
|
* @param p1 the segment end coordinate
|
|
* @param ss the segment string to add intersections to
|
|
* @param segIndex the index of the segment
|
|
*/
|
|
void snapSegment(const geom::CoordinateXY& p0, const geom::CoordinateXY& p1, NodedSegmentString* ss, std::size_t segIndex);
|
|
|
|
/**
|
|
* Add nodes for any vertices in hot pixels that were
|
|
* added as nodes during segment noding.
|
|
*/
|
|
void addVertexNodeSnaps(NodedSegmentString* ss);
|
|
|
|
void snapVertexNode(const geom::CoordinateXY& p0, NodedSegmentString* ss, std::size_t segIndex);
|
|
|
|
public:
|
|
|
|
SnapRoundingNoder(const geom::PrecisionModel* p_pm)
|
|
: pm(p_pm)
|
|
, pixelIndex(p_pm)
|
|
{}
|
|
|
|
/**
|
|
* @return a Collection of NodedSegmentStrings representing the substrings
|
|
*/
|
|
std::vector<SegmentString*>* getNodedSubstrings() const override;
|
|
|
|
/**
|
|
* Computes the nodes in the snap-rounding line arrangement.
|
|
* The nodes are added to the {@link NodedSegmentString}s provided as the input.
|
|
*/
|
|
void computeNodes(std::vector<SegmentString*>* inputSegStrings) override; //override
|
|
|
|
};
|
|
|
|
|
|
} // namespace geos::noding::snapround
|
|
} // namespace geos::noding
|
|
} // namespace geos
|
|
|
|
|
|
|