JavaFX:添加地图并在其上绘制

时间:2017-05-29 08:45:32

标签: google-maps javafx

我正在使用GMapsFx构建JavaFx应用程序并尝试在其中嵌入Google地图。

我尝试使用此API在地图顶部绘制省略号,但API仅提供弧线。
因此,为了解决这个问题,我尝试绘制四分之三的椭圆,但设法只绘制了四分之三的圆,看起来GMapsFx忽略其中一个半径并绘制圆弧。

以下代码段的结果:

double centerLat = 31.166724;
double centerLong = 34.793119;
double latDelta = 0.5;
double longDelta = 0.01;
LatLong centreP = new LatLong(centerLat, centerLong);
LatLong start = new LatLong(centerLat, centerLong + longDelta);
LatLong end= new LatLong(centerLat + latDelta, centerLong);
MVCArray p= ArcBuilder.buildArcPoints(centreP, end, start);

com.lynden.gmapsfx.shapes.Polyline pp = new com.lynden.gmapsfx.shapes.Polyline();
pp.setPath(p);
map.addMapShape(pp);

出现在下图中。

Result of the code

消化数字:
中心:31.166724,34.793119
开始于:31.166724,34.803119
结束:31.666724,34.793119

你可以看到endcenter彼此非常接近(我们应该得到一个非常高而窄的弧),弧实际上在东边开始很远,给出四分之一圈。

  1. 导致此问题的原因是什么?
  2. 是否有更好的方法\框架在 JavaFx 中的地图上绘制省略号?

1 个答案:

答案 0 :(得分:1)

ArcBuilder仅使用一个半径;开始和结束LatLong用于获取弧的起点和终点的方位。因此,它不能用于绘制椭圆。

由于库不提供椭圆形状,我改为写了EllipseBuilder类:

import com.lynden.gmapsfx.javascript.object.LatLong;
import com.lynden.gmapsfx.javascript.object.MVCArray;

public class EllipseBuilder {

  private static final int DEFAULT_ELLIPSE_POINTS = 10000;

  /**
   * Generates the points for an ellipse based on two radii from a center point.
   *
   * @param center
   *            The LatLong point of the center.
   * @param longRadius
   *            longitude radius in meters
   * @param latRadius
   *            latitude radius in meters
   * @return An array of LatLong points in an MVC array representing the ellipse.
   */
  public static final MVCArray buildEllipsePoints(LatLong center, double longRadius, double latRadius) {
    return buildEllipsePoints(center, longRadius, latRadius, 0.);
  }

  /**
   * Generates the points for an ellipse based on two radii from a center point and a counter clockwise rotation angle.
   *
   * @param center
   *            The LatLong point of the center.
   * @param longRadius
   *            longitude radius in meters
   * @param latRadius
   *            latitude radius in meters
   * @param rotAngle
   *            rotation angle in degree, counter clockwise
   * @return An array of LatLong points in an MVC array representing the ellipse.
   */
  public static final MVCArray buildEllipsePoints(LatLong center, double longRadius, double latRadius, double rotAngle) {
    int points = DEFAULT_ELLIPSE_POINTS;

    MVCArray res = new MVCArray();

    double longRadiusSquared = longRadius * longRadius;
    double latRadiusSquared = latRadius * latRadius;

    double radiiProduct = longRadius * latRadius;

    double theta = 0d;
    double angleIncrement = 360.0 / points;
    for (int i = 0; (i < points + 1); i++) {
        theta = i * angleIncrement;
        double r = radiiProduct / (Math.sqrt(latRadiusSquared * Math.pow(Math.sin(Math.toRadians(theta)), 2)
                + longRadiusSquared * Math.pow(Math.cos(Math.toRadians(theta)), 2)));
        res.push(center.getDestinationPoint(theta - rotAngle, r));
    }

    return res;
  }
}

使用以下代码调用

double centerLat = 31.166724;
double centerLong = 34.793119;
double latDelta = 0.5;
double longDelta = 0.01;
LatLong centreP = new LatLong(centerLat, centerLong);
LatLong start = new LatLong(centerLat, centerLong + longDelta);
LatLong end = new LatLong(centerLat + latDelta, centerLong);

double longRadius = centreP.distanceFrom(start);
double latRadius = centreP.distanceFrom(end);

MVCArray p = EllipseBuilder.buildEllipsePoints(centreP, longRadius, latRadius);

com.lynden.gmapsfx.shapes.Polyline pp = new com.lynden.gmapsfx.shapes.Polyline();
pp.setPath(p);
map.addMapShape(pp);

// Add markers to the map
MarkerOptions markerOptionsStart = new MarkerOptions();
markerOptionsStart.position(start).visible(Boolean.TRUE).title("Start").label("S");
Marker markerStart = new Marker(markerOptionsStart);
map.addMarker(markerStart);

MarkerOptions markerOptionsEnd = new MarkerOptions();
markerOptionsEnd.position(end).visible(Boolean.TRUE).title("End").label("E");
Marker markerEnd = new Marker(markerOptionsEnd);
map.addMarker(markerEnd);

生成此图片:

GMapFX Ellipse Example

要绘制旋转的椭圆,请添加度数角度。椭圆将以逆时针方向旋转:

double longRadius = centreP.distanceFrom(start);
double latRadius = centreP.distanceFrom(end);
double rotAngle = 20.;

MVCArray p = EllipseBuilder.buildEllipsePoints(centreP, longRadius, latRadius, rotAngle);

椭圆旋转20度,逆时针旋转:

GMapFX Rotated Ellipse Example

我使用标记来标记起点和终点。

因为在你的情况下椭圆非常窄,我对DEFAULT_ELLIPSE_POINTS使用了非常高的值。根据用例,此值应该更小,因此将其设置为参数而不是静态变量可能很有用。