Google 地图 Android API:根据 GroundOverlay 的 PNG 已知像素绘制多边形

Google Maps Android API: Draw polygon based on pixels known from GroundOverlay's PNG

我正在使用 Google 地图 Android API 使用以下代码在 Google 地图上添加一个 PNG 文件作为自己的平面图:

GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions();
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromAsset("building-d.png");
groundOverlayOptions.image(bitmapDescriptor);
groundOverlayOptions.anchor(0, 1);

LatLng buildingSW = new LatLng(47.014815, 8.305098);
LatLng buildingNE = new LatLng(47.015148, 8.305440);
LatLng buildingNW = new LatLng(47.015168, 8.305144);
LatLng buildingSE = new LatLng(47.014792, 8.305385);

Location swLoc = locationFromLatLng(buildingSW);
Location seLoc = locationFromLatLng(buildingSE);
Location nwLoc = locationFromLatLng(buildingNW);
Location neLoc = locationFromLatLng(buildingNE);

float angle = swLoc.bearingTo(nwLoc);
groundOverlayOptions.bearing(angle);

float width = swLoc.distanceTo(seLoc);
groundOverlayOptions.position(buildingSW, width);

mMap.addGroundOverlay(groundOverlayOptions);

现在我知道在 PNG 中像素坐标 422/301、708/301、422/10 和 708/10(这些是角)处有一个房间。我想在覆盖那个房间的 GroundOverlay 上画一个多边形。我该怎么做?我是否需要将我的像素坐标转换为 LatLng,如果需要,如何转换?

顺便说一下:我真的必须为 GroundOverlay 使用 PNG 吗?是否没有其他受支持的矢量格式,如 eps、pdf、...?

你应该这样工作: 你的室内地图位置应该相对于一个特定的点(比如说 BOTTOM-LEFT 是 0,0),然后所有其他位置都将相对于那个点以米为单位,所以你通常会得到小于 100 米的值。

有了这个你就得"move, rotate and scale"关于世界的室内地图。 只需在桌面上拿一张不是 LAT/LNG 的地图,然后找到您拥有的相同室内点的坐标(通常我们会得到左下角和右上角位置的真实和室内位置),这样您就可以找到它的位置应该在世界上。 也看看比例因子(取决于纬度,地图必须缩放) https://en.wikipedia.org/wiki/Mercator_projection#Scale_factor

我们通过执行类似 1/cos(latitudeINradians)

的操作来计算该值
public static double getScalingFactor(double latitude) {
        return 1 / (Math.cos(Math.toRadians(latitude)));
    }

如果你能找到办法,请告诉我,否则我会搜索并尝试剥离我们的代码

看到你对另一个答案的评论,让我用一些代码来完成:

在 latlng 47.014816、8.305098 中设置 "origin" 后,您必须将这些坐标转换为墨卡托坐标,您可以执行类似于以下操作的操作:

public boolean initializeByTwoCouplesOfCooordsAndScale(double[] coordAreal, double[] coordBreal, double[] coordAvirtual, double[] coordBvirtual, double scalingFactor) {
    if (coordAreal[0] == coordBreal[0] && coordAvirtual[1] == coordBvirtual[1] && coordAreal[1] == coordBreal[1] && coordAvirtual[0] == coordBvirtual[0]) {
        System.err.println("Coordinates must not be the same!");
        return false;
    }
    // aPoint is considered the "origin" point (0,0)
    aPoint = coordAreal;
    bPoint = coordAvirtual;
    // now calculate the angle of the Real world coordinate for the points
    double deltaRy = coordBreal[1] - coordAreal[1];
    double deltaRx = coordBreal[0] - coordAreal[0];
    double aR = Math.atan2(deltaRy, deltaRx);
    // Now calculate the angle of the virtual world coordinates
    double deltaVy = coordBvirtual[1] - coordAvirtual[1];
    double deltaVx = coordBvirtual[0] - coordAvirtual[0];
    double aV = Math.atan2(deltaVy, deltaVx);
    // Set the transformation angle as the difference between the real and the virtual angles.
    mPhi= (aR - aV);
    // Set the scaling factor as the provided one
    mScale = (scalingFactor);//scaling factor is in function below
    // Calculate the scaling factor error correction using the distances of the two systems.
    return true;
}

public static double getScalingFactor(double latitude) { return 1 / (Math.cos(Math.toRadians(纬度))); }

所以你可以调用方法:

initializeByTwoCouplesOfCooordsAndScale(new double[]{MERCATOR_LNG,MERCATOR_LAT},//real coordinates for point A REMEMBER: LNG,LAT = x,y!
new double[]{0d,0d}, //Virual coordinates for point A
new double[]{MERCATOR_POINT_B_LNG, MERCATOR_POINT_B_LAT},//real point B
new double[]{X_METERS,Y_METERS},//coordinates in meters of point B in virtual map
getScalingFactor(47.014816));

那你就可以用这个函数变形了:

public double[] transform(double[] coord) {
        double[] transCoord = new double[2];
    double xscaled = (coord[0] - bPoint[0]) * mScale; // XXX bPoint is the position of origin point in the "VIRTUAL" world. [0] is the x coordinate
    double yscaled =  (coord[1] - bPoint[1]) * mScale;

    transCoord[0] = (xscaled * Math.cos(mPhi)) - (yscaled * Math.sin(mPhi)) + aPoint[0]; //aPoint is the point with real coordinates of origin!
    transCoord[1] = (xscaled * Math.sin(mPhi)) + (yscaled * Math.cos(mPhi)) + aPoint[1];
    return transCoord;
}

您可以在网上找到一种将 latlng 转换为 mercator 的方法,它只是一堆数学 ;)