Created
March 22, 2016 12:58
-
-
Save wviana/ae07cafe4526f167e0d1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package neocom.dealerbook.models.layer.presenters; | |
import com.androidmapsextensions.GoogleMap; | |
import com.androidmapsextensions.TileOverlay; | |
import com.androidmapsextensions.TileOverlayOptions; | |
import com.google.android.gms.maps.model.LatLng; | |
import com.google.maps.android.heatmaps.HeatmapTileProvider; | |
import java.util.List; | |
import neocom.dealerbook.models.layer.dataAdapter.LayerDataAdapter; | |
/** | |
* Created by wviana on 04/03/16. | |
*/ | |
public class HeatPresenter implements LayerPresenter { | |
protected HeatmapTileProvider tileProvider; | |
protected TileOverlay tileOverlay; | |
@Override | |
public void present(LayerDataAdapter data, GoogleMap map) { | |
updateTileProvider(data.getLatLngList()); | |
if(tileOverlay == null && tileProvider != null) { | |
tileOverlay = createTileProvider(map); | |
} | |
} | |
protected TileOverlay createTileProvider(GoogleMap map) { | |
return map.addTileOverlay(new TileOverlayOptions().tileProvider(tileProvider)); | |
} | |
private void updateTileProvider(List<LatLng> points) { | |
if(tileProvider == null){ | |
tileProvider = new HeatmapTileProvider.Builder() | |
.data(points) | |
.build(); | |
} else { | |
tileProvider.setData(points); | |
if (tileOverlay != null) tileOverlay.clearTileCache(); | |
} | |
} | |
@Override | |
public void clear() { | |
if (tileOverlay != null) { | |
tileOverlay.remove(); | |
tileOverlay = null; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package neocom.dealerbook.models.layer.presenters; | |
import com.androidmapsextensions.GoogleMap; | |
import com.cocoahero.android.geojson.GeoJSON; | |
import com.cocoahero.android.geojson.GeoJSONObject; | |
import neocom.dealerbook.models.layer.dataAdapter.LayerDataAdapter; | |
/** | |
* Created by wviana on 03/03/16. | |
*/ | |
public interface LayerPresenter { | |
void present(LayerDataAdapter data, GoogleMap map); | |
void clear(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package neocom.dealerbook.models.layer.presenters; | |
import android.graphics.Color; | |
import android.support.annotation.NonNull; | |
import android.util.Log; | |
import com.androidmapsextensions.GoogleMap; | |
import com.androidmapsextensions.TileOverlay; | |
import com.androidmapsextensions.TileOverlayOptions; | |
import com.google.android.gms.maps.model.LatLng; | |
import com.google.android.gms.maps.model.LatLngBounds; | |
import com.google.maps.android.geometry.Point; | |
import com.google.maps.android.heatmaps.Gradient; | |
import com.google.maps.android.heatmaps.HeatmapTileProvider; | |
import com.google.maps.android.heatmaps.WeightedLatLng; | |
import com.google.maps.android.projection.SphericalMercatorProjection; | |
import org.apache.commons.math3.ml.clustering.CentroidCluster; | |
import org.apache.commons.math3.ml.clustering.KMeansPlusPlusClusterer; | |
import java.util.ArrayList; | |
import java.util.List; | |
import neocom.dealerbook.models.layer.dataAdapter.LayerDataAdapter; | |
import neocom.dealerbook.models.layer.dataAdapter.WeightedLatLngWrapper; | |
/** | |
* Created by wviana on 04/03/16. | |
*/ | |
public class WeightedHeatPresenter extends HeatPresenter { | |
public static final int CLUSTER_NUMBER = 5; | |
public static final int CLUSTER_MAX_ITERATIONS = 10; | |
public static final int HEAT_RADIUS_SIZE = 40; | |
private final int[] colors = { | |
Color.rgb(254, 217, 118), | |
Color.rgb(254, 178, 76), | |
Color.rgb(253, 141, 60), | |
Color.rgb(252, 78, 42), | |
Color.rgb(227, 26, 28), | |
Color.rgb(177, 0, 38) | |
}; | |
private final float[] range = {0.4f, 0.5f, 0.6f, 0.7f, 0.9f, 1f}; | |
@Override | |
public void present(LayerDataAdapter data, GoogleMap map) { | |
LatLngBounds currentBound = map.getProjection().getVisibleRegion().latLngBounds; | |
List<WeightedLatLng> showablePoints = filterByBound(data, currentBound); | |
if (showablePoints.size() > CLUSTER_NUMBER) { | |
showablePoints = normalizePoints(showablePoints); | |
} | |
updateTileProvider(showablePoints); | |
if(tileOverlay == null && tileProvider != null) { | |
tileOverlay = createTileProvider(map); | |
} | |
} | |
@NonNull | |
private List<WeightedLatLng> normalizePoints(List<WeightedLatLng> pointsInsideBound) { | |
List<WeightedLatLngWrapper> wrapperedPoints = WeightedLatLngWrapper.wrappeList(pointsInsideBound); | |
KMeansPlusPlusClusterer<WeightedLatLngWrapper> clusterer = new KMeansPlusPlusClusterer<>(CLUSTER_NUMBER, CLUSTER_MAX_ITERATIONS); | |
List<CentroidCluster<WeightedLatLngWrapper>> clusterResults = clusterer.cluster(wrapperedPoints); | |
List<WeightedLatLng> reValuedPoints = new ArrayList<>(); | |
for(CentroidCluster<WeightedLatLngWrapper> cluster : clusterResults){ | |
for (WeightedLatLngWrapper point : cluster.getPoints()){ | |
LatLng latLng = pointToLatLng(point.getWeightedLatLng().getPoint()); | |
double value = cluster.getCenter().getPoint()[0]; | |
reValuedPoints.add(new WeightedLatLng(latLng, value)); | |
} | |
} | |
return reValuedPoints; | |
} | |
@NonNull | |
private List<WeightedLatLng> filterByBound(LayerDataAdapter data, LatLngBounds currentBound) { | |
List<WeightedLatLng> pointsInsideBound = new ArrayList<>(); | |
for (WeightedLatLng point : data.getWeightedLatLngList()){ | |
LatLng pointLL = pointToLatLng(point.getPoint()); | |
if (currentBound.contains(pointLL)){ | |
pointsInsideBound.add(point); | |
} | |
} | |
return pointsInsideBound; | |
} | |
private LatLng pointToLatLng(Point point1) { | |
SphericalMercatorProjection projection = new SphericalMercatorProjection(1.0D); | |
return projection.toLatLng(point1); | |
} | |
//TODO refactoring de HeatPresenter ser super classe. | |
private void updateTileProvider(List<WeightedLatLng> points) { | |
try { | |
if(tileProvider == null){ | |
tileProvider = new HeatmapTileProvider.Builder() | |
.weightedData(points) | |
.radius(HEAT_RADIUS_SIZE) | |
.gradient(new Gradient(colors, range)) | |
.build(); | |
} else { | |
tileProvider.setWeightedData(points); | |
if (tileOverlay != null) tileOverlay.clearTileCache(); | |
} | |
} catch (IllegalArgumentException e) { | |
//clear(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment