如何将给定坐标转换为“直径”的边界框? x?

发布于 2024-12-20 08:32:06 字数 282 浏览 10 评论 0原文

例如,我有十进制格式的纬度和经度(而不是像 lat=44.1° 9.5' 30'' 这样的度数-小时-分钟)。要搜索附近的对象,我必须将搜索“半径”指定为具有四个值的矩形:

north = 44.1;
south = -9.9;
east = -22.4;
west = 55.2;

是否有公式或经验法则如何将十进制纬度/经度值转换为矩形边界框,以便给定的纬度/经度是在那个盒子的中心吗?

我必须自己摆弄 WGS84 椭球算法吗?或者是否有针对该问题的开放解决方案?

For example, I have a latitude and longitude in decimal format (as opposed to Degrees-Hours-Minutes like lat=44.1° 9.5' 30''). To search for nearby objects, I must specify the search "radius" as a rectangle with four values:

north = 44.1;
south = -9.9;
east = -22.4;
west = 55.2;

Is there a formula or rule of thumb how to convert decimal lat/long values into a rectangular bounding box, such that the given latitude/longitude is in the center of that box?

Must I fiddle around myself with a WGS84 ellipsoid algorithm or are there open solutions to the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不可一世的女人 2024-12-27 08:32:06

我确实遇到了这个问题,而且解决方案并不是那么简单,但好消息是,经过大量工作(以及来自 SO 和 Google 的大量帮助),我想我已经解决了它。

周围有很多库,例如 Proj4,它们提供了多种算法来执行所需的转换,但我发现这一切有点令人困惑,最终编写了自己的代码(我总是想知道事情是如何工作的) 。

我的解决方案基于 ECEF ,它的工作原理如下...
我相信您已经明白了,纬度线之间的距离始终相同(10 度到 20 度之间的距离与 20 到 30 度之间的距离相同),但经度线在两极交汇。所以赤道10度和20度经线之间的距离比两极附近大得多(在两极处为0)。
因此,您可以轻松计算出 2 纬度之间有多少米,但要使用经度来计算,您必须考虑纬度。
在赤道附近,1 度的纬度与 1 度的长度的距离几乎相同,因此,如果我们投影的地图的中心为 (0, 0),我们可以简单地将纬度和经度乘以一个常数,从而获得距离米任何给定点的地图中心。
所以我的算法有效地旋转地球,直到地图的实际中心位于 0, 0。

所以说中心实际上位于 (50.52, -4.82) - 在我的例子中就是这样。
想象一下,您正拿着一个地球仪,并在 0 纬度、0 长的位置俯视它,位于您正下方的可见中心。
我们需要做的是将当前位于我们正下方 (0, 0) 的地球仪向西(向右)方向旋转,直到 (0, -4.82) 位于我们下方。
然后我们向南(向下)旋转地球,直到(50.52,-4.82)位于我们下方。
第三步,我们可能想要顺时针或逆时针旋转它,以纠正地图相对于真北的方向(如果真北在地图上是笔直的,或者如果您感兴趣的只是距离而不是距离)轴承,你不需要这样做)
从概念上讲,这就是我们需要做的,但这与我们的算法有何关系?
答案是一个变换(类),我们输入三个旋转角度。此类有一个公共函数,给定纬度/经度对,它将在旋转后返回地球上该点的新纬度/经度对。
一旦我们完成了这些,知道了地球的半径,我们就可以将这个新的对转换为 x 和 y 坐标,表示距地图原点的距离。

我应该在这里提到,地球赤道处比两极处更宽,但处理这个问题的数学根本不值得费心。无论您如何计算 x、y 坐标,它们总是会稍微偏离,因为地球并不平坦,对我来说,下面提供的代码可以完成这项工作。
如果你的地图非常接近两极,我怀疑这个算法的结果可能会变得非常不准确 - 基本上纬度/经度在两极并不能很好地工作(只需从上面看一下谷歌地球)。

MapTransform 类需要您设置一些内容。
设置半径(1000);设置变换以使用半径为 1000(单位)的球体
setBody(“地球”);设置与地球平均半径的变换(以米为单位)
设置旋转(x,y,z);将变换设置为绕 Z 轴旋转 z 度,Y 轴旋转 y 度,然后 X 轴旋转 x 度。
- 基本上,给定您的中心点(纬度,经度)并考虑到地图上的正北是笔直向上的,您将需要以下内容: setRotation(0, 纬度, -long);
- 旋转的顺序在这里非常重要,并且基于坐标系(回头看你拿着的地球仪),其中 Z 轴与地球的旋转重合,Y 轴向上旋转地球仪最近的表面/向下,X 轴是您正在观察的轴 - 希望这是有道理的,这是一个很难描述的概念 - 请参阅 旋转矩阵

考虑到您需要从特定点从纬度/经度映射到米,以上内容应该就是您所需要的。

函数 getMapPosition(lat, long) 将从您的原点返回一个包含 x, y 的 double[],以地图单位(如果以米为单位指定半径,则为米)。

我的类在将坐标应用于特定地图图块方面走得更远...

setMapOrigin(x, y);设置地图的旋转原点(旋转后观察者正下方的点)相对于地图左下角的位置。名义上,这应该以米为单位(当然,如果您使用 setBody("EARTH");),但需要使用与指定半径相同的单位。
setMapSize(w, h);设置地图的大小(以米为单位)或您决定使用的任何单位。

最后,setBitmapSize(w, h) 允许您描述要将地图投影到的位图的大小(以像素为单位)。在我的应用程序中,我有地图区域的位图表示,并使用转换来提供位图上应绘制点的像素的精确坐标。但是,这不是您提出的问题的一部分,因此您可能不需要它。

真的希望这能有所帮助——看起来就像我一个月前看到的所有例子一样冗长和复杂。

import java.text.DecimalFormat;

public class MapTransform {

    private double circumference;
    private RotationMatrix rotationMatrix;
    private double originX;
    private double originY;
    private double mapWidth;
    private double mapHeight;
    private int bitmapWidth;
    private int bitmapHeight;

    public MapTransform() {
        this.circumference = 0;
        this.rotationMatrix = new RotationMatrix();
        this.rotationMatrix.makeIdentity();
        this.originX = 0;
        this.originY = 0;
        this.mapWidth = 0;
        this.mapHeight = 0;
        this.bitmapWidth = 0;
        this.bitmapHeight = 0;
    }


    public void setCircumference(double circumference) {
        this.circumference = circumference;
    }
    public void setRadius(double radius) {
        this.circumference = 2 * Math.PI * radius;
    }
    public void setBody(String body) {
        if (body.toUpperCase().equals("EARTH")) {
            setRadius(6371009);     //mean radius of the earth in metres 
//          setRadius(6378137);     //equatorial radius of the earth in metres 
//          setRadius(6356752);     //polar radius of the earth in metres 
        }
        else {
            setRadius(0);
        }
    }

    public void setRotation(double xRotateDegrees, double yRotateDegrees, double zRotateDegrees) {
        RotationMatrix xMatrix = new RotationMatrix();
        RotationMatrix yMatrix = new RotationMatrix();
        RotationMatrix zMatrix = new RotationMatrix();
        xMatrix.makeRotateX(Math.toRadians(xRotateDegrees));
        yMatrix.makeRotateY(Math.toRadians(yRotateDegrees));
        zMatrix.makeRotateZ(Math.toRadians(zRotateDegrees));
        this.rotationMatrix = zMatrix.concatenate(yMatrix).concatenate(xMatrix);
    }

    public void setMapOrigin(double originX, double originY) {
        this.originX = originX;
        this.originY = originY;
    }

    public void setMapSize(double width, double height) {
        this.mapWidth = width;
        this.mapHeight = height;
    }

    public void setBitmapSize(int width, int height) {
        this.bitmapWidth = width;
        this.bitmapHeight = height;
    }


    public double[] getMapPosition(double[] geoPosition) {
        return getMapPosition(geoPosition[0], geoPosition[1]);
    }
    public double[] getMapPosition(double latitude, double longitude) {
        // convert the GeoPosition into an NVector
        NVector vec = new NVector(latitude, longitude);
        // rotate the vector in 3D
        vec = rotationMatrix.transform(vec);
        // convert the vector into 2D units by applying circumference to latitude/longitude and adding origins
        double x = vec.getLongitude() * this.circumference / 360;
        double y = vec.getLatitude() * this.circumference / 360;
        // return a MapPosition
        return new double[] {x, y};
    }


    public float[] getPixelPosition(double[] mapPosition) {
        return getPixelPosition(mapPosition[0], mapPosition[1]);
    }
    public float[] getPixelPosition(double mapX, double mapY) {
        // apply origin and scale based on map and bitmap widths 
        float x =  (float) ((this.originX + mapX) * this.bitmapWidth / this.mapWidth);
        // apply origin and scale based on map and bitmap heights, but invert to measure from top left instead of bottom left
        float y =  (float) (this.bitmapHeight - (this.originY + mapY) * this.bitmapHeight / this.mapHeight);
        return new float[] {x, y};
    }


    public class RotationMatrix {
        String name = "";
        public double array [][] = {{0,0,0},{0,0,0},{0,0,0}};

        public RotationMatrix() {}

        public RotationMatrix(String name) {
            this.name = name;
        }
        public void makeIdentity() {
            for(int x = 0; x <= 2; x++) {
                for (int y = 0; y <= 2; y++) {
                    array[x][y] = (x == y)? 1: 0;
                }
            }
        }

        public void makeRotateX(double thetaRadians) {
            double cosTheta = Math.cos(thetaRadians);
            double sinTheta = Math.sin(thetaRadians);
            makeIdentity();
            array[1][1] = cosTheta;
            array[2][1] = -sinTheta;
            array[1][2] = sinTheta;
            array[2][2] = cosTheta;
        }

        public void makeRotateY(double thetaRadians) {
            double cosTheta = Math.cos(thetaRadians);
            double sinTheta = Math.sin(thetaRadians);
            makeIdentity();
            array[0][0] = cosTheta;
            array[2][0] = sinTheta;
            array[0][2] = -sinTheta;
            array[2][2] = cosTheta;
        }

        public void makeRotateZ(double thetaRadians) {
            double cosTheta = Math.cos(thetaRadians);
            double sinTheta = Math.sin(thetaRadians);
            makeIdentity();
            array[0][0] = cosTheta;
            array[1][0] = -sinTheta;
            array[0][1] = sinTheta;
            array[1][1] = cosTheta;
        }

        public NVector transform(NVector vec) {
            NVector vec2 = new NVector();
            vec2.x = vec.x * array[0][0] + vec.y * array[1][0] + vec.z * array[2][0];
            vec2.y = vec.x * array[0][1] + vec.y * array[1][1] + vec.z * array[2][1];
            vec2.z = vec.x * array[0][2] + vec.y * array[1][2] + vec.z * array[2][2];
            return vec2;
        }

        public void output() {
            if (this.name != null && this.name.length() == 0) {
                System.out.println(this.name + "-------");
            }
            DecimalFormat df = new DecimalFormat("0.00");
            for(int y = 0; y <= 2; y++) {
                String out = "| ";
                double test = 0;
                for(int x = 0; x <= 2; x++) {
                    String f = df.format(array[x][y]);
                    if (f.length() < 5) f = " " + f;
                    out += f + " ";
                    test = test + array[x][y] * array[x][y];
                }
                if (test > 0.99 && test < 1.01) {test = 1.0;}
                out += "| (=" + test + ")";
                System.out.println(out);
            }
            System.out.println();
        }

        public RotationMatrix concatenate(RotationMatrix m2) {
            RotationMatrix outputMatrix = new RotationMatrix();
            for(int x = 0; x <= 2; x++) {
                for(int y = 0; y <=2; y++) {
                    outputMatrix.array[x][y] = 0;
                    for (int q = 0; q <= 2; q++) {
                        outputMatrix.array[x][y] += this.array[x][q] * m2.array[q][y];
                    }
                }
            }
            return outputMatrix;
        }

    }

    public class NVector {
        double x;
        double y;
        double z;

        public NVector() {
            this.x = 0;
            this.y = 0;
            this.z = 0;
        }

        public NVector(double x, double y, double z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public NVector(double latitude, double longitude) {
            setLatitudeLongitude(latitude, longitude);
        }

        public NVector(double[] geoPosition) {
            setLatitudeLongitude(geoPosition[0], geoPosition[1]);
        }

        private void setLatitudeLongitude(double latitude, double longitude) {
            double latitudeRadians = Math.toRadians(latitude);
            double longitudeRadians = Math.toRadians(longitude);
            double cosLatitude = Math.cos(latitudeRadians);
            double cosLongitude = Math.cos(longitudeRadians);
            double sinLatitude = Math.sin(latitudeRadians);
            double sinLongitude = Math.sin(longitudeRadians);

            this.x = cosLatitude * cosLongitude;
            this.y = cosLatitude * sinLongitude;
            this.z = sinLatitude;
        }

        public double getLatitude() {
            return Math.toDegrees(Math.atan2(this.z, Math.sqrt(this.x * this.x + this.y * this.y)));
        }
        public double getLongitude() {
            return Math.toDegrees(Math.atan2(this.y, this.x));
        }
        public double[] getGeoPosition() {
            double[] geoPosition = new double[] {this.getLatitude(), this.getLongitude()};
            return geoPosition;
        }

        public void output() {
            output("");
        }

        public void output(String name) {
            if (name != null && name.length() == 0) {
                System.out.println("NVector: " + name);
            }
            DecimalFormat df = new DecimalFormat("0.00");
            String vector = df.format(this.x) + "," + df.format(this.y) + "," + df.format(this.z);
            String coords = "";
            try {
                coords = df.format(Math.toDegrees(this.getLatitude())) + "N " + df.format(Math.toDegrees(this.getLongitude())) + "E";
            }
            catch(Exception e) {
                coords = "(coords unknown)";
            }
            System.out.println("(" + vector + ") at " + coords);
        }
    }
}

I had exactly this problem and the solution isn't that straight forward, but the good news is that after a lot of work (and a great deal of help from SO and Google) I think I've cracked it.

There are lots of libraries around such as Proj4 which offer a multitude of algorithms to perform the required transformations, but coming at it cold I found it all a bit confusing and ended up writing my own code (I always like to know how things work).

My solution is based on ECEF and it works like this...
As I'm sure you've figured out, lines of latitude are always the same distance apart (the distance between 10 degrees and 20 degrees is the same as that between 20 and 30), but lines of longitude converge to meet at the poles. So the distance between 10 degrees and 20 degrees longitude at the equator is much larger than near the poles (and is 0 at the poles).
So you can easily work out how many metres between 2 degrees of latitude, but to do this with longitude you have to take the latitude into account.
Near the equator 1 degree of lat is pretty much the same distance as 1 degree of long, so if the map we're projecting had it's centre (0, 0) we can simply multiply lat and long by a constant to get metres from the map centre for any given point.
So my algorithm effectively rotates the globe until the actual centre of the map is at 0, 0.

So say the centre is really at (50.52, -4.82) - which it is in my case.
Imagine you're holding a globe and looking down on it with 0 lat, 0 long directly below you in the visible centre.
What we need to do is take our globe which currently has (0, 0) directly below us and rotate it in a westward (to the right) direction until (0, -4.82) is below us.
Then we rotate the globe southward (down) until (50.52, -4.82) is below us.
As a third step, we may then want to rotate it clockwise or anti-clockwise to correct for the orientation of the map with respect to true north (if true north is straight up on your map or if all you are interested in is distance not bearing, you won't need to do this)
So conceptually that's what we need to do, but how does that relate to our algorithm?
The answer is a transform (class) where we feed in three angles of rotation. This class has a public function which, given a lat/long pair, will return a new lat/long pair of that point on the globe after rotation.
And once we've done that, knowing the radius of the earth, we can convert this new pair into x and y coordinates, representing the distance from our map origin.

I should mention here that the earth is wider at the equator than it is at the poles, but the maths to deal with this is quite simply not worth the bother. However you calculate your x, y coords they will always be slightly out since the earth is not flat and for me, the code presented below does the job.
If your map is very close to the poles I suspect the results from this algorith may become quite inaccurate - basically lat/long doesn't really work very well at the poles (just take a look at google earth from above).

The MapTransform class requires you to setup a few things.
setRadius(1000); sets up the transform to work with a sphere of radius 1000 (units)
setBody("EARTH"); sets up the transform with the mean radius of the earth (in metres)
setRotation(x, y, z); sets up the transform to rotate about Z axis by z degrees, Y axis by y degrees then X axis by x degrees.
- basically, given your centre point (lat, long) and given that true north on the map is straight up, you would need the following: setRotation(0, lat, -long);
- the order of rotation is very important here and based on a coordinate system (looking back at the globe you're holding) where the Z axis coincides with the rotation of the earth, the Y axis rotates the closest surface of the globe up/down and the X axis is the axis you are looking along - hope this makes sense, it's a difficult concept to describe - see Rotation Matrix

Given your requirement to map from lat/long to metres from a specific point, the above should be all you need.

The function getMapPosition(lat, long) will return a double[] containing x, y in map units (metres if radius was specified in metres) from your origin

My class goes a bit further in terms of applying the coordinates to a specific map tile...

setMapOrigin(x, y); sets up where the rotational origin of the map (the point directly below the observer after rotation) is in relation to the bottom left corner of your map. Nominally this should be in metres (certainly if you used setBody("EARTH");) but needs to be in the same units as the specified radius.
setMapSize(w, h); sets up the size of the map in metres or what ever units you decided to use.

Finally, setBitmapSize(w, h) allows you to describe the size of the bitmap (in pixels) onto which you are projecting your map. In my application I have a bitmap representation of the map area and use the transform to supply the exact coorinates of the pixel on my bitmap where a point should be plotted. However, this isn't part of the question you asked so you may not need it.

Really hope this helps - seems just as long winded and complicated as all the examples I was looking at a month ago now.

import java.text.DecimalFormat;

public class MapTransform {

    private double circumference;
    private RotationMatrix rotationMatrix;
    private double originX;
    private double originY;
    private double mapWidth;
    private double mapHeight;
    private int bitmapWidth;
    private int bitmapHeight;

    public MapTransform() {
        this.circumference = 0;
        this.rotationMatrix = new RotationMatrix();
        this.rotationMatrix.makeIdentity();
        this.originX = 0;
        this.originY = 0;
        this.mapWidth = 0;
        this.mapHeight = 0;
        this.bitmapWidth = 0;
        this.bitmapHeight = 0;
    }


    public void setCircumference(double circumference) {
        this.circumference = circumference;
    }
    public void setRadius(double radius) {
        this.circumference = 2 * Math.PI * radius;
    }
    public void setBody(String body) {
        if (body.toUpperCase().equals("EARTH")) {
            setRadius(6371009);     //mean radius of the earth in metres 
//          setRadius(6378137);     //equatorial radius of the earth in metres 
//          setRadius(6356752);     //polar radius of the earth in metres 
        }
        else {
            setRadius(0);
        }
    }

    public void setRotation(double xRotateDegrees, double yRotateDegrees, double zRotateDegrees) {
        RotationMatrix xMatrix = new RotationMatrix();
        RotationMatrix yMatrix = new RotationMatrix();
        RotationMatrix zMatrix = new RotationMatrix();
        xMatrix.makeRotateX(Math.toRadians(xRotateDegrees));
        yMatrix.makeRotateY(Math.toRadians(yRotateDegrees));
        zMatrix.makeRotateZ(Math.toRadians(zRotateDegrees));
        this.rotationMatrix = zMatrix.concatenate(yMatrix).concatenate(xMatrix);
    }

    public void setMapOrigin(double originX, double originY) {
        this.originX = originX;
        this.originY = originY;
    }

    public void setMapSize(double width, double height) {
        this.mapWidth = width;
        this.mapHeight = height;
    }

    public void setBitmapSize(int width, int height) {
        this.bitmapWidth = width;
        this.bitmapHeight = height;
    }


    public double[] getMapPosition(double[] geoPosition) {
        return getMapPosition(geoPosition[0], geoPosition[1]);
    }
    public double[] getMapPosition(double latitude, double longitude) {
        // convert the GeoPosition into an NVector
        NVector vec = new NVector(latitude, longitude);
        // rotate the vector in 3D
        vec = rotationMatrix.transform(vec);
        // convert the vector into 2D units by applying circumference to latitude/longitude and adding origins
        double x = vec.getLongitude() * this.circumference / 360;
        double y = vec.getLatitude() * this.circumference / 360;
        // return a MapPosition
        return new double[] {x, y};
    }


    public float[] getPixelPosition(double[] mapPosition) {
        return getPixelPosition(mapPosition[0], mapPosition[1]);
    }
    public float[] getPixelPosition(double mapX, double mapY) {
        // apply origin and scale based on map and bitmap widths 
        float x =  (float) ((this.originX + mapX) * this.bitmapWidth / this.mapWidth);
        // apply origin and scale based on map and bitmap heights, but invert to measure from top left instead of bottom left
        float y =  (float) (this.bitmapHeight - (this.originY + mapY) * this.bitmapHeight / this.mapHeight);
        return new float[] {x, y};
    }


    public class RotationMatrix {
        String name = "";
        public double array [][] = {{0,0,0},{0,0,0},{0,0,0}};

        public RotationMatrix() {}

        public RotationMatrix(String name) {
            this.name = name;
        }
        public void makeIdentity() {
            for(int x = 0; x <= 2; x++) {
                for (int y = 0; y <= 2; y++) {
                    array[x][y] = (x == y)? 1: 0;
                }
            }
        }

        public void makeRotateX(double thetaRadians) {
            double cosTheta = Math.cos(thetaRadians);
            double sinTheta = Math.sin(thetaRadians);
            makeIdentity();
            array[1][1] = cosTheta;
            array[2][1] = -sinTheta;
            array[1][2] = sinTheta;
            array[2][2] = cosTheta;
        }

        public void makeRotateY(double thetaRadians) {
            double cosTheta = Math.cos(thetaRadians);
            double sinTheta = Math.sin(thetaRadians);
            makeIdentity();
            array[0][0] = cosTheta;
            array[2][0] = sinTheta;
            array[0][2] = -sinTheta;
            array[2][2] = cosTheta;
        }

        public void makeRotateZ(double thetaRadians) {
            double cosTheta = Math.cos(thetaRadians);
            double sinTheta = Math.sin(thetaRadians);
            makeIdentity();
            array[0][0] = cosTheta;
            array[1][0] = -sinTheta;
            array[0][1] = sinTheta;
            array[1][1] = cosTheta;
        }

        public NVector transform(NVector vec) {
            NVector vec2 = new NVector();
            vec2.x = vec.x * array[0][0] + vec.y * array[1][0] + vec.z * array[2][0];
            vec2.y = vec.x * array[0][1] + vec.y * array[1][1] + vec.z * array[2][1];
            vec2.z = vec.x * array[0][2] + vec.y * array[1][2] + vec.z * array[2][2];
            return vec2;
        }

        public void output() {
            if (this.name != null && this.name.length() == 0) {
                System.out.println(this.name + "-------");
            }
            DecimalFormat df = new DecimalFormat("0.00");
            for(int y = 0; y <= 2; y++) {
                String out = "| ";
                double test = 0;
                for(int x = 0; x <= 2; x++) {
                    String f = df.format(array[x][y]);
                    if (f.length() < 5) f = " " + f;
                    out += f + " ";
                    test = test + array[x][y] * array[x][y];
                }
                if (test > 0.99 && test < 1.01) {test = 1.0;}
                out += "| (=" + test + ")";
                System.out.println(out);
            }
            System.out.println();
        }

        public RotationMatrix concatenate(RotationMatrix m2) {
            RotationMatrix outputMatrix = new RotationMatrix();
            for(int x = 0; x <= 2; x++) {
                for(int y = 0; y <=2; y++) {
                    outputMatrix.array[x][y] = 0;
                    for (int q = 0; q <= 2; q++) {
                        outputMatrix.array[x][y] += this.array[x][q] * m2.array[q][y];
                    }
                }
            }
            return outputMatrix;
        }

    }

    public class NVector {
        double x;
        double y;
        double z;

        public NVector() {
            this.x = 0;
            this.y = 0;
            this.z = 0;
        }

        public NVector(double x, double y, double z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public NVector(double latitude, double longitude) {
            setLatitudeLongitude(latitude, longitude);
        }

        public NVector(double[] geoPosition) {
            setLatitudeLongitude(geoPosition[0], geoPosition[1]);
        }

        private void setLatitudeLongitude(double latitude, double longitude) {
            double latitudeRadians = Math.toRadians(latitude);
            double longitudeRadians = Math.toRadians(longitude);
            double cosLatitude = Math.cos(latitudeRadians);
            double cosLongitude = Math.cos(longitudeRadians);
            double sinLatitude = Math.sin(latitudeRadians);
            double sinLongitude = Math.sin(longitudeRadians);

            this.x = cosLatitude * cosLongitude;
            this.y = cosLatitude * sinLongitude;
            this.z = sinLatitude;
        }

        public double getLatitude() {
            return Math.toDegrees(Math.atan2(this.z, Math.sqrt(this.x * this.x + this.y * this.y)));
        }
        public double getLongitude() {
            return Math.toDegrees(Math.atan2(this.y, this.x));
        }
        public double[] getGeoPosition() {
            double[] geoPosition = new double[] {this.getLatitude(), this.getLongitude()};
            return geoPosition;
        }

        public void output() {
            output("");
        }

        public void output(String name) {
            if (name != null && name.length() == 0) {
                System.out.println("NVector: " + name);
            }
            DecimalFormat df = new DecimalFormat("0.00");
            String vector = df.format(this.x) + "," + df.format(this.y) + "," + df.format(this.z);
            String coords = "";
            try {
                coords = df.format(Math.toDegrees(this.getLatitude())) + "N " + df.format(Math.toDegrees(this.getLongitude())) + "E";
            }
            catch(Exception e) {
                coords = "(coords unknown)";
            }
            System.out.println("(" + vector + ") at " + coords);
        }
    }
}
一影成城 2024-12-27 08:32:06

如果您谈论的是地球上的坐标,那么流形上的“矩形边界框”是否真的没有明确的定义?

难道你不能通过对笛卡尔坐标中矩形的尺寸进行平均来近似“盒子”的中心:

x_center = x_left + (x_right - x_left) / 2
y_center = y_bottom + (y_top - y_bottom) / 2

If you're talking about coordinates on a globe, isn't there really no clear definition of "rectangular bounding box" on a manifold?

Couldn't you just approximate the center of the "box" by averaging the dimensions of the rectagle as in cartesian coordinates:

x_center = x_left + (x_right - x_left) / 2
y_center = y_bottom + (y_top - y_bottom) / 2
楠木可依 2024-12-27 08:32:06

为什么不从中心点开始进行范围/方位来定义框角的纬度/经度(如果这就是您所要求的)?使用四个轴承45°、135°、225°、315°。请参阅此网站了解“距离/方位的目标点”:http://www .movable-type.co.uk/scripts/latlong.html

Why not do a range/bearing from your center point to define the lat/lon's of the corner of the box (if that is what you are asking)? Use the four bearings 45 deg, 135 deg, 225 deg, 315 deg. See this web site for "Destination point from range/bearing": http://www.movable-type.co.uk/scripts/latlong.html

把人绕傻吧 2024-12-27 08:32:06

如果你只需要从你的原点到另一个纬度的距离,我在SO上发现了这个(惊喜),那么对我的另一篇文章的另一个更短的答案。
原始答案是此处,但我相信您正在查找的代码因为是...

public static double distFrom(double lat1, double lng1, double lat2, double lng2) { 
    double earthRadius = 6371009; //mean radius of the earth in metres 
    double dLat = Math.toRadians(lat2-lat1); 
    double dLng = Math.toRadians(lng2-lng1); 
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
               Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * 
               Math.sin(dLng/2) * Math.sin(dLng/2); 
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    double dist = earthRadius * c; 

    return dist; 
}

Another, much shorter answer to my other post if you just need the distance to another lat long from your point of origin which I found on SO (surprise).
Original answer was here, but I believe the code you're looking for is...

public static double distFrom(double lat1, double lng1, double lat2, double lng2) { 
    double earthRadius = 6371009; //mean radius of the earth in metres 
    double dLat = Math.toRadians(lat2-lat1); 
    double dLng = Math.toRadians(lng2-lng1); 
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
               Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * 
               Math.sin(dLng/2) * Math.sin(dLng/2); 
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    double dist = earthRadius * c; 

    return dist; 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文