[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