5

Sto cercando di risolvere un problema con il tracciamento di un percorso da un enorme set (di 100 k +) di punti geografici a un MapView su Android. In primo luogo vorrei dire che ho cercato molto spesso in StackOverflow e non ho trovato una risposta.Il collo di bottiglia del mio codice non è in realtà un disegno su tela, ma il metodo Projection.toPixels(GeoPoint, Point) o Rect.contains(point.x, point.y)..sono saltando i punti non visibili sullo schermo e mostra anche solo ogni nesimo punto in base al livello di zoom corrente. Quando la mappa viene ingrandita, voglio visualizzare il percorso più preciso possibile, così salgo zero (o quasi zero) punti, così che quando trovo punti visibili devo chiamare il metodo di proiezione per ogni singolo punto della collezione. Ed è quello che ci vuole davvero molto tempo (non secondi, ma il panning delle mappe non è fluido e non lo sto testando su HTC Wildfire :)). Ho provato a memorizzare i punti calcolati nella cache, ma dal momento che i punti vengono ricalcolati dopo ogni pan/zoom della mappa non ha aiutato affatto .Disegno (filtro) 100k + punta a MapView in Android

ho pensato di utilizzo di un qualche tipo di prugna secca e algoritmo di ricerca, invece di scorrere la matrice, ma ho capito i dati di input non è ordinato (non riesco a buttare via qualsiasi filiale impilati tra due punti invisibili). Questo è possibile risolvere con un ordinamento semplice all'inizio, ma non sono ancora sicuro che anche il conteggio logaritmico delle chiamate getProjection() e Rect.contains(point.x, point.y) anziché lineare risolverà il problema delle prestazioni.

Bellow è il mio codice corrente. Per favore aiutami se sai come migliorarlo. Molte grazie!

public void drawPath(MapView mv, Canvas canvas) { 
    displayed = false; 

    tmpPath.reset(); 

    int zoomLevel = mapView.getZoomLevel(); 
    int skippedPoints = (int) Math.pow(2, (Math.max((19 - zoomLevel), 0))); 
    int mPointsSize = mPoints.size(); 
    int mPointsLastIndex = mPointsSize - 1; 
    int stop = mPointsLastIndex - skippedPoints; 

    mapView.getDrawingRect(currentMapBoundsRect); 
    Projection projection = mv.getProjection(); 

    for (int i = 0; i < mPointsSize; i += skippedPoints) { 

     if (i > stop) { 
      break; 
     } 
//HERE IS THE PROBLEM I THINK - THIS METHOD AND THE IF CONDITION BELOW 
     projection.toPixels(mPoints.get(i), point); 

     if (currentMapBoundsRect.contains(point.x, point.y)) { 
      if (!displayed) { 
       Point tmpPoint = new Point(); 
       projection.toPixels(mPoints.get(Math.max(i - 1, 0)), 
         tmpPoint); 
       tmpPath.moveTo(tmpPoint.x, tmpPoint.y); 
       tmpPath.lineTo(point.x, point.y); 
       displayed = true; 
      } else { 

       tmpPath.lineTo(point.x, point.y); 

      } 

     } else if (displayed) { 
      tmpPath.lineTo(point.x, point.y); 
      displayed = false; 

     } 

    } 

    canvas.drawPath(tmpPath, this.pathPaint); 

} 
+0

Quindi ho eseguito un po 'di tracciamento e circa l'85% di carico utilizza il metodo 'Projection.toPixels()' Ci deve essere un modo per ottimizzarlo:/ – simekadam

+0

Un altro modo potrebbe essere utilizzare un qualche tipo di mappatura. HashMap con coord come chiave .. Come dividere il mondo in segmenti rettangolari e quindi filtrare quelli in base allo stato corrente di mapView. Quindi prendilo da HashMap e visualizzalo. Ma questo sembra abbastanza complicato :) Pensi che sia possibile? Solo se ha senso o meno .. – simekadam

risposta

3

Quindi ho capito come rendere tutto molto più veloce! Lo posterò qui, qualcuno potrebbe averlo trovato utile in futuro. È emerso che l'utilizzo di projection.toPixels() può davvero danneggiare le prestazioni dell'applicazione. Così ho capito che il modo migliore di prendere ogni singolo GeoPoint, convertirlo in Point e quindi controllare se è contenuta in mappa viewport è, quando io conto actuall raggio viewport della mappa come segue:

mapView.getGlobalVisibleRect(currentMapBoundsRect); 
    GeoPoint point1 = projection.fromPixels(currentMapBoundsRect.centerX(), currentMapBoundsRect.centerY()); 
    GeoPoint point2 = projection.fromPixels(currentMapBoundsRect.left, currentMapBoundsRect.top); 
    float[] results2 = new float[3]; 
    Location.distanceBetween(point1.getLatitudeE6()/1E6, point1.getLongitudeE6()/1E6, point2.getLatitudeE6()/1E6, point2.getLongitudeE6()/1E6, results2); 

Il raggio è nei risultati2 [0] ..

Quindi posso prendere ogni singolo GeoPoint e contare la distanza tra esso e il centro della mappa mapView.getMapCenter(). Quindi posso confrontare il raggio con la distanza calcolata e decidere se non visualizzare il punto.

Quindi è tutto, spero Sarà utile.