2009-08-19 12 views
15

क्या अक्षांश/देशांतर निर्देशांक के सेट के आसपास न्यूनतम बाध्य आयत निर्धारित करने के लिए कोई एल्गोरिदम है?अक्षांश/देशांतर निर्देशांक संग्रह के लिए न्यूनतम बाध्य आयत निर्धारित करने के लिए एल्गोरिदम

एक फ्लैट पृथ्वी मानना ​​ठीक है क्योंकि निर्देशांक बहुत दूर नहीं होंगे। स्यूडोकोड ठीक है, लेकिन अगर किसी ने इसे उद्देश्य-सी में किया है, तो यह भी बेहतर होगा। मैं जो करने की कोशिश कर रहा हूं वह मानचित्र पर प्रदर्शित होने वाले बिंदुओं की संख्या के आधार पर मानचित्र के ज़ूम स्तर को सेट कर रहा है।

+1

मुझे यकीन है कि यह अब आपके पास न की बड़ी चिंता (2 साल बाद) है हूँ, लेकिन आपको पता होना चाहिए यह संभव है - कम से कम सिद्धांत रूप में - सभी सूचीबद्ध उत्तरों के लिए शानदार रूप से असफल होने के लिए। प्रशांत पर +170 के निचले बाएं एक्स और -170 के ऊपरी दाएं एक्स के साथ प्रशांत पर एक या अधिक बहुभुजों पर विचार करें। यह आपके दिमाग को आपके बाउंडिंग बॉक्स को फिट करने की कोशिश कर पिघलाएगा। यह आलेख: http://www.stonybrook.edu/libmap/coordinates/seriesa/no2/a2.htm (ग्लोबल गॉटचास सेक्शन) का तात्पर्य है कि समस्या नहीं हो सकती है, और हल करने की आवश्यकता नहीं है। – tomfumb

उत्तर

11

यह आपके शीर्ष बाएं बिंदु और आपके निचले दाएं बिंदु के लिए सबसे बड़ा अक्षांश/देशांतर के लिए सबसे छोटा अक्षांश/देशांतर प्राप्त करेगा।

double minLat = 900; 
double minLon = 900; 
double maxLat = -900; 
double maxLon = -900; 
foreach(Point point in latloncollection) 
{ 
    minLat = Math.min(minLat, point.lat); 
    minLon = Math.min(minLon, point.lon); 
    maxLat = Math.max(maxLat, point.lat); 
    maxLon = Math.max(maxLon, point.lon); 
} 
+0

भले ही हम यह सुनिश्चित करने के लिए जानते हैं कि लैट और लॉन पूर्ण मूल्य 900 से ऊपर नहीं जाएंगे, मुझे लगता है कि सूची के पहले बिंदु पर न्यूनतम और अधिकतम मान शुरू करने के लिए यह अच्छा होगा, और उसके बाद शुरू होने वाले बेहतर लोगों को खोजने का प्रयास करें सूची में दूसरा आइटम। – mbritto

0

के लिए आप क्या करना चाहते हैं, तो आप शायद अभी के लिए अक्षांश और लांग न्यूनतम और अधिकतम मूल्य खोजने के लिए और अपने आयत की सीमा के रूप में उन इस्तेमाल कर सकते हैं। और अधिक परिष्कृत समाधान के लिए देखें:

Calculate minimum area rectangle for a polygon

0

आप ऑब्जेक्टिव-सी में हैं तो आप ऑब्जेक्टिव-सी ++ का उपयोग करने के बजाय, इस स्थिति में आप का एक बहुत कुछ करने के लिए एसटीएल उपयोग कर सकते हैं सक्षम हो सकता है आप के लिए भारी उठाने:

#include <vector> 
#include <algorithm> 

std::vector<float> latitude_set; 
std::vector<float> longitude_set; 

latitude_set.push_back(latitude_a); 
latitude_set.push_back(latitude_b); 
latitude_set.push_back(latitude_c); 
latitude_set.push_back(latitude_d); 
latitude_set.push_back(latitude_e); 

longitude_set.push_back(longitude_a); 
longitude_set.push_back(longitude_b); 
longitude_set.push_back(longitude_c); 
longitude_set.push_back(longitude_d); 
longitude_set.push_back(longitude_e); 

float min_latitude = *std::min_element(latitude_set.begin(), latitude_set.end()); 
float max_latitude = *std::max_element(latitude_set.begin(), latitude_set.end()); 

float min_longitude = *std::min_element(longitude_set.begin(), longitude_set.end()); 
float max_longitude = *std::max_element(longitude_set.begin(), longitude_set.end()); 
+0

नियमित सी ++ में पुस्तकालय भी हैं। साथ ही, यह स्थिर रूप से एक अच्छा विचार कोडिंग कैसे कर रहा है? – Foredecker

+0

यह मानक-अनुरूप सी ++ है। अक्षांश और देशांतर वैक्टर की स्थैतिक भरने केवल उदाहरण के लिए सेवा प्रदान करती है ... आप किसी भी तरह से वेक्टर में आइटम जोड़ सकते हैं। – fbrereto

+0

मुझे यकीन नहीं है कि मैं भारी उठाने वाला कोण देखता हूं जब सरल ओबीजेसी कोड हल्का होता है ... किसी भी तरह से आप इसे काटते हैं तो आप सभी बिंदु मानों को देख रहे हैं। –

0

तुम सब सबसे बाईं ओर, सर्वोच्च, राइट-सबसे, और सबसे नीचे मूल्यों को प्राप्त करने की जरूरत है। आप इसे आसानी से सॉर्ट करके आसानी से पूरा कर सकते हैं, और जब तक सेट बहुत बड़ा नहीं होता है, तो यह बहुत महंगा नहीं होगा।

यदि आप compareLatitude: और compareLongitude: नामक अपनी लेट/लांग क्लास विधियां देते हैं, तो यह और भी आसान होगा।

CGFloat north, west, east, south; 
[latLongCollection sortUsingSelector:@selector(compareLongitude:)]; 
west = [[latLongCollection objectAtIndex:0] longitude]; 
east = [[latLongCollection lastObject] longitude]; 
[latLongCollection sortUsingSelector:@selector(compareLatitude:)]; 
south = [[latLongCollection objectAtIndex:0] latitude]; 
north = [[latLongCollection lastObject] latitude]; 

ऐसा कुछ काम करना चाहिए, मानते हैं कि समन्वय का संग्रह एक एनएसएमयूटेबलएरे है।

+0

मेरी सरणी एमकेएनोटेशन ऑब्जेक्ट्स के एनएसएमयूटेबलएरे है। तुलना करने के लिए मुझे उन चयनकर्ता तरीकों को लागू करने का सबसे अच्छा तरीका सोचना होगा। यह मैन्युअल रूप से सूची के माध्यम से फिर से शुरू करने से बहुत अलग नहीं है, लेकिन यह थोड़ा और अधिक "सुरुचिपूर्ण" है। –

10

इस विधि है कि मैं अपने एप्लिकेशन में से एक में इस्तेमाल करते हैं। के बाद से ओपी सीमांकन आयत का उपयोग करने के लिए नक्शे पर सेट करना चाहता है

- (void)centerMapAroundAnnotations 
{ 
    // if we have no annotations we can skip all of this 
    if ([[myMapView annotations] count] == 0) 
     return; 

    // then run through each annotation in the list to find the 
    // minimum and maximum latitude and longitude values 
    CLLocationCoordinate2D min; 
    CLLocationCoordinate2D max; 
    BOOL minMaxInitialized = NO; 
    NSUInteger numberOfValidAnnotations = 0; 

    for (id<MKAnnotation> a in [myMapView annotations]) 
    { 
     // only use annotations that are of our own custom type 
     // in the event that the user is browsing from a location far away 
     // you can omit this if you want the user's location to be included in the region 
     if ([a isKindOfClass: [ECAnnotation class]]) 
     { 
      // if we haven't grabbed the first good value, do so now 
      if (!minMaxInitialized) 
      { 
       min = a.coordinate; 
       max = a.coordinate; 
       minMaxInitialized = YES; 
      } 
      else // otherwise compare with the current value 
      { 
       min.latitude = MIN(min.latitude, a.coordinate.latitude); 
       min.longitude = MIN(min.longitude, a.coordinate.longitude); 

       max.latitude = MAX(max.latitude, a.coordinate.latitude); 
       max.longitude = MAX(max.longitude, a.coordinate.longitude); 
      } 
      ++numberOfValidAnnotations; 
     } 
    } 

    // If we don't have any valid annotations we can leave now, 
    // this will happen in the event that there is only the user location 
    if (numberOfValidAnnotations == 0) 
     return; 

    // Now that we have a min and max lat/lon create locations for the 
    // three points in a right triangle 
    CLLocation* locSouthWest = [[CLLocation alloc] 
           initWithLatitude: min.latitude 
           longitude: min.longitude]; 
    CLLocation* locSouthEast = [[CLLocation alloc] 
           initWithLatitude: min.latitude 
           longitude: max.longitude]; 
    CLLocation* locNorthEast = [[CLLocation alloc] 
           initWithLatitude: max.latitude 
           longitude: max.longitude]; 

    // Create a region centered at the midpoint of our hypotenuse 
    CLLocationCoordinate2D regionCenter; 
    regionCenter.latitude = (min.latitude + max.latitude)/2.0; 
    regionCenter.longitude = (min.longitude + max.longitude)/2.0; 

    // Use the locations that we just created to calculate the distance 
    // between each of the points in meters. 
    CLLocationDistance latMeters = [locSouthEast getDistanceFrom: locNorthEast]; 
    CLLocationDistance lonMeters = [locSouthEast getDistanceFrom: locSouthWest]; 

    MKCoordinateRegion region; 
    region = MKCoordinateRegionMakeWithDistance(regionCenter, latMeters, lonMeters); 

    MKCoordinateRegion fitRegion = [myMapView regionThatFits: region]; 
    [myMapView setRegion: fitRegion animated: YES]; 

    // Clean up 
    [locSouthWest release]; 
    [locSouthEast release]; 
    [locNorthEast release]; 
} 
+0

ग्रेट कोड स्निपेट, इसे साझा करने के लिए धन्यवाद। – Goles

+1

बस बुच एंटोन से एक संदेश प्राप्त हुआ - getDistanceFrom: आईफोन ओएस 3.2 के रूप में बहिष्कृत किया गया है। आपका कोड अब दूरी का उपयोग करना चाहिए: इसके बजाय। – jessecurry

1
public BoundingRectangle calculateBoundingRectangle() 
    { 
     Coordinate bndRectTopLeft = new Coordinate(); 
     Coordinate bndRectBtRight = new Coordinate(); 

     // Initialize bounding rectangle with first point 
     Coordinate firstPoint = getVertices().get(0); 
     bndRectTopLeft.setLongitude(firstPoint.getLongitude()); 
     bndRectTopLeft.setLatitude(firstPoint.getLatitude()); 
     bndRectBtRight.setLongitude(firstPoint.getLongitude()); 
     bndRectBtRight.setLatitude(firstPoint.getLatitude()); 

     double tempLong; 
     double tempLat; 
     // Iterate through all the points 
     for (int i = 0; i < getVertices().size(); i++) 
     { 
      Coordinate curNode = getVertices().get(i); 

      tempLong = curNode.getLongitude(); 
      tempLat = curNode.getLatitude(); 
      if (bndRectTopLeft.getLongitude() > tempLong) bndRectTopLeft.setLongitude(tempLong); 
      if (bndRectTopLeft.getLatitude() < tempLat) bndRectTopLeft.setLatitude(tempLat); 
      if (bndRectBtRight.getLongitude() < tempLong) bndRectBtRight.setLongitude(tempLong); 
      if (bndRectBtRight.getLatitude() > tempLat) bndRectBtRight.setLatitude(tempLat); 

     } 

     bndRectTopLeft.setLatitude(bndRectTopLeft.getLatitude()); 
     bndRectBtRight.setLatitude(bndRectBtRight.getLatitude()); 

     // Throw an error if boundaries contains poles 
     if ((Math.toRadians(topLeft.getLatitude()) >= (Math.PI/2)) || (Math.toRadians(bottomRight.getLatitude()) <= -(Math.PI/2))) 
     { 
      // Error 
      throw new Exception("boundaries contains poles"); 
     } 
     // Now calculate bounding x coordinates 
     // Calculate it along latitude circle for the latitude closure to the 
     // pole 
     // (either north or south). For the other end the loitering distance 
     // will be slightly higher 
     double tempLat1 = bndRectTopLeft.getLatitude(); 
     if (bndRectBtRight.getLatitude() < 0) 
     { 
      if (tempLat1 < (-bndRectBtRight.getLatitude())) 
      { 
       tempLat1 = (-bndRectBtRight.getLatitude()); 
      } 
     } 

     bndRectTopLeft.setLongitude(bndRectTopLeft.getLongitude()); 
     bndRectBtRight.setLongitude(bndRectBtRight.getLongitude()); 
     // What if international date line is coming in between ? 
     // It will not affect any calculation but the range for x coordinate for the bounding rectangle will be -2.PI to +2.PI 
     // But the bounding rectangle should not cross itself 
     if ((Math.toRadians(bottomRight.getLongitude()) - Math.toRadians(topLeft.getLongitude())) >= (2 * Math.PI)) 
     { 
      // Throw some error 
      throw new Exception("Bounding Rectangle crossing itself"); 
     } 

     return new BoundingRectangle(bndRectTopLeft, bndRectBtRight); 
    } 

यह अपवाद है, तो क्षेत्र को पार करने के डंडे संभाल लेंगे ...

2

, एल्गोरिथ्म है कि तथ्य को ध्यान में रखना करने की आवश्यकता है अक्षांश और रेखांश एक गोलाकार समन्वय प्रणाली में हैं और नक्शा एक 2 आयामी समन्वय प्रणाली का उपयोग करता है। समाधान अब तक तैनात में से कोई भी समय इसे ध्यान में है और इस तरह एक गलत सीमांकन आयत के साथ खत्म हो लेकिन सौभाग्य से यह "नया क्या है MapKit में" WWDC 2013 से इस नमूना कोड में पाया MKMapPointForCoordinate विधि का उपयोग कर एक मान्य समाधान बनाने के लिए काफी आसान है सत्र वीडियो

MKMapRect MapRectBoundingMapPoints(MKMapPoint points[], NSInteger pointCount){ 
    double minX = INFINITY, maxX = -INFINITY, minY = INFINITY, maxY = -INFINITY; 
    NSInteger i; 
    for(i = -; i< pointCount; i++){ 
     MKMapPoint p = points[i]; 
     minX = MIN(p.x,minX); 
     minY = MIN(p.y,minY); 
     maxX = MAX(p.x,maxX); 
     maxY = MAX(p.y,maxY); 
    } 
    return MKMapRectMake(minX,minY,maxX - minX,maxY-minY); 
} 


CLLocationCoordinate2D london = CLLocationCoordinate2DMake(51.500756,-0.124661); 
CLLocationCoordinate2D paris = CLLocationCoordinate2DMake(48.855228,2.34523); 
MKMapPoint points[] = {MKMapPointForCoordinate(london),MKMapPointForCoordinate(paris)}; 
MKMapRect rect = MapRectBoundingMapPoints(points,2); 
rect = MKMapRectInset(rect, 
    -rect.size.width * 0.05, 
    -rect.size.height * 0.05); 
MKCoordinateRegion coordinateRegion = MKCoordinateRegionForMapRect(rect); 

आप आसानी से अगर आप पसंद करते एनोटेशन का एक NSArray पर काम करने की विधि बदल सकते हैं। जैसे

- (MKCoordinateRegion)regionForAnnotations:(NSArray*)anns{ 
    MKCoordinateRegion r; 
    if ([anns count] == 0){ 
     return r; 
    } 

    double minX = INFINITY, maxX = -INFINITY, minY = INFINITY, maxY = -INFINITY; 
    for(id<MKAnnotation> a in anns){ 
     MKMapPoint p = MKMapPointForCoordinate(a.coordinate); 
     minX = MIN(p.x,minX); 
     minY = MIN(p.y,minY); 
     maxX = MAX(p.x,maxX); 
     maxY = MAX(p.y,maxY); 
    } 
    MKMapRect rect = MKMapRectMake(minX,minY,maxX - minX,maxY-minY); 
    rect = MKMapRectInset(rect, 
          -rect.size.width * 0.05, 
          -rect.size.height * 0.05); 
    return MKCoordinateRegionForMapRect(rect); 
} 
0

क्या @malhal लिखा सही है, सभी प्रश्नों के उत्तर यहाँ गलत हैं और यहाँ एक उदाहरण है: यहां विधि मैं अपने आवेदन में उपयोग कर रहा हूँ है

देशांतर -178 ले लो, -175, + 175, +178। अन्य उत्तरों के मुताबिक, उनके चारों ओर सबसे छोटा बाउंडिंग बॉक्स होगा: -178 (पश्चिम): +178 (पूर्व), जो पूरी दुनिया है।यह सच नहीं है, क्योंकि यदि आप इसके पीछे से देखते हैं तो धरती घूमती है, आपके पास एक छोटा बाउंडिंग बॉक्स होगा: +175 (पश्चिम): -175 (पूर्व)।

यह समस्या -180/180 180 के करीब लंबी अवधि के लिए होगी। मेरा दिमाग अक्षांश के बारे में सोचने की कोशिश करता है, लेकिन अगर उन्हें कोई समस्या है तो यह उन ध्रुवों के आस-पास है जो उदाहरण के लिए Google मानचित्र "चारों ओर नहीं जाते" हैं, इसलिए इससे कोई फर्क नहीं पड़ता (इसके ध्रुवों के बाद से)।

यहाँ एक उदाहरण समाधान (CoffeeScript) है:

# This is the object that keeps the mins/maxes 
corners = 
    latitude: 
    south: undefined 
    north: undefined 
    longitude: 
    normal: 
     west: undefined 
     east: undefined 
    # This keeps the min/max longitude after adding +360 to negative ones 
    reverse: 
     west: undefined 
     east: undefined 

points.forEach (point) -> 
    latitude = point.latitude 
    longitude = point.longitude 
    # Setting latitude corners 
    corners.latitude.south = latitude if not corners.latitude.south? or latitude < corners.latitude.south 
    corners.latitude.north = latitude if not corners.latitude.north? or latitude > corners.latitude.north 
    # Setting normal longitude corners 
    corners.longitude.normal.west = longitude if not corners.longitude.normal.west? or longitude < corners.longitude.normal.west 
    corners.longitude.normal.east = longitude if not corners.longitude.normal.east? or longitude > corners.longitude.normal.east 
    # Setting reverse longitude corners (when looking from the other side) 
    longitude = if longitude < 0 then longitude + 360 else longitude 
    corners.longitude.reverse.west = longitude if not corners.longitude.reverse.west? or longitude < corners.longitude.reverse.west 
    corners.longitude.reverse.east = longitude if not corners.longitude.reverse.east? or longitude > corners.longitude.reverse.east 

# Choosing the closest corners 
# Extreme examples: 
# Same:   -174 - -178 = +186 - +182 (both eastgtive) 
# Better normal: +2 - -4 < 176 - +2 (around the front) 
# Better reverse: +182 - +178 < +178 - -178 (around the back) 
if corners.longitude.normal.east - corners.longitude.normal.west < corners.longitude.reverse.east - corners.longitude.reverse.west 
    corners.longitude = corners.longitude.normal 
else 
    corners.longitude = corners.longitude.reverse 
    corners.longitude.west = corners.longitude.west - 360 if corners.longitude.west > 180 
    corners.longitude.east = corners.longitude.east - 360 if corners.longitude.east > 180 

# Now: 
# SW corner at: corners.latitude.south/corners.longitude.west 
# NE corner at: corners.latitude.north/corners.longitude.east 
संबंधित मुद्दे

 संबंधित मुद्दे