qreal totalDistance() const { GeoDataLineString measure; GeoDataCoordinates sourcePosition(m_source.longitude(), m_source.latitude()); GeoDataCoordinates targetPosition(m_target.longitude(), m_target.latitude()); measure << sourcePosition << targetPosition; return measure.length(m_planetRadius); }
qreal YoursRunner::distance( const GeoDataDocument* document ) const { QVector<GeoDataFolder*> folders = document->folderList(); foreach( const GeoDataFolder *folder, folders ) { foreach( const GeoDataPlacemark *placemark, folder->placemarkList() ) { GeoDataGeometry* geometry = placemark->geometry(); if ( geometry->geometryId() == GeoDataLineStringId ) { GeoDataLineString* lineString = dynamic_cast<GeoDataLineString*>( geometry ); Q_ASSERT( lineString && "Internal error: geometry ID does not match class type" ); return lineString->length( EARTH_RADIUS ); } } }
GeoDataDocument* MapQuestRunner::parse( const QByteArray &content ) const { QDomDocument xml; if ( !xml.setContent( content ) ) { mDebug() << "Cannot parse xml file with routing instructions."; return 0; } // mDebug() << xml.toString(2); QDomElement root = xml.documentElement(); GeoDataDocument* result = new GeoDataDocument(); result->setName( "MapQuest" ); GeoDataPlacemark* routePlacemark = new GeoDataPlacemark; routePlacemark->setName( "Route" ); GeoDataLineString* routeWaypoints = new GeoDataLineString; QDomNodeList shapePoints = root.elementsByTagName( "shapePoints" ); if ( shapePoints.size() == 1 ) { QDomNodeList geometry = shapePoints.at( 0 ).toElement().elementsByTagName( "latLng" ); for ( int i=0; i<geometry.size(); ++i ) { double const lat = geometry.item( i ).namedItem( "lat" ).toElement().text().toDouble(); double const lon = geometry.item( i ).namedItem( "lng" ).toElement().text().toDouble(); GeoDataCoordinates const position( lon, lat, 0.0, GeoDataCoordinates::Degree ); routeWaypoints->append( position ); } } routePlacemark->setGeometry( routeWaypoints ); QTime time; time = time.addSecs( root.elementsByTagName( "time" ).at( 0 ).toElement().text().toInt() ); qreal length = routeWaypoints->length( EARTH_RADIUS ); const QString name = nameString( "MQ", length, time ); const GeoDataExtendedData data = routeData( length, time ); routePlacemark->setExtendedData( data ); result->setName( name ); result->append( routePlacemark ); QMap<int,int> mapping; QDomNodeList maneuvers = root.elementsByTagName( "maneuverIndexes" ); if ( maneuvers.size() == 1 ) { maneuvers = maneuvers.at( 0 ).childNodes(); for ( int i=0; i<maneuvers.size(); ++i ) { mapping[i] = maneuvers.at( i ).toElement().text().toInt(); if ( mapping[i] == routeWaypoints->size() ) { --mapping[i]; } } } QDomNodeList instructions = root.elementsByTagName( "maneuver" ); unsigned int const lastInstruction = qMax<int>( 0, instructions.length()-1 ); // ignore the last 'Welcome to xy' instruction for ( unsigned int i = 0; i < lastInstruction; ++i ) { QDomElement node = instructions.item( i ).toElement(); QDomNodeList maneuver = node.elementsByTagName( "turnType" ); QDomNodeList textNodes = node.elementsByTagName( "narrative" ); QDomNodeList points = node.elementsByTagName( "startPoint" ); QDomNodeList streets = node.elementsByTagName( "streets" ); Q_ASSERT( mapping.contains( i ) ); if ( textNodes.size() == 1 && maneuver.size() == 1 && points.size() == 1 && mapping.contains( i ) ) { GeoDataPlacemark* instruction = new GeoDataPlacemark; instruction->setName( textNodes.at( 0 ).toElement().text() ); GeoDataExtendedData extendedData; GeoDataData turnType; turnType.setName( "turnType" ); turnType.setValue( maneuverType( maneuver.at( 0 ).toElement().text().toInt() ) ); extendedData.addValue( turnType ); if ( streets.size() == 1 ) { GeoDataData roadName; roadName.setName( "roadName" ); roadName.setValue( streets.at( 0 ).toElement().text() ); extendedData.addValue( roadName ); } instruction->setExtendedData( extendedData ); int const start = mapping[i]; int const end = mapping.contains(i+1) ? mapping[i+1] : routeWaypoints->size()-1; if ( start >= 0 && start < routeWaypoints->size() && end < routeWaypoints->size() ) { instruction->setName( textNodes.item( 0 ).toElement().text() ); GeoDataLineString *lineString = new GeoDataLineString; for ( int j=start; j<=end; ++j ) { *lineString << GeoDataCoordinates( routeWaypoints->at( j ).longitude(), routeWaypoints->at( j ).latitude() ); } if ( !lineString->isEmpty() ) { instruction->setGeometry( lineString ); result->append( instruction ); } } } } if ( routeWaypoints->size() < 1 ) { delete result; result = 0; } return result; }
GeoDataDocument* OpenRouteServiceRunner::parse( const QByteArray &content ) const { QDomDocument xml; if ( !xml.setContent( content ) ) { mDebug() << "Cannot parse xml file with routing instructions."; return nullptr; } QDomElement root = xml.documentElement(); GeoDataDocument* result = new GeoDataDocument(); result->setName(QStringLiteral("OpenRouteService")); QDomNodeList errors = root.elementsByTagName(QStringLiteral("xls:Error")); if ( errors.size() > 0 ) { return nullptr; // Returning early because fallback routing providers are used now // The code below can be used to parse OpenGis errors reported by ORS // and may be useful in the future for (int i=0 ; i < errors.length(); ++i ) { QDomNode node = errors.item( i ); QString errorMessage = node.attributes().namedItem(QStringLiteral("message")).nodeValue(); QRegExp regexp = QRegExp( "^(.*) Please Check your Position: (-?[0-9]+.[0-9]+) (-?[0-9]+.[0-9]+) !" ); if ( regexp.indexIn( errorMessage ) == 0 ) { if ( regexp.capturedTexts().size() == 4 ) { GeoDataPlacemark* placemark = new GeoDataPlacemark; placemark->setName( regexp.capturedTexts().at( 1 ) ); GeoDataCoordinates position; position.setLongitude( regexp.capturedTexts().at( 2 ).toDouble(), GeoDataCoordinates::Degree ); position.setLatitude( regexp.capturedTexts().at( 3 ).toDouble(), GeoDataCoordinates::Degree ); placemark->setCoordinate( position ); result->append( placemark ); } } else { mDebug() << "Error message " << errorMessage << " not parsable."; /** @todo: How to handle this now with plugins? */ // QString message = tr( "Sorry, a problem occurred when calculating the route. Try adjusting start and destination points." ); // QPointer<QMessageBox> messageBox = new QMessageBox( QMessageBox::Warning, "Route Error", message ); // messageBox->setDetailedText( errorMessage ); // messageBox->exec(); // delete messageBox; } } } GeoDataPlacemark* routePlacemark = new GeoDataPlacemark; routePlacemark->setName(QStringLiteral("Route")); QTime time; QDomNodeList summary = root.elementsByTagName(QStringLiteral("xls:RouteSummary")); if ( summary.size() > 0 ) { QDomNodeList timeNodeList = summary.item(0).toElement().elementsByTagName(QStringLiteral("xls:TotalTime")); if ( timeNodeList.size() == 1 ) { QRegExp regexp = QRegExp( "^P(?:(\\d+)D)?T(?:(\\d+)H)?(?:(\\d+)M)?(\\d+)S" ); if ( regexp.indexIn( timeNodeList.item( 0 ).toElement().text() ) == 0 ) { QStringList matches = regexp.capturedTexts(); unsigned int hours( 0 ), minutes( 0 ), seconds( 0 ); switch ( matches.size() ) { case 5: // days = regexp.cap( matches.size() - 4 ).toInt(); // Intentionally no break case 4: hours = regexp.cap( matches.size() - 3 ).toInt(); // Intentionally no break case 3: minutes = regexp.cap( matches.size() - 2 ).toInt(); // Intentionally no break case 2: seconds = regexp.cap( matches.size() - 1 ).toInt(); break; default: mDebug() << "Unable to parse time string " << timeNodeList.item( 0 ).toElement().text(); } time = QTime( hours, minutes, seconds, 0 ); } } } GeoDataLineString* routeWaypoints = new GeoDataLineString; QDomNodeList geometry = root.elementsByTagName(QStringLiteral("xls:RouteGeometry")); if ( geometry.size() > 0 ) { QDomNodeList waypoints = geometry.item( 0 ).toElement().elementsByTagName( "gml:pos" ); for (int i=0 ; i < waypoints.length(); ++i ) { QDomNode node = waypoints.item( i ); const QStringList content = node.toElement().text().split(QLatin1Char(' ')); if ( content.length() == 2 ) { GeoDataCoordinates position; position.setLongitude( content.at( 0 ).toDouble(), GeoDataCoordinates::Degree ); position.setLatitude( content.at( 1 ).toDouble(), GeoDataCoordinates::Degree ); routeWaypoints->append( position ); } } } routePlacemark->setGeometry( routeWaypoints ); qreal length = routeWaypoints->length( EARTH_RADIUS ); const QString name = nameString( "ORS", length, time ); const GeoDataExtendedData data = routeData( length, time ); routePlacemark->setExtendedData( data ); result->setName( name ); result->append( routePlacemark ); QDomNodeList instructionList = root.elementsByTagName(QStringLiteral("xls:RouteInstructionsList")); if ( instructionList.size() > 0 ) { QDomNodeList instructions = instructionList.item(0).toElement().elementsByTagName(QStringLiteral("xls:RouteInstruction")); for (int i=0 ; i < instructions.length(); ++i ) { QDomElement node = instructions.item( i ).toElement(); QDomNodeList textNodes = node.elementsByTagName(QStringLiteral("xls:Instruction")); QDomNodeList positions = node.elementsByTagName(QStringLiteral("gml:pos")); if ( textNodes.size() > 0 && positions.size() > 0 ) { const QStringList content = positions.at(0).toElement().text().split(QLatin1Char(' ')); if ( content.length() == 2 ) { GeoDataLineString *lineString = new GeoDataLineString; for( int i = 0; i < positions.count(); ++i ) { const QStringList pointList = positions.at(i).toElement().text().split(QLatin1Char(' ')); GeoDataCoordinates position; position.setLongitude( pointList.at( 0 ).toDouble(), GeoDataCoordinates::Degree ); position.setLatitude( pointList.at( 1 ).toDouble(), GeoDataCoordinates::Degree ); lineString->append( position ); } GeoDataPlacemark* instruction = new GeoDataPlacemark; QString const text = textNodes.item( 0 ).toElement().text().remove(QRegExp("<[^>]*>")); GeoDataExtendedData extendedData; GeoDataData turnTypeData; turnTypeData.setName(QStringLiteral("turnType")); QString road; RoutingInstruction::TurnType turnType = parseTurnType( text, &road ); turnTypeData.setValue( turnType ); extendedData.addValue( turnTypeData ); if ( !road.isEmpty() ) { GeoDataData roadName; roadName.setName(QStringLiteral("roadName")); roadName.setValue( road ); extendedData.addValue( roadName ); } QString const instructionText = turnType == RoutingInstruction::Unknown ? text : RoutingInstruction::generateRoadInstruction( turnType, road ); instruction->setName( instructionText ); instruction->setExtendedData( extendedData ); instruction->setGeometry( lineString ); result->append( instruction ); } } } } return result; }
void EclipsesItem::calculate() { int np, kp, j; double lat1, lng1, lat2, lng2, lat3, lng3, lat4, lng4; double ltf[60], lnf[60]; m_ecl->putEclSelect( m_index ); // FIXME: set observer location m_ecl->getMaxPos( lat1, lng1 ); m_ecl->setLocalPos( lat1, lng1, 0 ); // eclipse's maximum location m_maxLocation = GeoDataCoordinates( lng1, lat1, 0., GeoDataCoordinates::Degree ); // calculate central line np = m_ecl->eclPltCentral( true, lat1, lng1 ); kp = np; m_centralLine.clear(); m_centralLine << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); if( np > 3 ) { // central eclipse while( np > 3 ) { np = m_ecl->eclPltCentral( false, lat1, lng1 ); if( np > 3 ) { m_centralLine << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } } } // calculate umbra np = kp; m_umbra.clear(); if( np > 3 ) { // total or annual eclipse // northern /southern boundaries of umbra np = m_ecl->centralBound( true, lat1, lng1, lat2, lng2 ); GeoDataLinearRing lowerUmbra( Tessellate ), upperUmbra( Tessellate ); lowerUmbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); upperUmbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); while( np > 0 ) { np = m_ecl->centralBound( false, lat1, lng1, lat2, lng2 ); if( lat1 <= 90. ) { lowerUmbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } if( lat1 <= 90. ) { upperUmbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng2, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat2, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } } GeoDataLinearRing invertedUpperUmbra( Tessellate ); QVector<GeoDataCoordinates>::const_iterator iter = upperUmbra.constEnd() - 1; for( ; iter != upperUmbra.constBegin(); --iter ) { invertedUpperUmbra << *iter; } invertedUpperUmbra << upperUmbra.first(); upperUmbra = invertedUpperUmbra; m_umbra << lowerUmbra << upperUmbra; } // shadow cones m_shadowConeUmbra.clear(); m_shadowConePenumbra.clear(); m_shadowCone60MagPenumbra.clear(); m_ecl->getLocalMax( lat2, lat3, lat4 ); m_ecl->getShadowCone( lat2, true, 40, ltf, lnf ); for( j = 0; j < 40; ++j ) { if( ltf[j] < 100. ) { m_shadowConeUmbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lnf[j], GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(ltf[j], GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } } m_ecl->setPenumbraAngle( 1., 0 ); m_ecl->getShadowCone( lat2, false, 60, ltf, lnf ); for( j = 0; j < 60; ++j ) { if( ltf[j] < 100. ) { m_shadowConePenumbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lnf[j], GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(ltf[j], GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } } m_ecl->setPenumbraAngle( 0.6, 1 ); m_ecl->getShadowCone( lat2, false, 60, ltf, lnf ); for( j = 0; j < 60; ++j ) { if( ltf[j] < 100. ) { m_shadowCone60MagPenumbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lnf[j], GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(ltf[j], GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } } m_ecl->setPenumbraAngle( 1., 0 ); // eclipse boundaries m_southernPenumbra.clear(); m_northernPenumbra.clear(); np = m_ecl->GNSBound( true, true, lat1, lng2 ); while( np > 0 ) { np = m_ecl->GNSBound( false, true, lat1, lng1 ); if( ( np > 0 ) && ( lat1 <= 90. ) ) { m_southernPenumbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } } np = m_ecl->GNSBound( true, false, lat1, lng1 ); while( np > 0 ) { np = m_ecl->GNSBound( false, false, lat1, lng1 ); if( ( np > 0 ) && ( lat1 <= 90. ) ) { m_northernPenumbra << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } } // sunrise / sunset boundaries QList<GeoDataLinearRing*> sunBoundaries; np = m_ecl->GRSBound( true, lat1, lng1, lat3, lng3 ); GeoDataLinearRing *lowerBoundary = new GeoDataLinearRing( Tessellate ); *lowerBoundary << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng1, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat1, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); GeoDataLinearRing *upperBoundary = new GeoDataLinearRing( Tessellate ); *upperBoundary << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng3, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat3, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); m_sunBoundaries.clear(); while ( np > 0 ) { np = m_ecl->GRSBound( false, lat2, lng2, lat4, lng4 ); bool pline = fabs( lng1 - lng2 ) < 10.; // during partial eclipses, the Rise/Set // lines switch at one stage. // This will prevent an ugly line between // the switch points. If there is a // longitude jump then add the current // section to our sun boundaries collection // and start a new section if ( !pline && !lowerBoundary->isEmpty() ) { sunBoundaries.prepend( lowerBoundary ); lowerBoundary = new GeoDataLinearRing( Tessellate ); } if ( ( np > 0 ) && ( lat2 <= 90. ) && ( lat1 <= 90. ) ) { *lowerBoundary << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng2, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat2, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } pline = fabs( lng3 - lng4 ) < 10.; // during partial eclipses, the Rise/Set lines // switch at one stage. // This will prevent an ugly line between the // switch points. If there is a longitude jump // then add the current section to our sun // boundaries collection and start a new section if ( !pline && !upperBoundary->isEmpty() ) { sunBoundaries.prepend( upperBoundary ); upperBoundary = new GeoDataLinearRing( Tessellate ); } if ( pline && ( np > 0 ) && ( lat4 <= 90. ) && ( lat3 <= 90. ) ) { *upperBoundary << GeoDataCoordinates( GeoDataCoordinates::normalizeLon(lng4, GeoDataCoordinates::Degree), GeoDataCoordinates::normalizeLat(lat4, GeoDataCoordinates::Degree), 0., GeoDataCoordinates::Degree ); } lng1 = lng2; lat1 = lat2; lng3 = lng4; lat3 = lat4; } if ( !lowerBoundary->isEmpty() ) { sunBoundaries.prepend(lowerBoundary); } else { delete lowerBoundary; } if ( !upperBoundary->isEmpty() ) { sunBoundaries.prepend(upperBoundary); } else { delete upperBoundary; } for ( int result = 0; result < 2; ++result ) { GeoDataLinearRing sunBoundary( Tessellate ); sunBoundary = *sunBoundaries.last(); sunBoundaries.pop_back(); while ( sunBoundaries.size() > 0) { int closestSection = -1; // TODO: Now that MableMath is not public anymore we need a // GeoDataCoordinates::distance() method in Marble. GeoDataLineString ruler; ruler << sunBoundary.last() << sunBoundary.first(); qreal closestDistance = ruler.length( 1 ); int closestEnd = 0; // 0 = start of section, 1 = end of section // Look for a section that is closest to our sunBoundary section. for ( int it = 0; it < sunBoundaries.size(); ++it ) { GeoDataLineString distanceStartSection; distanceStartSection << sunBoundary.last() << sunBoundaries.at( it )->first(); GeoDataLineString distanceEndSection; distanceEndSection << sunBoundary.last() << sunBoundaries.at( it )->last(); if ( distanceStartSection.length( 1 ) < closestDistance ) { closestDistance = distanceStartSection.length( 1 ); closestSection = it; closestEnd = 0; } if ( distanceEndSection.length(1) < closestDistance ) { closestDistance = distanceEndSection.length( 1 ); closestSection = it; closestEnd = 1; } } if ( closestSection == -1 ) { // There is no other section that is closer to the end of // our sunBoundary section than the startpoint of our // sunBoundary itself break; } else { // We now concatenate the closest section to the sunBoundary. // First we might have to invert it so that we concatenate // the right end if ( closestEnd == 1 ) { // TODO: replace this with a GeoDataLinearRing::invert() // method that needs to be added to Marble ... GeoDataLinearRing * invertedBoundary = new GeoDataLinearRing( Tessellate ); QVector<GeoDataCoordinates>::const_iterator iter = sunBoundaries.at( closestSection )->constEnd(); --iter; for( ; iter != sunBoundaries.at( closestSection )->constBegin(); --iter ) { *invertedBoundary << *iter; } *invertedBoundary << sunBoundaries.at( closestSection )->first(); delete sunBoundaries[closestSection]; sunBoundaries[closestSection] = invertedBoundary; } sunBoundary << *sunBoundaries[closestSection]; // Now remove the section that we've just added from the list delete sunBoundaries[closestSection]; sunBoundaries.removeAt( closestSection ); } } m_sunBoundaries << sunBoundary; if ( sunBoundaries.size() == 0 ) break; } m_calculationsNeedUpdate = false; }
GeoDataDocument *CycleStreetsRunner::parse( const QByteArray &content ) const { QDomDocument xml; if ( !xml.setContent( content ) ) { mDebug() << "Cannot parse xml file with routing instructions."; return 0; } GeoDataDocument *result = new GeoDataDocument(); result->setName( "CycleStreets" ); GeoDataPlacemark *routePlacemark = new GeoDataPlacemark; routePlacemark->setName( "Route" ); GeoDataLineString *routeWaypoints = new GeoDataLineString; QDomNodeList features = xml.elementsByTagName( "gml:featureMember" ); if ( features.isEmpty() ) { return 0; } QDomElement route = features.at( 0 ).toElement().firstChild().toElement(); QDomElement lineString = route.elementsByTagName( "gml:LineString" ).at( 0 ).toElement(); QDomElement coordinates = lineString.toElement().elementsByTagName( "gml:coordinates" ).at( 0 ).toElement(); QStringList coordinatesList = coordinates.text().split( ' ' ); QStringList::iterator iter = coordinatesList.begin(); QStringList::iterator end = coordinatesList.end(); for( ; iter != end; ++iter) { QStringList coordinate = iter->split(','); if ( coordinate.size() == 2 ) { double const lon = coordinate.at( 0 ).toDouble(); double const lat = coordinate.at( 1 ).toDouble(); GeoDataCoordinates const position( lon, lat, 0.0, GeoDataCoordinates::Degree ); routeWaypoints->append( position ); } } routePlacemark->setGeometry( routeWaypoints ); QDomElement durationElement = route.elementsByTagName( "cs:time" ).at(0).toElement(); QTime duration; duration = duration.addSecs( durationElement.text().toInt() ); qreal length = routeWaypoints->length( EARTH_RADIUS ); const QString name = nameString( "CS", length, duration ); const GeoDataExtendedData data = routeData( length, duration ); routePlacemark->setExtendedData( data ); result->setName( name ); result->append( routePlacemark ); int i; for ( i = 1; i < features.count() && features.at( i ).firstChildElement().tagName() != "cs:segment"; ++i ); for ( ; i < features.count(); ++i) { QDomElement segment = features.at( i ).toElement(); QString name = segment.elementsByTagName( "cs:name" ).at( 0 ).toElement().text(); QString maneuver = segment.elementsByTagName( "cs:turn" ).at( 0 ).toElement().text(); QStringList points = segment.elementsByTagName( "cs:points" ).at( 0 ).toElement().text().split( ' ' ); QStringList const elevation = segment.elementsByTagName( "cs:elevations" ).at( 0 ).toElement().text().split( ',' ); GeoDataPlacemark *instructions = new GeoDataPlacemark; QString instructionName; if ( !maneuver.isEmpty() ) { instructionName = maneuver.left( 1 ).toUpper() + maneuver.mid( 1 ); } else { instructionName = "Straight"; } if ( name != "Short un-named link" && name != "Un-named link" ){ instructionName.append( " into " + name ); } instructions->setName( instructionName ); GeoDataExtendedData extendedData; GeoDataData turnType; turnType.setName( "turnType" ); turnType.setValue( maneuverType( maneuver ) ); extendedData.addValue( turnType ); instructions->setExtendedData( extendedData ); GeoDataLineString *lineString = new GeoDataLineString; QStringList::iterator iter = points.begin(); QStringList::iterator end = points.end(); for ( int j=0; iter != end; ++iter, ++j ) { QStringList coordinate = iter->split( ',' ); if ( coordinate.size() == 2 ) { double const lon = coordinate.at( 0 ).toDouble(); double const lat = coordinate.at( 1 ).toDouble(); double const alt = j < elevation.size() ? elevation[j].toDouble() : 0.0; lineString->append( GeoDataCoordinates( lon, lat, alt, GeoDataCoordinates::Degree ) ); } } instructions->setGeometry( lineString ); result->append( instructions ); } return result; }