summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Nienhüser <nienhueser@kde.org>2016-10-27 18:39:31 (GMT)
committerFriedrich W. H. Kossebau <kossebau@kde.org>2016-11-05 16:49:24 (GMT)
commitc34a13f8f7c050fc2254b7fde0e51b64b7465bd5 (patch)
tree5c84f9ed3fbb6b04c6a95b5721bc35e3ce268c84
parent0979657e38f8473c8abf0c32b29db23ecdf62e71 (diff)
Filter small areas (less than 1 percent of tile area) on levels 11-15
-rw-r--r--tools/vectorosm-tilecreator/VectorClipper.cpp42
-rw-r--r--tools/vectorosm-tilecreator/VectorClipper.h14
2 files changed, 46 insertions, 10 deletions
diff --git a/tools/vectorosm-tilecreator/VectorClipper.cpp b/tools/vectorosm-tilecreator/VectorClipper.cpp
index ef27cb5..51da676 100644
--- a/tools/vectorosm-tilecreator/VectorClipper.cpp
+++ b/tools/vectorosm-tilecreator/VectorClipper.cpp
@@ -49,7 +49,7 @@ VectorClipper::VectorClipper(GeoDataDocument* document, int maxZoomLevel) :
}
}
-GeoDataDocument *VectorClipper::clipTo(const GeoDataLatLonBox &tileBoundary)
+GeoDataDocument *VectorClipper::clipTo(const GeoDataLatLonBox &tileBoundary, bool filterSmallAreas)
{
bool const useBaseClipper = false;
if (useBaseClipper) {
@@ -58,15 +58,21 @@ GeoDataDocument *VectorClipper::clipTo(const GeoDataLatLonBox &tileBoundary)
GeoDataDocument* tile = new GeoDataDocument();
auto const clip = clipPath(tileBoundary);
+ GeoDataLinearRing ring;
+ ring << GeoDataCoordinates(tileBoundary.west(), tileBoundary.north());
+ ring << GeoDataCoordinates(tileBoundary.east(), tileBoundary.north());
+ ring << GeoDataCoordinates(tileBoundary.east(), tileBoundary.south());
+ ring << GeoDataCoordinates(tileBoundary.west(), tileBoundary.south());
+ qreal const minArea = filterSmallAreas ? 0.01 * area(ring) : 0.0;
foreach (GeoDataPlacemark const * placemark, potentialIntersections(tileBoundary)) {
GeoDataGeometry const * const geometry = placemark ? placemark->geometry() : nullptr;
if (geometry && tileBoundary.intersects(geometry->latLonAltBox())) {
if(geometry->nodeType() == GeoDataTypes::GeoDataPolygonType) {
- clipPolygon(placemark, clip, tile);
+ clipPolygon(placemark, clip, minArea, tile);
} else if (geometry->nodeType() == GeoDataTypes::GeoDataLineStringType) {
- clipString<GeoDataLineString>(placemark, clip, tile);
+ clipString<GeoDataLineString>(placemark, clip, minArea, tile);
} else if (geometry->nodeType() == GeoDataTypes::GeoDataLinearRingType) {
- clipString<GeoDataLinearRing>(placemark, clip, tile);
+ clipString<GeoDataLinearRing>(placemark, clip, minArea, tile);
} else {
tile->append(new GeoDataPlacemark(*placemark));
}
@@ -242,7 +248,8 @@ GeoDataDocument *VectorClipper::clipTo(unsigned int zoomLevel, unsigned int tile
GeoDataLatLonBox tileBoundary;
m_tileProjection.geoCoordinates(zoomLevel, tileX, tileY, tileBoundary);
- GeoDataDocument *tile = clipTo(tileBoundary);
+ bool const filterSmallAreas = zoomLevel > 10 && zoomLevel < 17;
+ GeoDataDocument *tile = clipTo(tileBoundary, filterSmallAreas);
QString tileName = QString("%1/%2/%3").arg(zoomLevel).arg(tileX).arg(tileY);
tile->setName(tileName);
@@ -300,9 +307,32 @@ bool VectorClipper::canBeArea(GeoDataPlacemark::GeoDataVisualCategory visualCate
return true;
}
-void VectorClipper::clipPolygon(const GeoDataPlacemark *placemark, const ClipperLib::Path &tileBoundary, GeoDataDocument *document)
+qreal VectorClipper::area(const GeoDataLinearRing &ring)
+{
+ auto const iter = m_areas.find(&ring);
+ if (iter != m_areas.end()) {
+ return *iter;
+ }
+ int const n = ring.size();
+ qreal area = 0;
+ if (n<3) {
+ return area;
+ }
+ for (int i = 1; i < n; ++i ){
+ area += (ring[i].longitude() - ring[i-1].longitude() ) * ( ring[i].latitude() + ring[i-1].latitude());
+ }
+ area += (ring[0].longitude() - ring[n-1].longitude() ) * (ring[0].latitude() + ring[n-1].latitude());
+ qreal const result = EARTH_RADIUS * EARTH_RADIUS * qAbs(area * 0.5);
+ m_areas.insert(&ring, result);
+ return result;
+}
+
+void VectorClipper::clipPolygon(const GeoDataPlacemark *placemark, const ClipperLib::Path &tileBoundary, qreal minArea, GeoDataDocument *document)
{
const GeoDataPolygon* polygon = static_cast<const GeoDataPolygon*>(placemark->geometry());
+ if (minArea > 0.0 && area(polygon->outerBoundary()) < minArea) {
+ return;
+ }
using namespace ClipperLib;
Path path;
foreach(auto const & node, polygon->outerBoundary()) {
diff --git a/tools/vectorosm-tilecreator/VectorClipper.h b/tools/vectorosm-tilecreator/VectorClipper.h
index 30c42ce..9e93532 100644
--- a/tools/vectorosm-tilecreator/VectorClipper.h
+++ b/tools/vectorosm-tilecreator/VectorClipper.h
@@ -16,6 +16,7 @@
#include <GeoDataLatLonBox.h>
#include "GeoDataPlacemark.h"
+#include "GeoDataLinearRing.h"
#include <TileId.h>
#include <GeoSceneMercatorTileProjection.h>
@@ -30,7 +31,7 @@ class VectorClipper : public BaseFilter
public:
VectorClipper(GeoDataDocument* document, int maxZoomLevel);
- GeoDataDocument* clipTo(const GeoDataLatLonBox &box);
+ GeoDataDocument* clipTo(const GeoDataLatLonBox &box, bool filterSmallAreas);
GeoDataDocument* clipTo(unsigned int zoomLevel, unsigned int tileX, unsigned int tileY);
private:
@@ -38,11 +39,16 @@ private:
QVector<GeoDataPlacemark*> potentialIntersections(const GeoDataLatLonBox &box) const;
ClipperLib::Path clipPath(const GeoDataLatLonBox &box) const;
bool canBeArea(GeoDataPlacemark::GeoDataVisualCategory visualCategory) const;
+ qreal area(const GeoDataLinearRing &ring);
template<class T>
- void clipString(const GeoDataPlacemark *placemark, const ClipperLib::Path &tileBoundary, GeoDataDocument* document)
+ void clipString(const GeoDataPlacemark *placemark, const ClipperLib::Path &tileBoundary, qreal minArea, GeoDataDocument* document)
{
const T* ring = static_cast<const T*>(placemark->geometry());
+ bool const isClosed = ring->isClosed() && canBeArea(placemark->visualCategory());
+ if (isClosed && minArea > 0.0 && area(*static_cast<const GeoDataLinearRing*>(ring)) < minArea) {
+ return;
+ }
using namespace ClipperLib;
Path path;
foreach(auto const & node, *ring) {
@@ -51,7 +57,6 @@ private:
Clipper clipper;
clipper.PreserveCollinear(true);
- bool const isClosed = ring->isClosed() && canBeArea(placemark->visualCategory());
clipper.AddPath(tileBoundary, ptClip, true);
clipper.AddPath(path, ptSubject, isClosed);
PolyTree tree;
@@ -75,7 +80,7 @@ private:
}
}
- void clipPolygon(const GeoDataPlacemark *placemark, const ClipperLib::Path &tileBoundary, GeoDataDocument* document);
+ void clipPolygon(const GeoDataPlacemark *placemark, const ClipperLib::Path &tileBoundary, qreal minArea, GeoDataDocument* document);
void copyTags(const GeoDataPlacemark &source, GeoDataPlacemark &target) const;
void copyTags(const OsmPlacemarkData &originalPlacemarkData, OsmPlacemarkData& targetOsmData) const;
@@ -85,6 +90,7 @@ private:
QMap<TileId, QVector<GeoDataPlacemark*> > m_items;
int m_maxZoomLevel;
GeoSceneMercatorTileProjection m_tileProjection;
+ QHash<const GeoDataLinearRing*, qreal> m_areas;
};
}