【发布时间】:2015-07-08 03:32:50
【问题描述】:
我正在制作一个基于 GPS 坐标跟踪车辆的应用程序。
我创建了一个 SurfaceView 来为他绘制场地、车辆和路径(路线)。
结果如下所示:
黑点代表 GPS 坐标的到来,蓝色矩形是路径所覆盖的区域。 (路径宽度可配置)
我用蓝色矩形(这是我的问题)绘制的方式是路径所覆盖的区域。 (路径宽度可配置)
因此我需要克服一些情况。
- 我需要计算场的旋转角度,这样路径总是被抛在后面。 (已完成)
- 我需要计算每个矩形的旋转角度,使它们面向车辆。 (已完成)
将来我需要:
- 检测车辆何时在同一地点两次通过。 (基于经过的路径)
- 计算车辆行驶的面积 (m²)。
我想要一些绘制这条路径的提示。
我的代码:
public void draw(Canvas canvas) {
Log.d(getClass().getSimpleName(), "draw");
canvas.save();
// translate canvas to vehicle positon
canvas.translate((float) center.cartesian(0), (float) center.cartesian(1));
float fieldRotation = 0;
if (trackerHistory.size() > 1) {
/*
Before drawing the way, only takes the last position and finds the angle of rotation of the field.
*/
Vector lastPosition = new Vector(convertToTerrainCoordinates(lastPoint));
Vector preLastPosition = new Vector(convertToTerrainCoordinates(preLastPoint));
float shift = (float) lastPosition.distanceTo(preLastPosition);
/*
Having the last coordinate as a triangle, 'preLastCoord' saves the values of the legs, while 'shift' is the hypotenuse
*/
// If the Y offset is negative, then the opposite side is the Y displacement
if (preLastPosition.cartesian(1) < 0) {
// dividing the opposite side by hipetenusa, we have the sine of the angle that must be rotated.
double sin = preLastPosition.cartesian(1) / shift;
// when Y is negative, it is necessary to add or subtract 90 degrees depending on the value of X
// The "Math.asin()" calculates the radian arc to the sine previously calculated.
// And the "Math.toDegress()" converts degrees to radians from 0 to 360.
if (preLastPosition.cartesian(0) < 0) {
fieldRotation = (float) (Math.toDegrees(Math.asin(sin)) - 90d);
} else {
fieldRotation = (float) (Math.abs(Math.toDegrees(Math.asin(sin))) + 90d);
}
}
// if not, the opposite side is the X offset
else {
// dividing the opposite side by hipetenusa have the sine of the angle that must be rotated.
double senAngulo = preLastPosition.cartesian(0) / shift;
// The "Math.asin()" calculates the radian arc to the sine previously calculated.
// And the "Math.toDegress()" converts degrees to radians from 0 to 360.
fieldRotation = (float) Math.toDegrees(Math.asin(senAngulo));
}
}
final float dpiTrackerWidth = Navigator.meterToDpi(trackerWidth); // width of rect
final Path positionHistory = new Path(); // to draw the route
final Path circle = new Path(); // to draw the positions
/*
Iterate the historical positions and draw the path
*/
for (int i = 1; i < trackerHistory.size(); i++) {
Vector currentPosition = new Vector(convertToTerrainCoordinates(trackerHistory.get(i))); // vector with X and Y position
Vector lastPosition = new Vector(convertToTerrainCoordinates(trackerHistory.get(i - 1))); // vector with X and Y position
circle.addCircle((float) currentPosition.cartesian(0), (float) currentPosition.cartesian(1), 3, Path.Direction.CW);
circle.addCircle((float) lastPosition.cartesian(0), (float) lastPosition.cartesian(1), 3, Path.Direction.CW);
if (isInsideOfScreen(currentPosition.cartesian(0), currentPosition.cartesian(1)) ||
isInsideOfScreen(lastPosition.cartesian(0), lastPosition.cartesian(1))) {
/*
Calcule degree by triangle sides
*/
float shift = (float) currentPosition.distanceTo(lastPosition);
Vector dif = lastPosition.minus(currentPosition);
float sin = (float) (dif.cartesian(0) / shift);
float degress = (float) Math.toDegrees(Math.asin(sin));
/*
Create a Rect to draw displacement between two coordinates
*/
RectF rect = new RectF();
rect.left = (float) (currentPosition.cartesian(0) - (dpiTrackerWidth / 2));
rect.right = rect.left + dpiTrackerWidth;
rect.top = (float) currentPosition.cartesian(1);
rect.bottom = rect.top - shift;
Path p = new Path();
Matrix m = new Matrix();
p.addRect(rect, Path.Direction.CCW);
m.postRotate(-degress, (float) currentPosition.cartesian(0), (float) currentPosition.cartesian(1));
p.transform(m);
positionHistory.addPath(p);
}
}
// rotates the map to make the route down.
canvas.rotate(fieldRotation);
canvas.drawPath(positionHistory, paint);
canvas.drawPath(circle, paint2);
canvas.restore();
}
我的目标是有这样的应用程序:https://play.google.com/store/apps/details?id=hu.zbertok.machineryguide(但现在只有 2D)
编辑:
澄清一下我的疑惑:
- 我对此没有太多经验。我想要一种更好的方法来绘制路径。对于矩形,它不是很好。请注意,曲线是一些空白区域。
- 另一点是矩形的旋转,我在绘制的时候旋转它们。我相信这会使检测重叠变得困难
- 我相信我需要数学帮助来处理对象的旋转和重叠检测。它还有助于绘制填充形状的路径。
【问题讨论】:
-
这条路径看起来已经很好了。我不清楚你在哪里以及如何需要帮助。用数学、算法或编程绘图。
-
感谢您的评论。我对此没有太多经验。我想要一种更好的方法来绘制路径。对于矩形,它不是很好。请注意,曲线是一些空白区域......另一点是矩形的旋转,我在绘制时旋转它们。我相信这会使检测重叠变得困难......我相信我需要数学帮助来进行对象的旋转和重叠检测。它还有助于绘制填充形状的路径。
标签: android canvas gps trigonometry