Commit 9c6b3d0e authored by Akshat Tandon's avatar Akshat Tandon
Browse files

Added way-concatenating module to osm-simplify.

Reviewers: nienhueser, rahn

Differential Revision: https://phabricator.kde.org/D2128
parent 43f3168e
......@@ -522,6 +522,17 @@ void GeoDataLineString::setTessellationFlags( TessellationFlags f )
p()->m_tessellationFlags = f;
}
void GeoDataLineString::reverse()
{
GeoDataGeometry::detach();
GeoDataLineStringPrivate* d = p();
delete d->m_rangeCorrected;
d->m_rangeCorrected = 0;
d->m_dirtyRange = true;
d->m_dirtyBox = true;
std::reverse(begin(), end());
}
GeoDataLineString GeoDataLineString::toNormalized() const
{
GeoDataLineString normalizedLineString;
......
......@@ -136,6 +136,10 @@ class GEODATA_EXPORT GeoDataLineString : public GeoDataGeometry
*/
void setTessellationFlags( TessellationFlags f );
/*!
\brief Reverses the LineString.
*/
void reverse();
/*!
\brief Returns the smallest latLonAltBox that contains the LineString.
......
......@@ -29,3 +29,13 @@ BaseFilter::~BaseFilter()
{
}
QList<GeoDataObject*>::const_iterator BaseFilter::objectsBegin() const
{
return m_objects.begin();
}
QList<GeoDataObject*>::const_iterator BaseFilter::objectsEnd() const
{
return m_objects.end();
}
......@@ -28,6 +28,9 @@ public:
virtual void process() = 0;
QList<GeoDataObject*>::const_iterator objectsBegin() const;
QList<GeoDataObject*>::const_iterator objectsEnd() const;
protected:
GeoDataDocument* m_document;
QList<GeoDataObject*> m_objects;
......
......@@ -27,6 +27,9 @@ BaseFilter.cpp
LineStringProcessor.cpp
TinyPlanetProcessor.cpp
NodeReducer.cpp
TagsFilter.cpp
WayConcatenator.cpp
WayChunk.cpp
)
add_definitions( -DMAKE_MARBLE_LIB )
......
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Akshat Tandon <akshat.tandon@research.iiit.ac.in>
//
#include <QString>
#include <QStringList>
#include "PlacemarkFilter.h"
#include "TagsFilter.h"
#include "GeoDataObject.h"
#include "GeoDataDocument.h"
#include "OsmPlacemarkData.h"
#include "GeoDataPlacemark.h"
namespace Marble{
TagsFilter::TagsFilter(GeoDataDocument *document, const QStringList &tagsList, bool andFlag ) : PlacemarkFilter(document)
{
int total=0, tagCount=0;
// qDebug()<<"Entered tagFilter";
QList<GeoDataObject*> previousObjects(m_objects);
m_objects.clear();
foreach (GeoDataObject *object, previousObjects) {
++total;
GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(object);
bool flag = andFlag;
QStringList::const_iterator itr = tagsList.begin();
for (; itr != tagsList.end(); ++itr) {
QStringList currentTag = (*itr).split('=');
QString currentKey;
QString currentValue;
if (currentTag.size() != 2) {
qDebug()<< "Invalid tag : "<< currentTag<<" ,rejecting it"<<endl;
continue;
} else {
currentKey = currentTag[0].trimmed();
currentValue = currentTag[1].trimmed();
}
bool contains;
if (currentValue == "*") {
contains = placemark->osmData().containsTagKey(currentKey);
} else {
contains = placemark->osmData().containsTag(currentKey, currentValue);
}
if (!contains) {
if (andFlag) {
flag = false;
break;
}
} else {
if (!andFlag) {
flag = true;
break;
}
}
}
if (flag) {
++tagCount;
// qDebug()<<"Contained tag";
m_objects.append(object);
// qDebug()<<"ID "<<placemark->osmData().id();
} else {
m_rejectedObjects.append(object);
}
}
// qDebug()<<"Done TagFiltering";
// qDebug()<<"Total"<<total;
// qDebug()<<"TagCount"<<tagcon;
// qDebug()<<"Is and : "<<andFlag;
}
void TagsFilter::process()
{
//does nothing
}
}
QList<GeoDataObject*>::const_iterator TagsFilter::rejectedObjectsBegin() const
{
return m_rejectedObjects.begin();
}
QList<GeoDataObject*>::const_iterator TagsFilter::rejectedObjectsEnd() const
{
return m_rejectedObjects.end();
}
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Akshat Tandon <akshat.tandon@research.iiit.ac.in>
//
#ifndef MARBLE_TAGSFILTER_H
#define MARBLE_TAGSFILTER_H
#include "PlacemarkFilter.h"
#include <QMap>
#include <QString>
namespace Marble{
class GeoDataDocument;
class TagsFilter : public PlacemarkFilter
{
public:
//Filters placemarks which have tags in the hash
TagsFilter(GeoDataDocument* document, const QStringList& tagsList, bool andFlag = false);
virtual void process();
QList<GeoDataObject*>::const_iterator rejectedObjectsBegin() const;
QList<GeoDataObject*>::const_iterator rejectedObjectsEnd() const;
private:
QList<GeoDataObject*> m_rejectedObjects;
};
}
#endif
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Akshat Tandon <akshat.tandon@research.iiit.ac.in>
//
#include <QList>
#include <QVector>
#include <QDebug>
#include "WayChunk.h"
#include "GeoDataCoordinates.h"
#include "GeoDataFeature.h"
#include "GeoDataPlacemark.h"
#include "GeoDataLineString.h"
#include "OsmPlacemarkData.h"
namespace Marble
{
WayChunk::WayChunk(GeoDataPlacemark *placemark, qint64 first, qint64 last)
{
m_wayList.append(placemark);
m_first = first;
m_last = last;
m_visualCategory = placemark->visualCategory();
}
WayChunk::~WayChunk()
{
}
qint64 WayChunk::first() const
{
return m_first;
}
qint64 WayChunk::last() const
{
return m_last;
}
void WayChunk::append(GeoDataPlacemark *placemark, qint64 last)
{
m_wayList.append(placemark);
m_last = last;
}
void WayChunk::prepend(GeoDataPlacemark *placemark, qint64 first)
{
m_wayList.prepend(placemark);
m_first = first;
}
void WayChunk::append(WayChunk *chunk)
{
m_wayList << chunk->m_wayList;
m_last = chunk->last();
}
GeoDataPlacemark* WayChunk::merge()
{
Q_ASSERT(!m_wayList.isEmpty());
GeoDataPlacemark *placemark = new GeoDataPlacemark(*(m_wayList.first()));
GeoDataLineString *line = static_cast<GeoDataLineString*>(placemark->geometry());
QList<GeoDataPlacemark*>::iterator itr = m_wayList.begin();
QList<GeoDataPlacemark*>::iterator itrEnd = m_wayList.end();
++itr;
for (; itr != itrEnd; ++itr) {
GeoDataLineString *currentLine = static_cast<GeoDataLineString*>( (*itr)->geometry() );
currentLine->remove(0);
(*line) << *currentLine;
}
//qDebug()<<"Merging placemark";
return placemark;
}
void WayChunk::reverse()
{
std::reverse(m_wayList.begin(), m_wayList.end());
QList<GeoDataPlacemark*>::iterator itr = m_wayList.begin();
for (; itr != m_wayList.end(); ++itr) {
GeoDataPlacemark *placemark = *itr;
GeoDataLineString *line = static_cast<GeoDataLineString*>(placemark->geometry());
line->reverse();
}
qSwap(m_first, m_last);
}
qint64 WayChunk::id() const
{
return m_wayList.first()->osmData().id();
}
void WayChunk::printIds() const
{
QList<GeoDataPlacemark*>::const_iterator itr = m_wayList.begin();
qDebug()<<"IDs of placemarks in chunk";
for (; itr != m_wayList.end(); ++itr) {
qDebug()<<"Id :- "<<(*itr)->osmData().id();
}
}
int WayChunk::size() const
{
return m_wayList.size();
}
bool WayChunk::concatPossible(GeoDataPlacemark *placemark) const
{
GeoDataFeature::GeoDataVisualCategory category = placemark->visualCategory();
return (category == m_visualCategory);
}
GeoDataFeature::GeoDataVisualCategory WayChunk::visualCategory() const
{
return m_visualCategory;
}
}
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Akshat Tandon <akshat.tandon@research.iiit.ac.in>
//
#ifndef MARBLE_WAYCHUNK_H
#define MARBLE_WAYCHUNK_H
#include <QList>
#include "GeoDataFeature.h"
#include "GeoDataLineString.h"
namespace Marble
{
class GeoDataPlacemark;
class WayChunk
{
public:
WayChunk(GeoDataPlacemark *placemark, qint64 first, qint64 last );
~WayChunk();
void append(GeoDataPlacemark *placemark, qint64 last);
void append(WayChunk *chunk);
void prepend(GeoDataPlacemark *placemark, qint64 first);
/*
* Creates a new placemark object by concatenating all the linsetrings which exist in the WayChunk
* Caller has the responsibility of deleting the object.
*/
GeoDataPlacemark* merge();
qint64 first() const;
qint64 last() const;
void reverse();
qint64 id() const;
void printIds() const;
int size() const;
bool concatPossible(GeoDataPlacemark *placemark) const;
GeoDataFeature::GeoDataVisualCategory visualCategory() const;
private:
QList<GeoDataPlacemark*> m_wayList;
qint64 m_first;
qint64 m_last;
GeoDataFeature::GeoDataVisualCategory m_visualCategory;
};
}
#endif
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Akshat Tandon <akshat.tandon@research.iiit.ac.in>
//
#include <QList>
#include <QHash>
#include "GeoDataPlacemark.h"
#include "GeoDataDocument.h"
#include "GeoDataObject.h"
#include "OsmPlacemarkData.h"
#include "StyleBuilder.h"
#include "WayConcatenator.h"
#include "WayChunk.h"
#include "TagsFilter.h"
namespace Marble
{
WayConcatenator::WayConcatenator(GeoDataDocument *document, const QStringList &tagsList, bool andFlag) : TagsFilter(document, tagsList, andFlag)
{
// qDebug()<< "Entered WayConcatenator";
}
WayConcatenator::~WayConcatenator()
{
QVector<WayChunk*>::iterator itr = m_chunks.begin();
for (; itr != m_chunks.end(); ++itr) {
delete *itr;
}
}
void WayConcatenator::process()
{
qint64 count = 0;
qint64 chunkCount = 0;
qint64 newCount = 0;
qint64 placemarkCount = 0;
// qDebug()<<"** Number of TagFiletered placemarks "<< m_objects.size();
foreach (GeoDataObject *object, m_objects) {
GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(object);
qDebug()<<" ";
++placemarkCount;
// qDebug()<<"No."<<plcCount;
if (placemark->geometry()->nodeType() == GeoDataTypes::GeoDataLineStringType) {
qDebug()<<"-- Placemark ID : "<<placemark->osmData().id()<<" visualCategory: "<<StyleBuilder::visualCategoryName(placemark->visualCategory());
GeoDataLineString *line = static_cast<GeoDataLineString*>(placemark->geometry());
qint64 firstId = placemark->osmData().nodeReference(line->first()).id();
qint64 lastId = placemark->osmData().nodeReference(line->last()).id();
bool containsFirst = m_hash.contains(firstId);
bool containsLast = m_hash.contains(lastId);
if (!containsFirst && !containsLast) {
qDebug()<<"No coords matched, creating a new chunk";
createWayChunk(placemark, firstId, lastId);
++count;
++chunkCount;
} else if (containsFirst && !containsLast) {
qDebug()<<"First coord matched";
WayChunk *chunk = getWayChunk(placemark, firstId);
if (chunk != nullptr) {
// qDebug()<< "First* Chunk found, concatenating to it";
concatFirst(placemark, chunk);
} else {
// qDebug()<<"";
qDebug()<< "First* No possible chunk found, creating a new chunk";
qDebug()<<"FirstId"<<firstId;
qDebug()<<"lastId"<<lastId;
// qDebug()<<"";
createWayChunk(placemark, firstId, lastId);
++chunkCount;
++newCount;
}
++count;
} else if (!containsFirst && containsLast) {
qDebug()<<"Last coord matched";
WayChunk *chunk = getWayChunk(placemark, lastId);
if (chunk != nullptr) {
// qDebug()<< "Last* Chunk found, concatenating to it";
concatLast(placemark, chunk);
} else {
// qDebug()<<"";
qDebug()<< "Last* No possible chunk found, creating a new chunk";
qDebug()<<"FirstId"<<firstId;
qDebug()<<"lastId"<<lastId;
// qDebug()<<"";
createWayChunk(placemark, firstId, lastId);
++chunkCount;
++newCount;
}
++count;
} else if (containsFirst && containsLast) {
qDebug()<<"Both coord matched";
WayChunk *chunk = getWayChunk(placemark, firstId);
WayChunk *otherChunk = getWayChunk(placemark, lastId);
if (chunk != nullptr && otherChunk != nullptr) {
// qDebug()<< "Both* Both chunks found, concatenating to it";
if(chunk == otherChunk){
qDebug()<<"#### Both the chunks are same, directly adding to the list of placemarks";
m_placemarks.append(*placemark);
} else {
concatBoth(placemark, chunk, otherChunk);
++count;
}
} else if(chunk != nullptr && otherChunk == nullptr) {
// qDebug()<< "Both* First chunk found, concatenating to it";
concatFirst(placemark, chunk);
++count;
} else if(chunk == nullptr && otherChunk != nullptr) {
// qDebug()<< "Both* Last chunk found, concatenating to it";
concatLast(placemark, otherChunk);
++count;
} else {
// qDebug()<<"";
qDebug()<< "Both* No possible chunk found, creating a new chunk";
qDebug()<<"FirstId"<<firstId;
qDebug()<<"lastId"<<lastId;
// qDebug()<<"";
createWayChunk(placemark, firstId, lastId);
++chunkCount;
++newCount;
++count;
}
}
// if(flag){
// qDebug()<<" Concat not possible";
// m_placemarks.append(*placemark);
// }
} else{
m_placemarks.append(*placemark);
}
}
addRejectedPlacemarks();
addWayChunks();
modifyDocument();
qDebug()<<"####################################";
qDebug()<<"Total OSM ways concatenated: "<<count;
qDebug()<<"* Counted no. of chunks: "<<chunkCount;
qDebug()<<"* Chunks formed due to no match"<<newCount;
// qDebug()<<"Total reverses required: "<<rvr;
}
void WayConcatenator::addRejectedPlacemarks()
{
QList<GeoDataObject*>::const_iterator itr = rejectedObjectsBegin();
QList<GeoDataObject*>::const_iterator endItr = rejectedObjectsEnd();
for (; itr != endItr; ++itr) {
GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(*itr);
m_placemarks.append(*placemark);
}
}
void WayConcatenator::addWayChunks()
{
qint64 totalSize = 0;
QSet<WayChunk*> chunkSet;
// QList<WayChunk*> chunkList = m_hash.values();
// QList<WayChunk*>::iterator cItr = chunkList.begin();
// qDebug()<<"* Chunk list size = "<<chunkList.size();
QVector<WayChunk*>::iterator itr = m_chunks.begin();
for (; itr != m_chunks.end(); ++itr) {
if (!chunkSet.contains(*itr)) {
chunkSet.insert(*itr);
GeoDataPlacemark* placemark = (*itr)->merge();
if (placemark) {
m_placemarks.append(*placemark);
totalSize += (*itr)->size();
qDebug()<<"Chunk:";
(*itr)->printIds();
qDebug()<<"Size of this chunk"<<(*itr)->size();
qDebug()<<"Merged";
qDebug()<<" ";
delete placemark;
}
}
}
qDebug()<<"*** Total number of ways merged"<<totalSize;
qDebug()<<"******* m_chunks vector size"<<m_chunks.size();
// qDebug()<< "Entered 1";
}
void WayConcatenator::modifyDocument()
{
m_document->clear();
QList<GeoDataPlacemark>::iterator itr;
itr = m_placemarks.begin();
for (; itr != m_placemarks.end(); ++itr) {
GeoDataPlacemark *placemark = new GeoDataPlacemark(*itr);
m_document->append(placemark);
}
}
void WayConcatenator::createWayChunk(GeoDataPlacemark *placemark, qint64 firstId, qint64 lastId)
{
WayChunk *chunk = new WayChunk(placemark, firstId, lastId);
m_hash.insert(firstId, chunk);
if (firstId != lastId) {
m_hash.insert(lastId, chunk);
}
m_chunks.append(chunk);
}