summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kolozsvari <freedawson@gmail.com>2016-08-20 05:45:49 (GMT)
committerDavid Kolozsvari <freedawson@gmail.com>2016-08-20 05:45:49 (GMT)
commitff63d11da85af11795977c5154f9580f5ef0d534 (patch)
treee3f7575b27313632c8e933df609fdf553e973b71
parentb52b6e3d3d7f5c31c2a0097084ff2215979ded34 (diff)
Proper parsing for polygons and their inner rings when cutting to tiles.
-rw-r--r--tools/osm-simplify/BaseClipper.cpp81
-rw-r--r--tools/osm-simplify/BaseClipper.h8
-rw-r--r--tools/osm-simplify/TinyPlanetProcessor.cpp111
-rw-r--r--tools/osm-simplify/TinyPlanetProcessor.h2
4 files changed, 141 insertions, 61 deletions
diff --git a/tools/osm-simplify/BaseClipper.cpp b/tools/osm-simplify/BaseClipper.cpp
index 96d06ff..37521e4 100644
--- a/tools/osm-simplify/BaseClipper.cpp
+++ b/tools/osm-simplify/BaseClipper.cpp
@@ -104,49 +104,84 @@ BaseClipper::BaseClipper() :
-QPolygonF BaseClipper::lineString2Qpolygon(const GeoDataLineString& lineString)
+QPolygonF BaseClipper::lineString2Qpolygon(const GeoDataLineString& lineString, bool reverseOrder)
{
QPolygonF polygon;
- foreach (const GeoDataCoordinates& coord, lineString) {
- // Need to flip the Y axis(latitude)
- QPointF point(coord.longitude(), -coord.latitude());
- polygon.append(point);
+ if(!reverseOrder) {
+ foreach (const GeoDataCoordinates& coord, lineString) {
+ // Need to flip the Y axis(latitude)
+ QPointF point(coord.longitude(), -coord.latitude());
+ polygon.append(point);
+ }
+ } else {
+ for(int i = lineString.size()-1; i >= 0; --i) {
+ // Need to flip the Y axis(latitude)
+ QPointF point(lineString.at(i).longitude(), -lineString.at(i).latitude());
+ polygon.append(point);
+ }
}
return polygon;
}
-QPolygonF BaseClipper::linearRing2Qpolygon(const GeoDataLinearRing& linearRing)
+QPolygonF BaseClipper::linearRing2Qpolygon(const GeoDataLinearRing& linearRing, bool reverseOrder)
{
QPolygonF polygon;
- foreach (const GeoDataCoordinates& coord, linearRing) {
- // Need to flip the Y axis(latitude)
- QPointF point(coord.longitude(), -coord.latitude());
- polygon.append(point);
+
+ if(!reverseOrder) {
+ foreach (const GeoDataCoordinates& coord, linearRing) {
+ // Need to flip the Y axis(latitude)
+ QPointF point(coord.longitude(), -coord.latitude());
+ polygon.append(point);
+ }
+ } else {
+ for(int i = linearRing.size()-1; i >= 0; --i) {
+ // Need to flip the Y axis(latitude)
+ QPointF point(linearRing.at(i).longitude(), -linearRing.at(i).latitude());
+ polygon.append(point);
+ }
}
return polygon;
}
-GeoDataLineString BaseClipper::qPolygon2lineString(const QPolygonF& polygon)
+GeoDataLineString BaseClipper::qPolygon2lineString(const QPolygonF& polygon, bool reverseOrder)
{
GeoDataLineString lineString;
- foreach (const QPointF& point, polygon) {
- // Flipping back the Y axis
- GeoDataCoordinates coord(point.x(), -point.y());
- lineString.append(coord);
+
+ if(!reverseOrder) {
+ foreach (const QPointF& point, polygon) {
+ // Flipping back the Y axis
+ GeoDataCoordinates coord(point.x(), -point.y());
+ lineString.append(coord);
+ }
+ } else {
+ for(int i = polygon.size()-1; i >= 0; --i) {
+ // Need to flip the Y axis(latitude)
+ GeoDataCoordinates coord(polygon.at(i).x(), -polygon.at(i).y());
+ lineString.append(coord);
+ }
}
return lineString;
}
-GeoDataLinearRing BaseClipper::qPolygon2linearRing(const QPolygonF& polygon)
+GeoDataLinearRing BaseClipper::qPolygon2linearRing(const QPolygonF& polygon, bool reverseOrder)
{
GeoDataLinearRing linearRing;
- foreach (const QPointF& point, polygon) {
- // Flipping back the Y axis
- GeoDataCoordinates coord(point.x(), -point.y());
- linearRing.append(coord);
+
+ if(!reverseOrder) {
+ foreach (const QPointF& point, polygon) {
+ // Flipping back the Y axis
+ GeoDataCoordinates coord(point.x(), -point.y());
+ linearRing.append(coord);
+ }
+ } else {
+ for(int i = polygon.size()-1; i >= 0; --i) {
+ // Need to flip the Y axis(latitude)
+ GeoDataCoordinates coord(polygon.at(i).x(), -polygon.at(i).y());
+ linearRing.append(coord);
+ }
}
return linearRing;
@@ -579,15 +614,15 @@ void BaseClipper::clipPolyObject ( const QPolygonF & polygon,
clippedPolyObjects.clear();
clippedPolyObject = polygon.intersected(m_viewport);
- if(clippedPolyObject == polygon) {
- clippedPolyObjects << polygon;
- } else if (clippedPolyObject == m_viewport.intersected(m_viewport)) {
+ if (clippedPolyObject == m_viewport.intersected(m_viewport)) {
clippedPolyObject = QPolygonF();
clippedPolyObject << m_topLeft << m_topEdge
<< m_topRight << m_rightEdge
<< m_bottomRight << m_bottomEdge
<< m_bottomLeft << m_leftEdge;
clippedPolyObjects << clippedPolyObject;
+ } else if(!clippedPolyObject.isEmpty()) {
+ clippedPolyObjects << polygon;
}
}
} else if(!clippedPolyObject.isEmpty()) {
diff --git a/tools/osm-simplify/BaseClipper.h b/tools/osm-simplify/BaseClipper.h
index 71b8d76..3967143 100644
--- a/tools/osm-simplify/BaseClipper.h
+++ b/tools/osm-simplify/BaseClipper.h
@@ -29,11 +29,11 @@ public:
static qreal tileX2lon( unsigned int x, unsigned int maxTileX );
static qreal tileY2lat( unsigned int y, unsigned int maxTileY );
- static QPolygonF lineString2Qpolygon(const GeoDataLineString &lineString);
- static QPolygonF linearRing2Qpolygon(const GeoDataLinearRing &linearRing);
+ static QPolygonF lineString2Qpolygon(const GeoDataLineString &lineString, bool reverseOrder = false);
+ static QPolygonF linearRing2Qpolygon(const GeoDataLinearRing &linearRing, bool reverseOrder = false);
- static GeoDataLineString qPolygon2lineString(const QPolygonF& polygon);
- static GeoDataLinearRing qPolygon2linearRing(const QPolygonF& polygon);
+ static GeoDataLineString qPolygon2lineString(const QPolygonF& polygon, bool reverseOrder = false);
+ static GeoDataLinearRing qPolygon2linearRing(const QPolygonF& polygon, bool reverseOrder = false);
void initClipRect(const GeoDataLatLonBox& clippingBox, int pointsToAddAtEdges);
diff --git a/tools/osm-simplify/TinyPlanetProcessor.cpp b/tools/osm-simplify/TinyPlanetProcessor.cpp
index af4ece2..026928e 100644
--- a/tools/osm-simplify/TinyPlanetProcessor.cpp
+++ b/tools/osm-simplify/TinyPlanetProcessor.cpp
@@ -14,9 +14,11 @@
#include "GeoDataPlacemark.h"
#include "OsmPlacemarkData.h"
+#include "OsmObjectManager.h"
#include <QDebug>
#include <QPolygonF>
+#include <QPair>
TinyPlanetProcessor::TinyPlanetProcessor(GeoDataDocument* document) :
PlacemarkFilter(document)
@@ -52,41 +54,79 @@ GeoDataDocument *TinyPlanetProcessor::cutToTiles(unsigned int zoomLevel, unsigne
if(tileBoundary.intersects(placemark->geometry()->latLonAltBox())) {
- if( placemark->geometry()->nodeType() == GeoDataTypes::GeoDataPolygonType ||
- placemark->visualCategory() == GeoDataFeature::Landmass) {
+ if( placemark->geometry()->nodeType() == GeoDataTypes::GeoDataPolygonType) {
- GeoDataLinearRing* marblePolygon;
- if(placemark->geometry()->nodeType() == GeoDataTypes::GeoDataPolygonType) {
- marblePolygon = &static_cast<GeoDataPolygon*>(placemark->geometry())->outerBoundary();
- } else if (placemark->geometry()->nodeType() == GeoDataTypes::GeoDataLinearRingType) {
- marblePolygon = static_cast<GeoDataLinearRing*>(placemark->geometry());
+ bool isClockwise = true;
+
+ GeoDataPolygon* marblePolygon = static_cast<GeoDataPolygon*>(placemark->geometry());
+ int index = -1;
+
+ using PolygonPair = QPair<GeoDataPlacemark*, QPolygonF>;
+ QVector<PolygonPair> newMarblePolygons;
+
+ isClockwise = marblePolygon->outerBoundary().isClockwise();
+ QPolygonF outerBoundaryPolygon = BaseClipper::linearRing2Qpolygon(marblePolygon->outerBoundary(), !isClockwise);
+
+ QVector<QPolygonF> outerBoundaries;
+ clipper.clipPolyObject(outerBoundaryPolygon, outerBoundaries, true);
+
+// qDebug() << "Size(s) after:";
+ foreach(const QPolygonF& polygon, outerBoundaries) {
+
+// qDebug() << polygon.size();
+
+ PolygonPair newMarblePolygon = qMakePair(new GeoDataPlacemark(), polygon);
+ GeoDataPolygon* geometry = new GeoDataPolygon();
+ geometry->setOuterBoundary(BaseClipper::qPolygon2linearRing(polygon, !isClockwise));
+ newMarblePolygon.first->setGeometry(geometry);
+
+ copyTags(*placemark, *(newMarblePolygon.first));
+ OsmObjectManager::initializeOsmData(newMarblePolygon.first);
+
+ placemark->osmData().memberReference(index);
+ copyTags(placemark->osmData().memberReference(index),
+ newMarblePolygon.first->osmData().memberReference(index));
+
+ newMarblePolygons.push_back(newMarblePolygon);
}
- QVector<QPolygonF> clippedPolygons;
+ foreach (const GeoDataLinearRing& innerBoundary, marblePolygon->innerBoundaries()) {
+ ++index;
+ isClockwise = innerBoundary.isClockwise();
+ QPolygonF innerBoundaryPolygon = BaseClipper::linearRing2Qpolygon(innerBoundary, !isClockwise);
+
+ QVector<QPolygonF> clippedPolygons;
- QPolygonF outerBoundary = BaseClipper::linearRing2Qpolygon(*marblePolygon);
+ clipper.clipPolyObject(innerBoundaryPolygon, clippedPolygons, true);
- clipper.clipPolyObject(outerBoundary, clippedPolygons, true);
+ foreach (const QPolygonF& polygon, clippedPolygons) {
+ bool isAdded = false;
+ foreach (const PolygonPair& newMarblePolygon, newMarblePolygons) {
+ if(!polygon.intersected(newMarblePolygon.second).isEmpty()) {
+ GeoDataPolygon* geometry = static_cast<GeoDataPolygon*>(newMarblePolygon.first->geometry());
+ geometry->appendInnerBoundary(BaseClipper::qPolygon2linearRing(polygon, !isClockwise));
- qDebug() << "Size(s) after:";
- foreach(const QPolygonF& polygon, clippedPolygons) {
+ OsmObjectManager::initializeOsmData(newMarblePolygon.first);
- qDebug() << polygon.size();
+ OsmPlacemarkData& innerRingData = newMarblePolygon.first->osmData().memberReference(geometry->innerBoundaries().size()-1);
+ OsmPlacemarkData& placemarkInnerRingData = placemark->osmData().memberReference(index);
- GeoDataLinearRing outerBoundary = BaseClipper::qPolygon2linearRing(polygon);
- GeoDataPolygon* newMarblePolygon = new GeoDataPolygon();
- newMarblePolygon->setOuterBoundary(outerBoundary);
+ copyTags(placemarkInnerRingData, innerRingData);
- GeoDataPlacemark* newPlacemark = new GeoDataPlacemark();
- newPlacemark->setGeometry(newMarblePolygon);
- newPlacemark->setVisualCategory(GeoDataFeature::Landmass);
+ isAdded = true;
+ }
+ }
- OsmPlacemarkData marbleLand;
- marbleLand.addTag("marble_land","landmass");
- newPlacemark->setOsmData(marbleLand);
+ if(!isAdded) {
+ qDebug() << "Polygon not added. Why?";
+ }
+ }
+ }
- tile->append(newPlacemark);
+ foreach (const PolygonPair& newMarblePolygon, newMarblePolygons) {
+ tile->append(newMarblePolygon.first);
}
+
} else if (placemark->geometry()->nodeType() == GeoDataTypes::GeoDataLineStringType) {
GeoDataLineString* marbleWay = static_cast<GeoDataLineString*>(placemark->geometry());
@@ -96,17 +136,16 @@ GeoDataDocument *TinyPlanetProcessor::cutToTiles(unsigned int zoomLevel, unsigne
clipper.clipPolyObject(way, clippedPolygons, false);
- qDebug() << "Size before:" << way.size();
- qDebug() << "Size(s) after:";
+// qDebug() << "Size before:" << way.size();
+// qDebug() << "Size(s) after:";
foreach(const QPolygonF& polygon, clippedPolygons) {
- qDebug() << polygon.size();
+// qDebug() << polygon.size();
GeoDataLineString* newMarbleWay = new GeoDataLineString(BaseClipper::qPolygon2lineString(polygon));
GeoDataPlacemark* newPlacemark = new GeoDataPlacemark();
newPlacemark->setGeometry(newMarbleWay);
- newPlacemark->setVisualCategory(placemark->visualCategory());
copyTags(*placemark, *newPlacemark);
tile->append(newPlacemark);
@@ -119,20 +158,17 @@ GeoDataDocument *TinyPlanetProcessor::cutToTiles(unsigned int zoomLevel, unsigne
QPolygonF closedWay = BaseClipper::linearRing2Qpolygon(*marbleClosedWay);
- // If we cut a closed way to pieces, the results shouldn't be closed ways too
- clipper.clipPolyObject(closedWay, clippedPolygons, false);
+ clipper.clipPolyObject(closedWay, clippedPolygons, true);
- qDebug() << "Size(s) after:";
+// qDebug() << "Size(s) after:";
foreach(const QPolygonF& polygon, clippedPolygons) {
- qDebug() << polygon.size();
+// qDebug() << polygon.size();
- // When a linearRing is cut to pieces, the resulting geometries will be lineStrings
- GeoDataLineString* newMarbleWay = new GeoDataLineString(BaseClipper::qPolygon2lineString(polygon));
+ GeoDataLinearRing* newMarbleWay = new GeoDataLinearRing(BaseClipper::qPolygon2linearRing(polygon));
GeoDataPlacemark* newPlacemark = new GeoDataPlacemark();
newPlacemark->setGeometry(newMarbleWay);
- newPlacemark->setVisualCategory(placemark->visualCategory());
copyTags(*placemark, *newPlacemark);
tile->append(newPlacemark);
@@ -156,3 +192,10 @@ void TinyPlanetProcessor::copyTags(const GeoDataPlacemark &source, GeoDataPlacem
osmData.addTag(iter.key(), iter.value());
}
}
+
+void TinyPlanetProcessor::copyTags(const OsmPlacemarkData &originalPlacemarkData, OsmPlacemarkData &targetOsmData) const
+{
+ for (auto iter=originalPlacemarkData.tagsBegin(), end=originalPlacemarkData.tagsEnd(); iter != end; ++iter) {
+ targetOsmData.addTag(iter.key(), iter.value());
+ }
+}
diff --git a/tools/osm-simplify/TinyPlanetProcessor.h b/tools/osm-simplify/TinyPlanetProcessor.h
index 25b70bb..086ceb4 100644
--- a/tools/osm-simplify/TinyPlanetProcessor.h
+++ b/tools/osm-simplify/TinyPlanetProcessor.h
@@ -12,6 +12,7 @@
#define TINYPLANETPROCESSOR_H
#include "PlacemarkFilter.h"
+#include "OsmPlacemarkData.h"
class TinyPlanetProcessor : public PlacemarkFilter
{
@@ -24,6 +25,7 @@ public:
private:
void copyTags(const GeoDataPlacemark &source, GeoDataPlacemark &target) const;
+ void copyTags(const OsmPlacemarkData &originalPlacemarkData, OsmPlacemarkData& targetOsmData) const;
};
#endif // TINYPLANETPROCESSOR_H