GeoDataDocument* GosmoreRunnerPrivate::createDocument( GeoDataLineString* routeWaypoints, const QVector<GeoDataPlacemark*> instructions ) { if ( !routeWaypoints || routeWaypoints->isEmpty() ) { return nullptr; } GeoDataDocument* result = new GeoDataDocument(); GeoDataPlacemark* routePlacemark = new GeoDataPlacemark; routePlacemark->setName(QStringLiteral("Route")); routePlacemark->setGeometry( routeWaypoints ); result->append( routePlacemark ); QString name = QStringLiteral("%1 %2 (Gosmore)"); QString unit = QLatin1String( "m" ); qreal length = routeWaypoints->length( EARTH_RADIUS ); if (length >= 1000) { length /= 1000.0; unit = "km"; } result->setName( name.arg( length, 0, 'f', 1 ).arg( unit ) ); for( GeoDataPlacemark* placemark: instructions ) { result->append( placemark ); } return result; }
void TestGeoDataTrack::simpleParseTest() { GeoDataDocument* dataDocument = parseKml( simpleExampleContent ); GeoDataFolder *folder = dataDocument->folderList().at( 0 ); QCOMPARE( folder->placemarkList().size(), 1 ); GeoDataPlacemark* placemark = folder->placemarkList().at( 0 ); QCOMPARE( placemark->geometry()->geometryId(), GeoDataTrackId ); GeoDataTrack* track = static_cast<GeoDataTrack*>( placemark->geometry() ); QCOMPARE( track->size(), 7 ); { QDateTime when = track->whenList().at( 0 ); QCOMPARE( when, QDateTime( QDate( 2010, 5, 28 ), QTime( 2, 2, 9 ), Qt::UTC ) ); } { GeoDataCoordinates coord = track->coordinatesList().at( 0 ); QCOMPARE( coord.longitude( GeoDataCoordinates::Degree ), -122.207881 ); QCOMPARE( coord.latitude( GeoDataCoordinates::Degree ), 37.371915 ); QCOMPARE( coord.altitude(), 156.000000 ); } { GeoDataCoordinates coord = track->coordinatesAt( QDateTime( QDate( 2010, 5, 28 ), QTime( 2, 2, 9 ), Qt::UTC ) ); QCOMPARE( coord.longitude( GeoDataCoordinates::Degree ), -122.207881 ); QCOMPARE( coord.latitude( GeoDataCoordinates::Degree ), 37.371915 ); QCOMPARE( coord.altitude(), 156.000000 ); } delete dataDocument; }
void GosmoreRunner::reverseGeocoding( const GeoDataCoordinates &coordinates ) { if ( !d->m_gosmoreMapFile.exists() ) { emit reverseGeocodingFinished( coordinates, GeoDataPlacemark() ); return; } QString queryString = "flat=%1&flon=%2&tlat=%1&tlon=%2&fastest=1&v=motorcar"; double lon = coordinates.longitude( GeoDataCoordinates::Degree ); double lat = coordinates.latitude( GeoDataCoordinates::Degree ); queryString = queryString.arg( lat, 0, 'f', 8).arg(lon, 0, 'f', 8 ); QByteArray output = d->retrieveWaypoints( queryString ); GeoDataPlacemark placemark; placemark.setCoordinate( coordinates ); QStringList lines = QString::fromUtf8( output ).split( '\r' ); if ( lines.size() > 2 ) { QStringList fields = lines.at( lines.size()-2 ).split(','); if ( fields.size() >= 5 ) { QString road = fields.last().trimmed(); placemark.setAddress( road ); GeoDataExtendedData extendedData; extendedData.addValue( GeoDataData( "road", road ) ); placemark.setExtendedData( extendedData ); } } emit reverseGeocodingFinished( coordinates, placemark ); }
void HostipRunner::slotRequestFinished( QNetworkReply* reply ) { double lon(0.0), lat(0.0); for ( QString line = reply->readLine(); !line.isEmpty(); line = reply->readLine() ) { QString lonInd = "Longitude: "; if ( line.startsWith(lonInd) ) { lon = line.mid( lonInd.length() ).toDouble(); } QString latInd = "Latitude: "; if (line.startsWith( latInd) ) { lat = line.mid( latInd.length() ).toDouble(); } } QVector<GeoDataPlacemark*> placemarks; if (lon != 0.0 && lat != 0.0) { GeoDataPlacemark *placemark = new GeoDataPlacemark; placemark->setName( m_hostInfo.hostName() ); QString description("%1 (%2)"); placemark->setDescription( description. arg( m_hostInfo.hostName() ). arg( m_hostInfo.addresses().first().toString() ) ); placemark->setCoordinate( lon * DEG2RAD, lat * DEG2RAD ); placemark->setVisualCategory( GeoDataFeature::Coordinate ); placemarks << placemark; } emit searchFinished( placemarks ); }
void TestGxTimeStamp::simpleParseTest() { QString const centerContent ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "<kml xmlns=\"http://www.opengis.net/kml/2.2\"" " xmlns:gx=\"http://www.google.com/kml/ext/2.2\">" "<Document>" "<Placemark>" "<Camera>" "<gx:TimeStamp>" "<when>1987-06-05T04:03:02-01:00</when>" "</gx:TimeStamp>" "</Camera>" "</Placemark>" "</Document>" "</kml>" ); GeoDataDocument* dataDocument = parseKml( centerContent ); QCOMPARE( dataDocument->placemarkList().size(), 1 ); GeoDataPlacemark *placemark = dataDocument->placemarkList().at( 0 ); GeoDataAbstractView* view = placemark->abstractView(); QVERIFY( view != 0 ); GeoDataCamera* camera = dynamic_cast<GeoDataCamera*>( view ); QVERIFY( camera != 0 ); QCOMPARE( camera->timeStamp().when().toUTC(), QDateTime::fromString( "1987-06-05T04:03:02-01:00", Qt::ISODate).toUTC() ); delete dataDocument; }
bool PositionTracking::saveTrack( const QString& fileName ) { if ( fileName.isEmpty() ) { return false; } GeoWriter writer; //FIXME: a better way to do this? writer.setDocumentType( kml::kmlTag_nameSpaceOgc22 ); GeoDataDocument *document = new GeoDataDocument; QFileInfo fileInfo( fileName ); QString name = fileInfo.baseName(); document->setName( name ); foreach( const GeoDataStyle &style, d->m_document.styles() ) { document->addStyle( style ); } foreach( const GeoDataStyleMap &map, d->m_document.styleMaps() ) { document->addStyleMap( map ); } GeoDataPlacemark *track = new GeoDataPlacemark( *d->m_currentTrackPlacemark ); track->setName( "Track " + name ); document->append( track ); QFile file( fileName ); file.open( QIODevice::WriteOnly ); bool const result = writer.write( &file, document ); file.close(); delete document; return result; }
void LocalDatabaseRunner::search( const QString &searchTerm, const GeoDataLatLonAltBox &preferred ) { QVector<GeoDataPlacemark*> vector; if (model()) { const QAbstractItemModel * placemarkModel = model()->placemarkModel(); if (placemarkModel) { QModelIndexList resultList; QModelIndex firstIndex = placemarkModel->index( 0, 0 ); resultList = placemarkModel->match( firstIndex, Qt::DisplayRole, searchTerm, -1, Qt::MatchStartsWith ); foreach ( const QModelIndex& index, resultList ) { if( !index.isValid() ) { mDebug() << "invalid index!!!"; continue; } GeoDataPlacemark *placemark = dynamic_cast<GeoDataPlacemark*>(qvariant_cast<GeoDataObject*>( index.data( MarblePlacemarkModel::ObjectPointerRole ))); if ( placemark && ( preferred.isEmpty() || preferred.contains( placemark->coordinate() ) ) ) { vector.append( new GeoDataPlacemark( *placemark )); } } } } emit searchFinished( vector ); }
void TestGxTimeSpan::simpleParseTest() { QString const centerContent ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "<kml xmlns=\"http://www.opengis.net/kml/2.2\"" " xmlns:gx=\"http://www.google.com/kml/ext/2.2\">" "<Document>" "<Placemark>" "<LookAt>" "<gx:TimeSpan>" "<begin>2010-05-28T02:02:09Z</begin>" "<end>2010-05-28T02:02:56Z</end>" "</gx:TimeSpan>" "</LookAt>" "</Placemark>" "</Document>" "</kml>" ); GeoDataDocument* dataDocument = parseKml( centerContent ); QCOMPARE( dataDocument->placemarkList().size(), 1 ); GeoDataPlacemark *placemark = dataDocument->placemarkList().at( 0 ); QVERIFY( placemark->lookAt() != 0 ); QCOMPARE( placemark->lookAt()->timeSpan().begin().when(), QDateTime::fromString( "2010-05-28T02:02:09Z", Qt::ISODate) ); QCOMPARE( placemark->lookAt()->timeSpan().end().when(), QDateTime::fromString( "2010-05-28T02:02:56Z", Qt::ISODate) ); delete dataDocument; }
void TestGeoDataTrack::withoutTimeTest() { //"Simple Example" from kmlreference; when elements emptied QString content( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "<kml xmlns=\"http://www.opengis.net/kml/2.2\"" " xmlns:gx=\"http://www.google.com/kml/ext/2.2\">" "<Folder>" " <Placemark>" " <gx:Track>" " <when></when>" " <when></when>" " <when></when>" " <when></when>" " <when></when>" " <when></when>" " <when></when>" " <gx:coord>-122.207881 37.371915 156.000000</gx:coord>" " <gx:coord>-122.205712 37.373288 152.000000</gx:coord>" " <gx:coord>-122.204678 37.373939 147.000000</gx:coord>" " <gx:coord>-122.203572 37.374630 142.199997</gx:coord>" " <gx:coord>-122.203451 37.374706 141.800003</gx:coord>" " <gx:coord>-122.203329 37.374780 141.199997</gx:coord>" " <gx:coord>-122.203207 37.374857 140.199997</gx:coord>" " </gx:Track>" " </Placemark>" "</Folder>" "</kml>" ); GeoDataDocument* dataDocument = parseKml( content ); GeoDataFolder *folder = dataDocument->folderList().at( 0 ); QCOMPARE( folder->placemarkList().size(), 1 ); GeoDataPlacemark* placemark = folder->placemarkList().at( 0 ); QCOMPARE( placemark->geometry()->geometryId(), GeoDataTrackId ); GeoDataTrack* track = static_cast<GeoDataTrack*>( placemark->geometry() ); QCOMPARE( track->size(), 7 ); { GeoDataCoordinates coord = track->coordinatesList().at( 0 ); QCOMPARE( coord.longitude( GeoDataCoordinates::Degree ), -122.207881 ); QCOMPARE( coord.latitude( GeoDataCoordinates::Degree ), 37.371915 ); QCOMPARE( coord.altitude(), 156.000000 ); } { const GeoDataLineString *lineString = track->lineString(); QCOMPARE( lineString->size(), 7 ); GeoDataCoordinates coord = lineString->at( 0 ); QCOMPARE( coord.longitude( GeoDataCoordinates::Degree ), -122.207881 ); QCOMPARE( coord.latitude( GeoDataCoordinates::Degree ), 37.371915 ); QCOMPARE( coord.altitude(), 156.000000 ); } delete dataDocument; }
void TourWidgetPrivate::addRemovePlacemark() { GeoDataDelete *deleteItem = new GeoDataDelete; GeoDataPlacemark *placemark = new GeoDataPlacemark; placemark->setTargetId( m_delegate->defaultFeatureId() ); deleteItem->append( placemark ); GeoDataUpdate *update = new GeoDataUpdate; update->setDelete( deleteItem ); GeoDataAnimatedUpdate *animatedUpdate = new GeoDataAnimatedUpdate; animatedUpdate->setUpdate( update ); addTourPrimitive( animatedUpdate ); }
void LocalOsmSearchRunner::search( const QString &searchTerm, const GeoDataLatLonBox &preferred ) { const DatabaseQuery userQuery( model(), searchTerm, preferred ); QVector<OsmPlacemark> placemarks = m_database.find( userQuery ); QVector<GeoDataPlacemark*> result; for( const OsmPlacemark &placemark: placemarks ) { GeoDataPlacemark* hit = new GeoDataPlacemark; hit->setName( placemark.name() ); if ( placemark.category() == OsmPlacemark::Address && !placemark.houseNumber().isEmpty() ) { hit->setName(hit->name() + QLatin1Char(' ') + placemark.houseNumber()); } if ( !placemark.additionalInformation().isEmpty() ) { hit->setName(hit->name() + QLatin1Char('(') + placemark.additionalInformation() + QLatin1Char(')')); } if ( placemark.category() != OsmPlacemark::UnknownCategory ) { hit->setVisualCategory( m_categoryMap[placemark.category()] ); } hit->setGeometry( new GeoDataPoint( placemark.longitude(), placemark.latitude(), 0.0, GeoDataCoordinates::Degree ) ); result << hit; } emit searchFinished( result ); }
GeoDataDocument* MonavRunnerPrivate::createDocument( Marble::GeoDataLineString* geometry, const QVector< Marble::GeoDataPlacemark* >& instructions, const QString& name, const Marble::GeoDataExtendedData& data ) { if ( !geometry || geometry->isEmpty() ) { return 0; } GeoDataDocument* result = new GeoDataDocument; GeoDataPlacemark* routePlacemark = new GeoDataPlacemark; routePlacemark->setName(QStringLiteral("Route")); routePlacemark->setGeometry( geometry ); routePlacemark->setExtendedData( data ); result->append( routePlacemark ); foreach( GeoDataPlacemark* placemark, instructions ) { result->append( placemark ); }
QVector<GeoDataPlacemark*> GosmoreRunnerPrivate::parseGosmoreInstructions( const QByteArray &content ) { // Determine gosmore version QStringList lines = QString::fromUtf8(content).split(QLatin1Char('\r')); if ( lines.size() > 2 ) { const QStringList fields = lines.at(lines.size()-2).split(QLatin1Char(',')); m_parser.setFieldIndex( WaypointParser::RoadName, fields.size()-1 ); if ( fields.size() < 5 || fields.size() > 6 ) { // Can happen when gosmore changes the output format, returns garbage // or the last street name contains a comma. We may still parse it correctly, just try. mDebug() << "Unexpected number of fields. This gosmore version may be unsupported."; } } QVector<GeoDataPlacemark*> result; QTextStream stream( content ); stream.setCodec("UTF8"); stream.setAutoDetectUnicode( true ); RoutingInstructions directions = InstructionTransformation::process( m_parser.parse( stream ) ); for( int i=0; i<directions.size(); ++i ) { GeoDataPlacemark* placemark = new GeoDataPlacemark( directions[i].instructionText() ); GeoDataExtendedData extendedData; GeoDataData turnType; turnType.setName(QStringLiteral("turnType")); turnType.setValue( qVariantFromValue<int>( int( directions[i].turnType() ) ) ); extendedData.addValue( turnType ); GeoDataData roadName; roadName.setName(QStringLiteral("roadName")); roadName.setValue( directions[i].roadName() ); extendedData.addValue( roadName ); placemark->setExtendedData( extendedData ); Q_ASSERT( !directions[i].points().isEmpty() ); GeoDataLineString* geometry = new GeoDataLineString; QVector<RoutingWaypoint> items = directions[i].points(); for (int j=0; j<items.size(); ++j ) { RoutingPoint point = items[j].point(); GeoDataCoordinates coordinates( point.lon(), point.lat(), 0.0, GeoDataCoordinates::Degree ); geometry->append( coordinates ); } placemark->setGeometry( geometry ); result.push_back( placemark ); } return result; }
void TourWidgetPrivate::addChangePlacemark() { GeoDataChange *change = new GeoDataChange; GeoDataPlacemark *placemark = 0; GeoDataFeature *lastFeature = m_delegate->findFeature( m_delegate->defaultFeatureId() ); if( lastFeature != 0 && lastFeature->nodeType() == GeoDataTypes::GeoDataPlacemarkType ) { GeoDataPlacemark *target = static_cast<GeoDataPlacemark*>( lastFeature ); placemark = new GeoDataPlacemark( *target ); placemark->setTargetId( m_delegate->defaultFeatureId() ); placemark->setId( "" ); } else { placemark = new GeoDataPlacemark; } change->append( placemark ); GeoDataUpdate *update = new GeoDataUpdate; update->setChange( change ); GeoDataAnimatedUpdate *animatedUpdate = new GeoDataAnimatedUpdate; animatedUpdate->setUpdate( update ); addTourPrimitive( animatedUpdate ); }
void MonavMap::parseBoundingBox( const QFileInfo &file ) { GeoDataLineString points; bool tooLarge = false; QFile input( file.absoluteFilePath() ); if ( input.open( QFile::ReadOnly ) ) { GeoDataParser parser( GeoData_KML ); if ( !parser.read( &input ) ) { mDebug() << "Could not parse file: " << parser.errorString(); return; } GeoDocument *doc = parser.releaseDocument(); input.close(); GeoDataDocument *document = dynamic_cast<GeoDataDocument*>( doc ); QVector<GeoDataPlacemark*> placemarks = document->placemarkList(); if ( placemarks.size() == 1 ) { GeoDataPlacemark* placemark = placemarks.first(); m_name = placemark->name(); m_version = placemark->extendedData().value( "version" ).value().toString(); m_date = placemark->extendedData().value( "date" ).value().toString(); m_transport = placemark->extendedData().value( "transport" ).value().toString(); m_payload = placemark->extendedData().value( "payload" ).value().toString(); GeoDataMultiGeometry* geometry = dynamic_cast<GeoDataMultiGeometry*>( placemark->geometry() ); if ( geometry->size() > 1500 ) { tooLarge = true; } for ( int i = 0; geometry && i < geometry->size(); ++i ) { GeoDataLinearRing* poly = dynamic_cast<GeoDataLinearRing*>( geometry->child( i ) ); if ( poly ) { for ( int j = 0; j < poly->size(); ++j ) { points << poly->at( j ); } m_tiles.push_back( *poly ); } if ( poly->size() > 1500 ) { tooLarge = true; } } } else { mDebug() << "File " << file.absoluteFilePath() << " does not contain one placemark, but " << placemarks.size(); } delete doc; } m_boundingBox = points.latLonAltBox(); if ( tooLarge ) { // The bounding box polygon is rather complicated, therefore not allowing a quick check // and also occupying memory. Discard the polygon and only store the rectangular bounding // box. Only happens for non-simplified bounding box polygons. mDebug() << "Discarding too large bounding box poylgon for " << file.absoluteFilePath() << ". Please check for a map update."; m_tiles.clear(); } }
void OsmNominatimRunner::handleReverseGeocodingResult( QNetworkReply* reply ) { if ( !reply->bytesAvailable() ) { returnNoReverseGeocodingResult(); return; } QDomDocument xml; if ( !xml.setContent( reply->readAll() ) ) { mDebug() << "Cannot parse osm nominatim result " << xml.toString(); returnNoReverseGeocodingResult(); return; } QDomElement root = xml.documentElement(); QDomNodeList places = root.elementsByTagName( "result" ); if ( places.size() == 1 ) { QString address = places.item( 0 ).toElement().text(); GeoDataPlacemark placemark; placemark.setAddress( address ); placemark.setCoordinate( GeoDataPoint( m_coordinates ) ); QDomNodeList details = root.elementsByTagName( "addressparts" ); if ( details.size() == 1 ) { GeoDataExtendedData extendedData; addData( details, "road", &extendedData ); addData( details, "house_number", &extendedData ); addData( details, "village", &extendedData ); addData( details, "city", &extendedData ); addData( details, "county", &extendedData ); addData( details, "state", &extendedData ); addData( details, "postcode", &extendedData ); addData( details, "country", &extendedData ); placemark.setExtendedData( extendedData ); } emit reverseGeocodingFinished( m_coordinates, placemark ); } else { returnNoReverseGeocodingResult(); } }
int AbstractGeoPolygonGraphicsItem::extractElevation(const GeoDataPlacemark &placemark) { int elevation = 0; const OsmPlacemarkData &osmData = placemark.osmData(); const auto tagIter = osmData.findTag(QStringLiteral("ele")); if (tagIter != osmData.tagsEnd()) { elevation = tagIter.value().toInt(); } return elevation; }
void GeoDataContainer::unpack( QDataStream& stream ) { Q_D(GeoDataContainer); GeoDataFeature::unpack( stream ); int count; stream >> count; for ( int i = 0; i < count; ++i ) { int featureId; stream >> featureId; switch( featureId ) { case GeoDataDocumentId: /* not usable!!!! */ break; case GeoDataFolderId: { GeoDataFolder *folder = new GeoDataFolder; folder->unpack( stream ); d->m_vector.append( folder ); } break; case GeoDataPlacemarkId: { GeoDataPlacemark *placemark = new GeoDataPlacemark; placemark->unpack( stream ); d->m_vector.append( placemark ); } break; case GeoDataNetworkLinkId: break; case GeoDataScreenOverlayId: break; case GeoDataGroundOverlayId: break; default: break; }; } }
GeoDataDocument* MonavRunnerPrivate::createDocument( GeoDataLineString *geometry, const QVector<GeoDataPlacemark*> &instructions ) const { if ( !geometry || geometry->isEmpty() ) { return 0; } GeoDataDocument* result = new GeoDataDocument; GeoDataPlacemark* routePlacemark = new GeoDataPlacemark; routePlacemark->setName( "Route" ); routePlacemark->setGeometry( geometry ); result->append( routePlacemark ); QString name = "%1 %2 (Monav)"; QString unit = "m"; qreal length = geometry->length( EARTH_RADIUS ); if ( length >= 1000 ) { length /= 1000.0; unit = "km"; } foreach( GeoDataPlacemark* placemark, instructions ) { result->append( placemark ); }
GeoDataLatLonAltBox GeoDataContainer::latLonAltBox() const { Q_D(const GeoDataContainer); GeoDataLatLonAltBox result; QVector<GeoDataFeature*>::const_iterator it = d->m_vector.constBegin(); QVector<GeoDataFeature*>::const_iterator end = d->m_vector.constEnd(); for (; it != end; ++it) { // Get all the placemarks from GeoDataContainer if ( (*it)->nodeType() == GeoDataTypes::GeoDataPlacemarkType ) { GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>(*it); // Only use visible placemarks for extracting their latLonAltBox and // making an union with the global latLonAltBox Marble will fit its // zoom to if (placemark->isVisible()) { if (result.isEmpty()) { result = placemark->geometry()->latLonAltBox(); } else { result |= placemark->geometry()->latLonAltBox(); } } } else if ( (*it)->nodeType() == GeoDataTypes::GeoDataFolderType || (*it)->nodeType() == GeoDataTypes::GeoDataDocumentType ) { GeoDataContainer *container = static_cast<GeoDataContainer*>(*it); if (result.isEmpty()) { result = container->latLonAltBox(); } else { result |= container->latLonAltBox(); } } } return result; }
const GeoDataLatLonAltBox& GeoDataRegion::latLonAltBox() const { // FIXME: This isn't exactly what a 'const' function should do, is it? // If the latLonAltBox hasn't been set try to determine it automatically if ( !d->m_latLonAltBox ) { // If there is a parent try to if ( d->m_parent ) { if ( d->m_parent->nodeType() == GeoDataTypes::GeoDataPlacemarkType ) { GeoDataPlacemark * placemark = dynamic_cast<GeoDataPlacemark*>( d->m_parent ); GeoDataGeometry * geometry = placemark->geometry(); if ( geometry ) { // TODO: automatically calculate the geometry from the // GeoDataGeometry object. // return geometry->latLonAltBox(); } d->m_latLonAltBox = new GeoDataLatLonAltBox( placemark->coordinate() ); } else { // If the parent is not a placemark then create a default LatLonAltBox // FIXME: reference a shared object instead d->m_latLonAltBox = new GeoDataLatLonAltBox(); } } else { // If there is no parent then create a default LatLonAltBox // FIXME: reference a shared object instead d->m_latLonAltBox = new GeoDataLatLonAltBox(); } } return *(d->m_latLonAltBox); }
void TourWidgetPrivate::addPlacemark() { // Get the normalized coordinates of the focus point. There will be automatically added a new // placemark. qreal lat = m_widget->focusPoint().latitude(); qreal lon = m_widget->focusPoint().longitude(); GeoDataCoordinates::normalizeLonLat( lon, lat ); GeoDataDocument *document = new GeoDataDocument; if( m_document->id().isEmpty() ) { if( m_document->name().isEmpty() ) { m_document->setId( "untitled_tour" ); } else { m_document->setId( m_document->name().trimmed().replace( " ", "_" ).toLower() ); } } document->setTargetId( m_document->id() ); GeoDataPlacemark *placemark = new GeoDataPlacemark; placemark->setCoordinate( lon, lat ); placemark->setVisible( true ); placemark->setBalloonVisible( true ); GeoDataStyle *newStyle = new GeoDataStyle( *placemark->style() ); newStyle->iconStyle().setIcon( QImage() ); newStyle->iconStyle().setIconPath( MarbleDirs::path("bitmaps/redflag_22.png") ); placemark->setStyle( newStyle ); document->append( placemark ); GeoDataCreate *create = new GeoDataCreate; create->append( document ); GeoDataUpdate *update = new GeoDataUpdate; update->setCreate( create ); GeoDataAnimatedUpdate *animatedUpdate = new GeoDataAnimatedUpdate; animatedUpdate->setUpdate( update ); if( m_delegate->editAnimatedUpdate( animatedUpdate ) ) { addTourPrimitive( animatedUpdate ); m_delegate->setDefaultFeatureId( placemark->id() ); } else { delete animatedUpdate; } }
void CountryByFlag::postQuestion( QObject *gameObject ) { /** * Find a random placemark */ Q_ASSERT_X( d->m_countryNames, "CountryByFlag::postQuestion", "CountryByFlagPrivate::m_countryNames is NULL" ); QVector<GeoDataPlacemark*> countryPlacemarks = d->m_countryNames->placemarkList(); uint randomSeed = uint(QTime::currentTime().msec()); qsrand( randomSeed ); bool found = false; GeoDataPlacemark *placemark = 0; QVariantList answerOptions; QString flagPath; while ( !found ) { int randomIndex = qrand()%countryPlacemarks.size(); placemark = countryPlacemarks[randomIndex]; if ( !d->m_continentsAndOceans.contains(placemark->name(), Qt::CaseSensitive) ) { flagPath = MarbleDirs::path( QString("flags/flag_%1.svg").arg(placemark->countryCode().toLower()) ); QImage flag = QFile::exists( flagPath ) ? QImage( flagPath ) : QImage(); if ( !flag.isNull() ) { flagPath = QString("%1flag_%2.svg").arg("../../../data/flags/").arg(placemark->countryCode().toLower()); found = true; } } } answerOptions << placemark->name() << countryPlacemarks[qrand()%countryPlacemarks.size()]->name() << countryPlacemarks[qrand()%countryPlacemarks.size()]->name() << countryPlacemarks[qrand()%countryPlacemarks.size()]->name(); // Randomize the options in the list answerOptions for ( int i = 0; i < answerOptions.size(); ++i ) { QVariant option = answerOptions.takeAt( qrand()%answerOptions.size() ); answerOptions.append( option ); } if ( gameObject ) { QMetaObject::invokeMethod( gameObject, "countryByFlagQuestion", Q_ARG(QVariant, QVariant::fromValue(answerOptions)), Q_ARG(QVariant, QVariant::fromValue(flagPath)), Q_ARG(QVariant, QVariant::fromValue(placemark->name())) ); } }
void GeoUriRunner::search(const QString &searchTerm, const GeoDataLatLonBox &) { QVector<GeoDataPlacemark*> vector; GeoUriParser uriParser(searchTerm); const bool success = uriParser.parse(); if (success && (uriParser.planet().id() == model()->planet()->id())) { const GeoDataCoordinates coordinates = uriParser.coordinates(); GeoDataPlacemark *placemark = new GeoDataPlacemark; placemark->setName(searchTerm); placemark->setCoordinate(coordinates); placemark->setVisualCategory(GeoDataPlacemark::Coordinate); placemark->setPopularity(1000000000); placemark->setZoomLevel(1); vector.append(placemark); } emit searchFinished(vector); }
void OsmNominatimRunner::handleResult( QNetworkReply* reply ) { QDomDocument xml; if (!xml.setContent(reply->readAll())) { qWarning() << "Cannot parse osm nominatim result"; returnNoResults(); return; } QVector<GeoDataPlacemark*> placemarks; QDomElement root = xml.documentElement(); QDomNodeList places = root.elementsByTagName("place"); for (int i=0; i<places.size(); ++i) { QDomNode place = places.at(i); QDomNamedNodeMap attributes = place.attributes(); QString lon = attributes.namedItem("lon").nodeValue(); QString lat = attributes.namedItem("lat").nodeValue(); QString desc = attributes.namedItem("display_name").nodeValue(); QString key = attributes.namedItem("class").nodeValue(); QString value = attributes.namedItem("type").nodeValue(); QString name = place.firstChildElement(value).text(); QString road = place.firstChildElement("road").text(); QString city = place.firstChildElement("city").text(); if( city.isEmpty() ) { city = place.firstChildElement("town").text(); if( city.isEmpty() ) { city = place.firstChildElement("village").text(); } if( city.isEmpty() ) { city = place.firstChildElement("hamlet").text(); } } QString administrative = place.firstChildElement("county").text(); if( administrative.isEmpty() ) { administrative = place.firstChildElement("region").text(); if( administrative.isEmpty() ) { administrative = place.firstChildElement("state").text(); } } QString country = place.firstChildElement("country").text(); QString description; for (int i=0; i<place.childNodes().size(); ++i) { QDomElement item = place.childNodes().at(i).toElement(); description += item.nodeName() + ':' + item.text() + '\n'; } description += "Category: " + key + '/' + value; if (!lon.isEmpty() && !lat.isEmpty() && !desc.isEmpty()) { QString placemarkName; GeoDataPlacemark* placemark = new GeoDataPlacemark; // try to provide 2 fields if (!name.isEmpty()) { placemarkName = name; } if (!road.isEmpty() && road != placemarkName ) { if( !placemarkName.isEmpty() ) { placemarkName += ", "; } placemarkName += road; } if (!city.isEmpty() && !placemarkName.contains(",") && city != placemarkName) { if( !placemarkName.isEmpty() ) { placemarkName += ", "; } placemarkName += city; } if (!administrative.isEmpty()&& !placemarkName.contains(",") && administrative != placemarkName) { if( !placemarkName.isEmpty() ) { placemarkName += ", "; } placemarkName += administrative; } if (!country.isEmpty()&& !placemarkName.contains(",") && country != placemarkName) { if( !placemarkName.isEmpty() ) { placemarkName += ", "; } placemarkName += country; } if (placemarkName.isEmpty()) { placemarkName = desc; } placemark->setName( placemarkName ); placemark->setDescription(description); placemark->setCoordinate( lon.toDouble(), lat.toDouble(), 0, GeoDataCoordinates::Degree ); GeoDataFeature::GeoDataVisualCategory category = GeoDataFeature::OsmVisualCategory( key + '=' + value ); placemark->setVisualCategory( category ); placemarks << placemark; } } emit searchFinished( placemarks ); }
bool JsonParser::read( QIODevice* device ) { // Assert previous document got released. delete m_document; m_document = new GeoDataDocument; Q_ASSERT( m_document ); // Read file data QJsonParseError error; const QJsonDocument jsonDoc = QJsonDocument::fromJson(device->readAll(), &error); if (jsonDoc.isNull()) { qDebug() << "Error parsing GeoJSON : " << error.errorString(); return false; } // Start parsing const QJsonValue featuresValue = jsonDoc.object().value(QStringLiteral("features")); // In GeoJSON format, geometries are stored in features, so we iterate on features if (featuresValue.isArray()) { const QJsonArray featureArray = featuresValue.toArray(); // Parse each feature for (int featureIndex = 0; featureIndex < featureArray.size(); ++featureIndex) { const QJsonObject featureObject = featureArray[featureIndex].toObject(); // Check if the feature contains a geometry const QJsonValue geometryValue = featureObject.value(QStringLiteral("geometry")); if (geometryValue.isObject()) { const QJsonObject geometryObject = geometryValue.toObject(); // Variables for creating the geometry QList<GeoDataGeometry*> geometryList; QList<GeoDataPlacemark*> placemarkList; // Create the different geometry types const QString geometryType = geometryObject.value(QStringLiteral("type")).toString().toUpper(); if (geometryType == QLatin1String("POLYGON")) { // Check first that there are coordinates const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates")); if (coordinatesValue.isArray()) { const QJsonArray coordinateArray = coordinatesValue.toArray(); GeoDataPolygon * geom = new GeoDataPolygon( RespectLatitudeCircle | Tessellate ); // Coordinates first array will be the outer boundary, if there are more // positions those will be inner holes for (int ringIndex = 0 ; ringIndex < coordinateArray.size(); ++ringIndex) { const QJsonArray ringArray = coordinateArray[ringIndex].toArray(); GeoDataLinearRing linearRing; for (int coordinatePairIndex = 0; coordinatePairIndex < ringArray.size(); ++coordinatePairIndex) { const QJsonArray coordinatePairArray = ringArray[coordinatePairIndex].toArray(); const qreal longitude = coordinatePairArray.at(0).toDouble(); const qreal latitude = coordinatePairArray.at(1).toDouble(); linearRing.append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) ); } // Outer ring if (ringIndex == 0) { geom->setOuterBoundary( linearRing ); } // Inner holes else { geom->appendInnerBoundary( linearRing ); } } geometryList.append( geom ); } } else if (geometryType == QLatin1String("MULTIPOLYGON")) { // Check first that there are coordinates const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates")); if (coordinatesValue.isArray()) { const QJsonArray coordinateArray = coordinatesValue.toArray(); for (int polygonIndex = 0; polygonIndex < coordinateArray.size(); ++polygonIndex) { const QJsonArray polygonArray = coordinateArray[polygonIndex].toArray(); GeoDataPolygon * geom = new GeoDataPolygon( RespectLatitudeCircle | Tessellate ); // Coordinates first array will be the outer boundary, if there are more // positions those will be inner holes for (int ringIndex = 0 ; ringIndex < polygonArray.size(); ++ringIndex) { const QJsonArray ringArray = polygonArray[ringIndex].toArray(); GeoDataLinearRing linearRing; for (int coordinatePairIndex = 0; coordinatePairIndex < ringArray.size(); ++coordinatePairIndex) { const QJsonArray coordinatePairArray = ringArray[coordinatePairIndex].toArray(); const qreal longitude = coordinatePairArray.at(0).toDouble(); const qreal latitude = coordinatePairArray.at(1).toDouble(); linearRing.append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) ); } // Outer ring if (ringIndex == 0) { geom->setOuterBoundary( linearRing ); } // Inner holes else { geom->appendInnerBoundary( linearRing ); } } geometryList.append( geom ); } } } else if (geometryType == QLatin1String("LINESTRING")) { // Check first that there are coordinates const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates")); if (coordinatesValue.isArray()) { const QJsonArray coordinateArray = coordinatesValue.toArray(); GeoDataLineString * geom = new GeoDataLineString( RespectLatitudeCircle | Tessellate ); for (int coordinatePairIndex = 0; coordinatePairIndex < coordinateArray.size(); ++coordinatePairIndex) { const QJsonArray coordinatePairArray = coordinateArray[coordinatePairIndex].toArray(); const qreal longitude = coordinatePairArray.at(0).toDouble(); const qreal latitude = coordinatePairArray.at(1).toDouble(); geom->append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) ); } geometryList.append( geom ); } } else if (geometryType == QLatin1String("MULTILINESTRING")) { // Check first that there are coordinates const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates")); if (coordinatesValue.isArray()) { const QJsonArray coordinateArray = coordinatesValue.toArray(); for (int lineStringIndex = 0; lineStringIndex < coordinateArray.size(); ++lineStringIndex) { const QJsonArray lineStringArray = coordinateArray[lineStringIndex].toArray(); GeoDataLineString * geom = new GeoDataLineString( RespectLatitudeCircle | Tessellate ); for (int coordinatePairIndex = 0; coordinatePairIndex < lineStringArray.size(); ++coordinatePairIndex) { const QJsonArray coordinatePairArray = lineStringArray[coordinatePairIndex].toArray(); const qreal longitude = coordinatePairArray.at(0).toDouble(); const qreal latitude = coordinatePairArray.at(1).toDouble(); geom->append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) ); } geometryList.append( geom ); } } } else if (geometryType == QLatin1String("POINT")) { // Check first that there are coordinates const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates")); if (coordinatesValue.isArray()) { const QJsonArray coordinatePairArray = coordinatesValue.toArray(); GeoDataPoint * geom = new GeoDataPoint(); const qreal longitude = coordinatePairArray.at(0).toDouble(); const qreal latitude = coordinatePairArray.at(1).toDouble(); geom->setCoordinates( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) ); geometryList.append( geom ); } } else if (geometryType == QLatin1String("MULTIPOINT")) { // Check first that there are coordinates const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates")); if (coordinatesValue.isArray()) { const QJsonArray coordinateArray = coordinatesValue.toArray(); for (int pointIndex = 0; pointIndex < coordinateArray.size(); ++pointIndex) { const QJsonArray coordinatePairArray = coordinateArray[pointIndex].toArray(); GeoDataPoint * geom = new GeoDataPoint(); const qreal longitude = coordinatePairArray.at(0).toDouble(); const qreal latitude = coordinatePairArray.at(1).toDouble(); geom->setCoordinates( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) ); geometryList.append( geom ); } } } // Parse the features properties const QJsonValue propertiesValue = featureObject.value(QStringLiteral("properties")); if (!geometryList.isEmpty() && propertiesValue.isObject()) { const QJsonObject propertiesObject = propertiesValue.toObject(); // First create a placemark for each geometry, there could be multi geometries // that are translated into more than one geometry/placemark for ( int numberGeometries = 0 ; numberGeometries < geometryList.length() ; numberGeometries++ ) { GeoDataPlacemark * placemark = new GeoDataPlacemark(); placemarkList.append( placemark ); } OsmPlacemarkData osmData; QJsonObject::ConstIterator it = propertiesObject.begin(); const QJsonObject::ConstIterator end = propertiesObject.end(); for ( ; it != end; ++it) { if (it.value().isObject() || it.value().isArray()) { qDebug() << "Skipping property, values of type arrays and objects not supported:" << it.key(); continue; } // pass value through QVariant to also get bool & numbers osmData.addTag(it.key(), it.value().toVariant().toString()); } // If the property read, is the features name const auto tagIter = osmData.findTag(QStringLiteral("name")); if (tagIter != osmData.tagsEnd()) { const QString& name = tagIter.value(); for (int pl = 0 ; pl < placemarkList.length(); ++pl) { placemarkList.at(pl)->setName(name); } } const GeoDataPlacemark::GeoDataVisualCategory category = StyleBuilder::determineVisualCategory(osmData); if (category != GeoDataPlacemark::None) { // Add the visual category to all the placemarks for (int pl = 0 ; pl < placemarkList.length(); ++pl) { placemarkList.at(pl)->setVisualCategory(category); placemarkList.at(pl)->setOsmData(osmData); } } } // Add the geometry to the document if ( geometryList.length() == placemarkList.length() ) { while( placemarkList.length() > 0 ) { GeoDataPlacemark * placemark = placemarkList.last(); placemarkList.pop_back(); GeoDataGeometry * geom = geometryList.last(); geometryList.pop_back(); placemark->setGeometry( geom ); placemark->setVisible( true ); m_document->append( placemark ); } } // If geometries or placemarks missing inside the lists, delete them qDeleteAll( geometryList.begin(), geometryList.end() ); geometryList.clear(); qDeleteAll( placemarkList.begin(), placemarkList.end() ); placemarkList.clear(); } } } return true; }
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::TransportCarShare || category == GeoDataFeature::MoneyAtm) && m_osmData.containsTagKey("operator")) { placemark->setName(m_osmData.tagValue("operator")); } else { placemark->setName(m_osmData.tagValue("name")); } placemark->setVisualCategory(category); placemark->setStyle( GeoDataStyle::Ptr() ); if (category == GeoDataFeature::NaturalTree) { qreal const lat = m_coordinates.latitude(GeoDataCoordinates::Degree); if (qAbs(lat) > 15) { /** @todo Should maybe auto-adjust to MarbleClock at some point */ QDate const date = QDate::currentDate(); bool const southernHemisphere = lat < 0; QDate const autumnStart = QDate(date.year(), southernHemisphere ? 3 : 9, 15); QDate const winterEnd = southernHemisphere ? QDate(date.year(), 8, 15) : QDate(date.year()+1, 2, 15); if (date > autumnStart && date < winterEnd) { QDate const autumnEnd = QDate(date.year(), southernHemisphere ? 5 : 11, 15); QString const season = date < autumnEnd ? "autumn" : "winter"; GeoDataIconStyle iconStyle = placemark->style()->iconStyle(); QString const bitmap = QString("bitmaps/osmcarto/symbols/48/individual/tree-29-%1.png").arg(season); iconStyle.setIconPath(MarbleDirs::path(bitmap)); GeoDataStyle::Ptr style(new GeoDataStyle(*placemark->style())); style->setIconStyle(iconStyle); placemark->setStyle(style); } } } placemark->setZoomLevel( 18 ); if (category >= GeoDataFeature::PlaceCity && category <= GeoDataFeature::PlaceVillage) { int const population = m_osmData.tagValue("population").toInt(); placemark->setPopulation(qMax(0, population)); if (population > 0) { placemark->setZoomLevel(populationIndex(population)); placemark->setPopularity(population); } else { switch (category) { case GeoDataFeature::PlaceCity: placemark->setZoomLevel(9); break; case GeoDataFeature::PlaceSuburb: placemark->setZoomLevel(13); break; case GeoDataFeature::PlaceHamlet: placemark->setZoomLevel(15); break; case GeoDataFeature::PlaceLocality: placemark->setZoomLevel(15); break; case GeoDataFeature::PlaceTown: placemark->setZoomLevel(11); break; case GeoDataFeature::PlaceVillage: placemark->setZoomLevel(13); break; default: placemark->setZoomLevel(10); break; } } } else if (category == GeoDataFeature::NaturalPeak) { placemark->setZoomLevel(11); bool isInteger = false; int const elevation = m_osmData.tagValue("ele").toInt(&isInteger); if (isInteger) { placemark->setName(QString("%1 (%2 m)").arg(placemark->name()).arg(elevation)); } } OsmObjectManager::registerId(m_osmData.id()); document->append(placemark); }
void TestModel::simpleParseTest() { QString const centerContent ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "<kml xmlns=\"http://www.opengis.net/kml/2.2\">" "<Placemark>" "<Model id=\"model_4\">" "<altitudeMode>relativeToGround</altitudeMode>" "<Location>" "<longitude>-105.27</longitude>" "<latitude>40.00</latitude>" "<altitude>23.4</altitude>" "</Location>" "<Orientation>" "<heading>1</heading>" "<tilt>2</tilt>" "<roll>3</roll>" "</Orientation>" "<Scale>" "<x>3</x>" "<y>4</y>" "<z>5</z>" "</Scale>" "<Link>" "<href>MackyBldg.kmz/files/CU Macky.dae</href>" "<refreshMode>onExpire</refreshMode>" "</Link>" "<ResourceMap id=\"resourcemap_for_model_4\">" "<Alias>" "<sourceHref>../files/CU-Macky-4sideturretnoCulling.jpg</sourceHref>" "<targetHref>../files/CU-Macky-4sideturretnoCulling.jpg</targetHref>" "</Alias>" "</ResourceMap>" "</Model>" "</Placemark>" "</kml>" ); GeoDataDocument* dataDocument = parseKml( centerContent ); QCOMPARE( dataDocument->placemarkList().size(), 1 ); GeoDataPlacemark *placemark = dataDocument->placemarkList().at( 0 ); GeoDataModel *model = dynamic_cast<GeoDataModel*>( placemark->geometry() ); QVERIFY( model != 0 ); QCOMPARE( model->altitudeMode(), RelativeToGround); QCOMPARE( model->location().altitude(), 23.4); QCOMPARE( model->location().latitude(GeoDataCoordinates::Degree), 40.00 ); QCOMPARE( model->location().longitude(GeoDataCoordinates::Degree), -105.27 ); QCOMPARE( model->orientation().heading(), 1.0); QCOMPARE( model->orientation().tilt(), 2.0); QCOMPARE( model->orientation().roll(), 3.0); QCOMPARE( model->scale().x(), 3.0); QCOMPARE( model->scale().y(), 4.0); QCOMPARE( model->scale().z(), 5.0); QCOMPARE( model->link().href(), QString("MackyBldg.kmz/files/CU Macky.dae")); QCOMPARE( model->link().refreshMode(), GeoDataLink::OnExpire ); QCOMPARE( model->targetHref(), QString("../files/CU-Macky-4sideturretnoCulling.jpg")); QCOMPARE( model->sourceHref(), QString("../files/CU-Macky-4sideturretnoCulling.jpg")); delete dataDocument; }
bool GeoDataPlacemark::operator==( const GeoDataPlacemark& other ) const { if ( !equals(other) || p()->m_countrycode != other.p()->m_countrycode || p()->m_area != other.p()->m_area || p()->m_population != other.p()->m_population || p()->m_state != other.p()->m_state ) { return false; } if ( !p()->m_geometry && !other.p()->m_geometry ) { return true; } else if ( (!p()->m_geometry && other.p()->m_geometry) || (p()->m_geometry && !other.p()->m_geometry) ) { return false; } if ( p()->m_geometry->nodeType() != other.p()->m_geometry->nodeType() ) { return false; } if ( p()->m_geometry->nodeType() == GeoDataTypes::GeoDataPolygonType ) { GeoDataPolygon *thisPoly = dynamic_cast<GeoDataPolygon*>( p()->m_geometry ); GeoDataPolygon *otherPoly = dynamic_cast<GeoDataPolygon*>( other.p()->m_geometry ); Q_ASSERT( thisPoly && otherPoly ); if ( *thisPoly != *otherPoly ) { return false; } } else if ( p()->m_geometry->nodeType() == GeoDataTypes::GeoDataLineStringType ) { GeoDataLineString *thisLine = dynamic_cast<GeoDataLineString*>( p()->m_geometry ); GeoDataLineString *otherLine = dynamic_cast<GeoDataLineString*>( other.p()->m_geometry ); Q_ASSERT( thisLine && otherLine ); if ( *thisLine != *otherLine ) { return false; } } else if ( p()->m_geometry->nodeType() == GeoDataTypes::GeoDataModelType ) { GeoDataModel *thisModel = dynamic_cast<GeoDataModel*>( p()->m_geometry ); GeoDataModel *otherModel = dynamic_cast<GeoDataModel*>( other.p()->m_geometry ); Q_ASSERT( thisModel && otherModel ); if ( *thisModel != *otherModel ) { return false; } /*} else if ( p()->m_geometry->nodeType() == GeoDataTypes::GeoDataMultiGeometryType ) { GeoDataMultiGeometry *thisMG = dynamic_cast<GeoDataMultiGeometry*>( p()->m_geometry ); GeoDataMultiGeometry *otherMG = dynamic_cast<GeoDataMultiGeometry*>( other.p()->m_geometry ); Q_ASSERT( thisMG && otherMG ); if ( *thisMG != *otherMG ) { return false; } */ // Does not have equality operators. I guess they need to be implemented soon. } else if ( p()->m_geometry->nodeType() == GeoDataTypes::GeoDataTrackType ) { GeoDataTrack *thisTrack = dynamic_cast<GeoDataTrack*>( p()->m_geometry ); GeoDataTrack *otherTrack = dynamic_cast<GeoDataTrack*>( other.p()->m_geometry ); Q_ASSERT( thisTrack && otherTrack ); if ( *thisTrack != *otherTrack ) { return false; } } else if ( p()->m_geometry->nodeType() == GeoDataTypes::GeoDataMultiTrackType ) { GeoDataMultiTrack *thisMT = dynamic_cast<GeoDataMultiTrack*>( p()->m_geometry ); GeoDataMultiTrack *otherMT = dynamic_cast<GeoDataMultiTrack*>( other.p()->m_geometry ); Q_ASSERT( thisMT && otherMT ); if ( *thisMT != *otherMT ) { return false; } } else if ( p()->m_geometry->nodeType() == GeoDataTypes::GeoDataPointType ) { GeoDataPoint *thisPoint = dynamic_cast<GeoDataPoint*>( p()->m_geometry ); GeoDataPoint *otherPoint = dynamic_cast<GeoDataPoint*>( other.p()->m_geometry ); Q_ASSERT( thisPoint && otherPoint ); if ( *thisPoint != *otherPoint ) { return false; } } return true; }
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; }