/*
* Geopaparazzi - Digital field mapping on Android based devices
* Copyright (C) 2016 HydroloGIS (www.hydrologis.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.geopaparazzi.core.maptools.tools;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.TypedValue;
import android.view.MotionEvent;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.index.strtree.STRtree;
import org.mapsforge.android.maps.MapView;
import org.mapsforge.android.maps.Projection;
import org.mapsforge.core.model.GeoPoint;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import eu.geopaparazzi.library.database.GPLog;
import eu.geopaparazzi.library.features.EditManager;
import eu.geopaparazzi.library.features.EditingView;
import eu.geopaparazzi.library.util.TimeUtilities;
import eu.geopaparazzi.core.GeopaparazziApplication;
import eu.geopaparazzi.core.R;
import eu.geopaparazzi.core.database.DaoGpsLog;
import eu.geopaparazzi.core.database.objects.GpsLogInfo;
import eu.geopaparazzi.core.maptools.MapTool;
import eu.geopaparazzi.core.mapview.overlays.SliderDrawProjection;
import static java.lang.Math.round;
/**
* A tool to get information about the gps log.
*
* @author Andrea Antonello (www.hydrologis.com)
*/
public class GpsLogInfoTool extends MapTool {
private final Paint linePaint = new Paint();
private final Paint colorBoxPaint = new Paint();
private final Paint whiteBoxPaint = new Paint();
private final Paint measureTextPaint = new Paint();
private final SliderDrawProjection projection;
private final String timeString;
private final String lonString;
private final String latString;
private final String altimString;
private final Rect rect = new Rect();
private DecimalFormat coordFormatter = new DecimalFormat("0.000000");
private DecimalFormat elevFormatter = new DecimalFormat("0.0");
private STRtree gpsLogInfoTree;
private GpsLogInfo gpsLogInfo;
private final int pixel;
/**
* Constructor.
*
* @param mapView the mapview reference.
*/
public GpsLogInfoTool(MapView mapView) throws IOException {
super(mapView);
Context context = GeopaparazziApplication.getInstance().getApplicationContext();
pixel = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, context.getResources().getDisplayMetrics());
timeString = context.getString(R.string.utctime);
lonString = context.getString(R.string.lon);
latString = context.getString(R.string.lat);
altimString = context.getString(R.string.altim);
EditingView editingView = EditManager.INSTANCE.getEditingView();
projection = new SliderDrawProjection(mapView, editingView);
readData(editingView);
whiteBoxPaint.setAntiAlias(false);
whiteBoxPaint.setColor(Color.argb(160, 255, 255, 255));
whiteBoxPaint.setStyle(Paint.Style.FILL);
}
private void readData(EditingView editingView) throws IOException {
int screenW = 0;
int screenE = editingView.getWidth();
int screenN = 0;
int screenS = editingView.getHeight();
GeoPoint llPoint = projection.fromPixels(screenW, screenS);
GeoPoint urPoint = projection.fromPixels(screenE, screenN);
double exp = 0.001;
gpsLogInfoTree = DaoGpsLog.getGpsLogInfoTree(urPoint.getLatitude() + exp, llPoint.getLatitude() - exp, urPoint.getLongitude() + exp, llPoint.getLongitude() - exp);
}
public void activate() {
if (mapView != null)
mapView.setClickable(false);
}
public void onToolDraw(Canvas canvas) {
int cWidth = canvas.getWidth();
int cHeight = canvas.getHeight();
int upper = 70;
if (gpsLogInfo == null)
return;
GpsLogInfo logInfo = gpsLogInfo;
int color = Color.BLACK;
try {
color = Color.parseColor(logInfo.color);
} catch (Exception e) {
// ignore
}
linePaint.setAntiAlias(true);
linePaint.setColor(color);
linePaint.setStrokeWidth(3f);
linePaint.setStyle(Paint.Style.STROKE);
colorBoxPaint.setAntiAlias(false);
colorBoxPaint.setColor(color);
colorBoxPaint.setStyle(Paint.Style.FILL);
measureTextPaint.setAntiAlias(true);
measureTextPaint.setTextSize(pixel);
measureTextPaint.setColor(color);
measureTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
String name = logInfo.logName;
String ts = " - ";
try {
ts = TimeUtilities.INSTANCE.TIME_FORMATTER_LOCAL.format(new Date(logInfo.timestamp));
} catch (Exception e) {
GPLog.error(this, "Error in timestamp: " + logInfo.timestamp, e);
}
String time = timeString + ts;
Coordinate pointXYZ = logInfo.pointXYZ;
if (pointXYZ == null)
pointXYZ = new Coordinate(-999, -999);
String lon = lonString + coordFormatter.format(pointXYZ.x);
String lat = latString + coordFormatter.format(pointXYZ.y);
String altim = altimString + elevFormatter.format(pointXYZ.z);
String[] texts = {name, time, lon, lat, altim};
int runningY = upper;
int textWidth = 0;
for (String text : texts) {
measureTextPaint.getTextBounds(text, 0, text.length(), rect);
int textHeight = rect.height();
runningY += textHeight + 3;
}
canvas.drawRect(0, 0, cWidth, runningY + 10, whiteBoxPaint);
canvas.drawRect(0, runningY, cWidth, runningY + 10, colorBoxPaint);
runningY = upper;
for (String text : texts) {
measureTextPaint.getTextBounds(text, 0, text.length(), rect);
textWidth = rect.width();
int textHeight = rect.height();
int x = cWidth / 2 - textWidth / 2;
canvas.drawText(text, x, runningY, measureTextPaint);
runningY += textHeight + 7;
}
GeoPoint geoPoint = new GeoPoint(pointXYZ.y, pointXYZ.x);
Point point = projection.toPixels(geoPoint, null);
canvas.drawLine(point.x, point.y, cWidth / 2, runningY, linePaint);
}
public boolean onToolTouchEvent(MotionEvent event) {
if (mapView == null || mapView.isClickable()) {
return false;
}
Projection pj = mapView.getProjection();
// handle drawing
float currentX = event.getX();
float currentY = event.getY();
int deltaPixels = 100;
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
GeoPoint currentGeoPoint = pj.fromPixels(round(currentX), round(currentY));
GeoPoint plusPoint = pj.fromPixels(round(currentX + deltaPixels), round(currentY + deltaPixels));
double touchLon = currentGeoPoint.getLongitude();
double touchLat = currentGeoPoint.getLatitude();
double lonPlus = plusPoint.getLongitude();
double latPlus = plusPoint.getLatitude();
double deltaX = Math.abs(touchLon - lonPlus);
double deltaY = Math.abs(touchLat - latPlus);
Coordinate touchCoord = new Coordinate(touchLon, touchLat);
Envelope queryEnvelope = new Envelope(touchCoord);
queryEnvelope.expandBy(deltaX, deltaY);
List<GpsLogInfo> result = gpsLogInfoTree.query(queryEnvelope);
if (result.size() == 0) {
return true;
} else {
GpsLogInfo nearest = null;
double minDist = Double.POSITIVE_INFINITY;
for (GpsLogInfo info : result) {
double dist = touchCoord.distance(info.pointXYZ);
if (dist < minDist) {
minDist = dist;
nearest = info;
}
}
gpsLogInfo = nearest;
}
break;
case MotionEvent.ACTION_UP:
gpsLogInfo = null;
break;
}
EditManager.INSTANCE.invalidateEditingView();
return true;
}
@Override
public void onViewChanged() {
EditingView editingView = EditManager.INSTANCE.getEditingView();
try {
readData(editingView);
} catch (IOException e) {
GPLog.error(this, null, e);
}
}
public void disable() {
if (mapView != null) {
mapView.setClickable(true);
mapView = null;
}
gpsLogInfo = null;
}
}