简体   繁体   English

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

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

I'm adding a PNG file as an own floorplan on top of Google Maps with the Google Maps Android API with the following code: 我使用以下代码通过Google Maps Android API在Google Maps顶部添加一个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);

Now I know that in the PNG there is a room at pixel coordinates 422/301, 708/301, 422/10 and 708/10 (those are the corners). 现在我知道在PNG中,像素坐标422 / 301、708 / 301、422 / 10和708/10(这些是角)处有一个空间。 I'd like to draw a polygon over the GroundOverlay covering that room. 我想在覆盖该房间的GroundOverlay上绘制一个多边形。 How should I do that? 我应该怎么做? Do I need to convert my pixel-coordinates to LatLng and if so, how? 我是否需要将像素坐标转换为LatLng

And by the way: Do I really have to use PNGs for GroundOverlay s and is there no other supported vector-format like eps, pdf, ...? 顺便说一句:我是否真的必须对GroundOverlay使用PNG,并且没有其他受支持的矢量格式,如eps,pdf,...?

You should work in this way: Your indoor map positions should be relative to a specific point (BOTTOM-LEFT is 0,0 let's say), then all the other positions will be relative to that point in meters, so you will endup in values under 100meters usually. 您应该以这种方式工作:您的室内地图位置应相对于特定点(假设BOTTOM-LEFT为0,0),然后所有其他位置都将相对于该点(以米为单位),因此最终将获得值通常在100米以下。

Having this you have to "move, rotate and scale" the indoor map with respect to the world. 有了这个,您必须相对于世界“移动,旋转和缩放”室内地图。 Just take a map on a desktop which is not LAT/LNG and find the coordinates for the same indoor points you have (usually we get real and indoor position for bottom-left and top-right positions) so you can find where it should be in the world. 只需在非LAT / LNG的桌面上绘制地图,然后找到您拥有的相同室内点的坐标即可(通常我们会获得左下角和右上角位置的真实和室内位置),因此您可以找到应该在哪里在世界上。 Take a look also at the scaling factor (depending on the latitude, the map must be scaled) https://en.wikipedia.org/wiki/Mercator_projection#Scale_factor 还要看看缩放因子(取决于纬度,必须缩放地图) https://en.wikipedia.org/wiki/Mercator_projection#Scale_factor

We calculate that value by doing something like 1/cos(latitudeINradians) 我们通过做类似1 / cos(latitudeINradians)的值来计算该值

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

Let me know if you can find a way, otherwise i will search and try to strip our code 让我知道您是否可以找到一种方法,否则我将进行搜索并尝试剥离我们的代码

Having seen your comment to the other answer, let me complete with some code: 看完您对另一个答案的评论后,让我完成一些代码:

Having set the "origin" in latlng 47.014816, 8.305098, you have to convert those coordinates to mercator and you can do something similar to the below: 在latlng 47.014816,8.305098中设置“原点”后,您必须将这些坐标转换为墨卡托,并且可以执行以下操作:

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(latitude))); public static double getScalingFactor(double latitude){return 1 /(Math.cos(Math.toRadians(latitude))); } }

So you can call the method: 因此,您可以调用该方法:

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));

then you can transform with this function: 那么您可以使用以下函数进行转换:

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;
}

you can find online a way to convert latlng to mercator, it just a bunch of math ;) 您可以在网上找到一种将latlng转换为墨卡托的方法,这只是一堆数学;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM