Commit 43f3168e authored by Dennis Nienhüser's avatar Dennis Nienhüser

Create placemarks with point geometry from non-trivial way nodes

Previously all nodes of the OSM file were examined (including those
part of ways and polygons) and completely discarded if their tags
did not result in a visual category or the visual category was a
highway one.

Now those nodes which are part of ways and polygons are removed early
in case they are trivial (have just a coordinate and an id). This is
fine because them being part of a way of polygon ensures all
information is still available. Otherwise they are kept.

This ensures that stale nodes (trivial but not referenced) are not
discarded anymore. Parsing should be slightly faster also given
that trivial nodes which are part of ways are not tried to be
converted to a placemark anymore.
parent 61c23847
......@@ -278,6 +278,21 @@ bool OsmPlacemarkData::isNull() const
return !m_id;
}
bool OsmPlacemarkData::isEmpty() const
{
return m_tags.isEmpty() &&
m_nodeReferences.isEmpty() &&
m_memberReferences.isEmpty() &&
m_relationReferences.isEmpty() &&
m_version.isEmpty() &&
m_changeset.isEmpty() &&
m_uid.isEmpty() &&
m_visible.isEmpty() &&
m_user.isEmpty() &&
m_timestamp.isEmpty() &&
m_action.isEmpty();
}
OsmPlacemarkData OsmPlacemarkData::fromParserAttributes( const QXmlStreamAttributes &attributes )
{
OsmPlacemarkData osmData;
......
......@@ -187,6 +187,11 @@ public:
*/
bool isNull() const;
/**
* @brief isEmpty returns true if no attribute other than the id has been set
*/
bool isEmpty() const;
/**
* @brief fromParserAttributes is a convenience function that parses all osm-related
* arguments of a tag
......
......@@ -34,15 +34,15 @@ void OsmNode::setCoordinates(const GeoDataCoordinates &coordinates)
void OsmNode::create(GeoDataDocument *document) const
{
GeoDataFeature::GeoDataVisualCategory const category = OsmPresetLibrary::determineVisualCategory(m_osmData);
if (category == GeoDataFeature::None ||
(category >= GeoDataFeature::HighwaySteps && category <= GeoDataFeature::HighwayMotorway)) {
return;
}
GeoDataPlacemark* placemark = new GeoDataPlacemark;
placemark->setOsmData(m_osmData);
placemark->setCoordinate(m_coordinates);
if (category == GeoDataFeature::None) {
placemark->setVisible(false);
}
if ((category == GeoDataFeature::TransportCarShare || category == GeoDataFeature::MoneyAtm)
&& m_osmData.containsTagKey("operator")) {
placemark->setName(m_osmData.tagValue("operator"));
......
......@@ -193,16 +193,22 @@ GeoDataDocument *OsmParser::createDocument(OsmNodes &nodes, OsmWays &ways, OsmRe
backgroundStyle->setId( "background" );
document->addStyle( backgroundStyle );
QSet<qint64> usedWays;
QSet<qint64> usedNodes, usedWays;
foreach(OsmRelation const &relation, relations) {
relation.create(document, ways, nodes, usedWays);
relation.create(document, ways, nodes, usedNodes, usedWays);
}
foreach(qint64 id, usedWays) {
ways.remove(id);
}
foreach(OsmWay const &way, ways) {
way.create(document, nodes);
way.create(document, nodes, usedNodes);
}
foreach(qint64 id, usedNodes) {
if (nodes[id].osmData().isEmpty()) {
nodes.remove(id);
}
}
foreach(OsmNode const &node, nodes) {
......
......@@ -48,7 +48,7 @@ void OsmRelation::addMember(qint64 reference, const QString &role, const QString
m_members << member;
}
void OsmRelation::create(GeoDataDocument *document, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedWays) const
void OsmRelation::create(GeoDataDocument *document, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedNodes, QSet<qint64> &usedWays) const
{
if (!m_osmData.containsTag("type", "multipolygon")) {
return;
......@@ -58,7 +58,8 @@ void OsmRelation::create(GeoDataDocument *document, const OsmWays &ways, const O
QStringList const outerRoles = QStringList() << "outer" << "";
QSet<qint64> outerWays;
QList<GeoDataLinearRing> outer = rings(outerRoles, ways, nodes, outerWays);
QSet<qint64> outerNodes;
QList<GeoDataLinearRing> outer = rings(outerRoles, ways, nodes, outerNodes, outerWays);
if (outer.isEmpty()) {
return;
} else if (outer.size() > 1) {
......@@ -115,7 +116,7 @@ void OsmRelation::create(GeoDataDocument *document, const OsmWays &ways, const O
QStringList const innerRoles = QStringList() << "inner";
QSet<qint64> innerWays;
QList<GeoDataLinearRing> inner = rings(innerRoles, ways, nodes, innerWays);
QList<GeoDataLinearRing> inner = rings(innerRoles, ways, nodes, usedNodes, innerWays);
foreach(qint64 wayId, innerWays) {
Q_ASSERT(ways.contains(wayId));
if (OsmPresetLibrary::determineVisualCategory(ways[wayId].osmData()) == GeoDataFeature::None) {
......@@ -129,14 +130,16 @@ void OsmRelation::create(GeoDataDocument *document, const OsmWays &ways, const O
polygon->appendInnerBoundary(ring);
}
placemark->setGeometry(polygon);
usedNodes |= outerNodes;
OsmObjectManager::registerId( m_osmData.id() );
document->append(placemark);
}
QList<GeoDataLinearRing> OsmRelation::rings(const QStringList &roles, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedWays) const
QList<GeoDataLinearRing> OsmRelation::rings(const QStringList &roles, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedNodes, QSet<qint64> &usedWays) const
{
QSet<qint64> currentWays;
QSet<qint64> currentNodes;
QList<qint64> roleMembers;
foreach(const OsmMember &member, m_members) {
if (roles.contains(member.role)) {
......@@ -193,6 +196,7 @@ QList<GeoDataLinearRing> OsmRelation::rings(const QStringList &roles, const OsmW
}
if ( id != lastReference ) {
ring << nodes[id].coordinates();
currentNodes << id;
}
}
lastReference = isReversed ? nextWay.references().first()
......@@ -217,6 +221,7 @@ QList<GeoDataLinearRing> OsmRelation::rings(const QStringList &roles, const OsmW
}
usedWays |= currentWays;
usedNodes |= currentNodes;
return result;
}
......
......@@ -32,7 +32,7 @@ public:
const OsmPlacemarkData & osmData() const;
void create(GeoDataDocument* document, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedWays) const;
void create(GeoDataDocument* document, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedNodes, QSet<qint64> &usedWays) const;
private:
struct OsmMember
......@@ -44,7 +44,7 @@ private:
OsmMember();
};
QList<GeoDataLinearRing> rings(const QStringList &roles, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedWays) const;
QList<GeoDataLinearRing> rings(const QStringList &roles, const OsmWays &ways, const OsmNodes &nodes, QSet<qint64> &usedNodes, QSet<qint64> &usedWays) const;
OsmPlacemarkData m_osmData;
QVector<OsmMember> m_members;
......
......@@ -22,7 +22,7 @@ namespace Marble {
QSet<QString> OsmWay::s_areaTags;
void OsmWay::create(GeoDataDocument *document, const OsmNodes &nodes) const
void OsmWay::create(GeoDataDocument *document, const OsmNodes &nodes, QSet<qint64> &usedNodes) const
{
bool const shouldRender =
!m_osmData.containsTagKey("area:highway") && // Not supported yet
......@@ -57,6 +57,7 @@ void OsmWay::create(GeoDataDocument *document, const OsmNodes &nodes) const
OsmNode const & node = nodeIter.value();
placemark->osmData().addNodeReference(node.coordinates(), node.osmData());
linearRing->append(node.coordinates());
usedNodes << nodeId;
}
*linearRing = GeoDataLinearRing(linearRing->optimized());
......@@ -74,6 +75,7 @@ void OsmWay::create(GeoDataDocument *document, const OsmNodes &nodes) const
OsmNode const & node = nodeIter.value();
placemark->osmData().addNodeReference(node.coordinates(), node.osmData());
lineString->append(node.coordinates());
usedNodes << nodeId;
}
*lineString = lineString->optimized();
......
......@@ -30,7 +30,7 @@ public:
const OsmPlacemarkData & osmData() const;
const QVector<qint64> &references() const;
void create(GeoDataDocument* document, const OsmNodes &nodes) const;
void create(GeoDataDocument* document, const OsmNodes &nodes, QSet<qint64> &usedNodes) const;
private:
bool isArea() const;
......
Markdown is supported
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