Commit ff63d11d authored by Dávid Kolozsvári's avatar Dávid Kolozsvári
Browse files

Proper parsing for polygons and their inner rings when cutting to tiles.

parent b52b6e3d
......@@ -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()) {
......
......@@ -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);
......
......@@ -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());
}
}
......@@ -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
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