GeoDataLineString GeoDataLineString::toNormalized() const { GeoDataLineString normalizedLineString; normalizedLineString.setTessellationFlags( tessellationFlags() ); qreal lon; qreal lat; // FIXME: Think about how we can avoid unnecessary copies // if the linestring stays the same. QVector<GeoDataCoordinates>::const_iterator end = p()->m_vector.constEnd(); for( QVector<GeoDataCoordinates>::const_iterator itCoords = p()->m_vector.constBegin(); itCoords != end; ++itCoords ) { itCoords->geoCoordinates( lon, lat ); qreal alt = itCoords->altitude(); GeoDataCoordinates::normalizeLonLat( lon, lat ); GeoDataCoordinates normalizedCoords( *itCoords ); normalizedCoords.set( lon, lat, alt ); normalizedLineString << normalizedCoords; } return normalizedLineString; }
bool PolylineAnnotation::processAddingNodesOnMove( QMouseEvent *mouseEvent ) { Q_ASSERT( mouseEvent->button() == Qt::NoButton ); const int index = virtualNodeContains( mouseEvent->pos() ); // If we are adjusting a virtual node which has just been clicked and became real, just // change its coordinates when moving it, as we do with nodes in Editing state on move. if ( m_adjustedNode != -1 ) { // The virtual node which has just been added is always the last within // GeoDataLinearRing's container.qreal lon, lat; qreal lon, lat; m_viewport->geoCoordinates( mouseEvent->pos().x(), mouseEvent->pos().y(), lon, lat, GeoDataCoordinates::Radian ); const GeoDataCoordinates newCoords( lon, lat ); GeoDataLineString *line = static_cast<GeoDataLineString*>( placemark()->geometry() ); line->at(m_adjustedNode) = newCoords; return true; // If we are hovering a virtual node, store its index in order to be painted in drawNodes // method. } else if ( index != -1 ) { m_virtualHoveredNode = index; return true; } return false; }
void PolylineAnnotation::updateRegions( GeoPainter *painter ) { if ( m_busy ) { return; } const GeoDataLineString line = static_cast<const GeoDataLineString>( *placemark()->geometry() ); if ( state() == SceneGraphicsItem::AddingNodes ) { // Create and update virtual nodes lists when being in the AddingPolgonNodes state, to // avoid overhead in other states. m_virtualNodesList.clear(); for ( int i = 0; i < line.size() - 1; ++i ) { const QRegion newRegion( painter->regionFromEllipse( line.at(i).interpolate( line.at(i+1), 0.5 ), hoveredDim, hoveredDim ) ); m_virtualNodesList.append( PolylineNode( newRegion ) ); } } // Update the polyline region; m_polylineRegion = painter->regionFromPolyline( line, 15 ); // Update the node lists. for ( int i = 0; i < m_nodesList.size(); ++i ) { const QRegion newRegion = m_nodesList.at(i).isSelected() ? painter->regionFromEllipse( line.at(i), selectedDim, selectedDim ) : painter->regionFromEllipse( line.at(i), regularDim, regularDim ); m_nodesList[i].setRegion( newRegion ); } }
bool GeoDataLineString::operator==( const GeoDataLineString &other ) const { if ( !GeoDataGeometry::equals(other) || size() != other.size() || tessellate() != other.tessellate() ) { return false; } const GeoDataLineStringPrivate* d = p(); const GeoDataLineStringPrivate* other_d = other.p(); QVector<GeoDataCoordinates>::const_iterator itCoords = d->m_vector.constBegin(); QVector<GeoDataCoordinates>::const_iterator otherItCoords = other_d->m_vector.constBegin(); QVector<GeoDataCoordinates>::const_iterator itEnd = d->m_vector.constEnd(); QVector<GeoDataCoordinates>::const_iterator otherItEnd = other_d->m_vector.constEnd(); for ( ; itCoords != itEnd && otherItCoords != otherItEnd; ++itCoords, ++otherItCoords ) { if ( *itCoords != *otherItCoords ) { return false; } } Q_ASSERT ( itCoords == itEnd && otherItCoords == otherItEnd ); return true; }
void OsmWayGraphicsItem::append( const GeoDataPoint& point ) { GeoDataLineString* line = dynamic_cast<GeoDataLineString*>(m_placemark->geometry()); if( line ) { line->append( point ); } }
bool PolylineAnnotation::processAddingNodesOnPress( QMouseEvent *mouseEvent ) { if ( mouseEvent->button() != Qt::LeftButton ) { return false; } GeoDataLineString *line = static_cast<GeoDataLineString*>( placemark()->geometry() ); // If a virtual node has just been clicked, add it to the polyline and start 'adjusting' // its position. const int virtualIndex = virtualNodeContains( mouseEvent->pos() ); if ( virtualIndex != -1 && m_adjustedNode == -1 ) { Q_ASSERT( m_virtualHoveredNode == virtualIndex ); line->insert( virtualIndex + 1, line->at( virtualIndex ).interpolate( line->at( virtualIndex + 1 ), 0.5 ) ); m_nodesList.insert( virtualIndex + 1, PolylineNode() ); m_adjustedNode = virtualIndex + 1; m_virtualHoveredNode = -1; return true; } // If a virtual node which has been previously clicked and selected to become a // 'real node' is clicked one more time, it stops from being 'adjusted'. const int realIndex = nodeContains( mouseEvent->pos() ); if ( realIndex != -1 && m_adjustedNode != -1 ) { m_adjustedNode = -1; return true; } return false; }
void RoutingWidget::handleSearchResult( RoutingInputWidget *widget ) { d->setActiveInput( widget ); MarblePlacemarkModel *model = widget->searchResultModel(); if ( model->rowCount() ) { QString const results = tr( "%n placemarks found", "", model->rowCount() ); d->m_ui.resultLabel->setText( results ); d->m_ui.resultLabel->setVisible( true ); // Make sure we have a selection activatePlacemark( model->index( 0, 0 ) ); } else { QString const results = tr( "No placemark found" ); d->m_ui.resultLabel->setText( "<font color=\"red\">" + results + "</font>" ); d->m_ui.resultLabel->setVisible( true ); } GeoDataLineString placemarks; for ( int i = 0; i < model->rowCount(); ++i ) { QVariant data = model->index( i, 0 ).data( MarblePlacemarkModel::CoordinateRole ); if ( !data.isNull() ) { placemarks << qVariantValue<GeoDataCoordinates>( data ); } } if ( placemarks.size() > 1 ) { d->m_widget->centerOn( GeoDataLatLonBox::fromLineString( placemarks ) ); //d->m_ui.descriptionLabel->setVisible( false ); if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) { d->m_ui.directionsListView->setVisible( true ); } } }
void GeoDataPlacemark::unpack( QDataStream& stream ) { detach(); p()->m_geometry->setParent( this ); GeoDataFeature::unpack( stream ); stream >> p()->m_countrycode; stream >> p()->m_area; stream >> p()->m_population; int geometryId; stream >> geometryId; switch( geometryId ) { case InvalidGeometryId: break; case GeoDataPointId: { GeoDataPoint* point = new GeoDataPoint; point->unpack( stream ); delete p()->m_geometry; p()->m_geometry = point; } break; case GeoDataLineStringId: { GeoDataLineString* lineString = new GeoDataLineString; lineString->unpack( stream ); delete p()->m_geometry; p()->m_geometry = lineString; } break; case GeoDataLinearRingId: { GeoDataLinearRing* linearRing = new GeoDataLinearRing; linearRing->unpack( stream ); delete p()->m_geometry; p()->m_geometry = linearRing; } break; case GeoDataPolygonId: { GeoDataPolygon* polygon = new GeoDataPolygon; polygon->unpack( stream ); delete p()->m_geometry; p()->m_geometry = polygon; } break; case GeoDataMultiGeometryId: { GeoDataMultiGeometry* multiGeometry = new GeoDataMultiGeometry; multiGeometry->unpack( stream ); delete p()->m_geometry; p()->m_geometry = multiGeometry; } break; case GeoDataModelId: break; default: break; }; }
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); }
void GeoDataMultiGeometry::unpack( QDataStream& stream ) { detach(); GeoDataGeometry::unpack( stream ); int size = 0; stream >> size; for( int i = 0; i < size; i++ ) { int geometryId; stream >> geometryId; switch( geometryId ) { case InvalidGeometryId: break; case GeoDataPointId: { GeoDataPoint *point = new GeoDataPoint; point->unpack( stream ); p()->m_vector.append( point ); } break; case GeoDataLineStringId: { GeoDataLineString *lineString = new GeoDataLineString; lineString->unpack( stream ); p()->m_vector.append( lineString ); } break; case GeoDataLinearRingId: { GeoDataLinearRing *linearRing = new GeoDataLinearRing; linearRing->unpack( stream ); p()->m_vector.append( linearRing ); } break; case GeoDataPolygonId: { GeoDataPolygon *polygon = new GeoDataPolygon; polygon->unpack( stream ); p()->m_vector.append( polygon ); } break; case GeoDataMultiGeometryId: { GeoDataMultiGeometry *multiGeometry = new GeoDataMultiGeometry; multiGeometry->unpack( stream ); p()->m_vector.append( multiGeometry ); } break; case GeoDataModelId: break; default: break; }; } }
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 AprsObject::render( GeoPainter *painter, ViewportParams *viewport, int fadeTime, int hideTime ) { Q_UNUSED( viewport ); if ( hideTime > 0 && m_history.last().timestamp().elapsed() > hideTime ) return; QColor baseColor = calculatePaintColor( m_seenFrom, m_history.last().timestamp(), fadeTime ); if ( m_history.count() > 1 ) { QList<GeoAprsCoordinates>::iterator spot = m_history.begin(); QList<GeoAprsCoordinates>::iterator endSpot = m_history.end(); GeoDataLineString lineString; lineString.setTessellate( true ); lineString << *spot; // *spot exists because m_history.count() > 1 for( ++spot; spot != endSpot; ++spot ) { if ( hideTime > 0 && ( *spot ).timestamp().elapsed() > hideTime ) break; lineString << *spot; // draw the new circle in whatever is appropriate for that point const QColor penColor = calculatePaintColor( spot->seenFrom(), spot->timestamp(), fadeTime ); painter->setPen( penColor ); painter->drawRect( *spot, 5, 5 ); } // draw the line in the base color painter->setPen( baseColor ); painter->drawPolyline( lineString ); } // Always draw the symbol then the text last so it's on top if ( m_havePixmap ) { if ( ! m_pixmap ) m_pixmap = new QPixmap ( m_pixmapFilename ); if ( m_pixmap && ! m_pixmap->isNull() ) painter->drawPixmap( m_history.last(), *m_pixmap ); else painter->drawRect( m_history.last(), 6, 6 ); } else painter->drawRect( m_history.last(), 6, 6 ); painter->setPen( baseColor ); painter->drawText( m_history.last(), m_myName ); }
void GosmoreRunnerPrivate::merge( GeoDataLineString* one, const GeoDataLineString& two ) { Q_ASSERT( one ); QVector<GeoDataCoordinates>::const_iterator iter = two.constBegin(); for( ; iter != two.constEnd(); ++iter ) { /** @todo: It might be needed to cut off some points at the start or end */ one->append( *iter ); } }
int RoutingModel::rightNeighbor( const GeoDataCoordinates &position, RouteRequest const *const route ) const { Q_ASSERT( route && "Must not pass a null route "); // Quick result for trivial cases if ( route->size() < 3 ) { return route->size() - 1; } // Generate an ordered list of all waypoints GeoDataLineString points = d->m_route.path(); QMap<int,int> mapping; // Force first mapping point to match the route start mapping[0] = 0; // Calculate the mapping between waypoints and via points // Need two for loops to avoid getting stuck in local minima for ( int j=1; j<route->size()-1; ++j ) { qreal minDistance = -1.0; for ( int i=mapping[j-1]; i<points.size(); ++i ) { qreal distance = distanceSphere( points[i], route->at(j) ); if (minDistance < 0.0 || distance < minDistance ) { mapping[j] = i; minDistance = distance; } } } // Determine waypoint with minimum distance to the provided position qreal minWaypointDistance = -1.0; int waypoint=0; for ( int i=0; i<points.size(); ++i ) { qreal waypointDistance = distanceSphere( points[i], position ); if ( minWaypointDistance < 0.0 || waypointDistance < minWaypointDistance ) { minWaypointDistance = waypointDistance; waypoint = i; } } // Force last mapping point to match the route destination mapping[route->size()-1] = points.size()-1; // Determine neighbor based on the mapping QMap<int, int>::const_iterator iter = mapping.constBegin(); for ( ; iter != mapping.constEnd(); ++iter ) { if ( iter.value() > waypoint ) { int index = iter.key(); Q_ASSERT( index >= 0 && index <= route->size() ); return index; } } return route->size()-1; }
GeoDataLineString GeoDataLineString::mid(int pos, int length) const { GeoDataLineString substring; auto d = substring.d_func(); d->m_vector = d_func()->m_vector.mid(pos, length); d->m_dirtyBox = true; d->m_dirtyRange = true; d->m_tessellationFlags = d_func()->m_tessellationFlags; d->m_extrude = d_func()->m_extrude; return substring; }
void EditPolylineDialog::handleItemMoving( GeoDataPlacemark *item ) { if( item == d->m_placemark ) { d->m_nodeModel->clear(); if( d->m_placemark->geometry()->nodeType() == GeoDataTypes::GeoDataLineStringType ) { GeoDataLineString *lineString = static_cast<GeoDataLineString*>( d->m_placemark->geometry() ); for( int i = 0; i < lineString->size(); ++i ) { d->m_nodeModel->addNode( lineString->at( i ) ); } } } }
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 ); } } }
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); } } }
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 ); } }
void RoutingModel::exportGpx( QIODevice *device ) const { QString content( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" ); content += "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"Marble\" version=\"1.1\" "; content += "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "; content += "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 "; content += "http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"; content += "<metadata>\n <link href=\"http://edu.kde.org/marble\">\n "; content += "<text>Marble Virtual Globe</text>\n </link>\n</metadata>\n"; content += " <rte>\n <name>Route</name>\n"; bool hasAltitude = false; for ( int i=0; !hasAltitude && i<d->m_route.size(); ++i ) { hasAltitude = d->m_route.at( i ).maneuver().position().altitude() != 0.0; } for ( int i=0; i<d->m_route.size(); ++i ) { const Maneuver &maneuver = d->m_route.at( i ).maneuver(); qreal lon = maneuver.position().longitude( GeoDataCoordinates::Degree ); qreal lat = maneuver.position().latitude( GeoDataCoordinates::Degree ); QString const text = maneuver.instructionText(); content += QString( " <rtept lat=\"%1\" lon=\"%2\">\n" ).arg( lat, 0, 'f', 7 ).arg( lon, 0, 'f', 7 ); content += QString( " <name>%1</name>\n").arg( text ); if ( hasAltitude ) { content += QString( " <ele>%1</ele>\n" ).arg( maneuver.position().altitude(), 0, 'f', 2 ); } content += QString( " </rtept>\n" ); } content += " </rte>\n"; content += "<trk>\n <name>Route</name>\n <trkseg>\n"; GeoDataLineString points = d->m_route.path(); hasAltitude = false; for ( int i=0; !hasAltitude && i<points.size(); ++i ) { hasAltitude = points[i].altitude() != 0.0; } for ( int i=0; i<points.size(); ++i ) { GeoDataCoordinates const &point = points[i]; qreal lon = point.longitude( GeoDataCoordinates::Degree ); qreal lat = point.latitude( GeoDataCoordinates::Degree ); content += QString( " <trkpt lat=\"%1\" lon=\"%2\">\n" ).arg( lat, 0, 'f', 7 ).arg( lon, 0, 'f', 7 ); if ( hasAltitude ) { content += QString( " <ele>%1</ele>\n" ).arg( point.altitude(), 0, 'f', 2 ); } content += QString( " </trkpt>\n" ); } content += " </trkseg>\n </trk>\n"; content += "</gpx>\n"; device->write( content.toUtf8() ); }
void PolylineAnnotation::deleteClickedNode() { if ( state() != SceneGraphicsItem::Editing ) { return; } GeoDataLineString *line = static_cast<GeoDataLineString*>( placemark()->geometry() ); if ( m_nodesList.size() <= 2 ) { setRequest( SceneGraphicsItem::RemovePolylineRequest ); return; } m_nodesList.removeAt( m_clickedNodeIndex ); line->remove( m_clickedNodeIndex ); }
void GeoDataLineStringPrivate::optimize (GeoDataLineString& lineString) const { QVector<GeoDataCoordinates>::iterator itCoords = lineString.begin(); QVector<GeoDataCoordinates>::const_iterator itEnd = lineString.constEnd(); if (lineString.size() < 2) return; // Calculate the least non-zero detail-level by checking the bounding box int startLevel = levelForResolution( ( lineString.latLonAltBox().width() + lineString.latLonAltBox().height() ) / 2 ); int currentLevel = startLevel; int maxLevel = startLevel; GeoDataCoordinates currentCoords; lineString.first().setDetail(startLevel); // Iterate through the linestring to assign different detail levels to the nodes. // In general the first and last node should have the start level assigned as // a detail level. // Starting from the first node the algorithm picks those nodes which // have a distance from each other that is just above the resolution that is // associated with the start level (which we use as a "current level"). // Each of those nodes get the current level assigned as the detail level. // After iterating through the linestring we increment the current level value // and starting again with the first node we assign detail values in a similar way // to the remaining nodes which have no final detail level assigned yet. // We do as many iterations through the lineString as needed and bump up the // current level until all nodes have a non-zero detail level assigned. while ( currentLevel < 16 && currentLevel <= maxLevel + 1 ) { itCoords = lineString.begin(); currentCoords = *itCoords; ++itCoords; for( ; itCoords != itEnd; ++itCoords) { if (itCoords->detail() != 0 && itCoords->detail() < currentLevel) continue; if ( currentLevel == startLevel && (itCoords->longitude() == -M_PI || itCoords->longitude() == M_PI || itCoords->latitude() < -89 * DEG2RAD || itCoords->latitude() > 89 * DEG2RAD)) { itCoords->setDetail(startLevel); currentCoords = *itCoords; maxLevel = currentLevel; continue; } if (distanceSphere( currentCoords, *itCoords ) < resolutionForLevel(currentLevel + 1)) { itCoords->setDetail(currentLevel + 1); } else { itCoords->setDetail(currentLevel); currentCoords = *itCoords; maxLevel = currentLevel; } } ++currentLevel; } lineString.last().setDetail(startLevel); }
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 PolylineAnnotation::setupRegionsLists( GeoPainter *painter ) { Q_ASSERT( state() == SceneGraphicsItem::DrawingPolyline || !m_regionsInitialized ); const GeoDataLineString line = static_cast<const GeoDataLineString>( *placemark()->geometry() ); // Add poyline nodes. QVector<GeoDataCoordinates>::ConstIterator itBegin = line.constBegin(); QVector<GeoDataCoordinates>::ConstIterator itEnd = line.constEnd(); m_nodesList.clear(); for ( ; itBegin != itEnd; ++itBegin ) { const PolylineNode newNode = PolylineNode( painter->regionFromEllipse( *itBegin, regularDim, regularDim ) ); m_nodesList.append( newNode ); } // Add region from polyline so that events on polyline's 'lines' could be caught. m_polylineRegion = painter->regionFromPolyline( line, 15 ); }
bool PolylineAnnotation::processMergingOnPress( QMouseEvent *mouseEvent ) { if ( mouseEvent->button() != Qt::LeftButton ) { return false; } GeoDataLineString line = static_cast<GeoDataLineString>( *placemark()->geometry() ); const int index = nodeContains( mouseEvent->pos() ); if ( index == -1 ) { return false; } // If this is the first node selected to be merged. if ( m_firstMergedNode == -1 ) { m_firstMergedNode = index; m_nodesList[index].setFlag( PolylineNode::NodeIsMerged ); } else { Q_ASSERT( m_firstMergedNode != -1 ); // Clicking two times the same node results in unmarking it for merging. if ( m_firstMergedNode == index ) { m_nodesList[index].setFlag( PolylineNode::NodeIsMerged, false ); m_firstMergedNode = -1; return true; } // If these two nodes are the last ones remained as part of the polyline, remove // the whole polyline. if ( line.size() <= 2 ) { setRequest( SceneGraphicsItem::RemovePolylineRequest ); return true; } m_nodesList[index].setFlag( PolylineNode::NodeIsMerged ); m_secondMergedNode = index; delete m_animation; m_animation = new MergingPolylineNodesAnimation( this ); setRequest( SceneGraphicsItem::StartPolylineAnimation ); } return true; }
void RoutingModelPrivate::importPlacemark( RouteSegment &outline, QVector<RouteSegment> &segments, const GeoDataPlacemark *placemark ) { GeoDataGeometry* geometry = placemark->geometry(); GeoDataLineString* lineString = dynamic_cast<GeoDataLineString*>( geometry ); QStringList blacklist = QStringList() << "" << "Route" << "Tessellated"; RouteSegment segment; bool isOutline = true; if ( !blacklist.contains( placemark->name() ) ) { if( lineString ) { Maneuver maneuver; maneuver.setInstructionText( placemark->name() ); maneuver.setPosition( lineString->at( 0 ) ); if ( placemark->extendedData().contains( "turnType" ) ) { QVariant turnType = placemark->extendedData().value( "turnType" ).value(); // The enum value is converted to/from an int in the QVariant // because only a limited set of data types can be serialized with QVariant's // toString() method (which is used to serialize <ExtendedData>/<Data> values) maneuver.setDirection( Maneuver::Direction( turnType.toInt() ) ); } if ( placemark->extendedData().contains( "roadName" ) ) { QVariant roadName = placemark->extendedData().value( "roadName" ).value(); maneuver.setRoadName( roadName.toString() ); } segment.setManeuver( maneuver ); isOutline = false; } } if ( lineString ) { segment.setPath( *lineString ); if ( isOutline ) { outline = segment; } else { segments.push_back( segment ); } } }
void PolylineAnnotation::deleteAllSelectedNodes() { if ( state() != SceneGraphicsItem::Editing ) { return; } GeoDataLineString *line = static_cast<GeoDataLineString*>( placemark()->geometry() ); for ( int i = 0; i < line->size(); ++i ) { if ( m_nodesList.at(i).isSelected() ) { if ( m_nodesList.size() <= 2 ) { setRequest( SceneGraphicsItem::RemovePolylineRequest ); return; } m_nodesList.removeAt( i ); line->remove( i ); --i; } } }
GeoDataLatLonAltBox GeoDataLatLonAltBox::fromLineString( const GeoDataLineString& lineString ) { // If the line string is empty return a boundingbox that contains everything if ( lineString.size() == 0 ) { return GeoDataLatLonAltBox(); } const qreal altitude = lineString.first().altitude(); GeoDataLatLonAltBox temp ( GeoDataLatLonBox::fromLineString( lineString ), altitude, altitude ); qreal maxAltitude = altitude; qreal minAltitude = altitude; // If there's only a single node stored then the boundingbox only contains that point if ( lineString.size() == 1 ) { temp.setMinAltitude( minAltitude ); temp.setMaxAltitude( maxAltitude ); return temp; } QVector<GeoDataCoordinates>::ConstIterator it( lineString.constBegin() ); QVector<GeoDataCoordinates>::ConstIterator itEnd( lineString.constEnd() ); for ( ; it != itEnd; ++it ) { // Get coordinates and normalize them to the desired range. const qreal altitude = (it)->altitude(); // Determining the maximum and minimum latitude if ( altitude > maxAltitude ) maxAltitude = altitude; if ( altitude < minAltitude ) minAltitude = altitude; } temp.setMinAltitude( minAltitude ); temp.setMaxAltitude( maxAltitude ); return temp; }
void EditPolylineDialog::checkFields() { bool ok = true; if ( d->m_name->text().isEmpty() ) { QMessageBox::warning( this, tr( "No name specified" ), tr( "Please specify a name for this polyline." ) ); ok = false; } else { if ( d->m_placemark->geometry()->nodeType() == GeoDataTypes::GeoDataLineStringType ) { GeoDataLineString *lineString = static_cast<GeoDataLineString*>( d->m_placemark->geometry() ); if( lineString->size() < 2 ) { QMessageBox::warning( this, tr( "Not enough nodes specified." ), tr( "Please specify at least 2 nodes for the path by clicking on the map." ) ); ok = false; } } } if( ok ) { accept(); } }
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; }