void GeoLink::paint(GeoPainter* painter) const { if (!geoPeer.isSelf() && data_model->getMainLocation(geoPeer) != GeoPeerLoc::DEFAULT) { painter->setPen(Qt::yellow); foreach (const RsPgpId& gpg_id, geoPeer.getConnectionsList()) { const GeoPeer& other = data_model->getPeer(gpg_id); if (!other.isNull() && !other.isSelf() && other.getAssociatedSSLIds().size() > 0 && data_model->getMainLocation(other) != GeoPeerLoc::DEFAULT) { GeoDataLineString conLine; conLine.append(data_model->getMainLocation(geoPeer)); conLine.append(data_model->getMainLocation(other)); painter->drawPolyline(conLine); } } }
void OsmWayGraphicsItem::append( const GeoDataPoint& point ) { GeoDataLineString* line = dynamic_cast<GeoDataLineString*>(m_placemark->geometry()); if( line ) { line->append( point ); } }
GeoDataLineString GosmoreRunnerPrivate::parseGosmoreOutput( const QByteArray &content ) { GeoDataLineString routeWaypoints; QStringList lines = QString::fromLocal8Bit( content ).split( '\r' ); foreach( const QString &line, lines ) { QStringList fields = line.split(','); if (fields.size() >= 5) { qreal lon = fields.at(1).toDouble(); qreal lat = fields.at(0).toDouble(); GeoDataCoordinates coordinates( lon, lat, 0.0, GeoDataCoordinates::Degree ); routeWaypoints.append( coordinates ); } }
bool PolylineAnnotation::processEditingOnMove( QMouseEvent *mouseEvent ) { if ( !m_viewport ) { return false; } qreal lon, lat; m_viewport->geoCoordinates( mouseEvent->pos().x(), mouseEvent->pos().y(), lon, lat, GeoDataCoordinates::Radian ); const GeoDataCoordinates newCoords( lon, lat ); if ( m_interactingObj == InteractingNode ) { GeoDataLineString *line = static_cast<GeoDataLineString*>( placemark()->geometry() ); line->at(m_clickedNodeIndex) = newCoords; return true; } else if ( m_interactingObj == InteractingPolyline ) { GeoDataLineString *lineString = static_cast<GeoDataLineString*>( placemark()->geometry() ); const GeoDataLineString oldLineString = *lineString; lineString->clear(); const qreal deltaLat = lat - m_movedPointCoords.latitude(); const qreal deltaLon = lon - m_movedPointCoords.longitude(); Quaternion latRectAxis = Quaternion::fromEuler( 0, lon, 0); Quaternion latAxis = Quaternion::fromEuler( -deltaLat, 0, 0); Quaternion lonAxis = Quaternion::fromEuler(0, deltaLon, 0); Quaternion rotAxis = latRectAxis * latAxis * latRectAxis.inverse() * lonAxis; qreal lonRotated, latRotated; for ( int i = 0; i < oldLineString.size(); ++i ) { Quaternion qpos = oldLineString.at(i).quaternion(); qpos.rotateAroundAxis(rotAxis); qpos.getSpherical( lonRotated, latRotated ); GeoDataCoordinates movedPoint( lonRotated, latRotated, 0 ); lineString->append( movedPoint ); } m_movedPointCoords = newCoords; return true; } return dealWithHovering( mouseEvent ); }
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; }
GeoNode* OsmNdTagHandler::parse( GeoParser &geoParser ) const { Q_ASSERT( dynamic_cast<OsmParser *>( &geoParser ) != 0 ); OsmParser &parser = static_cast<OsmParser &>( geoParser ); Q_ASSERT( parser.isStartElement() ); GeoStackItem parentItem = parser.parentElement(); if ( parentItem.represents( osmTag_way ) ) { GeoDataLineString *s = parentItem.nodeAs<GeoDataLineString>(); Q_ASSERT( s ); quint64 id = parser.attribute( "ref" ).toULongLong(); if ( GeoDataPoint *p = parser.node( id ) ) { s->append( GeoDataCoordinates( p->coordinates().longitude(), p->coordinates().latitude() ) ); } return 0; } return 0; }
void PolylineAnnotation::move( const GeoDataCoordinates &source, const GeoDataCoordinates &destination ) { GeoDataLineString *lineString = static_cast<GeoDataLineString*>( placemark()->geometry() ); GeoDataLineString oldLineString = *lineString; lineString->clear(); const qreal deltaLat = destination.latitude() - source.latitude(); const qreal deltaLon = destination.longitude() - source.longitude(); Quaternion latRectAxis = Quaternion::fromEuler( 0, destination.longitude(), 0); Quaternion latAxis = Quaternion::fromEuler( -deltaLat, 0, 0); Quaternion lonAxis = Quaternion::fromEuler(0, deltaLon, 0); Quaternion rotAxis = latRectAxis * latAxis * latRectAxis.inverse() * lonAxis; qreal lonRotated, latRotated; for ( int i = 0; i < oldLineString.size(); ++i ) { Quaternion qpos = oldLineString.at(i).quaternion(); qpos.rotateAroundAxis(rotAxis); qpos.getSpherical( lonRotated, latRotated ); GeoDataCoordinates movedPoint( lonRotated, latRotated, 0 ); lineString->append( movedPoint ); } }
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; }
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; }
GeoDataDocument *ShpRunner::parseFile(const QString &fileName, DocumentRole role, QString &error) { QFileInfo fileinfo( fileName ); if (fileinfo.suffix().compare(QLatin1String("shp"), Qt::CaseInsensitive) != 0) { error = QStringLiteral("File %1 does not have a shp suffix").arg(fileName); mDebug() << error; return nullptr; } SHPHandle handle = SHPOpen( fileName.toStdString().c_str(), "rb" ); if ( !handle ) { error = QStringLiteral("Failed to read %1").arg(fileName); mDebug() << error; return nullptr; } int entities; int shapeType; SHPGetInfo( handle, &entities, &shapeType, NULL, NULL ); mDebug() << " SHP info " << entities << " Entities " << shapeType << " Shape Type "; DBFHandle dbfhandle; dbfhandle = DBFOpen( fileName.toStdString().c_str(), "rb"); int nameField = DBFGetFieldIndex( dbfhandle, "Name" ); int noteField = DBFGetFieldIndex( dbfhandle, "Note" ); int mapColorField = DBFGetFieldIndex( dbfhandle, "mapcolor13" ); GeoDataDocument *document = new GeoDataDocument; document->setDocumentRole( role ); if ( mapColorField != -1 ) { GeoDataSchema schema; schema.setId(QStringLiteral("default")); GeoDataSimpleField simpleField; simpleField.setName(QStringLiteral("mapcolor13")); simpleField.setType( GeoDataSimpleField::Double ); schema.addSimpleField( simpleField ); document->addSchema( schema ); } for ( int i=0; i< entities; ++i ) { GeoDataPlacemark *placemark = 0; placemark = new GeoDataPlacemark; document->append( placemark ); SHPObject *shape = SHPReadObject( handle, i ); if (nameField != -1) { const char* info = DBFReadStringAttribute( dbfhandle, i, nameField ); // TODO: defaults to utf-8 encoding, but could be also something else, optionally noted in a .cpg file placemark->setName( info ); mDebug() << "name " << placemark->name(); } if (noteField != -1) { const char* note = DBFReadStringAttribute( dbfhandle, i, noteField ); // TODO: defaults to utf-8 encoding, see comment for name placemark->setDescription( note ); mDebug() << "desc " << placemark->description(); } double mapColor = DBFReadDoubleAttribute( dbfhandle, i, mapColorField ); if ( mapColor ) { GeoDataStyle::Ptr style(new GeoDataStyle); if ( mapColor >= 0 && mapColor <=255 ) { quint8 colorIndex = quint8( mapColor ); style->polyStyle().setColorIndex( colorIndex ); } else { quint8 colorIndex = 0; // mapColor is undefined in this case style->polyStyle().setColorIndex( colorIndex ); } placemark->setStyle( style ); } switch ( shapeType ) { case SHPT_POINT: { GeoDataPoint *point = new GeoDataPoint( *shape->padfX, *shape->padfY, 0, GeoDataCoordinates::Degree ); placemark->setGeometry( point ); mDebug() << "point " << placemark->name(); break; } case SHPT_MULTIPOINT: { GeoDataMultiGeometry *geom = new GeoDataMultiGeometry; for( int j=0; j<shape->nVertices; ++j ) { geom->append( new GeoDataPoint( GeoDataCoordinates( shape->padfX[j], shape->padfY[j], 0, GeoDataCoordinates::Degree ) ) ); } placemark->setGeometry( geom ); mDebug() << "multipoint " << placemark->name(); break; } case SHPT_ARC: { if ( shape->nParts != 1 ) { GeoDataMultiGeometry *geom = new GeoDataMultiGeometry; for( int j=0; j<shape->nParts; ++j ) { GeoDataLineString *line = new GeoDataLineString; int itEnd = (j + 1 < shape->nParts) ? shape->panPartStart[j+1] : shape->nVertices; for( int k=shape->panPartStart[j]; k<itEnd; ++k ) { line->append( GeoDataCoordinates( shape->padfX[k], shape->padfY[k], 0, GeoDataCoordinates::Degree ) ); } geom->append( line ); } placemark->setGeometry( geom ); mDebug() << "arc " << placemark->name() << " " << shape->nParts; } else { GeoDataLineString *line = new GeoDataLineString; for( int j=0; j<shape->nVertices; ++j ) { line->append( GeoDataCoordinates( shape->padfX[j], shape->padfY[j], 0, GeoDataCoordinates::Degree ) ); } placemark->setGeometry( line ); mDebug() << "arc " << placemark->name() << " " << shape->nParts; } break; } case SHPT_POLYGON: { if ( shape->nParts != 1 ) { bool isRingClockwise = false; GeoDataMultiGeometry *multigeom = new GeoDataMultiGeometry; GeoDataPolygon *poly = 0; int polygonCount = 0; for( int j=0; j<shape->nParts; ++j ) { GeoDataLinearRing ring; int itStart = shape->panPartStart[j]; int itEnd = (j + 1 < shape->nParts) ? shape->panPartStart[j+1] : shape->nVertices; for( int k = itStart; k<itEnd; ++k ) { ring.append( GeoDataCoordinates( shape->padfX[k], shape->padfY[k], 0, GeoDataCoordinates::Degree ) ); } isRingClockwise = ring.isClockwise(); if ( j == 0 || isRingClockwise ) { poly = new GeoDataPolygon; ++polygonCount; poly->setOuterBoundary( ring ); if ( polygonCount > 1 ) { multigeom->append( poly ); } } else { poly->appendInnerBoundary( ring ); } } if ( polygonCount > 1 ) { placemark->setGeometry( multigeom ); } else { placemark->setGeometry( poly ); delete multigeom; multigeom = 0; } mDebug() << "donut " << placemark->name() << " " << shape->nParts; } else { GeoDataPolygon *poly = new GeoDataPolygon; GeoDataLinearRing ring; for( int j=0; j<shape->nVertices; ++j ) { ring.append( GeoDataCoordinates( shape->padfX[j], shape->padfY[j], 0, GeoDataCoordinates::Degree ) ); } poly->setOuterBoundary( ring ); placemark->setGeometry( poly ); mDebug() << "poly " << placemark->name() << " " << shape->nParts; } break; } } } SHPClose( handle ); DBFClose( dbfhandle ); if ( document->size() ) { document->setFileName( fileName ); return document; } else { delete document; return nullptr; } }
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; }
int MonavRunnerPrivate::retrieveRoute( const Marble::RouteRequest* route, QVector< Marble::GeoDataPlacemark* >* instructions, Marble::GeoDataLineString* geometry ) const { RoutingResult reply; if ( retrieveData( route, &reply ) ) { /** @todo: make use of reply.seconds, the estimated travel time */ for ( int i = 0; i < reply.pathNodes.size(); ++i ) { qreal lon = reply.pathNodes[i].longitude; qreal lat = reply.pathNodes[i].latitude; GeoDataCoordinates coordinates( lon, lat, 0, GeoDataCoordinates::Degree ); geometry->append( coordinates ); } RoutingWaypoints waypoints; int k = 0; for ( int i = 0; i < reply.pathEdges.size(); ++i ) { QString road = reply.nameStrings[reply.pathEdges[i].name]; QString type = reply.typeStrings[reply.pathEdges[i].type]; RoutingWaypoint::JunctionType junction = RoutingWaypoint::Other; if (type == QLatin1String("roundabout") && reply.pathEdges[i].branchingPossible) { junction = RoutingWaypoint::Roundabout; } for ( unsigned int l = 0; l < reply.pathEdges[i].length; ++k, ++l ) { qreal lon = reply.pathNodes[k].longitude; qreal lat = reply.pathNodes[k].latitude; RoutingPoint point( lon, lat ); bool const last = l == reply.pathEdges[i].length - 1; RoutingWaypoint::JunctionType finalJunction = last ? junction : ( reply.pathEdges[i].branchingPossible ? RoutingWaypoint::Other : RoutingWaypoint::None ); RoutingWaypoint waypoint( point, finalJunction, "", type, -1, road ); waypoints.push_back( waypoint ); } } RoutingInstructions directions = InstructionTransformation::process( waypoints ); 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 ); instructions->push_back( placemark ); } int duration = (int) reply.seconds; return duration; } return 0; }
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; }