[Marble-commits] KDE/kdeedu/marble/src/lib/routing
Dennis Nienhüser
earthwings at gentoo.org
Sun Nov 7 18:16:31 CET 2010
SVN commit 1193952 by nienhueser:
Replace the analytical approach of comparing linestrings by an empirical one. Fixes slow (>1 sec) behavior when ranking large routes. The empirical approach is faster by a magnitude of about three for large routes (> 100 km).
M +45 -18 AlternativeRoutesModel.cpp
--- trunk/KDE/kdeedu/marble/src/lib/routing/AlternativeRoutesModel.cpp #1193951:1193952
@@ -6,8 +6,8 @@
#include "RoutingModel.h"
#include "RouteAnnotator.h"
-#include <QtCore/QTime>
#include <QtCore/QTimer>
+#include <QtGui/QPainter>
namespace Marble {
@@ -83,6 +83,9 @@
static GeoDataLineString* waypoints( const GeoDataDocument* document );
+ static int nonZero( const QImage &image );
+
+ static QPolygonF polygon( const GeoDataLineString* lineString, qreal x, qreal y, qreal sx, qreal sy );
};
@@ -92,6 +95,30 @@
// nothing to do
}
+int AlternativeRoutesModelPrivate::nonZero( const QImage &image )
+{
+ QRgb* destLine = 0;
+ QRgb const black = qRgb( 0, 0, 0 );
+ int count = 0;
+ for ( int y = 0; y < image.height(); ++y ) {
+ destLine = (QRgb*) image.scanLine( y );
+ for ( int x = 0; x < image.width(); ++x ) {
+ count += destLine[x] == black ? 0 : 1;
+ }
+ }
+ return count;
+}
+
+QPolygonF AlternativeRoutesModelPrivate::polygon( const GeoDataLineString* lineString, qreal x, qreal y, qreal sx, qreal sy )
+{
+ QPolygonF poly;
+ for ( int i=0; i<lineString->size(); ++i ) {
+ poly << QPointF( qAbs( ( *lineString)[i].longitude() - x ) * sx,
+ qAbs( ( *lineString)[i].latitude() - y ) * sy );
+ }
+ return poly;
+}
+
bool AlternativeRoutesModelPrivate::filter( const GeoDataDocument* document ) const
{
for ( int i=0; i<m_routes.size(); ++i ) {
@@ -163,34 +190,34 @@
qreal AlternativeRoutesModelPrivate::unidirectionalSimilarity( const GeoDataDocument* routeA, const GeoDataDocument* routeB )
{
- qreal similarity = 0.0;
-
GeoDataLineString* waypointsA = waypoints( routeA );
GeoDataLineString* waypointsB = waypoints( routeB );
if ( !waypointsA || !waypointsB )
{
- return similarity;
+ return 0.0;
}
- QMap<int,qreal> mapping;
- for ( int a=0; a<waypointsA->size(); ++a ) {
- mapping[a] = AlternativeRoutesModelPrivate::distance( waypointsB, waypointsA->at( a ) );
+ QImage image( 64, 64, QImage::Format_ARGB32_Premultiplied );
+ image.fill( qRgb( 0, 0, 0 ) );
+ GeoDataLatLonBox box = GeoDataLatLonBox::fromLineString( *waypointsA );
+ box = box.united( GeoDataLatLonBox::fromLineString( *waypointsB ) );
+ if ( !box.width() || !box.height() ) {
+ return 0.0;
}
- qreal lengthA = waypointsA->length( EARTH_RADIUS );
+ qreal const sw = image.width() / box.width();
+ qreal const sh = image.height() / box.height();
- qreal nearThreshold = 100.0 / EARTH_RADIUS;
- qreal distance = 0.0;
- for ( int a=1; a<waypointsA->size(); ++a ) {
- if ( mapping[a] > nearThreshold ) {
- distance += distanceSphere( waypointsA->at(a-1), waypointsA->at(a) );
- }
- }
+ QPainter painter( &image );
+ painter.setPen( QColor( Qt::white ) );
- distance *= EARTH_RADIUS;
+ painter.drawPoints( AlternativeRoutesModelPrivate::polygon( waypointsA, box.west(), box.north(), sw, sh ) );
+ int const countA = AlternativeRoutesModelPrivate::nonZero( image );
- Q_ASSERT( distance >= 0 && distance <= lengthA );
- return 1 - distance / lengthA;
+ painter.drawPoints( AlternativeRoutesModelPrivate::polygon( waypointsB, box.west(), box.north(), sw, sh ) );
+ int const countB = AlternativeRoutesModelPrivate::nonZero( image );
+ Q_ASSERT( countA <= countB );
+ return countB ? 1.0 - qreal( countB - countA ) / countB : 0;
}
bool AlternativeRoutesModelPrivate::higherScore( const GeoDataDocument* one, const GeoDataDocument* two )
More information about the Marble-commits
mailing list