[geos-commits] r2458 - in trunk/source:
headers/geos/operation/overlay
headers/geos/operation/overlay/snap operation/overlay
operation/overlay/snap
svn_geos at osgeo.org
svn_geos at osgeo.org
Sat May 2 07:01:07 EDT 2009
Author: strk
Date: 2009-05-02 07:01:07 -0400 (Sat, 02 May 2009)
New Revision: 2458
Added:
trunk/source/headers/geos/operation/overlay/snap/
trunk/source/headers/geos/operation/overlay/snap/LineStringSnapper.h
trunk/source/operation/overlay/snap/
trunk/source/operation/overlay/snap/LineStringSnapper.cpp
Modified:
trunk/source/headers/geos/operation/overlay/Makefile.am
trunk/source/operation/overlay/Makefile.am
Log:
Port overlay.snap.LineStringSnapper from JTS-1.10
Modified: trunk/source/headers/geos/operation/overlay/Makefile.am
===================================================================
--- trunk/source/headers/geos/operation/overlay/Makefile.am 2009-05-02 10:59:19 UTC (rev 2457)
+++ trunk/source/headers/geos/operation/overlay/Makefile.am 2009-05-02 11:01:07 UTC (rev 2458)
@@ -23,4 +23,5 @@
OverlayNodeFactory.h \
OverlayResultValidator.h \
PointBuilder.h \
- PolygonBuilder.h
+ PolygonBuilder.h \
+ snap/LineStringSnapper.h
Added: trunk/source/headers/geos/operation/overlay/snap/LineStringSnapper.h
===================================================================
--- trunk/source/headers/geos/operation/overlay/snap/LineStringSnapper.h (rev 0)
+++ trunk/source/headers/geos/operation/overlay/snap/LineStringSnapper.h 2009-05-02 11:01:07 UTC (rev 2458)
@@ -0,0 +1,167 @@
+/**********************************************************************
+ * $Id$
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2009 Sandro Santilli <strk at keybit.net>
+ *
+ * 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: operation/overlay/snap/LineStringSnapper.java rev 1.5 (JTS-1.10)
+ *
+ **********************************************************************/
+
+#ifndef GEOS_OP_OVERLAY_SNAP_LINESTRINGSNAPPER_H
+#define GEOS_OP_OVERLAY_SNAP_LINESTRINGSNAPPER_H
+
+#include <geos/geom/LineSegment.h> // for composition
+#include <geos/geom/LineString.h> // for inlined ctor
+
+//#include <vector>
+#include <memory> // for auto_ptr
+
+// Forward declarations
+namespace geos {
+ namespace geom {
+ class CoordinateSequence;
+ }
+}
+
+namespace geos {
+namespace operation { // geos::operation
+namespace overlay { // geos::operation::overlay
+namespace snap { // geos::operation::overlay::snap
+
+/** \brief
+ * Snaps the vertices and segments of a LineString to a set
+ * of target snap vertices.
+ *
+ * A snapping distance tolerance is used to control where snapping is performed.
+ *
+ */
+class LineStringSnapper {
+
+public:
+
+ /**
+ * Creates a new snapper using the points in the given LineString
+ * as source snap points.
+ *
+ * @param srcLline a LineString to snap
+ * @param nSnapTolerance the snap tolerance to use
+ */
+ LineStringSnapper(const geom::LineString& srcLline,
+ double nSnapTolerance)
+ :
+ snapTolerance(nSnapTolerance),
+ srcPts(*(srcLline.getCoordinatesRO())),
+ seg(),
+ isClosed(false)
+ {
+ }
+
+ /**
+ * Creates a new snapper using the given points
+ * as source points to be snapped.
+ *
+ * @param nSrcPts the points to snap
+ * @param nSnapTolerance the snap tolerance to use
+ */
+ LineStringSnapper(const geom::CoordinateSequence& nSrcPts,
+ double nSnapTolerance)
+ :
+ snapTolerance(nSnapTolerance),
+ srcPts(nSrcPts),
+ seg(),
+ isClosed(false)
+ {
+ }
+
+ /**
+ * Snaps the vertices and segments of the source points
+ * to the given set of target snap points.
+ *
+ * @param snapPts the vertices to snap to
+ * @return a sequence formed by the snapped points
+ */
+ std::auto_ptr<geom::CoordinateSequence> snapTo(
+ const geom::CoordinateSequence& snapPts);
+
+private:
+
+ /**
+ * Snap source vertices to vertices in the target.
+ *
+ * @param srcCoords the points to snap
+ * @param snapPts the points to snap to
+ */
+ void snapVertices(geom::CoordinateSequence& srcCoords,
+ const geom::CoordinateSequence& snapPts);
+
+
+ // return pointer into snapPts memory, or null
+ const geom::Coordinate*
+ findSnapForVertex(const geom::Coordinate& pt,
+ const geom::CoordinateSequence& snapPts);
+
+ /**
+ * Snap segments of the source to nearby snap vertices.
+ * Source segments are "cracked" at a snap vertex, and further
+ * snapping takes place on the modified list of segments.
+ * For each distinct snap vertex, at most one source segment
+ * is snapped to. This prevents "cracking" multiple segments
+ * at the same point, which would almost certainly cause the result
+ * to be invalid.
+ *
+ * @param srcCoords
+ * @param snapPts
+ */
+ void snapSegments(geom::CoordinateSequence& srcCoords,
+ const geom::CoordinateSequence& snapPts);
+
+ /** \brief
+ * Finds a src segment which snaps to (is close to)
+ * the given snap point.
+ *
+ * Only one segment is determined - this is to prevent * snapping to multiple segments, which would almost certainly
+ * cause invalid geometry to be created.
+ * (The heuristic approach of snapping is really only appropriate when
+ * snap pts snap to a unique spot on the src geometry.)
+ *
+ * @param snapPt the point to snap to
+ * @param srcCoords the source segment coordinates
+ * @return the index of the snapped segment
+ * @return -1 if no segment snaps
+ */
+ int findSegmentIndexToSnap(const geom::Coordinate& snapPt,
+ const geom::CoordinateSequence& srcCoords);
+
+
+
+ double snapTolerance;
+
+ const geom::CoordinateSequence& srcPts;
+
+ geom::LineSegment seg; // for reuse during snapping
+
+ bool isClosed;
+
+};
+
+} // namespace geos::operation::overlay::snap
+} // namespace geos::operation::overlay
+} // namespace geos::operation
+} // namespace geos
+
+#endif // ndef GEOS_OP_OVERLAY_SNAP_LINESTRINGSNAPPER_H
+
+/**********************************************************************
+ * $Log$
+ **********************************************************************/
+
Modified: trunk/source/operation/overlay/Makefile.am
===================================================================
--- trunk/source/operation/overlay/Makefile.am 2009-05-02 10:59:19 UTC (rev 2457)
+++ trunk/source/operation/overlay/Makefile.am 2009-05-02 11:01:07 UTC (rev 2458)
@@ -17,7 +17,8 @@
OverlayOp.cpp \
OverlayResultValidator.cpp \
PointBuilder.cpp \
- PolygonBuilder.cpp
+ PolygonBuilder.cpp \
+ snap/LineStringSnapper.cpp
libopoverlay_la_LIBADD =
Added: trunk/source/operation/overlay/snap/LineStringSnapper.cpp
===================================================================
--- trunk/source/operation/overlay/snap/LineStringSnapper.cpp (rev 0)
+++ trunk/source/operation/overlay/snap/LineStringSnapper.cpp 2009-05-02 11:01:07 UTC (rev 2458)
@@ -0,0 +1,143 @@
+/**********************************************************************
+ * $Id$
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2009 Sandro Santilli <strk at keybit.net>
+ *
+ * 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: operation/overlay/snap/LineStringSnapper.java rev 1.5 (JTS-1.10)
+ *
+ **********************************************************************/
+
+#include <geos/operation/overlay/snap/LineStringSnapper.h>
+#include <geos/geom/CoordinateSequence.h>
+
+#include <cassert>
+#include <limits> // for numeric_limits
+#include <memory> // for auto_ptr
+
+#ifndef GEOS_DEBUG
+#define GEOS_DEBUG 0
+#endif
+
+using namespace std;
+using namespace geos::geom;
+
+namespace geos {
+namespace operation { // geos.operation
+namespace overlay { // geos.operation.overlay
+namespace snap { // geos.operation.overlay.snap
+
+/*public*/
+auto_ptr<CoordinateSequence>
+LineStringSnapper::snapTo(const CoordinateSequence& snapPts)
+{
+ auto_ptr<CoordinateSequence> coordList(snapPts.clone());
+
+ snapVertices(*coordList, snapPts);
+ snapSegments(*coordList, snapPts);
+
+ return coordList;
+}
+
+/*private*/
+void
+LineStringSnapper::snapVertices(geom::CoordinateSequence& srcCoords,
+ const geom::CoordinateSequence& snapPts)
+{
+ // try snapping vertices
+ // assume src list has a closing point (is a ring)
+ for (int i = 0; i < srcCoords.size() - 1; i++) {
+ const Coordinate& srcPt = srcCoords.getAt(i);
+ const Coordinate* snapVert = findSnapForVertex(srcPt, snapPts);
+ if (snapVert != NULL) {
+ // update src with snap pt
+ srcCoords.setAt(*snapVert, i);
+ // keep final closing point in synch (rings only)
+ if (i == 0 && isClosed)
+ srcCoords.setAt(*snapVert, srcCoords.size() - 1);
+ }
+ }
+}
+
+/*private*/
+const geom::Coordinate*
+LineStringSnapper::findSnapForVertex(const geom::Coordinate& pt,
+ const geom::CoordinateSequence& snapPts)
+{
+ for (int i = 0; i < snapPts.size(); i++) {
+ // if point is already equal to a src pt, don't snap
+ if (pt.equals2D(snapPts[i]))
+ return 0;
+ if (pt.distance(snapPts[i]) < snapTolerance)
+ return &(snapPts[i]);
+ }
+ return 0;
+}
+
+/*private*/
+void
+LineStringSnapper::snapSegments(geom::CoordinateSequence& srcCoords,
+ const geom::CoordinateSequence& snapPts)
+{
+ int distinctPtCount = snapPts.size();
+
+ // check for duplicate snap pts.
+ // Need to do this better - need to check all points for dups (using a Set?)
+ if (snapPts[0].equals2D(snapPts[snapPts.size() - 1]))
+ distinctPtCount = snapPts.size() - 1;
+
+ for (int i = 0; i < distinctPtCount; i++) {
+ const Coordinate& snapPt = snapPts[i];
+ int index = findSegmentIndexToSnap(snapPt, srcCoords);
+ /**
+ * If a segment to snap to was found, "crack" it at the snap pt.
+ * The new pt is inserted immediately into the src segment list,
+ * so that subsequent snapping will take place on the latest segments.
+ * Duplicate points are not added.
+ */
+ if (index >= 0) {
+ srcCoords.add(index + 1, snapPt, false);
+ }
+ }
+}
+
+/*private*/
+int
+LineStringSnapper::findSegmentIndexToSnap(const geom::Coordinate& snapPt,
+ const geom::CoordinateSequence& srcCoords)
+{
+ double minDist = numeric_limits<double>::max();
+ int snapIndex = -1;
+ for (int i = 0; i < srcCoords.size() - 1; i++) {
+ seg.p0 = srcCoords.getAt(i);
+ seg.p1 = srcCoords.getAt(i + 1);
+
+ /**
+ * If the snap pt is already in the src list, don't snap
+ */
+ if (seg.p0.equals2D(snapPt) || seg.p1.equals2D(snapPt))
+ return -1;
+
+ double dist = seg.distance(snapPt);
+ if (dist < snapTolerance && dist < minDist) {
+ minDist = dist;
+ snapIndex = i;
+ }
+ }
+ return snapIndex;
+}
+
+} // namespace geos.operation.snap
+} // namespace geos.operation.overlay
+} // namespace geos.operation
+} // namespace geos
+
More information about the geos-commits
mailing list