source: subversion/applications/utils/import/srtm2wayinfo/relations.cpp

Last change on this file was 18202, checked in by herm, 8 years ago

Added a type tag to the generated relations.

File size: 4.1 KB
Line 
1/* Copyright (c) 2009 Hermann Kraus
2 * This software is available under a "MIT Style" license
3 * (see COPYING).
4 */
5/** \file
6  * Create altitude relations from an OSMData object.
7  */
8#include "relations.h"
9#include "osm-parse.h"
10#include "srtm.h"
11
12#include <QIODevice>
13
14/** Create a new relation writer object. */
15RelationWriter::RelationWriter(OsmData *data, QIODevice *output, SrtmDownloader *downloader)
16{
17    this->data = data;
18    this->output = output;
19    relationId = -1;
20    this->downloader = downloader;
21}
22
23/** Write relations to file. */
24void RelationWriter::writeRelations()
25{
26    output->write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
27        "<osm version=\"0.6\" generator=\"SRTM2Wayinfo\">\n");
28    OsmWay way;
29    data->ways->startReading();
30    while (data->ways->get(way)) {
31        processWay(&way);
32    }
33    output->write("</osm>\n");
34}
35
36/** Process a single way.
37  * Creates a new relation for every part of the way between to intersections.
38  */
39void RelationWriter::processWay(OsmWay *way)
40{
41    OsmNodeId startNode = 0, lastNode = 0; //No node 0 exists
42    float length = 0, up = 0, down = 0;
43    OsmNodeId id;
44    foreach (id, way->nodes) {
45        if (startNode == 0) {
46            startNode = id;
47            lastNode = id;
48            continue;
49        }
50        calc(lastNode, id, &length, &up, &down);
51        lastNode = id;
52        if ((*data->nodes)[id].isIntersection()) {
53            writeRelation(way->id, startNode, id, length, up, down);
54            startNode = id;
55            length = 0;
56            up = 0;
57            down = 0;
58        }
59    }
60    if (startNode != id) {
61        //Write info for last segment of way
62        writeRelation(way->id, startNode, id, length, up, down);
63    }
64}
65
66/** Writes a single relation to file. */
67void RelationWriter::writeRelation(OsmWayId wayId, OsmNodeId startNode, OsmNodeId endNode, float length, float up, float down)
68{
69    //Note: QString::arg is not locale dependent except if the parameter is written as %L1
70    QString text =
71        QString("<relation id=\"%1\" visible=\"true\">\n"
72        "\t<member type=\"way\" ref=\"%2\" role=\"\"/>\n"
73        "\t<member type=\"node\" ref=\"%3\" role=\"from\"/>\n"
74        "\t<member type=\"node\" ref=\"%4\" role=\"to\"/>\n"
75        "\t<tag k=\"length\" v=\"%5\"/>\n"
76        "\t<tag k=\"up\" v=\"%6\"/>\n"
77        "\t<tag k=\"down\" v=\"%7\"/>\n"
78        "\t<tag k=\"type\" v=\"altitude\">\n"
79        "</relation>\n").arg(relationId--).arg(wayId).arg(startNode).arg(endNode).arg(length, 3, 'f').arg(up, 3, 'f').arg(down, 4, 'f');
80    output->write(text.toAscii());
81}
82
83/** Calculates distance and altitude differences between two nodes. */
84void RelationWriter::calc(OsmNodeId from, OsmNodeId to, float *length, float *up, float *down)
85{
86    *length += distance((*data->nodes)[from].lat(), (*data->nodes)[from].lon(), (*data->nodes)[to].lat(), (*data->nodes)[to].lon());
87    calcUpDown((*data->nodes)[from].lat(), (*data->nodes)[from].lon(), (*data->nodes)[to].lat(), (*data->nodes)[to].lon(), up, down);
88}
89
90/** Calculate the altitude differences.
91  *
92  * If the distance between two nodes is longer than the average distance between 2 SRTM points
93  * the segment is split recursively until it is shorter than this distance.
94  */
95void RelationWriter::calcUpDown(float from_lat, float from_lon, float to_lat, float to_lon, float *up, float *down)
96{
97    float dist = distance(from_lat, from_lon, to_lat, to_lon);
98    if (dist < MAX_DIST) {
99        float alt_from = downloader->getAltitudeFromLatLon(from_lat, from_lon);
100        float alt_to   = downloader->getAltitudeFromLatLon(to_lat, to_lon);
101        if (alt_from == SRTM_DATA_VOID || alt_to == SRTM_DATA_VOID) return; //Do nothing when no data is available.
102        float diff = alt_to - alt_from;
103        if (diff > 0.0) {
104            *up += diff;
105        } else {
106            *down -= diff;
107        }
108    } else {
109        float center_lat = (from_lat + to_lat) / 2;
110        float center_lon = (from_lon + to_lon) / 2;
111        //Go on recursively
112        calcUpDown(from_lat, from_lon, center_lat, center_lon, up, down);
113        calcUpDown(center_lat, center_lon, to_lat, to_lon, up, down);
114    }
115}
116
Note: See TracBrowser for help on using the repository browser.