MKMapRect und Anzeige von anzeigen-overlays, die sich über 180th meridian
Arbeite ich mit Fenstern und Grenzen kehrte aus Google Geocoding API. Wenn dabei die reverse geocoding für eine bestimmte Koordinate, der Dienst gibt mehrere Ergebnisse mit unterschiedlichen Granularität (Land -, Verwaltungs-Gebiet, Lokalität, sublocality, route, etc.). Ich möchte wählen Sie die am besten geeignete auf die Ergebnisse angesichts der aktuell sichtbare Bereich auf der Karte.
Habe ich beigelegt, Algorithmus, vergleicht die Verhältnisse der Flächen (in MKMapPoint
2) von der Lage-viewport", den aktuellen Viewports und deren Kreuzung (mit MKMapRectIntersection
- Funktion). Dies funktioniert sehr gut, solange sich die Lage viewport nicht erstrecken sich über die 180-meridian. In diesem Fall ist Ihre Schnittmenge ist 0.
Habe ich angefangen, zu untersuchen, die Ursache und als debugging-Hilfe-ich mache Anzeige MKPolygon
overlays auf die Karte, um mir zu geben visuelle Hinweise, was Los ist. Vermeiden Sie mögliche Fehler eingeführt durch meinen code-Konvertierung zwischen geo-Koordinaten und MKMapRect
habe ich konstruiert, die mit dem polygon-overlay mit original-Koordinaten aus Google-Ergebnisse wie dieses:
CLLocationCoordinate2D sw, ne, nw, se;
sw = location.viewportSouthWest.coordinate;
ne = location.viewportNorthEast.coordinate;
nw = CLLocationCoordinate2DMake(ne.latitude, sw.longitude);
se = CLLocationCoordinate2DMake(sw.latitude, ne.longitude);
CLLocationCoordinate2D coords[] = {nw, ne, se, sw};
MKPolygon *p = [MKPolygon polygonWithCoordinates:coords count:4];
Beispielsweise der problematischen Lage, hier ist der viewport zurückgegeben, für die Vereinigten Staaten, das Letzte Ergebnis vom Typ Land, wenn geocoding-Koordinaten irgendwo in Virginia:
Southwest: 18.9110643, 172.4546967
Northeast: 71.3898880, -66.9453948
Beachten Sie, wie die Südwest-Koordinate, die sich in der unteren linken Ecke der Lage viewport liegt auf dem 180-meridian. Bei der Anzeige dieser Position überlagert, die als polygon auf der Karte zeigt es falsch an das Recht der USA Grenzen (großes braunes Rechteck, nur in der linken unteren Ecke sichtbar):
Ähnlich, Anzeige Lage viewport für Russland zeigt das Rechteck falsch positioniert Links von der Grenze zu Russland.
Visuell bestätigt, dass es ähnliche problem, wenn ich konvertieren Sie die Lage viewport MKMapPoint
s und MKMapRect
und finden keine Schnittmenge zwischen den kartenviewport (weißes Rechteck im Bild oben) und die Lage viewport.
Den Weg berechne ich die map rect ist ähnlich wie Antworten in dieser Frage ALSO:
Wie passen eine bestimmte Grenzen, die aus der NE-und SW-Koordinaten in den sichtbaren Kartenausschnitt?
...das funktioniert , es sei denn die Koordinaten Spannweite der 180th meridian. Die Prüfung der MKMapRect
mit MKMapRectSpans180thMeridian
zurück false
, so dass Bau-Methode ist falsch.
Apple-Dokumentation ist nicht hilfreich in dieser Hinsicht. Einzige Hinweis den ich gefunden habe ist in MKOverlay.h
:
//boundingMapRect should be the smallest rectangle that completely contains
//the overlay.
//For overlays that span the 180th meridian, boundingMapRect should have
//either a negative MinX or a MaxX that is greater than MKMapSizeWorld.width.
@property (nonatomic, readonly) MKMapRect boundingMapRect;
Was ist der richtige Weg, um die polygon-overlay, die sich über die 180th meridian?
Wie Sie sich richtig zu konstruieren MKMapRect
über 180th meridian?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Laut Kommentar in
MKOverlay.h
, wenn der nw-und sw-Ecken angegeben wurden als negativMKMapPoint
Werte der overlay sollte "korrekt gezeichnet".Wenn wir versuchen, diese:
Den daraus resultierenden
p.boundingMapRect
zurückYES
fürMKMapRectSpans180thMeridian
(aber der code bereits herausgefunden, dass aus den Koordinaten, da Sie nicht über die maprect, um mit zu beginnen).Leider allerdings, die Schaffung der maprect mit den negativen Werten behebt nur die Hälfte des Problems. Die Hälfte der Fläche, die östlich der Datumsgrenze ist jetzt korrekt gezeichnet. Jedoch, die andere Hälfte westlich der Datumsgrenze nicht gezogen bei allen.
Offenbar, die gebaut-in
MKPolygonView
nicht nennenMKMapRectSpans180thMeridian
und ziehen Sie das polygon in zwei Teile.Können Sie erstellen ein benutzerdefiniertes overlay-Ansicht und diese zeichnen sich selbst (Sie würde erstellen Sie ein overlay, aber die Aussicht ziehen würde zwei Polygone).
Oder Sie könnte einfach erstellen Sie zwei
MKPolygon
overlays und lassen Sie die map anzeigen, Sie zu zeichnen, indem Sie den folgenden nach dem oben genannten code:Übrigens, es gibt ein ähnliches Problem mit der Zeichnung
MKPolyline
overlays cross +/-180 (siehe diese Frage).Da dieser Bereich ist völlig unter-dokumentiert, die Map-Kit-Funktionen-Referenz geändert werden sollte:
Um diese Frage zu lösen, ich Griff zu den guten alten investigativen Tests. Bitte entschuldigen Sie die Kommentare um die Prosa. Sie ermöglichen copy & paste alle Quelle unten verbatim, so dass Sie spielen können, mit ihm selbst.
Zuerst eine kleine Hilfsfunktion wandelt die Eckpunkte der
MKMapRect
zurück in Koordinatenraum, so dass wir vergleichen unsere Ergebnisse Umbauten mit den Start-Koordinaten:/*
Und jetzt, let ' s test
Wie Erstellen MapRect Spanning 180th Meridian:
*/
/*
Wir verwenden Lage viewport Asien, zurückgegeben durch die Google-Geocoding-API, weil es überspannt die antimeridian. Die Nordosten Ecke liegt bereits in der westlichen Hemisphäre—longitudal Bereich
(-180,0)
:*/
/*
Für die Referenz, hier sind die Grenzen auf die ganze Welt projiziert, einige 268 Millionen, nach der Umstellung auf
MKMapPoints
. Unsere kleine helper-Funktion zeigt uns, dass die Mercator-Projektion verwendet, ist hier nicht äußern, breiten, oben ±85 Grad. Längengrad überspannt nett von -180 bis 180 Grad.*/
/*
Warum wurde die
MKPolygon
overlay, erstellt durch geo-Koordinaten, dargestellt an der falschen Stelle auf der Karte?*/
/*
Es sieht aus wie die Längengrade habe getauscht der falsche Weg. Asien ist
{{ -12, 25}, {81, -168}}
. Die daraus resultierendeMKMapRect
nicht passieren den test mit derMKMapRectSpans180thMeridian
Funktion —und wir wissen, dass es sein sollte!False Versucht
Also die
MKPolygon
nicht berechnenMKMapRect
richtig, wenn die Koordinaten reichen antimeridian. OK, dann erstellen Sie die Karte rect uns. Hier sind zwei Methoden vorgeschlagen, die in Antworten auf Wie passen eine bestimmte Grenzen, die aus der NE-und SW-Koordinaten in den sichtbaren Kartenausschnitt?*/
/*
Neugierig haben wir das gleiche Ergebnis wie vorher. Macht es Sinn, dass
MKPolygon
sollte wohl berechnen Sie seine Grenzen mitMKRectUnion
sowieso.Nun habe ich fertig, der nächste mir selbst. Berechnen Sie die MapRect Ursprung, Breite und Höhe manuell, beim Versuch, die Lust haben und sich keine sorgen über die richtige Reihenfolge der Ecken.
*/
/*
Hey! Es ist das gleiche Ergebnis wie vorher. Dies ist, wie die breiten ausgelagert, wenn die Koordinaten Kreuz den antimeridian. Und es ist wahrscheinlich, wie die
MKMapRectUnion
funktioniert es auch. Nicht gut...*/
/*
Denken Sie daran, den Asien ist
{{ -12, 25}, {81, -168}}
. Wir sind immer wieder die richtigen Koordinaten, aber dieMKMapRect
nicht umspannen den antimeridian nachMKMapRectSpans180thMeridian
. Was zum...?!Die Lösung
Den Tipp von
MKOverlay.h
sagte:Keine dieser Bedingungen erfüllt ist. Was ist schlimmer, die
rb.size.width
ist negative 144 Millionen Euro. Das ist definitiv falsch.Wir haben zum richtigen rect-Werte, wenn wir an den antimeridian, so dass eine dieser Voraussetzungen erfüllt ist:
*/
/*
Schließlich haben wir zufrieden die
MKMapRectSpans180thMeridian
. Karte rect Breite ist positiv. Was ist mit den Koordinaten? Nordöstlich Länge von191.6455
. Eingewickelt rund um den Globus (-360), es ist-168.3545
. Q. E. D.Haben wir berechneten die richtige
MKMapRect
erstreckt sich über die 180th meridian von der Erfüllung der zweiten Bedingung: die MaxX (rc.origin.x + rc.size.width
= 152870935.0 + 124248035.2 = 277118970.2) größer ist dann die Breite der Welt (268 Millionen Euro).Was über die Erfüllung der ersten Bedingung, negative MinX ===
origin.x
?*/
/*
Dies geht auch bei der
MKMapRectSpans180thMeridian
test. Und die umgekehrte Konvertierung von geo-Koordinaten gibt uns übereinstimmen, außer für den Südwesten Längengrad:-334.9841
. Aber verpackt rund um die Welt (+360), ist es25.0159
. Q. E. D.So gibt es zwei korrekte Formen, um zu berechnen, MKMapRect, die sich über 180th meridian. Mit positive und mit negativ Herkunft.
Alternative Methode
Den negativen Ursprung Methode oben gezeigt (
rd
) entspricht dem Ergebnis der durch die alternative Methode vorgeschlagen, durch Anna Karenina in einer anderen Antwort auf diese Frage:*/
/*
Wenn wir also manuell konvertieren zu
MKMapPoint
s und fudge, die negativen Ursprungs sind, auch dieMKPolygon
berechnet dieboundingMapRect
richtig. Resultierenden map rect-entspricht der nagative Herkunft Methode oben (rd
).*/
/*
Oder sollte ich sagen fast gleichwertig... weil neugierig, die folgenden Behauptungen scheitern würden:
*/
/*
Man würde denke, Sie wissen, wie vergleichen floating-point-zahlen, aber ich schweife ab...
*/
Damit ist die test-Funktion-source-code.
Die Anzeige Von Overlay -
Als in der Frage genannten, zu Debuggen, das problem, das ich verwendet habe
MKPolygon
s zu visualisieren, was Los war. Es stellt sich heraus, dass die beiden Formen derMKMapRect
s, die span antimeridian anders dargestellt werden, wenn überlagert auf der Karte. Wenn Sie nähern sich dem antimeridian von der west-Hemisphäre, nur die mit negativen Ursprungs angezeigt bekommt. Ebenso die positive origin-form wird angezeigt, wenn Sie nähern sich der 180th meridian aus der östlichen Hemisphäre. DieMKPolygonView
behandelt nicht die spanning von 180th meridian für Sie. Sie müssen passen Sie die polygon-Punkte selbst.Dies ist, wie die zum erstellen von polygon aus der Karte rect:
Habe ich einfach verwendet, brute-force und Hinzugefügt, die das polygon zweimal—eine in jeder form.
Ich hoffe, dies hilft anderen Seelen, die Wandern in das land der Drachen hinter der 180th meridian.
Kurz gesagt, wenn das polygon überquert den antimeridian, überprüfen Sie die mapPoints.
Wenn Sie die mapPoint.x ist größer als die primeMeridian.x, subtrahieren Sie die Breite der Welt aus der mapPoint.x.
Diese teilt die Karte unten der Nullmeridian. Das Luder ist negativ und die mapSize ist kleiner als die Breite der Welt. Palimondo Antwort war enorm hilfreich, herauszufinden dieses heraus.
Arbeite ich mit geodesicPolylines und verbrachte ein paar Tage auf dieser. Endlich eine Antwort gefunden!