Complete Note#1 in the http://wiki.osgeo.org/wiki/GEOS_Provenance_Review to get out...
[geos.git] / src / simplify / DouglasPeuckerSimplifier.cpp
blobd33191bd6baf0f215c846d4be04ab6f915070ca6
1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2006 Refractions Research Inc.
8 * This is free software; you can redistribute and/or modify it under
9 * the terms of the GNU Lesser General Licence as published
10 * by the Free Software Foundation.
11 * See the COPYING file for more information.
13 **********************************************************************
15 * Last port: simplify/DouglasPeuckerSimplifier.java rev. 1.5 (JTS-1.7)
17 **********************************************************************/
19 #include <geos/simplify/DouglasPeuckerSimplifier.h>
20 #include <geos/simplify/DouglasPeuckerLineSimplifier.h>
21 #include <geos/geom/Geometry.h> // for AutoPtr typedefs
22 #include <geos/geom/MultiPolygon.h>
23 #include <geos/geom/CoordinateSequence.h> // for AutoPtr typedefs
24 #include <geos/geom/GeometryFactory.h>
25 #include <geos/geom/CoordinateSequenceFactory.h>
26 #include <geos/geom/util/GeometryTransformer.h> // for DPTransformer inheritance
27 #include <geos/util/IllegalArgumentException.h>
28 #include <geos/util.h>
30 #include <memory> // for auto_ptr
31 #include <cassert>
33 #ifndef GEOS_DEBUG
34 #define GEOS_DEBUG 0
35 #endif
37 #ifdef GEOS_DEBUG
38 #include <iostream>
39 #endif
41 using namespace geos::geom;
43 namespace geos {
44 namespace simplify { // geos::simplify
46 class DPTransformer: public geom::util::GeometryTransformer {
48 public:
50 DPTransformer(double tolerance);
52 protected:
54 CoordinateSequence::AutoPtr transformCoordinates(
55 const CoordinateSequence* coords,
56 const Geometry* parent);
58 Geometry::AutoPtr transformPolygon(
59 const Polygon* geom,
60 const Geometry* parent);
62 Geometry::AutoPtr transformMultiPolygon(
63 const MultiPolygon* geom,
64 const Geometry* parent);
66 private:
69 * Creates a valid area geometry from one that possibly has
70 * bad topology (i.e. self-intersections).
71 * Since buffer can handle invalid topology, but always returns
72 * valid geometry, constructing a 0-width buffer "corrects" the
73 * topology.
74 * Note this only works for area geometries, since buffer always returns
75 * areas. This also may return empty geometries, if the input
76 * has no actual area.
78 * @param roughAreaGeom an area geometry possibly containing
79 * self-intersections
80 * @return a valid area geometry
82 Geometry::AutoPtr createValidArea(const Geometry* roughAreaGeom);
84 double distanceTolerance;
88 DPTransformer::DPTransformer(double t)
90 distanceTolerance(t)
94 Geometry::AutoPtr
95 DPTransformer::createValidArea(const Geometry* roughAreaGeom)
97 return Geometry::AutoPtr(roughAreaGeom->buffer(0.0));
100 CoordinateSequence::AutoPtr
101 DPTransformer::transformCoordinates(
102 const CoordinateSequence* coords,
103 const Geometry* parent)
105 ::geos::ignore_unused_variable_warning(parent);
107 const Coordinate::Vect* inputPts = coords->toVector();
108 assert(inputPts);
110 std::auto_ptr<Coordinate::Vect> newPts =
111 DouglasPeuckerLineSimplifier::simplify(*inputPts,
112 distanceTolerance);
114 return CoordinateSequence::AutoPtr(
115 factory->getCoordinateSequenceFactory()->create(
116 newPts.release()
120 Geometry::AutoPtr
121 DPTransformer::transformPolygon(
122 const Polygon* geom,
123 const Geometry* parent)
126 #if GEOS_DEBUG
127 std::cerr << "DPTransformer::transformPolygon(Polygon " << geom << ", Geometry " << parent << ");" << std::endl;
128 #endif
130 Geometry::AutoPtr roughGeom(GeometryTransformer::transformPolygon(geom, parent));
132 // don't try and correct if the parent is going to do this
133 if ( dynamic_cast<const MultiPolygon*>(parent) )
135 return roughGeom;
138 return createValidArea(roughGeom.get());
141 Geometry::AutoPtr
142 DPTransformer::transformMultiPolygon(
143 const MultiPolygon* geom,
144 const Geometry* parent)
146 #if GEOS_DEBUG
147 std::cerr << "DPTransformer::transformMultiPolygon(MultiPolygon " << geom << ", Geometry " << parent << ");" << std::endl;
148 #endif
149 Geometry::AutoPtr roughGeom(GeometryTransformer::transformMultiPolygon(geom, parent));
150 return createValidArea(roughGeom.get());
153 /************************************************************************/
157 //DouglasPeuckerSimplifier::
159 /*public static*/
160 Geometry::AutoPtr
161 DouglasPeuckerSimplifier::simplify(const Geometry* geom,
162 double tolerance)
164 DouglasPeuckerSimplifier tss(geom);
165 tss.setDistanceTolerance(tolerance);
166 return tss.getResultGeometry();
169 /*public*/
170 DouglasPeuckerSimplifier::DouglasPeuckerSimplifier(const Geometry* geom)
172 inputGeom(geom)
176 /*public*/
177 void
178 DouglasPeuckerSimplifier::setDistanceTolerance(double tol)
180 if (tol < 0.0)
181 throw util::IllegalArgumentException("Tolerance must be non-negative");
182 distanceTolerance = tol;
185 Geometry::AutoPtr
186 DouglasPeuckerSimplifier::getResultGeometry()
188 DPTransformer t(distanceTolerance);
189 return t.transform(inputGeom);
193 } // namespace geos::simplify
194 } // namespace geos
196 /**********************************************************************
197 * $Log$
198 * Revision 1.2 2006/04/13 16:44:49 strk
199 * Fixed a bug in DPTransformer handling of MultiPolygons
201 * Revision 1.1 2006/04/11 16:04:34 strk
202 * geos::simplify::DouglasPeukerSimplifier class + unit test
204 **********************************************************************/