Initial version of track search. (still lots of TODOs, but works)

This commit is contained in:
Rodrigo Damazio
2011-11-20 22:50:59 -02:00
commit bb3a14aac0
490 changed files with 59622 additions and 0 deletions
@@ -0,0 +1,129 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.util.Log;
/**
* A dynamic speed path descriptor.
*
* @author Vangelis S.
*/
public class DynamicSpeedTrackPathDescriptor
implements TrackPathDescriptor, OnSharedPreferenceChangeListener {
private int slowSpeed;
private int normalSpeed;
private int speedMargin;
private double averageMovingSpeed;
private final Context context;
public DynamicSpeedTrackPathDescriptor(Context context){
this.context = context;
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs == null) {
speedMargin = 25;
return;
}
prefs.registerOnSharedPreferenceChangeListener(this);
speedMargin = Integer.parseInt(prefs.getString(
context.getString(R.string.track_color_mode_dynamic_speed_variation_key), "25"));
}
/**
* Get the slow speed calculated based on the % below the average speed.
* @return The speed limit considered as slow.
*/
public int getSlowSpeed()
{
slowSpeed = (int) (averageMovingSpeed - (averageMovingSpeed * speedMargin / 100));
return slowSpeed;
}
/**
* Get the medium speed calculated based on the % above the average speed.
* @return The speed limit considered as normal.
*/
public int getNormalSpeed()
{
normalSpeed = (int) (averageMovingSpeed + (averageMovingSpeed * speedMargin / 100));
return normalSpeed;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "DynamicSpeedTrackPathDescriptor: onSharedPreferences changed " + key);
if (key == null
|| !key.equals(context.getString(R.string.track_color_mode_dynamic_speed_variation_key))) {
return;
}
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs == null) {
speedMargin = 25;
return;
}
speedMargin =
Integer.parseInt(
prefs.getString(
context.getString(R.string.track_color_mode_dynamic_speed_variation_key), "25"));
}
@Override
public boolean needsRedraw() {
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
long currentTrackId = prefs.getLong(context.getString(R.string.selected_track_key), -1);
if(currentTrackId == -1) {
// Could not find track.
return false;
}
Track track = MyTracksProviderUtils.Factory.get(context).getTrack(currentTrackId);
TripStatistics stats = track.getStatistics();
double newaverageSpeed = (int) Math.floor(stats.getAverageMovingSpeed() * 3.6);
if(averageMovingSpeed == 0) {
averageMovingSpeed = newaverageSpeed;
return true;
}
double difference = Math.max(averageMovingSpeed, newaverageSpeed);
if (difference == 0.0) {
difference = 0.0;
} else {
difference = Math.abs(averageMovingSpeed - newaverageSpeed) / difference * 100;
}
if(difference >= 20) {
averageMovingSpeed = newaverageSpeed;
return true;
}
return false;
}
}
@@ -0,0 +1,141 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import com.google.android.apps.mytracks.ColoredPath;
import com.google.android.apps.mytracks.MapOverlay.CachedLocation;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.Projection;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import java.util.ArrayList;
import java.util.List;
/**
* A path painter that varies the path colors based on fixed speeds or average speed margin
* depending of the TrackPathDescriptor passed to its constructor.
*
* @author Vangelis S.
*/
public class DynamicSpeedTrackPathPainter implements TrackPathPainter {
private final Paint selectedTrackPaintSlow;
private final Paint selectedTrackPaintMedium;
private final Paint selectedTrackPaintFast;
private final List<ColoredPath> coloredPaths;
private final TrackPathDescriptor trackPathDescriptor;
private int slowSpeed;
private int normalSpeed;
public DynamicSpeedTrackPathPainter (Context context, TrackPathDescriptor trackPathDescriptor) {
this.trackPathDescriptor = trackPathDescriptor;
selectedTrackPaintSlow = TrackPathUtilities.getPaint(R.color.slow_path, context);
selectedTrackPaintMedium = TrackPathUtilities.getPaint(R.color.normal_path, context);
selectedTrackPaintFast = TrackPathUtilities.getPaint(R.color.fast_path, context);
this.coloredPaths = new ArrayList<ColoredPath>();
}
@Override
public void drawTrack(Canvas canvas) {
for(int i = 0; i < coloredPaths.size(); ++i) {
ColoredPath coloredPath = coloredPaths.get(i);
canvas.drawPath(coloredPath.getPath(), coloredPath.getPathPaint());
}
}
@Override
public void updatePath(Projection projection, Rect viewRect, int startLocationIdx,
Boolean alwaysVisible, List<CachedLocation> points) {
// Whether to start a new segment on new valid and visible point.
boolean newSegment = startLocationIdx <= 0 || !points.get(startLocationIdx - 1).valid;
boolean lastVisible = !newSegment;
final Point pt = new Point();
clear();
slowSpeed = trackPathDescriptor.getSlowSpeed();
normalSpeed = trackPathDescriptor.getNormalSpeed();
// Loop over track points.
for (int i = startLocationIdx; i < points.size(); ++i) {
CachedLocation loc = points.get(i);
// Check if valid, if not then indicate a new segment.
if (!loc.valid) {
newSegment = true;
continue;
}
final GeoPoint geoPoint = loc.geoPoint;
// Check if this breaks the existing segment.
boolean visible = alwaysVisible || viewRect.contains(
geoPoint.getLongitudeE6(), geoPoint.getLatitudeE6());
if (!visible && !lastVisible) {
// This is a point outside view not connected to a visible one.
newSegment = true;
}
lastVisible = visible;
// Either move to beginning of a new segment or continue the old one.
if (newSegment) {
projection.toPixels(geoPoint, pt);
newSegment = false;
} else {
ColoredPath coloredPath;
if(loc.speed <= slowSpeed) {
coloredPath = new ColoredPath(selectedTrackPaintSlow);
}
else if(loc.speed <= normalSpeed) {
coloredPath = new ColoredPath(selectedTrackPaintMedium);
} else {
coloredPath = new ColoredPath(selectedTrackPaintFast);
}
coloredPath.getPath().moveTo(pt.x, pt.y);
projection.toPixels(geoPoint, pt);
coloredPath.getPath().lineTo(pt.x, pt.y);
coloredPaths.add(coloredPath);
}
}
}
@Override
public void clear()
{
coloredPaths.clear();
}
@Override
public boolean needsRedraw() {
return trackPathDescriptor.needsRedraw();
}
@Override
public Path getLastPath() {
Path path = new Path();
for(int i = 0; i < coloredPaths.size(); ++i) {
path.addPath(coloredPaths.get(i).getPath());
}
return path;
}
}
@@ -0,0 +1,115 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.Constants;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.util.Log;
/**
* A fixed speed path descriptor.
*
* @author Vangelis S.
*/
public class FixedSpeedTrackPathDescriptor implements TrackPathDescriptor, OnSharedPreferenceChangeListener {
private int slowSpeed;
private int normalSpeed;
private final Context context;
public FixedSpeedTrackPathDescriptor(Context context) {
this.context = context;
context.getSharedPreferences(Constants.SETTINGS_NAME, 0)
.registerOnSharedPreferenceChangeListener(this);
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs == null) {
slowSpeed = 9;
normalSpeed = 17;
return;
}
try {
slowSpeed = Integer.parseInt(prefs.getString(context.getString(
R.string.track_color_mode_fixed_speed_slow_key), "9"));
} catch (NumberFormatException e) {
slowSpeed = 9;
}
try {
normalSpeed = Integer.parseInt(prefs.getString(context.getString(
R.string.track_color_mode_fixed_speed_medium_key), "17"));
} catch (NumberFormatException e) {
normalSpeed = 17;
}
}
/**
* Gets the slow speed for reference.
* @return The speed limit considered as slow.
*/
public int getSlowSpeed() {
return slowSpeed;
}
/**
* Gets the normal speed for reference.
* @return The speed limit considered as normal.
*/
public int getNormalSpeed() {
return normalSpeed;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "FixedSpeedTrackPathDescriptor: onSharedPreferences changed " + key);
if (key == null
|| (!key.equals(context.getString(R.string.track_color_mode_fixed_speed_slow_key))
&& !key.equals(context.getString(R.string.track_color_mode_fixed_speed_medium_key)))) {
return;
}
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs == null) {
slowSpeed = 9;
normalSpeed = 17;
return;
}
try {
slowSpeed = Integer.parseInt(prefs.getString(context.getString(
R.string.track_color_mode_fixed_speed_slow_key), "9"));
} catch (NumberFormatException e) {
slowSpeed = 9;
}
try {
normalSpeed = Integer.parseInt(prefs.getString(context.getString(
R.string.track_color_mode_fixed_speed_medium_key), "17"));
} catch (NumberFormatException e) {
normalSpeed = 17;
}
}
@Override
public boolean needsRedraw() {
return false;
}
}
@@ -0,0 +1,112 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import com.google.android.apps.mytracks.MapOverlay.CachedLocation;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.Projection;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import java.util.List;
/**
* A path painter that not variates the path colors.
*
* @author Vangelis S.
*/
public class SingleColorTrackPathPainter implements TrackPathPainter {
private final Paint selectedTrackPaint;
private Path path;
public SingleColorTrackPathPainter(Context context) {
selectedTrackPaint = TrackPathUtilities.getPaint(R.color.red, context);
}
@Override
public void drawTrack(Canvas canvas) {
canvas.drawPath(path, selectedTrackPaint);
}
@Override
public void updatePath(Projection projection, Rect viewRect, int startLocationIdx,
Boolean alwaysVisible, List<CachedLocation> points) {
// Whether to start a new segment on new valid and visible point.
boolean newSegment = startLocationIdx <= 0 || !points.get(startLocationIdx - 1).valid;
boolean lastVisible = !newSegment;
final Point pt = new Point();
// Loop over track points.
int numPoints = points.size();
path = newPath();
path.incReserve(numPoints);
for (int i = startLocationIdx; i < numPoints ; ++i) {
CachedLocation loc = points.get(i);
// Check if valid, if not then indicate a new segment.
if (!loc.valid) {
newSegment = true;
continue;
}
final GeoPoint geoPoint = loc.geoPoint;
// Check if this breaks the existing segment.
boolean visible = alwaysVisible
|| viewRect.contains(geoPoint.getLongitudeE6(), geoPoint.getLatitudeE6());
if (!visible && !lastVisible) {
// This is a point outside view not connected to a visible one.
newSegment = true;
}
lastVisible = visible;
// Either move to beginning of a new segment or continue the old one.
projection.toPixels(geoPoint, pt);
if (newSegment) {
path.moveTo(pt.x, pt.y);
newSegment = false;
} else {
path.lineTo(pt.x, pt.y);
}
}
}
@Override
public void clear() {
path = null;
}
@Override
public boolean needsRedraw() {
return false;
}
@Override
public Path getLastPath() {
return path;
}
// Visible for testing
public Path newPath() {
return new Path();
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
/**
* An interface for classes which describe how to draw a track path.
*
* @author Vangelis S.
*/
public interface TrackPathDescriptor {
/**
* @return The maximum speed which is considered slow.
*/
int getSlowSpeed();
/**
* @return The maximum speed which is considered normal.
*/
int getNormalSpeed();
/**
* @return True if the path needs to be updated.
*/
boolean needsRedraw();
}
@@ -0,0 +1,68 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import com.google.android.apps.mytracks.MapOverlay.CachedLocation;
import com.google.android.maps.Projection;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Rect;
import java.util.List;
/**
* An interface for classes which paint the track path.
*
* @author Vangelis S.
*/
public interface TrackPathPainter {
/**
* Clears the related data.
*/
void clear();
/**
* Draws the path to the canvas.
* @param canvas The Canvas to draw upon
*/
void drawTrack(Canvas canvas);
/**
* Updates the path.
* @param projection The Canvas to draw upon.
* @param viewRect The Path to be drawn.
* @param startLocationIdx The start point from where update the path.
* @param alwaysVisible Flag for alwaysvisible.
* @param points The list of points used to update the path.
*/
void updatePath(Projection projection, Rect viewRect, int startLocationIdx,
Boolean alwaysVisible, List<CachedLocation> points);
/**
* @return True if the path needs to be updated.
*/
boolean needsRedraw();
/**
* @return The path being used currently.
*/
Path getLastPath();
}
@@ -0,0 +1,66 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.Constants;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
/**
* A factory for TrackPathPainters.
*
* @author Vangelis S.
*/
public class TrackPathPainterFactory {
private TrackPathPainterFactory() {
}
/**
* Get a new TrackPathPainter.
* @param context Context to fetch system preferences.
* @return The TrackPathPainter that corresponds to the track color mode setting.
*/
public static TrackPathPainter getTrackPathPainter(Context context) {
SharedPreferences prefs =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs == null) {
return new SingleColorTrackPathPainter(context);
}
String colorMode = prefs.getString(context.getString(R.string.track_color_mode_key), null);
Log.i(TAG, "Creating track path painter of type: " + colorMode);
if (colorMode == null
|| colorMode.equals(context.getString(R.string.display_track_color_value_none))) {
return new SingleColorTrackPathPainter(context);
} else if (colorMode.equals(context.getString(R.string.display_track_color_value_fixed))) {
return new DynamicSpeedTrackPathPainter(context,
new FixedSpeedTrackPathDescriptor(context));
} else if (colorMode.equals(context.getString(R.string.display_track_color_value_dynamic))) {
return new DynamicSpeedTrackPathPainter(context,
new DynamicSpeedTrackPathDescriptor(context));
} else {
Log.w(TAG, "Using default track path painter. Unrecognized painter: " + colorMode);
return new SingleColorTrackPathPainter(context);
}
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import android.content.Context;
import android.graphics.Paint;
/**
* Various utility functions for TrackPath painting.
*
* @author Vangelis S.
*/
public class TrackPathUtilities {
public static Paint getPaint(int id, Context context) {
Paint paint = new Paint();
paint.setColor(context.getResources().getColor(id));
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
return paint;
}
}