इंटरनेशनल डेट लाइन के चारों ओर लपेटो


13

OpenLayers का उपयोग करते हुए, मैंने एक फ़िल्टर के साथ एक WFS परत (GeoServer पर) जोड़ा, जो सभी विशेषताओं (काला) को लौटाता है जो कुछ तारीखों के भीतर कुछ लैटिन अमेरिकी देशों में रखे गए मेरे बहुभुज (पीले) को प्रतिच्छेद करता है।

यहाँ छवि विवरण दर्ज करें

हालाँकि, जो सुविधा क्षैतिज रूप से पार कर जाती है, वह वास्तव में मेरे बहुभुज को नहीं काटती है। यह सुविधा हवाई और फिजी के बीच प्रशांत महासागर में है और लैटिन अमेरिका में नहीं है। समस्या यह है कि अंतर्राष्ट्रीय तिथि रेखा को पार करने के बजाय इसे पूरी दुनिया में लपेटकर मानचित्र पर प्रस्तुत किया जा रहा है।

संभाव्य विशेषता को परिभाषित किया गया है:

POLYGON ((- 179.700417 14.202717, -178.687422 13.992875,179.024138 8.24716, -179.98241 8.035567, -179.700717 14.202717)

मेरे पास इस तरह की कई समस्याग्रस्त डेट लाइन विशेषताएं हैं लेकिन इस उदाहरण के लिए इसे नीचे तक सीमित कर दिया है। मैं अपने आवेदन में इसे अनदेखा नहीं कर सकता क्योंकि मेरे पास उनमें से कई हैं।

मैंने "wraDateLine: true" का उपयोग बेस लेयर और WFS लेयर में एक ही परिणाम के साथ करने की कोशिश की है।

यकीन नहीं होता कि यह जियो सेवर की समस्या होगी या ओपन लायर की समस्या होगी।

क्या कोई मेरी अंतर्राष्ट्रीय तिथि रेखा समस्या का समाधान जानता है?


2
मुझे नहीं पता कि सॉफ़्टवेयर को इस तरह की समस्या क्यों है, दुनिया सपाट है, है ना ?!
डेविड एफए

शायद एक दिशा पैरामीटर होना चाहिए।
कैप्टनड्रैगन

@CaptDragon इस समस्या का कोई हल?
अनिल

@ अनिल अभी तक कोई नहीं। कृपया मुझे पता है अगर तुम एक मिल।
कैप्ट्रैगन

जवाबों:


6

दुर्भाग्य से यह एक ज्ञात समस्या है। मुद्दा यह है कि इस तरह की तारीख रेखा को पार करने वाले ज्यामितीय अस्पष्ट हैं। OL और GeoServer रेंडरर्स के पास यह जानने का कोई आसान तरीका नहीं है कि इरादा दुनिया भर में "छोटा" रास्ता तय करना है, इसलिए वे उदाहरण के लिए 170 से -170 "नियमित" तरीके से व्याख्या करते हैं और दुनिया भर में लंबा रास्ता तय करते हैं।

दुर्भाग्य से इसके लिए कोई अच्छा उपाय नहीं है सिवाय इसके कि आपके ज्यामिति को अलग कर दें जो डेटलाइन के पार हैं।


धन्यवाद +1, मैं सहमत हूं, लेकिन मैं अपने ज्यामिति को विभाजित नहीं कर सकता। आइए देखें कि क्या किसी और के विचार हैं।
कैप्टनड्रैगन

मैंने ओपनलायर्स पर उन्हें अच्छी तरह से विभाजित करने का एक तरीका निकाला ।
कैप्ट्रैगन

7

ग्रीनविच मेरिडियन (या कहीं और) में विभाजित होने वाले प्रोजेक्शन का उपयोग करने के लिए अपने नक्शे को पुन: प्रक्षेपित करें, ताकि आपके द्वारा रुचि रखने वाले बहुभुज आपके नक्शे में असंतोष को पार न करें।


बहुभुज दुनिया को अच्छी तरह से कवर करते हैं हमेशा ऐसे बहुभुज होंगे जो कुछ रेखा को पार करेंगे। हालांकि, क्या आप किसी ऐसे अनुमान के बारे में जानते हैं जो इस तरह विभाजित नहीं है?
CaptDragon

1
सभी अनुमानों को दुनिया को कहीं न कहीं विभाजित करना चाहिए, यह गणित में निहित है (यदि आप मुझ पर विश्वास नहीं करते हैं तो एक नारंगी छीलें :-))। आप अपने कार्य के लिए सबसे अच्छा प्रक्षेपण चुन सकते हैं।
इयान Turton

हां आप ठीक हैं। मैं इसे कुछ दिनों के लिए खुला छोड़ दूंगा और देखूंगा कि क्या कोई अन्य विचार आया है। आपके सुझाव के लिए धन्यवाद। :-)
CaptDragon

2

मैं इस मुद्दे पर काफी समय से शोध कर रहा था क्योंकि मैंने एक ऐसा एप्लिकेशन विकसित किया है जो उपयोगकर्ता को ड्रैगबॉक्स एक्शन के माध्यम से या तो दर्ज किए गए पॉइंट पॉइंट्स को प्लॉट करने की अनुमति देता है। जब मैंने इस साहसिक कार्य को शुरू किया तो मैं ओपन लॉयर्स के लिए बिल्कुल नया था। मैन्युअल रूप से दर्ज सीमा बिंदुओं के साथ समस्या यह थी कि अगर एओआई ने अंतर्राष्ट्रीय डेटलाइन को कवर किया तो आयत को दुनिया भर में गलत तरीके से खींचा जाएगा। कई StackExchange उपयोगकर्ताओं ने इस समस्या के बारे में केवल एक OpenLayers उत्तरदाता द्वारा बताया जाना है कि (और मैं यहाँ पर चर्चा कर रहा हूँ) "OpenLayers को इस चूक के कारण खींचे जाने वाले बिंदुओं के दिशात्मक इरादे को जानने का कोई तरीका नहीं है ..."। उह, मुझे उस प्रतिक्रिया पर बीएस का झंडा बुलंद करना होगा क्योंकि मैंने अब ओपनलायर्स के बारे में काफी खतरनाक हो जाना सीख लिया है और यह मुद्दा मेरे साथ हो रहा है। मुझे उनकी प्रतिक्रिया के साथ समस्या यह है कि मैं एक हद तक निर्देशांक लोड करता हूं, जो परिभाषा के अनुसार, ऊपरी दाएं देशांतर और अक्षांश के साथ-साथ निचले बाएँ देशांतर और अक्षांश को निर्दिष्ट करता है। यदि ऊपरी राइट लॉन्गिट्यूड IDL के पश्चिमी तरफ है और लोअर लेफ्ट लॉन्गिट्यूड IDL के पूर्वी तरफ स्थित है, तो यह बहुत स्पष्ट है कि उपयोगकर्ता किस तरह से बहुभुज को प्लॉट करना चाहता है और फिर भी OpenLayers लॉन्गिट्यूडिनल मान और ड्राइंग को स्वैप करने पर जोर देता है। बहुभुज दुनिया भर में गलत तरीका है। हद घोषणा और समस्याग्रस्त OpenLayers विधि कॉल का एक नमूना नीचे दिखाया गया है। यदि ऊपरी राइट लॉन्गिट्यूड IDL के पश्चिमी तरफ है और लोअर लेफ्ट लॉन्गिट्यूड IDL के पूर्वी तरफ स्थित है, तो यह बहुत स्पष्ट है कि उपयोगकर्ता किस तरह से बहुभुज को प्लॉट करना चाहता है और फिर भी OpenLayers लॉन्गिट्यूडिनल मान और ड्राइंग को स्वैप करने पर जोर देता है। बहुभुज दुनिया भर में गलत तरीका है। हद घोषणा और समस्याग्रस्त OpenLayers विधि कॉल का एक नमूना नीचे दिखाया गया है। यदि ऊपरी राइट लॉन्गिट्यूड IDL के पश्चिमी तरफ है और लोअर लेफ्ट लॉन्गिट्यूड IDL के पूर्वी तरफ स्थित है, तो यह बहुत स्पष्ट है कि उपयोगकर्ता किस तरह से बहुभुज को प्लॉट करना चाहता है और फिर भी OpenLayers लॉन्गिट्यूडिनल मान और ड्राइंग को स्वैप करने पर जोर देता है। बहुभुज दुनिया भर में गलत तरीका है। हद घोषणा और समस्याग्रस्त OpenLayers विधि कॉल का एक नमूना नीचे दिखाया गया है।

// I would start out with the following entered values as an example
lonLL = 175.781; // minX
latLL = 13.992;  // minY
lonUR = -165.937;// maxX
latUR = 25.945;  // maxY

// I would then make the following call
var manCoordEntryExtent = ol.extent.boundingExtent([[lonLL,latLL], [lonUR, latUR]]);

// Looking at the resulting structure in the debugger I get:
0: -165.937   // minX
1: 13.992     // minY
2: 175.781    // maxX
3: 25.945     // maxY
length: 4
__proto__: []

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

मुझे यह पता लगाने की आवश्यकता थी कि ऐसा क्यों हो रहा था इसलिए मैंने ओपन लाइयर्स 4 लाइब्रेरी में इस ol.extent.boundingExtent विधि में खोदा।

/**
 * Build an extent that includes all given coordinates.
 *
 * @param {Array.<ol.Coordinate>} coordinates Coordinates.
 * @return {ol.Extent} Bounding extent.
 * @api
 */
ol.extent.boundingExtent = function(coordinates) {
  var extent = ol.extent.createEmpty();
  for (var i = 0, ii = coordinates.length; i < ii; ++i) {
    ol.extent.extendCoordinate(extent, coordinates[i]);
  }
  return extent;
};

It first calls ol.extent.createEmpty to initially create an extent structure

/**
 * Create an empty extent.
 * @return {ol.Extent} Empty extent.
 * @api
 */
ol.extent.createEmpty = function() {
  return [Infinity, Infinity, -Infinity, -Infinity];
};

// It then iterates thru the number of coordinates and fills in the extent   structure values, however...
// Here is where the problem is.  Notice the complete lack of any explanation as to what the hell this
// method is doing.  Why is it doing what it does?  All I know is that it cannot handle plots across 
// the IDL and it corrupts your extent structure if you try.

/**
 * @param {ol.Extent} extent Extent.
 * @param {ol.Coordinate} coordinate Coordinate.
 */
ol.extent.extendCoordinate = function(extent, coordinate) {
  if (coordinate[0] < extent[0]) {
    extent[0] = coordinate[0];
  }
  if (coordinate[0] > extent[2]) {
    extent[2] = coordinate[0];
  }
  if (coordinate[1] < extent[1]) {
    extent[1] = coordinate[1];
  }
  if (coordinate[1] > extent[3]) {
    extent[3] = coordinate[1];
  }
};

// The solution was for me to test for IDL myself and if found then create an empty extent and populate it myself manually.

// Using the same extent coordinates as before
lonLL = 175.781; // minX
latLL = 13.992;  // minY
lonUR = -165.937;// maxX
latUR = 25.945;  // maxY

// I test for Dateline instance (Dont have to worry about the potential of there being a polygon covering both Meridian 
// and Anti-meridian as a valid polygon is limited to a maximum size of just over 12 million square kilometers.)
if ((lonLL > 0.0) && (lonUR < 0.0)) {
    // Manually build the coordinates for the Area calculation as the boundingExtent 
    // codepath corrupts an extent to be plotted across the Dateline
    var manCoordEntryExtent = ol.extent.createEmpty();
    manCoordEntryExtent[0] = lonLL;
    manCoordEntryExtent[1] = latLL;
    manCoordEntryExtent[2] = lonUR + 360.0;
    manCoordEntryExtent[3] = latUR;
} else {
    var manCoordEntryExtent = ol.extent.boundingExtent([[lonLL,latLL], [lonUR, latUR]]);
}

// Looking at the resulting structure in the debugger I get:
0: 175.781 // minX
1: 13.992  // minY
2: 194.063 // maxX
3: 25.945  // maxY
length: 4
__proto__: []

मेरा कोड गतिशील रूप से क्षेत्र की गणना करता है ताकि मैं यह निर्धारित कर सकूं कि उपयोगकर्ता ने एक वैध आकार का एओआई बहुभुज बनाया है। जब मैं एक ड्रैगबॉक्स उत्पन्न चयन को संसाधित कर रहा हूं, तो मैं परिणामी ज्यामिति संरचना से और एक ईपीएसजी के लिए निर्देशांक का अनुरोध कर रहा हूं: 4326 प्रक्षेपण जब यह एक लिपटे हुए दुनिया से निर्देशांक देता है तो पहले 180.0 डिग्री के अतीत के निर्देशांक इस प्रकार बढ़ रहे हैं और इस तरह से लोनुर गणना का कारण बनता है। 360.0 - 165.937 = 194.063। मेरा क्षेत्र गणना कोडपाथ निम्नलिखित आईडीएल परीक्षण का उपयोग करता है और क्रमबद्ध रूप से दर्ज किए गए निर्देशांक के लिए समान कोडपथ का उपयोग करने के लिए मुझे समन्वय मूल्य का अनुकरण करने की आवश्यकता थी जैसे कि इसे ड्रैगबॉक्स गेटगोमेट्री कॉल से वापस किया गया था। मैं वास्तव में एक GEOJSON बहुभुज संरचना का परीक्षण कर रहा हूं, जो कि 3 आयाम है, जिसका पहला आयाम रिंग नंबर है;

 function getArea(coords, extent) {

  // Test for Western side of Dateline instance
  if (((coords[0][0][0] <= -180.0) && (coords[0][2][0] > -180.0)) ||
      // Test for Eastern side of Dateline instance
      ((coords[0][0][0] < 180.0) && (coords[0][2][0] >= 180.0))) {
 .
 .
 .

यदि ये परीक्षण इस बिंदु से गुजरते हैं तो कोड आईडीएल पर क्षेत्र की गणना करने के लिए विकसित किए गए एल्गोरिथ्म का उपयोग करता है अन्यथा यह इसे हर जगह सामान्य रूप से गणना करता है।

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

शायद यह समाधान किसी और की मदद करेगा या उन्हें एक अलग दिशा में सोचने में मदद करेगा। समाधान मेरे पास आया जब मैं आखिरकार आईडीएल की समस्या को दो मुद्दों में तोड़ने में सक्षम था। वास्तविक क्षेत्र गणना आईडीएल पर बहुभुज की साजिश रचने के साथ एक मुद्दा था।


1
OL बस> = ऑपरेटर का उपयोग करता है यह जानने के लिए कि साजिश रचते समय किस तरफ जाना है। यदि आप 170 देते हैं तो 190 यह छोटा रास्ता होगा; यदि आप 170 देते हैं तो -170, यह लंबा रास्ता तय करेगा। यदि आप हमेशा -180 और 180 के बीच के देशांतर को "सामान्यीकृत" करते हैं, तो आप जानकारी खो देते हैं। सूचना वापस पाने का एक तरीका यह है कि अंकों के बीच की दूरी को> 180
Rivenfall

1

कार्यक्षेत्र: उदाहरण

var mapserv = new OpenLayers.Layer.MapServer( "OpenLayers Basic",
                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                {layers: 'basic'},
                {wrapDateLine: true} );

http://openlayers.org/dev/examples/wrapDateLine.html


मैं आपके द्वारा पोस्ट किए गए लिंक का WFS उपयोग कर रहा हूं: "आप इसे 'Layer.WMS' या 'Layer.MapServer' लेयर के साथ कर सकते हैं"
CaptDragon

यदि दोनों समर्थित हैं और आपको Layer.MapServer की कोई विशिष्ट आवश्यकता नहीं है, तो Layer.WMS (जो अभी भी MapServer से सेवा की जा सकती है) के साथ जाएं।
डेविड एफएफ

@ डेविड: धन्यवाद, लेकिन मुझे डब्ल्यूएफएस की वेक्टर क्षमताओं का उपयोग करने की आवश्यकता है।
CaptDragon

1

दो साल बाद, मैंने इस समस्या को वेक्टर लेयर पर सुविधाओं के साथ रखा। मुझे यह फ़ाइल कोड के एक स्निपेट से मिली, जिसमें दिखाया गया है कि अगर यह डेटलाइन पार कर गया, तो एक समापन बिंदु कैसे फ्लिप करें:

if(Math.abs(startPoint.x-endPoint.x) > 180) {
  if(startPoint.x < endPoint.x) {
    endPoint.x -= 360;
  } else {
    endPoint.x += 360;
  }
}

अपडेट करें:

वास्तव में उपरोक्त ने दुनिया भर में एक से अधिक क्रांति के लिए काम नहीं किया। मैंने यह कर दिया ।

यहाँ छवि विवरण दर्ज करें


1

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

OpenLayers.Geometry.prototype.crossesDateLine = function() {
    var lastX = this.components[0];
    for (var i=0; i < this.components.length; i++) {
        if (Math.abs(this.components[i].x - lastX) > 180) return i;
        lastX = this.components[i].x;
    }
    return false;
};
OpenLayers.Geometry.prototype.dateLineFix = function() {
    var linestrings = [];
    if (this.crossesDateLine()) {
        var string1 = [];
        for (var i = 0; i < this.crossesDateLine(); i++)
            string1.push(this.components[i]);
        var ls1 = new OpenLayers.Geometry.LineString(string1);
        var string2 = [];
        for (var i = this.crossesDateLine(); i < this.components.length; i++)
            string2.push(this.components[i]);
        var ls2 = new OpenLayers.Geometry.LineString(string2);

        if (!ls1.crossesDateLine()) {
            linestrings.push(ls1);
        } else {
            var split = ls1.dateLineFix();
            for (var i = 0; i < split.components.length; i++)
                linestrings.push(split.components[i]);
        }
        if (!ls2.crossesDateLine()) {
            linestrings.push(ls2);
        } else {
            var split = ls2.dateLineFix();
            for (var i = 0; i < split.components.length; i++)
                linestrings.push(split.components[i]);
        }
    } else {
        linestrings.push(this);
    }
    return new OpenLayers.Geometry.MultiLineString(linestrings);
};

DateLineFix फ़ंक्शन किसी भी सेगमेंट के लिए दिए गए LineString को पुन: प्राप्त करता है जो दिनांक रेखा को पार करता है। इसके बाद उन्हें डेटलाइन पर दो में कटौती करता है और सभी परिणामी खंडों को मल्टीलाइनरिंग के रूप में लौटाता है।

यह मेरे उद्देश्य के लिए पूरी तरह से काम करता है (एक ध्रुवीय लाट-लोन ग्रिड ड्राइंग)।


0

मेरे पास डेटलाइन के साथ कुछ समस्याएँ थीं और मैं उन सभी को ठीक करने में कामयाब रहा। आप निम्नलिखित का प्रयास कर सकते हैं।

  1. अपने बहुभुज को तोड़ने के बिना मैन्युअल रूप से जियोसर्वर लेयर बाउंडिंग बॉक्स मानों को अपडेट करें और देखें कि क्या यह समस्या हल करता है।

  2. Openlayers में मैंने जो एक फिक्स किया है, वह + ve देशांतर से -ve तक डेटलाइन को पार करते समय टाइल्स गायब है। http://trac.osgeo.org/openlayers/ticket/2754 यह सुनिश्चित नहीं करें कि यह WFS के लिए लागू है या नहीं। आप नवीनतम ओपनर विकास संस्करण प्राप्त कर सकते हैं और कोशिश कर सकते हैं।


0

मैंने लाइनस्ट्रीम के साथ इस समस्या का सामना किया है और इसके लिए एक समाधान बनाया है। मुझे यकीन नहीं है कि यह आपको पॉलीगन्स के साथ मदद करेगा। आप इसे मेरे उत्तर पर देख सकते हैं। यहाँ देखें: https://repl.it/@gpantic/OpenLayersSplitRouteOverPacific


1
यदि यह प्रश्न का उत्तर देता है तो कृपया लिंक प्रदान करने के बजाय अपने उत्तर में सभी जानकारी जोड़ें।
बेरा

0

EPSG: 3832 (WGS84 PDC) एक प्रशांत महासागर केंद्रित प्रक्षेपण है। यह प्राइम मेरिडियन क्रॉसिंग समस्याओं के लिए आईडीएल क्रॉसिंग समस्याओं का व्यापार करेगा। यह एक मुद्दा नहीं हो सकता है जो आप दर्शा रहे हैं पर निर्भर करता है। मुझे आर्कटिक और अंटार्कटिक सर्किल के पास के मुद्दे भी मिले।

इस लेख का श्रेय जाता है ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.