Commit c34a13f8 authored by Dennis Nienhüser's avatar Dennis Nienhüser Committed by Friedrich W. H. Kossebau
Browse files

Filter small areas (less than 1 percent of tile area) on levels 11-15

parent 0979657e
......@@ -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()) {
......
......@@ -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;
};
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment