Esempio n. 1
0
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 );
}
Esempio n. 2
0
void PlasmaRunner::collectMatches(QList<Plasma::QueryMatch> &matches,
                                  const QString &query, const GeoDataFolder *folder)
{
    const QString queryLower = query.toLower();

    QVector<GeoDataFeature*>::const_iterator it = folder->constBegin();
    QVector<GeoDataFeature*>::const_iterator end = folder->constEnd();

    for (; it != end; ++it) {
        GeoDataFolder *folder = dynamic_cast<GeoDataFolder*>(*it);
        if ( folder ) {
            collectMatches(matches, query, folder);
            continue;
        }

        GeoDataPlacemark *placemark = dynamic_cast<GeoDataPlacemark*>( *it );
        if ( placemark ) {
            // For short query strings only match exactly, to get a sane number of matches
            if (query.length() < minContainsMatchLength) {
                if ( placemark->name().toLower() != queryLower &&
                     ( placemark->descriptionIsCDATA() || // TODO: support also with CDATA
                       placemark->description().toLower() != queryLower ) ) {
                    continue;
                }
            } else {
                if ( ! placemark->name().toLower().contains(queryLower) &&
                     ( placemark->descriptionIsCDATA() || // TODO: support also with CDATA
                       ! placemark->description().toLower().contains(queryLower) ) ) {
                    continue;
                }
            }

            const GeoDataCoordinates coordinates = placemark->coordinate();
            const qreal lon = coordinates.longitude(GeoDataCoordinates::Degree);
            const qreal lat = coordinates.latitude(GeoDataCoordinates::Degree);
            const QVariant coordinatesData = QVariantList()
                << QVariant(lon)
                << QVariant(lat)
                << QVariant(placemark->lookAt()->range()*METER2KM);

            Plasma::QueryMatch match(this);
            match.setIcon(QIcon::fromTheme(QStringLiteral("marble")));
            match.setText(placemark->name());
            match.setSubtext(i18n("Show in OpenStreetMap with Marble"));
            match.setData(coordinatesData);
            match.setId(placemark->name()+QString::number(lat)+QString::number(lon));
            match.setRelevance(1.0);
            match.setType(Plasma::QueryMatch::ExactMatch);

            matches << match;
        }
    }
}
Esempio n. 3
0
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())) );
    }
}
Esempio n. 4
0
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();
    }
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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;
    }
}
Esempio n. 7
0
void CountryByShape::postQuestion( QObject *gameObject )
{
    //Find a random placemark

    Q_ASSERT_X( d->m_countryNames, "CountryByShape::postQuestion",
                "CountryByShapePrivate::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;
    GeoDataPoint *point = 0;
    GeoDataCoordinates coord;
    GeoDataLatLonAltBox box;
    QVariantList answerOptions;
    while ( !found ) {
        int randomIndex = qrand()%countryPlacemarks.size();
        placemark = countryPlacemarks[randomIndex];
        point = dynamic_cast<GeoDataPoint*>( placemark->geometry() );
        coord = point->coordinates();

        if ( point ) {
            /**
             * Find the country geometry and fetch corresponding
             * GeoDataLatLonAltBox to zoom in to that country so that
             * it fills the viewport.
             */

            Q_ASSERT_X( d->m_countryBoundaries, "CountryByShape::postQuestion",
                        "CountryByShapePrivate::m_countryBoundaries is NULL" );

            QVector<GeoDataFeature*>::Iterator i = d->m_countryBoundaries->begin();
            QVector<GeoDataFeature*>::Iterator const end = d->m_countryBoundaries->end();
            for ( ; i != end; ++i ) {
                GeoDataPlacemark *country = static_cast<GeoDataPlacemark*>( *i );

                GeoDataPolygon *polygon = dynamic_cast<GeoDataPolygon*>( country->geometry() );
                GeoDataLinearRing *linearring = dynamic_cast<GeoDataLinearRing*>( country->geometry() );
                GeoDataMultiGeometry *multigeom = dynamic_cast<GeoDataMultiGeometry*>( country->geometry() );

                if ( polygon &&
                    polygon->contains( coord ) &&
                    !d->m_continentsAndOceans.contains(country->name(), Qt::CaseSensitive) )
                {
                    box = polygon->latLonAltBox();
                    found = true;
                    break;
                }
                if ( linearring &&
                    linearring->contains( coord ) &&
                    !d->m_continentsAndOceans.contains(country->name(), Qt::CaseSensitive) )
                {
                    box = linearring->latLonAltBox();
                    found = true;
                    break;
                }
                if ( multigeom ) {
                    QVector<GeoDataGeometry*>::Iterator iter = multigeom->begin();
                    QVector<GeoDataGeometry*>::Iterator const end = multigeom->end();

                    for ( ; iter != end; ++iter ) {
                        GeoDataPolygon *poly  = dynamic_cast<GeoDataPolygon*>( *iter );
                        if ( poly &&
                            poly->contains( coord ) &&
                            !d->m_continentsAndOceans.contains(country->name(), Qt::CaseSensitive) )
                        {
                            box = poly->latLonAltBox();
                            found = true;
                            break;
                        }
                    }
                }
                if ( found ) {
                    break;
                }
            }
        }
    }
    d->m_marbleWidget->setHighlightEnabled( true );
    emit announceHighlight( coord.longitude(GeoDataCoordinates::Degree),
                            coord.latitude(GeoDataCoordinates::Degree),
                            GeoDataCoordinates::Degree );

    /**
     * Now disable the highlight feature so that
     * the user click doesn't disturbe the highlight
     * we did to ask question.
     */ 
    d->m_marbleWidget->setHighlightEnabled( false );

    d->m_marbleWidget->centerOn( box, true );

    answerOptions << placemark->name()
    << countryPlacemarks[qrand()%countryPlacemarks.size()]->name()
    << countryPlacemarks[qrand()%countryPlacemarks.size()]->name()
    << countryPlacemarks[qrand()%countryPlacemarks.size()]->name();

    // Randomize options in 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, "countryByShapeQuestion",
                                   Q_ARG(QVariant, QVariant(answerOptions)),
                                   Q_ARG(QVariant, QVariant(placemark->name())) );
    }
}