EVOLUTION-MANAGER
Edit File: GeometryPrecisionReducer.cpp
/********************************************************************** * * GEOS - Geometry Engine Open Source * http://geos.osgeo.org * * Copyright (C) 2005-2006 Refractions Research Inc. * 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: precision/GeometryPrecisionReducer.cpp rev. 1.10 (JTS-1.7) * **********************************************************************/ #include <geos/precision/GeometryPrecisionReducer.h> #include <geos/precision/PrecisionReducerCoordinateOperation.h> #include <geos/geom/util/GeometryEditor.h> #include <geos/geom/util/CoordinateOperation.h> #include <geos/geom/Coordinate.h> #include <geos/geom/CoordinateSequence.h> #include <geos/geom/CoordinateSequenceFactory.h> #include <geos/geom/PrecisionModel.h> #include <geos/geom/GeometryFactory.h> #include <geos/geom/LineString.h> #include <geos/geom/LinearRing.h> #include <vector> #include <typeinfo> using namespace std; using namespace geos::geom; using namespace geos::geom::util; namespace geos { namespace precision { // geos.precision /* private */ unique_ptr<Geometry> GeometryPrecisionReducer::reducePointwise(const Geometry& geom) { GeometryEditor geomEdit(newFactory); /** * For polygonal geometries, collapses are always removed, in order * to produce correct topology */ bool finalRemoveCollapsed = removeCollapsed; if(geom.getDimension() >= 2) { finalRemoveCollapsed = true; } PrecisionReducerCoordinateOperation prco(targetPM, finalRemoveCollapsed); std::unique_ptr<Geometry> g(geomEdit.edit(&geom, &prco)); return g; } /* public */ unique_ptr<Geometry> GeometryPrecisionReducer::reduce(const Geometry& geom) { unique_ptr<Geometry> reducePW = reducePointwise(geom); if(isPointwise) { return reducePW; } //TODO: handle GeometryCollections containing polys if(!reducePW->isPolygonal()) { return reducePW; } // Geometry is polygonal - test if topology needs to be fixed if(reducePW->isValid()) { return reducePW; } // hack to fix topology. // TODO: implement snap-rounding and use that. return fixPolygonalTopology(*reducePW); } /* public */ GeometryPrecisionReducer::GeometryPrecisionReducer(const GeometryFactory& changeFactory) : newFactory(&changeFactory), targetPM(*(changeFactory.getPrecisionModel())), removeCollapsed(true), isPointwise(false) {} /* private */ unique_ptr<Geometry> GeometryPrecisionReducer::fixPolygonalTopology(const geom::Geometry& geom) { /** * If precision model was *not* changed, need to flip * geometry to targetPM, buffer in that model, then flip back */ unique_ptr<Geometry> tmp; GeometryFactory::Ptr tmpFactory; const Geometry* geomToBuffer = &geom; if(! newFactory) { tmpFactory = createFactory(*geom.getFactory(), targetPM); tmp.reset(tmpFactory->createGeometry(&geom)); geomToBuffer = tmp.get(); } unique_ptr<Geometry> bufGeom(geomToBuffer->buffer(0)); if(! newFactory) { // a slick way to copy the geometry with the original precision factory bufGeom.reset(geom.getFactory()->createGeometry(bufGeom.get())); } return bufGeom; } /* private */ GeometryFactory::Ptr GeometryPrecisionReducer::createFactory(const GeometryFactory& oldGF, const PrecisionModel& newPM) { GeometryFactory::Ptr p_newFactory( GeometryFactory::create(&newPM, oldGF.getSRID(), const_cast<CoordinateSequenceFactory*>(oldGF.getCoordinateSequenceFactory())) ); return p_newFactory; } } // namespace geos.precision } // namespace geos