math बाउंडिंग बॉक्स की गणना जावा में एक लेट/लम्बा समन्वय से एक निश्चित दूरी से दूर है




geospatial trigonometry (6)

एक समन्वय (लेट, लम्बा) दिया गया है, मैं एक स्क्वायर बाउंडिंग बॉक्स की गणना करने की कोशिश कर रहा हूं जो निर्देशांक से दी गई दूरी (जैसे 50 किमी) दूर है। तो इनपुट के रूप में मेरे पास लेट, लंबी और दूरी है और आउटपुट के रूप में मुझे दो निर्देशांक चाहिए; एक दक्षिण-पश्चिम (नीचे-बाएं) कोने वाला है और एक उत्तर-पूर्व (शीर्ष-दाएं) कोने वाला है। मैंने यहां कुछ जवाब देखे हैं जो इस प्रश्न को पायथन में संबोधित करने का प्रयास करते हैं, लेकिन मैं विशेष रूप से जावा कार्यान्वयन की तलाश में हूं।

बस स्पष्ट होने के लिए, मैं केवल पृथ्वी पर एल्गोरिदम का उपयोग करना चाहता हूं और इसलिए मुझे एक चर त्रिज्या को समायोजित करने की आवश्यकता नहीं है।

यह बेहद सटीक नहीं होना चाहिए (+/- 20% ठीक है) और इसका उपयोग केवल छोटी दूरी पर बाध्यकारी बक्से की गणना करने के लिए किया जाएगा (150 किमी से अधिक नहीं)। तो मैं एक कुशल एल्गोरिदम के लिए कुछ सटीकता बलिदान से खुश हूं। किसी भी प्रकार की मदद की बेहद सराहना की जाती है।

संपादित करें: मुझे स्पष्ट होना चाहिए था, मैं वास्तव में एक वर्ग के बाद हूं, सर्कल नहीं। मैं समझता हूं कि स्क्वायर के परिधि के साथ एक वर्ग के केंद्र और विभिन्न बिंदुओं के बीच की दूरी एक स्थिर मूल्य नहीं है जैसे कि यह एक सर्कल के साथ है। मुझे लगता है कि मेरा मतलब एक वर्ग है जहां आप केंद्र से एक रेखा को परिधि पर चार बिंदुओं में से किसी एक में खींचते हैं जिसके परिणामस्वरूप परिधि के एक तरफ लंबवत रेखा होती है, तो उन 4 लाइनों की लंबाई समान होती है।


double R = 6371; // earth radius in km
double radius = 50; // km
double x1 = lon - Math.toDegrees(radius/R/Math.cos(Math.toRadians(lat)));
double x2 = lon + Math.toDegrees(radius/R/Math.cos(Math.toRadians(lat)));
double y1 = lat + Math.toDegrees(radius/R);
double y2 = lat - Math.toDegrees(radius/R);

हालांकि मैं जेटीएस की भी सिफारिश करता हूं।

यह गणना करता है लेकिन Google धरती स्वीकार नहीं करता है और 3 डी मॉडल को मैप नहीं करता है।

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package assetmap;




 public class Main {

 public double degrees;
 public double pi= 3.1416;
 public static double lon=80.304737;
 public static double lat=26.447521;
 public static double x1,x2,y1,y2;


 public static void main(String[] args) {

 double R = 6371; // earth radius in km 26.447521

 double radius = 0.300; // km

 x1 =   (lon - Math.toDegrees(radius / R / Math.cos(Math.toRadians(lat))));

 x2 =    (lon + Math.toDegrees(radius / R / Math.cos(Math.toRadians(lat))));

 y1 =   (lat + Math.toDegrees(radius / R));

 y2 =   (lat - Math.toDegrees(radius / R));


 System.out.println(x1+"---|"+x2+"---|"+y1+"|---|"+y2);


 }

}

यह प्रिंट करता है

80.30172366789824---|80.30775033210176---|26.450218964817754|---|26.444823035182242

एम एल:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Placemark>
    <name>United Nations Headquarters</name>
    <Region>
        <LatLonAltBox>
            <north>26.447251203518224</north>
            <south>26.447790796481772</south>
            <east>80.30503833321018</east>
            <west>80.30443566678983</west>
            <minAltitude>0</minAltitude>
            <maxAltitude>30</maxAltitude>
            <altitudeMode>absolute</altitudeMode>
        </LatLonAltBox>
        <Lod>
            <minLodPixels>128</minLodPixels>
            <maxLodPixels>-1</maxLodPixels>
            <minFadeExtent>0</minFadeExtent>
            <maxFadeExtent>0</maxFadeExtent>
        </Lod>
    </Region>
    <Model id="model_1">
        <altitudeMode>absolute</altitudeMode>
        <Location>
            <longitude>80.304737</longitude>
            <latitude>26.447521</latitude>
            <altitude>0.406173708576</altitude>
        </Location>
        <Orientation>
            <heading>0</heading>
            <tilt>0</tilt>
            <roll>0</roll>
        </Orientation>
        <Scale>
            <x>10</x>
            <y>10</y>
            <z>10</z>
        </Scale>
        <Link>
            <href>un.dae</href>
        </Link>
        <ResourceMap>
            <Alias>
                <targetHref>_01.jpg</targetHref>
                <sourceHref>../images/_01.jpg</sourceHref>
            </Alias>
            <Alias>
                <targetHref>_02.jpg</targetHref>
                <sourceHref>../images/_02.jpg</sourceHref>
            </Alias>
            <Alias>
                <targetHref>_04.jpg</targetHref>
                <sourceHref>../images/_04.jpg</sourceHref>
            </Alias>
            <Alias>
                <targetHref>_05.jpg</targetHref>
                <sourceHref>../images/_05.jpg</sourceHref>
            </Alias>
            <Alias>
                <targetHref>_06.jpg</targetHref>
                <sourceHref>../images/_06.jpg</sourceHref>
            </Alias>
            <Alias>
                <targetHref>_07.jpg</targetHref>
                <sourceHref>../images/_07.jpg</sourceHref>
            </Alias>
            <Alias>
                <targetHref>_08.jpg</targetHref>
                <sourceHref>../images/_08.jpg</sourceHref>
            </Alias>
            <Alias>
                <targetHref>_09.jpg</targetHref>
                <sourceHref>../images/_09.jpg</sourceHref>
            </Alias>
        </ResourceMap>
    </Model>
</Placemark>
</kml>

double R = 6371;  // earth radius in km

double radius = 50; // km

double x1 = lon - Math.toDegrees(radius/R/Math.cos(Math.toRadians(lat)));

double x2 = lon + Math.toDegrees(radius/R/Math.cos(Math.toRadians(lat)));

double y1 = lat + Math.toDegrees(radius/R);

double y2 = lat - Math.toDegrees(radius/R);

हालांकि मैं जेटीएस की भी सिफारिश करता हूं।


पिछले सभी उत्तरों केवल आंशिक रूप से सही हैं । विशेष रूप से ऑस्ट्रेलिया जैसे क्षेत्र में, वे हमेशा ध्रुव को शामिल करते हैं और 10 किमी के लिए भी एक बहुत बड़े आयत की गणना करते हैं।

Http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#UsingIndex पर जनवरी फिलिप Matuschek द्वारा विशेष रूप से एल्गोरिदम ऑस्ट्रेलिया में लगभग हर बिंदु के लिए (-37, -90, -180, 180) से एक बहुत बड़ा आयत शामिल था। यह डेटाबेस में एक बड़े उपयोगकर्ताओं को हिट करता है और देश के लगभग आधा देश में सभी उपयोगकर्ताओं के लिए दूरी की गणना की जानी चाहिए।

मैंने पाया कि रोचेस्टर इंस्टीट्यूट ऑफ टेक्नोलॉजी द्वारा ड्रूपल एपीआई अर्थ एल्गोरिदम ध्रुव के साथ-साथ कहीं और बेहतर काम करता है और इसे लागू करना बहुत आसान है।

https://www.rit.edu/drupal/api/drupal/sites%21all%21modules%21location%21earth.inc/7.54

बाउंडिंग आयताकार की गणना के लिए उपरोक्त एल्गोरिदम से earth_latitude_range और earth_longitude_range उपयोग करें

कार्यान्वयन जावा है

    /**
 * Get bouding rectangle using Drupal Earth Algorithm
 * @see https://www.rit.edu/drupal/api/drupal/sites%21all%21modules%21location%21earth.inc/7.54
 * @param lat
 * @param lng
 * @param distance
 * @return
 */
default BoundingRectangle getBoundingRectangleDrupalEarthAlgo(double lat, double lng, int distance) {
    lng = Math.toRadians(lng);
    lat = Math.toRadians(lat);
    double radius = earth_radius(lat);
    List<Double> retLats = earth_latitude_range(lat, radius, distance);
    List<Double> retLngs = earth_longitude_range(lat, lng, radius, distance);
    return new BoundingRectangle(retLats.get(0), retLats.get(1), retLngs.get(0), retLngs.get(1));
}


/**
 * Calculate latitude range based on earths radius at a given point
 * @param latitude
 * @param longitude
 * @param distance
 * @return
 */
default List<Double> earth_latitude_range(double lat, double radius, double distance) {
      // Estimate the min and max latitudes within distance of a given location.

      double angle = distance / radius;
      double minlat = lat - angle;
      double maxlat = lat + angle;
      double rightangle = Math.PI / 2;
      // Wrapped around the south pole.
      if (minlat < -rightangle) {
        double overshoot = -minlat - rightangle;
        minlat = -rightangle + overshoot;
        if (minlat > maxlat) {
          maxlat = minlat;
        }
        minlat = -rightangle;
      }
      // Wrapped around the north pole.
      if (maxlat > rightangle) {
        double overshoot = maxlat - rightangle;
        maxlat = rightangle - overshoot;
        if (maxlat < minlat) {
          minlat = maxlat;
        }
        maxlat = rightangle;
      }
      List<Double> ret = new ArrayList<>();
      ret.add((minlat));
      ret.add((maxlat));
      return ret;
    }

/**
 * Calculate longitude range based on earths radius at a given point
 * @param lat
 * @param lng
 * @param earth_radius
 * @param distance
 * @return
 */
default List<Double> earth_longitude_range(double lat, double lng, double earth_radius, int distance) {
      // Estimate the min and max longitudes within distance of a given location.
      double radius = earth_radius * Math.cos(lat);

      double angle;
      if (radius > 0) {
        angle = Math.abs(distance / radius);
        angle = Math.min(angle, Math.PI);
      }
      else {
        angle = Math.PI;
      }
      double minlong = lng - angle;
      double maxlong = lng + angle;
      if (minlong < -Math.PI) {
        minlong = minlong + Math.PI * 2;
      }
      if (maxlong > Math.PI) {
        maxlong = maxlong - Math.PI * 2;
      }

      List<Double> ret = new ArrayList<>();
      ret.add((minlong));
      ret.add((maxlong));
      return ret;
    }

/**
 * Calculate earth radius at given latitude
 * @param latitude
 * @return
 */
default Double earth_radius(double latitude) {
      // Estimate the Earth's radius at a given latitude.
      // Default to an approximate average radius for the United States.
      double lat = Math.toRadians(latitude);

      double x = Math.cos(lat) / 6378137.0;
      double y = Math.sin(lat) / (6378137.0 * (1 - (1 / 298.257223563)));

      //Make sure earth's radius is in km , not meters
      return (1 / (Math.sqrt(x * x + y * y)))/1000;
    }

और दूरी की गणना करने के लिए Google मानचित्र द्वारा प्रलेखित दूरी गणना फॉर्मूला का उपयोग करें

https://developers.google.com/maps/solutions/store-locator/clothing-store-locator#outputting-data-as-xml-using-php

मील की जगह किलोमीटर से खोज करने के लिए, 3 9 5 9 को 6371 के साथ बदलें । (लैट, एलएनजी) = (37, -122) और कॉलम लैट और एलएनजी के साथ मार्कर टेबल , सूत्र है:

SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;

यहां एक सरल समाधान है जिसका उपयोग मैंने बाउंडिंग बॉक्स निर्देशांक उत्पन्न करने के लिए किया था जिसका उपयोग मैं जीपीएस दशमलव सिरिनेट से आस-पास के बड़े शहरों को प्राप्त करने के लिए जियोनाम सीटीजेसन एपीआई के साथ उपयोग करता हूं।

यह मेरे FusionTableModifyJava भंडार से जावा विधि है: FusionTableModifyJava

मेरे पास एक दशमलव जीपीएस स्थान था और मुझे उस स्थान के निकट "शहर" का सबसे बड़ा शहर / राज्य ढूंढना था। मुझे उस बाउंडिंग बॉक्स में सबसे बड़ा शहर वापस पाने के लिए शहरों के पास जाने के लिए अपेक्षाकृत सटीक बाउंडिंग बॉक्स की आवश्यकता थी। जेसन जीनोनाम वेबसाईट। मैं स्थान और "त्रिज्या" को पास करता हूं जिसमें मुझे दिलचस्पी है (किमी में) और यह शहरों, जेएसओएन को पास करने के लिए आवश्यक उत्तर, दक्षिण, पूर्व, पश्चिम दशमलव निर्देशांक वापस देता है।

(मैंने अपने संसाधनों को करने में इन संसाधनों को उपयोगी पाया:

अक्षांश / देशांतर बिंदुओं के बीच दूरी, असर और अधिक की गणना करें।

देशांतर - विकिपीडिया )

यह सुपर सटीक नहीं है बल्कि इसके लिए पर्याप्त सटीक है जिसके लिए मैं इसका उपयोग कर रहा था:

    // Compute bounding Box coordinates for use with Geonames API.
    class BoundingBox
    {
        public double north, south, east, west;
        public BoundingBox(String location, float km)
        {
             //System.out.println(location + " : "+ km);
            String[] parts = location.replaceAll("\\s","").split(","); //remove spaces and split on ,

            double lat = Double.parseDouble(parts[0]);
            double lng = Double.parseDouble(parts[1]);

            double adjust = .008983112; // 1km in degrees at equator.
            //adjust = 0.008983152770714983; // 1km in degrees at equator.

            //System.out.println("deg: "+(1.0/40075.017)*360.0);


            north = lat + ( km * adjust);
            south = lat - ( km * adjust);

            double lngRatio = 1/Math.cos(Math.toRadians(lat)); //ratio for lng size
            //System.out.println("lngRatio: "+lngRatio);

            east = lng + (km * adjust) * lngRatio;
            west = lng - (km * adjust) * lngRatio;
        }

    }

मैंने बाध्यकारी निर्देशांक खोजने के बारे में एक लेख लिखा:

http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates

लेख सूत्रों को बताता है और जावा कार्यान्वयन भी प्रदान करता है। (यह भी दिखाता है कि न्यूनतम / अधिकतम रेखांश के लिए आयरनमैन का सूत्र गलत क्यों है।)


import com.vividsolutions.jts.geom.Envelope;

...
Envelope env = new Envelope(centerPoint.getCoordinate());
env.expandBy(distance_in_degrees); 
...

अब env में आपका लिफाफा है। यह वास्तव में एक "वर्ग" नहीं है (जो भी किसी क्षेत्र की सतह पर है), लेकिन यह करना चाहिए।

आपको ध्यान रखना चाहिए कि डिग्री की दूरी केंद्र बिंदु के अक्षांश पर निर्भर करेगी। भूमध्य रेखा पर, अक्षांश की 1 डिग्री लगभग 111 किमी है, लेकिन न्यूयॉर्क में, यह केवल 75 किमी है।

वास्तव में अच्छी बात यह है कि आप अपने सभी बिंदुओं को com.vividsolutions.jts.index.strtree.STRtree में टॉस कर सकते हैं और फिर उस लिफाफे के अंदर बिंदुओं की त्वरित गणना करने के लिए इसका उपयोग कर सकते हैं।





bounding-box