Нарисуйте географически точную дугу на карте для Android
Я хотел бы нарисовать дугу с центральной точкой GPS и двумя конечными точками GPS. Я могу использовать любое программное обеспечение для отображения, которое можно использовать с android.
до сих пор я пробовал Google Maps для android. Mapbox для android. ARCGIS for android. Ни один из них, похоже, не способен выполнить эту простую задачу.
Я предполагаю, что мне нужно какое-то наложение?
2 ответов
прежде всего, вы должны изменить представления геоданных.
из этого:
36°46'02.5"S 174°50'03.6"E GRC 36°56'18.3"S 174°33'09.7"E CWA 36°52'19.2"S 174°29'23.5"E 5.0' NM 36°48'19.8"S 174°25'37.7"E GRC 36°41'06.1"S 174°37'32.9"E CCA 36°39'54.5"S 174°38'40.7"E 1.5' NM 36°41'00.3"S 174°39'57.1"E GRC 36°39'49.4"S 174°41'32.3"E CCA 36°38'43.5"S 174°40'15.7"E 1.5' NM 36°39'17.5"S 174°41'59.7"E GRC 36°39'38.6"S 174°44'37.7"E GRC 36°37'08.8"S 174°47'27.4"E CWA 36°42'03.8"S 174°46'17.0"E 5.0' NM
для этого:
-36.76736 174.83433 GRC -36.93842 174.55269 CWA -36.87200 174.48986 0.08333 NM -36.80550 174.42714 GRC -36.68503 174.62581 CCA -36.66514 174.64464 0.02500 NM -36.68342 174.66586 GRC -36.66372 174.69231 CCA -36.64542 174.67103 0.02500 NM -36.65486 174.69992 GRC -36.66072 174.74381 GRC -36.61911 174.79094 CWA -36.70106 174.77139 0.08333 NM
затем вы можете использовать их для построения пути (например,путь SVG):
<svg
...>
<g
transform="matrix(1250,0,0,1250,46206.909,-217995.49)"
...>
<path
d=" M -36.76736,174.83433 L -36.93842,174.55269 A 0.08333,0.08333 0 0,1 -36.80550,174.42714 L -36.68503,174.62581 A 0.02500,0.02500 0 0,0 -36.68342,174.66586 L -36.66372,174.69231 A 0.02500,0.02500 0 0,0 -36.65486,174.69992 L -36.66072,174.74381 L -36.61911,174.79094 A 0.08333,0.08333 0 0,1 -36.76736,174.83433 Z"
.../>
</g>
</svg>
на самом деле, нет API для создания кривых, дуг и т. д. в GMaps / OSMDroid, таким образом, вы должны нарисовать их как можно больше маленьких линий. Это означает, что делать математику, но эта математика может быть сделана библиотека GeographicLib:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MapView map = (MapView) findViewById(R.id.map);
map.setTileSource(TileSourceFactory.MAPNIK);
map.setBuiltInZoomControls(true);
map.setMultiTouchControls(true);
IMapController mapController = map.getController();
mapController.setZoom(9);
GeoPoint startPoint = new GeoPoint(-36.66372, 174.69231);
mapController.setCenter(startPoint);
Polygon polyline = new Polygon(this);
List<GeoPoint> points = new LinkedList<>();
// I filled the data manually, but it can be done more clever, of course.
GRC(points, new GeoPoint(-36.76736, 174.83433));
CWA(points, new GeoPoint(-36.93842, 174.55269),
new GeoPoint(-36.87200, 174.48986),
new GeoPoint(-36.80550, 174.42714),
0.08333);
CCA(points, new GeoPoint(-36.68503, 174.62581),
new GeoPoint(-36.66514, 174.64464),
new GeoPoint(-36.68342, 174.66586),
0.02500);
CCA(points, new GeoPoint(-36.66372, 174.69231),
new GeoPoint(-36.64542, 174.67103),
new GeoPoint(-36.65486, 174.69992),
0.02500);
GRC(points, new GeoPoint(-36.66072, 174.74381));
CWA(points, new GeoPoint(-36.61911, 174.79094),
new GeoPoint(-36.70106, 174.77139),
new GeoPoint(-36.76736, 174.83433), //close shape going to the start point
0.08333);
polyline.setPoints(points);
polyline.setFillColor(0xA0FF00FF);
polyline.setStrokeColor(Color.BLACK);
polyline.setStrokeWidth(2f);
map.getOverlays().add(polyline);
map.invalidate();
}
private void CCA(List<GeoPoint> points, GeoPoint startPoint, GeoPoint centerPoint, GeoPoint endPoint, double radius) {
points.add(startPoint);
GeodesicData f = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), startPoint.getLatitude(), startPoint.getLongitude());
GeodesicData t = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), endPoint.getLatitude(), endPoint.getLongitude());
double ffaz = f.azi1;
double tfaz = t.azi1;
final int decrement = 1;
while (Math.abs((int)ffaz) != Math.abs((int)tfaz)) {
GeodesicData llb = Geodesic.WGS84.Direct(centerPoint.getLatitude(), centerPoint.getLongitude(), ffaz, f.s12);
points.add(new GeoPoint(llb.lat2, llb.lon2));
ffaz -= decrement;
if (ffaz <0) {
ffaz += 360;
}
}
points.add(endPoint);
}
private void CWA(List<GeoPoint> points, GeoPoint startPoint, GeoPoint centerPoint, GeoPoint endPoint, double radius) {
points.add(startPoint);
GeodesicData f = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), startPoint.getLatitude(), startPoint.getLongitude());
GeodesicData t = Geodesic.WGS84.Inverse(centerPoint.getLatitude(), centerPoint.getLongitude(), endPoint.getLatitude(), endPoint.getLongitude());
double ffaz = f.azi1;
double tfaz = t.azi1 > 0 ? t.azi1 : 360 + t.azi1;
final int increment = 1;
while (Math.abs((int)ffaz) != Math.abs((int)tfaz)) {
GeodesicData llb = Geodesic.WGS84.Direct(centerPoint.getLatitude(), centerPoint.getLongitude(), ffaz, f.s12);
points.add(new GeoPoint(llb.lat2, llb.lon2));
ffaz += increment;
if (ffaz>360) {
ffaz -= 360;
}
}
points.add(endPoint);
}
private void GRC(List<GeoPoint> points, GeoPoint geoPoint) {
points.add(geoPoint);
}
я использовал osmdroid + OSMBonusPack, но код довольно универсален и может быть легко использован с картами Google.
результат:
кроме того, не могли бы вы рассказать, какие геоданные вы разместили? Форма на карте выглядит как разрешенная зона полета, я думаю.
к сожалению, я не могу дать вам полный ответ прямо сейчас, так как этот вопрос требует тяжелой математики, и я не могу полностью понять данные, которые вы показали в таблице. Я предполагаю, что вы пытаетесь получить конечный результат, который выглядит примерно как этой. Если это так, у вас есть центральная точка, радиус и дуга, начиная с LatLng и заканчивая LatLng (это также может быть вычислено из центральной точки с дополнительной математикой). Я попытаюсь обновить этот ответ, если я получу возможность написать код, обрабатывающий математическую сторону. Насколько я знаю, ни одна из библиотек карт (Google Maps, Mapbox) не включает это.
в принципе, я бы написал метод, который возвращает кучу точек latlng после дуги, которую вы хотите нарисовать. Из этого я бы нарисовал линию, используя addPolyline
метод.
// Draw line from list of LatLng called pointsArray
mapView.addPolyline(new PolylineOptions()
.add(pointsArray)
.color(Color.parseColor("#3bb2d0"))
.width(2));
надеюсь, это поможет вам, по крайней мере, с началом работы, и, как я уже сказал, я попытаюсь добавить математические биты позже, если у меня будет шанс.