package net.kazhik.android.tokyorunners;\r
\r
-import java.text.SimpleDateFormat;\r
import java.util.ArrayList;\r
-import java.util.Date;\r
import java.util.Iterator;\r
import java.util.List;\r
\r
import android.graphics.Paint;\r
import android.graphics.Path;\r
import android.graphics.Point;\r
+import android.graphics.PointF;\r
import android.graphics.RectF;\r
import android.graphics.Paint.FontMetrics;\r
-import android.graphics.drawable.Drawable;\r
import android.graphics.drawable.ShapeDrawable;\r
import android.graphics.drawable.shapes.PathShape;\r
+import android.location.Location;\r
+import android.location.LocationManager;\r
import android.os.Bundle;\r
import android.os.Debug;\r
-import android.util.Log;\r
import android.view.KeyEvent;\r
+import android.view.Menu;\r
import android.view.MenuItem;\r
-import android.widget.Toast;\r
\r
import com.google.android.maps.GeoPoint;\r
-import com.google.android.maps.ItemizedOverlay;\r
import com.google.android.maps.MapActivity;\r
import com.google.android.maps.MapController;\r
import com.google.android.maps.MapView;\r
import com.google.android.maps.MyLocationOverlay;\r
import com.google.android.maps.Overlay;\r
-import com.google.android.maps.OverlayItem;\r
import com.google.android.maps.Projection;\r
\r
// TODO: Auto-generated Javadoc\r
\r
/** The m_controller. */\r
private MapController m_controller;\r
- \r
+\r
/** The m_map overlays. */\r
private List<Overlay> m_mapOverlays;\r
- \r
- /** The m_overlay splitpoints. */\r
- private SplitPoints m_overlaySplitpoints;\r
- \r
- /** The m_prev point. */\r
- private GeoPoint m_prevPoint = null;\r
- \r
+\r
/** The m_start time. */\r
private long m_startTime = 0;\r
- \r
- /** The m_time formatter. */\r
- private final SimpleDateFormat m_timeFormatter = new SimpleDateFormat(\r
- "HH:mm:ss");\r
\r
/** The m_route paint. */\r
private static Paint m_routePaint;\r
- \r
+\r
/** The m_text paint. */\r
private static Paint m_textPaint;\r
- \r
+\r
/** The m_info paint. */\r
private static Paint m_infoPaint;\r
\r
+ private RunningRoute m_route;\r
+\r
static {\r
m_routePaint = new Paint(Paint.ANTI_ALIAS_FLAG);\r
m_routePaint.setStyle(Paint.Style.STROKE);\r
m_infoPaint.setTextSize(20);\r
m_infoPaint.setAntiAlias(true);\r
m_infoPaint.setFakeBoldText(true);\r
- m_infoPaint.setColor(Color.MAGENTA);\r
+ m_infoPaint.setColor(Color.LTGRAY);\r
\r
}\r
\r
*/\r
public class RunningRoute extends Overlay {\r
\r
- /** The m_start. */\r
- private GeoPoint m_start;\r
- \r
- /** The m_end. */\r
- private GeoPoint m_end;\r
+ private ArrayList<GeoPoint> m_pointList = new ArrayList<GeoPoint>();\r
\r
- /**\r
- * Instantiates a new running route.\r
- * \r
- * @param ptStart the pt start\r
- * @param ptEnd the pt end\r
- */\r
- public RunningRoute(GeoPoint ptStart, GeoPoint ptEnd) {\r
- m_start = ptStart;\r
- m_end = ptEnd;\r
+ public RunningRoute() {\r
+\r
+ }\r
+\r
+ public void addPoint(GeoPoint pt) {\r
+ m_pointList.add(pt);\r
}\r
\r
- /* (non-Javadoc)\r
- * @see com.google.android.maps.Overlay#draw(android.graphics.Canvas, com.google.android.maps.MapView, boolean)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see com.google.android.maps.Overlay#draw(android.graphics.Canvas,\r
+ * com.google.android.maps.MapView, boolean)\r
*/\r
@Override\r
public void draw(Canvas canvas, MapView mapView, boolean shadow) {\r
super.draw(canvas, mapView, shadow);\r
\r
if (!shadow) {\r
- Path path = new Path();\r
Projection projection = mapView.getProjection();\r
- Point pxStart = projection.toPixels(m_start, null);\r
- Point pxEnd = projection.toPixels(m_end, null);\r
- path.moveTo(pxStart.x, pxStart.y);\r
- path.lineTo(pxEnd.x, pxEnd.y);\r
-\r
- canvas.drawPath(path, m_routePaint);\r
+ Point pxStart = null;\r
+ Point pxEnd = null;\r
+ GeoPoint gpCenter = mapView.getMapCenter();\r
+ int latFrom = gpCenter.getLatitudeE6()\r
+ - (mapView.getLatitudeSpan() / 2);\r
+ int latTo = gpCenter.getLatitudeE6()\r
+ + (mapView.getLatitudeSpan() / 2);\r
+ int lonFrom = gpCenter.getLongitudeE6()\r
+ - (mapView.getLongitudeSpan() / 2);\r
+ int lonTo = gpCenter.getLongitudeE6()\r
+ + (mapView.getLongitudeSpan() / 2);\r
+ for (Iterator<GeoPoint> it = m_pointList.iterator(); it\r
+ .hasNext();) {\r
+ GeoPoint gp = it.next();\r
+\r
+ int lat = gp.getLatitudeE6();\r
+ int lon = gp.getLongitudeE6();\r
+ // 表示されない部分は描画しない\r
+ if (lat < latFrom || lat > latTo || lon < lonFrom\r
+ || lon > lonTo) {\r
+ continue;\r
+ }\r
+\r
+ pxEnd = projection.toPixels(gp, null);\r
+ if (pxStart != null) {\r
+\r
+ canvas.drawLine(pxStart.x, pxStart.y, pxEnd.x, pxEnd.y,\r
+ m_routePaint);\r
+ }\r
+\r
+ pxStart = pxEnd;\r
+ }\r
}\r
}\r
}\r
\r
/** The m_text. */\r
private String m_text;\r
- \r
+\r
/** The m_point. */\r
private GeoPoint m_point;\r
\r
/**\r
* Instantiates a new text overlay.\r
* \r
- * @param point the point\r
- * @param text the text\r
+ * @param point\r
+ * the point\r
+ * @param text\r
+ * the text\r
*/\r
public TextOverlay(GeoPoint point, String text) {\r
m_point = point;\r
m_text = text;\r
}\r
\r
- /* (non-Javadoc)\r
- * @see com.google.android.maps.Overlay#draw(android.graphics.Canvas, com.google.android.maps.MapView, boolean)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see com.google.android.maps.Overlay#draw(android.graphics.Canvas,\r
+ * com.google.android.maps.MapView, boolean)\r
*/\r
@Override\r
public void draw(Canvas canvas, MapView mapView, boolean shadow) {\r
/**\r
* Draw balloon.\r
* \r
- * @param canvas the canvas\r
- * @param pt the pt\r
+ * @param canvas\r
+ * the canvas\r
+ * @param pt\r
+ * the pt\r
*/\r
private void drawBalloon(Canvas canvas, Point pt) {\r
+ FontMetrics fontMetrics = m_textPaint.getFontMetrics();\r
float textWidth = m_textPaint.measureText(m_text);\r
- float textX = pt.x - textWidth / 2;\r
+ float textHeight = Math.abs(fontMetrics.top) + fontMetrics.bottom;\r
\r
- FontMetrics fontMetrics = m_textPaint.getFontMetrics();\r
- float textY = pt.y - (fontMetrics.ascent + fontMetrics.descent) / 2;\r
+ float triangleHeight = textHeight;\r
+ float triangleWidth = triangleHeight;\r
\r
- float margin = 5;\r
- float balloonStartX = textX - margin;\r
- float balloonEndX = textX + textWidth + margin;\r
- float balloonStartY = textY + fontMetrics.ascent - margin;\r
- float balloonEndY = textY + fontMetrics.descent + margin;\r
+ final float margin = 5;\r
+ float textX = pt.x - textWidth / 2;\r
\r
- RectF infoRect = new RectF(balloonStartX, balloonStartY,\r
- balloonEndX, balloonEndY);\r
+ float textY = pt.y - margin - triangleHeight;\r
+\r
+ RectF infoRect = new RectF(textX - margin, pt.y - textHeight\r
+ - (margin * 2) - triangleHeight,\r
+ textX + textWidth + margin, pt.y - triangleHeight);\r
\r
final float radius = 5;\r
+ // テキストが入る四角形を描画\r
canvas.drawRoundRect(infoRect, radius, radius, m_infoPaint);\r
\r
- float balloonCenterX = (balloonStartX + balloonEndX) / 2;\r
-\r
// ポイントを指す三角形を描画\r
- // int triangleWidth = (int) textX / 2;\r
- int triangleWidth = (int) textWidth / 2;\r
- int triangleHeight = triangleWidth / 2;\r
-\r
- // 三角形の頂点を表わすポイントの生成\r
- Point point = new Point((int) balloonCenterX - triangleWidth / 2,\r
- (int) balloonEndY);\r
- Point[] cornerPoint = new Point[3];\r
- cornerPoint[0] = new Point(0, 0);\r
- cornerPoint[1] = new Point(triangleWidth, 0);\r
- cornerPoint[2] = new Point(triangleWidth / 2, triangleHeight);\r
+\r
+ PointF[] cornerPoint = new PointF[3];\r
+ PointF point = new PointF(infoRect.centerX() - triangleWidth / 2,\r
+ infoRect.bottom);\r
+ cornerPoint[0] = new PointF(0, 0);\r
+ cornerPoint[1] = new PointF(triangleWidth, 0);\r
+ cornerPoint[2] = new PointF(triangleWidth / 2, triangleHeight);\r
\r
drawShape(canvas, point, cornerPoint, m_infoPaint.getColor());\r
\r
+ // テキストを描画\r
canvas.drawText(m_text, textX, textY, m_textPaint);\r
\r
}\r
/**\r
* 多角形の描画.\r
* \r
- * @param canvas the canvas\r
- * @param point 描画位置\r
- * @param corners 描画する頂点を表わすポイント\r
- * @param color 描画色\r
+ * @param canvas\r
+ * the canvas\r
+ * @param point\r
+ * 描画位置\r
+ * @param corners\r
+ * 描画する頂点を表わすポイント\r
+ * @param color\r
+ * 描画色\r
*/\r
- private void drawShape(Canvas canvas, Point point, Point[] corners,\r
+ private void drawShape(Canvas canvas, PointF point, PointF[] corners,\r
int color) {\r
float maxWidth = 0;\r
float maxHeight = 0;\r
// Pointを結ぶ頂点のパス作成\r
Path path = new Path();\r
for (int cornerCnt = 0; cornerCnt < corners.length; cornerCnt++) {\r
- int x = corners[cornerCnt].x;\r
- int y = corners[cornerCnt].y;\r
+ float x = corners[cornerCnt].x;\r
+ float y = corners[cornerCnt].y;\r
// はじめの頂点はmoveTo\r
if (cornerCnt == 0) {\r
path.moveTo(x, y);\r
ShapeDrawable drawable = new ShapeDrawable(new PathShape(path,\r
maxWidth, maxHeight));\r
drawable.getPaint().setColor(color);\r
- drawable.setBounds(point.x, point.y, point.x + (int) maxWidth,\r
- point.y + (int) maxHeight);\r
+ drawable.setBounds((int) point.x, (int) point.y, (int) point.x\r
+ + (int) maxWidth, (int) point.y + (int) maxHeight);\r
drawable.draw(canvas);\r
}\r
}\r
\r
- /**\r
- * The Class SplitPoints.\r
- */\r
- private class SplitPoints extends ItemizedOverlay<OverlayItem> {\r
-\r
- /** The m_splitpoints. */\r
- private ArrayList<OverlayItem> m_splitpoints = new ArrayList<OverlayItem>();\r
-\r
- /**\r
- * Instantiates a new split points.\r
- * \r
- * @param defaultMarker the default marker\r
- */\r
- public SplitPoints(Drawable defaultMarker) {\r
- super(boundCenterBottom(defaultMarker));\r
- }\r
-\r
- /**\r
- * Adds the splitpoint.\r
- * \r
- * @param overlay the overlay\r
- */\r
- public void addSplitpoint(OverlayItem overlay) {\r
- m_splitpoints.add(overlay);\r
- populate();\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see com.google.android.maps.ItemizedOverlay#createItem(int)\r
- */\r
- @Override\r
- protected OverlayItem createItem(int idx) {\r
- // Log.d(this.getClass().getName(), "createItem(): index: " + idx);\r
- return m_splitpoints.get(idx);\r
- }\r
-\r
- /**\r
- * Clear item.\r
- */\r
- public void clearItem() {\r
- m_splitpoints.clear();\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see com.google.android.maps.ItemizedOverlay#size()\r
- */\r
- @Override\r
- public int size() {\r
- return m_splitpoints.size();\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see com.google.android.maps.ItemizedOverlay#onTap(int)\r
- */\r
- @Override\r
- protected boolean onTap(int i) {\r
- Log.d(this.getClass().getName(), "onTap(): index: " + i);\r
- if (m_splitpoints.size() > 0) {\r
- Toast.makeText(MapMode.this, m_splitpoints.get(i).getSnippet(),\r
- Toast.LENGTH_LONG).show();\r
- }\r
- return true;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see com.google.android.maps.ItemizedOverlay#draw(android.graphics.Canvas, com.google.android.maps.MapView, boolean)\r
- */\r
- public void draw(Canvas canvas, MapView mapview, boolean shadow) {\r
- super.draw(canvas, mapview, shadow);\r
-\r
- }\r
- }\r
-\r
/** The m_running record receiver. */\r
private BroadcastReceiver m_runningRecordReceiver = new BroadcastReceiver() {\r
@Override\r
.getLongitudeE6());\r
m_controller.animateTo(gp);\r
\r
- // Route\r
- if (m_prevPoint != null) {\r
- RunningRoute route = new RunningRoute(m_prevPoint, gp);\r
- m_mapOverlays.add(route);\r
- }\r
+ m_route.addPoint(gp);\r
// Split point\r
if (rec.getName().length() > 0) {\r
- //drawSplitPoint(gp, rec.getName(), rec.getDate());\r
TextOverlay textOverlay = new TextOverlay(gp, rec.getName());\r
m_mapOverlays.add(textOverlay);\r
}\r
- m_prevPoint = gp;\r
}\r
\r
}\r
};\r
\r
- /* (non-Javadoc)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
* @see com.google.android.maps.MapActivity#isRouteDisplayed()\r
*/\r
@Override\r
return false;\r
}\r
\r
- /* (non-Javadoc)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
* @see com.google.android.maps.MapActivity#onResume()\r
*/\r
@Override\r
\r
}\r
\r
- /* (non-Javadoc)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
* @see com.google.android.maps.MapActivity#onPause()\r
*/\r
@Override\r
unregisterReceiver(m_runningRecordReceiver);\r
}\r
\r
- /* (non-Javadoc)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
* @see com.google.android.maps.MapActivity#onCreate(android.os.Bundle)\r
*/\r
@Override\r
\r
m_mapOverlays = mapView.getOverlays();\r
\r
- Drawable runner = getResources().getDrawable(R.drawable.runner);\r
- m_overlaySplitpoints = new SplitPoints(runner);\r
+ m_route = new RunningRoute();\r
+ m_mapOverlays.add(m_route);\r
\r
- long time1 = System.currentTimeMillis();\r
drawOverlays(mapView);\r
- Log.d(this.getClass().getName(), "drawOverlays() -- "\r
- + (System.currentTimeMillis() - time1));\r
}\r
\r
/**\r
* Draw overlays.\r
* \r
- * @param mapView the map view\r
+ * @param mapView\r
+ * the map view\r
*/\r
private void drawOverlays(MapView mapView) {\r
\r
\r
m_mapOverlays.add(myLocationOverlay);\r
\r
- m_overlaySplitpoints.clearItem();\r
-\r
Iterator<Record> it = TokyoRunners.getRecordIterator();\r
+ GeoPoint gp = null;\r
+ RunningRoute route = new RunningRoute();\r
while (it.hasNext()) {\r
Record rec = it.next();\r
if (rec.hasLocation()) {\r
- GeoPoint gp = new GeoPoint(rec.getLatitudeE6(), rec\r
- .getLongitudeE6());\r
- if (m_prevPoint != null) {\r
- RunningRoute route = new RunningRoute(m_prevPoint, gp);\r
- m_mapOverlays.add(route);\r
- }\r
- m_prevPoint = gp;\r
+ gp = new GeoPoint(rec.getLatitudeE6(), rec.getLongitudeE6());\r
+ route.addPoint(gp);\r
\r
if (rec.getName().length() > 0) {\r
TextOverlay textOverlay = new TextOverlay(gp, rec.getName());\r
m_startTime = rec.getDate().getTime();\r
}\r
}\r
+ m_mapOverlays.add(route);\r
+ if (gp != null) {\r
+ m_controller.setCenter(gp);\r
+ }\r
\r
}\r
\r
- /**\r
- * Draw split point.\r
+ /*\r
+ * (non-Javadoc)\r
* \r
- * @param gp the gp\r
- * @param pointName the point name\r
- * @param recDate the rec date\r
- */\r
- private void drawSplitPoint(GeoPoint gp, String pointName, Date recDate) {\r
- String snippet = pointName + "[" + m_timeFormatter.format(recDate)\r
- + "]";\r
- OverlayItem ovItem = new OverlayItem(gp, "", snippet);\r
- m_overlaySplitpoints.addSplitpoint(ovItem);\r
- if (m_overlaySplitpoints.size() == 1) {\r
- m_mapOverlays.add(m_overlaySplitpoints);\r
- }\r
- }\r
-\r
- /* (non-Javadoc)\r
* @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)\r
*/\r
public boolean onKeyDown(int keyCode, KeyEvent event) {\r
\r
}\r
\r
- /* (non-Javadoc)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
* @see android.app.Activity#onCreateDialog(int)\r
*/\r
@Override\r
return alertDialog;\r
}\r
\r
- /* (non-Javadoc)\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)\r
+ */\r
+ @Override\r
+ public boolean onCreateOptionsMenu(Menu menu) {\r
+ menu.add(Menu.NONE, Constants.MENU_HERE, Menu.NONE, R.string.menu_here)\r
+ .setIcon(android.R.drawable.ic_menu_mylocation);\r
+ return super.onCreateOptionsMenu(menu);\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)\r
*/\r
@Override\r
intent.setAction(Intent.ACTION_VIEW);\r
startActivity(intent);\r
break;\r
+ case Constants.MENU_HERE:\r
+ LocationManager locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);\r
+ Location loc = locMgr\r
+ .getLastKnownLocation(LocationManager.GPS_PROVIDER);\r
+ if (loc != null) {\r
+ GeoPoint gp = new GeoPoint((int) (loc.getLatitude() * 1E6),\r
+ (int) (loc.getLongitude() * 1E6));\r
+ m_controller.animateTo(gp);\r
+ }\r
+ break;\r
default:\r
break;\r
}\r