package id.ac.itats.skripsi.astarku;
import id.ac.itats.skripsi.databuilder.GraphAdapter;
import id.ac.itats.skripsi.shortestpath.engine.AStar2;
import id.ac.itats.skripsi.shortestpath.model.Graph;
import id.ac.itats.skripsi.shortestpath.model.Vertex;
import id.ac.itats.skripsi.util.MapMatchingUtil;
import id.ac.itats.skripsi.util.MapviewUtils;
import id.ac.itats.skripsi.util.Reporter;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mapsforge.core.graphics.Color;
import org.mapsforge.core.graphics.Style;
import org.mapsforge.core.model.LatLong;
import org.mapsforge.core.model.MapPosition;
import org.mapsforge.core.util.MercatorProjection;
import org.mapsforge.map.android.AndroidPreferences;
import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
import org.mapsforge.map.android.view.MapView;
import org.mapsforge.map.layer.Layer;
import org.mapsforge.map.layer.LayerManager;
import org.mapsforge.map.layer.cache.TileCache;
import org.mapsforge.map.layer.overlay.Marker;
import org.mapsforge.map.layer.overlay.Polyline;
import org.mapsforge.map.model.MapViewPosition;
import org.mapsforge.map.model.common.PreferencesFacade;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.SubMenu;
import com.actionbarsherlock.view.Window;
public class BasicMapViewer extends SherlockActivity implements ActionBar.OnNavigationListener {
protected final String TAG = BasicMapViewer.class.getSimpleName();
// Activity
private String[] mLocations;
// Mapview
protected String mapFile = "surabaya_new.map";
protected MapView mapView;
protected PreferencesFacade preferencesFacade;
protected TileCache tileCache;
private GestureDetector gestureDetector;
private LayerManager layerManager;
private volatile boolean shortestPathRunning = false;
private LatLong start, end;
private List<Layer> layersOverlay = new ArrayList<Layer>();
protected SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(android.view.MotionEvent motionEvent) {
MapViewPosition mapPosition = mapView.getModel().mapViewPosition;
LatLong geoPoint = mapPosition.getMapPosition().latLong;
if (shortestPathRunning) {
logUser("Calculation still in progress");
return false;
}
if (GraphAdapter.getGraph() == null) {
logUser("Graph not yet ready!");
return false;
}
float x = motionEvent.getX();
float y = motionEvent.getY();
double pixelX = MercatorProjection.longitudeToPixelX(geoPoint.longitude, mapPosition.getZoomLevel());
double pixelY = MercatorProjection.latitudeToPixelY(geoPoint.latitude, mapPosition.getZoomLevel());
pixelX -= mapView.getWidth() >> 1;
pixelY -= mapView.getHeight() >> 1;
LatLong tmpPoint = new LatLong(MercatorProjection.pixelYToLatitude(pixelY + y, mapPosition.getZoomLevel()),
MercatorProjection.pixelXToLongitude(pixelX + x, mapPosition.getZoomLevel()));
if (start != null && end == null) {
end = tmpPoint;
shortestPathRunning = true;
Marker marker = MapviewUtils.createMarker(BasicMapViewer.this, R.drawable.marker_red, tmpPoint);
layersOverlay.add(marker);
if (marker != null) {
layerManager.getLayers().add(marker);
layerManager.redrawLayers();
}
calcPath(start.latitude, start.longitude, end.latitude, end.longitude);
} else {
start = tmpPoint;
end = null;
for (Layer layer : layersOverlay) {
layerManager.getLayers().remove(layer);
}
Marker marker = MapviewUtils.createMarker(BasicMapViewer.this, R.drawable.marker_green, start);
layersOverlay.add(marker);
if (marker != null) {
layerManager.getLayers().add(marker);
layerManager.redrawLayers();
}
}
return true;
}
};
protected void addLayers(LayerManager layerManager, TileCache tileCache, MapViewPosition mapViewPosition) {
layerManager.getLayers().add(MapviewUtils.createTileRendererLayer(tileCache, mapViewPosition, getMapFile()));
}
protected TileCache createTileCache() {
return MapviewUtils.createExternalStorageTileCache(this, getPersistableId());
}
protected MapPosition getInitialPosition() {
return new MapPosition(new LatLong(-7.2517722, 112.6822205), (byte) 14);
}
protected File getMapFile() {
return new File(Environment.getExternalStorageDirectory() + "/routingengine/maps/" + mapFile);
}
protected MapView getMapView() {
return new MapView(this) {
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
if (gestureDetector.onTouchEvent(motionEvent)) {
return true;
}
return super.onTouchEvent(motionEvent);
}
};
}
protected String getPersistableId() {
return this.getClass().getSimpleName();
}
protected void init() {
this.mapView = getMapView();
layerManager = mapView.getLayerManager();
gestureDetector = new GestureDetector(this, gestureListener);
initializeMapView(this.mapView, this.preferencesFacade);
this.tileCache = createTileCache();
MapViewPosition mapViewPosition = this.initializePosition(this.mapView.getModel().mapViewPosition);
addLayers(this.mapView.getLayerManager(), this.tileCache, mapViewPosition);
setContentView();
}
protected void initializeMapView(MapView mapView, PreferencesFacade preferences) {
mapView.getModel().init(preferences);
mapView.setClickable(true);
mapView.getMapScaleBar().setVisible(false);
}
protected MapViewPosition initializePosition(MapViewPosition mapViewPosition) {
LatLong center = mapViewPosition.getCenter();
Log.i(TAG, "" + center);
if (center.equals(new LatLong(0, 0))) {
mapViewPosition.setMapPosition(this.getInitialPosition());
}
return mapViewPosition;
}
protected void addMarker(MotionEvent motionEvent) {
Marker marker = null;
MapViewPosition mapPosition = mapView.getModel().mapViewPosition;
LatLong geoPoint = mapPosition.getMapPosition().latLong;
float x = motionEvent.getX();
float y = motionEvent.getY();
double pixelX = MercatorProjection.longitudeToPixelX(geoPoint.longitude, mapPosition.getZoomLevel());
double pixelY = MercatorProjection.latitudeToPixelY(geoPoint.latitude, mapPosition.getZoomLevel());
pixelX -= mapView.getWidth() >> 1;
pixelY -= mapView.getHeight() >> 1;
LatLong latLong = new LatLong(MercatorProjection.pixelYToLatitude(pixelY + y, mapPosition.getZoomLevel()),
MercatorProjection.pixelXToLongitude(pixelX + x, mapPosition.getZoomLevel()));
marker = MapviewUtils.createMarker(this, R.drawable.marker_red, latLong);
this.mapView.getLayerManager().getLayers().add(marker);
this.mapView.getLayerManager().redrawLayers();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDecoration();
Intent service = new Intent(BasicMapViewer.this, GraphService.class);
startService(service);
SharedPreferences sharedPreferences = this.getSharedPreferences(getPersistableId(), MODE_PRIVATE);
this.preferencesFacade = new AndroidPreferences(sharedPreferences);
init();
}
@Override
protected void onDestroy() {
super.onDestroy();
this.mapView.destroy();
}
@Override
protected void onPause() {
super.onPause();
this.mapView.getModel().save(this.preferencesFacade);
this.preferencesFacade.save();
}
protected void setContentView() {
setContentView(this.mapView);
}
protected void initDecoration() {
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
requestWindowFeature(Window.FEATURE_PROGRESS);
getSupportActionBar().setBackgroundDrawable(getResources().getDrawable(R.drawable.ab_bg_black));
setSupportProgressBarVisibility(false);
getSupportActionBar().setDisplayShowTitleEnabled(false);
mLocations = getResources().getStringArray(R.array.locations);
Context context = getSupportActionBar().getThemedContext();
ArrayAdapter<CharSequence> list = ArrayAdapter.createFromResource(context, R.array.locations,
R.layout.sherlock_spinner_item);
list.setDropDownViewResource(R.layout.sherlock_spinner_dropdown_item);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setListNavigationCallbacks(list, this);
}
protected void logUser(String str) {
Toast.makeText(this, str, Toast.LENGTH_LONG).show();
}
protected void log(String str) {
Log.i(TAG, str);
}
// XXX ROUTING
protected void calcPath(final double fromLat, final double fromLon, final double toLat, final double toLon) {
new AsyncTask<Void, Integer, List<Vertex>>() {
int mProgress = 100;
Handler mHandler = new Handler();
Runnable mProgressRunner = new Runnable() {
@Override
public void run() {
mProgress +=1;
int progress = (Window.PROGRESS_END - Window.PROGRESS_START) / 100 * mProgress;
setSupportProgress(progress);
if (reporter.isFinish() == false) {
mHandler.postDelayed(mProgressRunner, 300);
}
}
};
Graph graph = GraphAdapter.getGraph();
Reporter reporter = new Reporter();
@Override
protected void onPreExecute() {
setSupportProgressBarVisibility(true);
}
@Override
protected List<Vertex> doInBackground(Void... params) {
if (mProgress == 100) {
mProgress = 0;
mProgressRunner.run();
}
Vertex source = MapMatchingUtil.doMatching(graph.getVerticeValues(), fromLat, fromLon);
System.out.println(source.id);
Vertex target = MapMatchingUtil.doMatching(graph.getVerticeValues(), toLat, toLon);
System.out.println(target.id);
AStar2 aStar2 = new AStar2(graph, reporter);
List<Vertex> path = aStar2.computePaths(source, target);
// while (mProgress < 100) {
// mProgress += 1;
//
// SystemClock.sleep(300);
// publishProgress(mProgress);
//
// }
return path;
}
@Override
protected void onPostExecute(List<Vertex> result) {
if (result != null) {
Polyline polyline = new Polyline(MapviewUtils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.BLUE), 7, Style.STROKE),
AndroidGraphicFactory.INSTANCE);
List<LatLong> latLongs = polyline.getLatLongs();
for (Vertex vertex : result) {
latLongs.add(new LatLong(Double.parseDouble(vertex.lat), Double.parseDouble(vertex.lon)));
}
layerManager.getLayers().add(polyline);
layerManager.redrawLayers();
layersOverlay.add(polyline);
logUser(reporter.getReport());
} else {
logUser(reporter.getReport());
for (Layer layer : layersOverlay) {
layerManager.getLayers().remove(layer);
}
}
shortestPathRunning = false;
setSupportProgressBarVisibility(false);
}
}.execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
SubMenu sub = menu.addSubMenu("Option");
sub.setIcon(R.drawable.abs__ic_menu_moreoverflow_normal_holo_dark);
sub.add(0, R.style.AppTheme, 0, "Setting");
sub.add(0, R.style.AppTheme, 0, "Help");
sub.add(0, R.style.AppTheme, 0, "About");
sub.getItem().setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_NEVER);
return true;
}
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
System.out.println("Selected: " + mLocations[itemPosition]);
return true;
}
}