summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Nienhüser <[email protected]>2015-09-09 10:12:05 +0200
committerDennis Nienhüser <[email protected]>2015-09-09 10:14:52 +0200
commit310893cc36fd043da4a780471d708ed291bbce79 (patch)
treebb28c942e91e04cabe459f5373f05d547c60c852
parent2ddbd502b424480845c820936b344fdaef4862dc (diff)
Calculate highway width based on tags
The width of highways cannot be determined from a single tag alone. After parsing an .osm file, run over it and adjust the style for highways' physical width based on their tag values.
-rw-r--r--src/plugins/runner/osm/OsmParser.cpp37
-rw-r--r--src/plugins/runner/osm/OsmParser.h5
-rw-r--r--src/plugins/runner/osm/OsmRunner.cpp1
3 files changed, 43 insertions, 0 deletions
diff --git a/src/plugins/runner/osm/OsmParser.cpp b/src/plugins/runner/osm/OsmParser.cpp
index 5769176..26066ef 100644
--- a/src/plugins/runner/osm/OsmParser.cpp
+++ b/src/plugins/runner/osm/OsmParser.cpp
@@ -17,6 +17,8 @@
#include "GeoDataDocument.h"
#include "GeoDataPlacemark.h"
#include "GeoDataPoint.h"
+#include "GeoDataTypes.h"
+#include "GeoDataStyle.h"
namespace Marble {
@@ -109,11 +111,46 @@ void OsmParser::addDummyPlacemark( GeoDataPlacemark *placemark )
m_dummyPlacemarks << placemark;
}
+void OsmParser::adjustStyles(GeoDataDocument* document)
+{
+ for (int i=0, n=document->size(); i<n; ++i) {
+ GeoDataFeature* feature = document->child(i);
+ if (feature->nodeType() == GeoDataTypes::GeoDataPlacemarkType) {
+ GeoDataPlacemark* placemark = static_cast<GeoDataPlacemark*>(feature);
+ if (isHighway(placemark)) {
+ calculateHighwayWidth(placemark);
+ }
+ }
+ }
+}
+
bool OsmParser::isValidRootElement()
{
return isValidElement(osm::osmTag_osm);
}
+bool OsmParser::isHighway(const GeoDataPlacemark *placemark) const
+{
+ return placemark->visualCategory() >= GeoDataFeature::HighwaySteps &&
+ placemark->visualCategory() <= GeoDataFeature::HighwayMotorway;
+}
+
+void OsmParser::calculateHighwayWidth(GeoDataPlacemark *placemark) const
+{
+ OsmPlacemarkData const & data = placemark->osmData();
+ bool const isOneWay = data.containsTag("oneway", "yes") || data.containsTag("oneway", "-1");
+ int const lanes = isOneWay ? 1 : 2; // also for motorway which implicitly is one way, but has two lanes and each direction has its own highway
+ double const laneWidth = 3.0;
+ double const margins = placemark->visualCategory() == GeoDataFeature::HighwayMotorway ? 2.0 : (isOneWay ? 1.0 : 0.0);
+ double const physicalWidth = margins + lanes * laneWidth;
+
+ GeoDataLineStyle lineStyle = placemark->style()->lineStyle();
+ lineStyle.setPhysicalWidth(physicalWidth);
+ GeoDataStyle* style = new GeoDataStyle(*placemark->style());
+ style->setLineStyle(lineStyle);
+ placemark->setStyle(style);
+}
+
bool OsmParser::isValidElement(const QString& tagName) const
{
if (!GeoParser::isValidElement(tagName))
diff --git a/src/plugins/runner/osm/OsmParser.h b/src/plugins/runner/osm/OsmParser.h
index e646ee3..4ff5474 100644
--- a/src/plugins/runner/osm/OsmParser.h
+++ b/src/plugins/runner/osm/OsmParser.h
@@ -28,6 +28,7 @@ class GeoDataPlacemark;
class GeoDataPoint;
class GeoDataPolygon;
class OsmPlacemarkData;
+class GeoDataDocument;
class OsmParser : public GeoParser
{
@@ -49,9 +50,13 @@ public:
static const QColor backgroundColor;
+ void adjustStyles(GeoDataDocument* document);
+
private:
virtual bool isValidElement(const QString& tagName) const;
virtual bool isValidRootElement();
+ bool isHighway(const GeoDataPlacemark *placemark) const;
+ void calculateHighwayWidth(GeoDataPlacemark *placemark) const;
virtual GeoDocument* createDocument() const;
diff --git a/src/plugins/runner/osm/OsmRunner.cpp b/src/plugins/runner/osm/OsmRunner.cpp
index 6822058..d46784f 100644
--- a/src/plugins/runner/osm/OsmRunner.cpp
+++ b/src/plugins/runner/osm/OsmRunner.cpp
@@ -47,6 +47,7 @@ void OsmRunner::parseFile( const QString &fileName, DocumentRole role = UnknownD
GeoDocument* document = parser.releaseDocument();
Q_ASSERT( document );
GeoDataDocument* doc = static_cast<GeoDataDocument*>( document );
+ parser.adjustStyles(doc);
doc->setDocumentRole( role );
doc->setFileName( fileName );