9 votos

La división de Linestrings en la línea de cambio de fecha con OpenLayers

Hace un par de años he publicado una pregunta titulado "La Línea de Fecha Internacional envoltura alrededor de la" @jdeolive me sugirió dividir las funciones en la línea de cambio de fecha. Así que lo intenté.

Así que cuando me intenta dividir mi satélite de la pista con splitWith en la línea de cambio de fecha vuelvo null. Sé que estoy dividiendo correctamente porque cuando me separé de Greenwich línea puedo obtener los resultados esperados.

Alguien sabe cómo puedo correctamente dividir un Linestring mediante programación a lo largo de la línea de cambio de fecha con OpenLayers? Me gustaría mucho aprecio código de ejemplo, si usted la tiene.

He intentado wrapDateLine pero no parece estar trabajando en capas vectoriales a pesar de mi capa vectorial ser como este:

vectorLayer = new OpenLayers.Layer.Vector("GroundTracks", {
    renderers: ['Canvas', 'VML'],
    wrapDateLine: true}); // <-- shoud be wraping.

enter image description here

Aquí está mi código:

var features = [];
var format = new OpenLayers.Format.WKT({
    'internalProjection': map.baseLayer.projection,
    'externalProjection': prjGeographic
});
var satTrack = format.read("LINESTRING (95.538611 13.286511, 94.730711 16.908947, 93.901095 20.528750, 93.043594 24.145177, 92.150978 27.757436, 91.214579 31.364666, 90.223791 34.965899, 89.165364 38.560019, 88.022401 42.145679, 86.772901 45.721205, 85.387568 49.284424, 83.826433 52.832413, 82.033480 56.361087, 79.927797 59.864504, 77.388419 63.333664, 74.227306 66.754285, 70.139140 70.102478, 64.605267 73.335774, 56.712904 76.373458, 44.881134 79.052803, 26.939886 81.047314, 02.704174 81.839241, -21.686285 81.101751, -39.887660 79.141947, -51.906937 76.480894, -59.912477 73.452897, -65.514482 70.225089, -69.645366 66.880243, -72.834535 63.461797, -75.393132 59.994131, -77.512464 56.491789, -79.315407 52.963919, -80.884039 49.416549, -82.275114 45.853820, -83.529088 42.278691, -84.675583 38.693355, -85.736827 35.099503, -86.729876 31.498490, -87.668095 27.891443, -88.562176 24.279331, -89.420849 20.663020, -90.251389 17.043303, -91.059999 13.420926, -91.852092 09.796602, -92.632515 06.171020, -93.405728 02.544857, -94.175960 -01.081217, -94.947343 -04.706542, -95.724045 -08.330456, -96.510402 -11.952298, -97.311065 -15.571400, -98.131162 -19.187081, -98.976502 -22.798638, -99.853829 -26.405335, -100.771148 -30.006378, -101.738172 -33.600889, -102.766925 -37.187866, -103.872602 -40.766117, -105.074803 -44.334175, -106.399366 -47.890158, -107.881153 -51.431559, -109.568417 -54.954914, -111.529886 -58.455253, -113.866668 -61.925160, -116.733085 -65.353081, -120.374635 -68.720132, -125.199754 -71.993642, -131.916790 -75.113368, -141.772276 -77.960803, -156.750096 -80.294831, -178.475596 -81.673196, 156.248392 -81.611421, 135.042323 -80.136505, 120.556535 -77.748172, 111.014840 -74.872356, 104.485504 -71.737081, 99.775637 -68.454400, 96.208126 -65.081545, 93.391438 -61.649716, 91.089380 -58.177038, 89.152970 -54.674643, 87.484294 -51.149703, 86.016609 -47.607042, 84.702947 -44.050030, 83.509299 -40.481112, 82.410411 -36.902133, 81.387093 -33.314533, 80.424442 -29.719485, 79.510644 -26.117981, 78.636145 -22.510889, 77.793053 -18.898997, 76.974710 -15.283040, 76.175371 -11.663718, 75.389950 -08.041709, 74.613831 -04.417680, 73.842693 -00.792294, 73.072378 02.833789, 72.298749 06.459907, 71.517566 10.085391, 70.724342 13.709564, 69.914194 17.331733, 69.081655 20.951185, 68.220447 24.567170, 67.323194 28.178891, 66.381031 31.785476, 65.383084 35.385943, 64.315735 38.979152, 63.161579 42.563725, 61.897893 46.137940, 60.494337 49.699551, 58.909396 53.245525, 57.084691 56.771602, 54.935577 60.271560, 52.334964 63.735923, 49.084320 67.149569, 44.859585 70.487030, 39.107498 73.702694, 30.852243 76.709182, 18.420695 79.329532, -00.339911 81.212453, -25.028018 81.831766)");

var featGreenwichLine = format.read("LINESTRING(0 -89, 0 89)");
var featDateLine = format.read("LINESTRING(180 -89, 180 89)");

features.push(featGreenwichLine);
features.push(featDateLine);
features.push(satTrack);

var resultsGreenwich = satTrack.geometry.splitWith(featGreenwichLine.geometry);
var resultsDateLine = satTrack.geometry.splitWith(featDateLine.geometry);

console.log(resultsGreenwich); //<--RETURNS EXPECTED RESULTS.
console.log(resultsDateLine);//<--RETURNS NULL.

vectorLayer.addFeatures(features);

Mi pregunta no es un duplicado de esta pregunta porque quieren saber cómo hacerlo en ogr2ogr

Actualización:

Esto es lo que un típico conjunto de datos que trabajo parece (24 horas satélite de la pista): El Linestring wkt se puede encontrar AQUÍ.

enter image description here

2voto

C. Ross Puntos 126

El problema es que su función no cruza la línea de la fecha de OpenLayers perspectiva, por lo que su línea de división no se cruzan de su función. Ejemplo de tus datos:

..., -178.475596 -81.673196, 156.248392 -81.611421,...

Ir de -178 a 156, y esto no cruzar la línea de la fecha de la OpenLayers perspectiva. En lugar de dividir en la línea de la fecha, usted debe dividir en su mínimo valor de X.

// Build the splitting line based on the min and max coordinates of the vector to split
var minX = 999999999;
var minY = -20037508.34 // minimum value of the spherical mercator projection
var maxY = 20037508.34  // maximum value of the spherical mercator projection
//Extract the minimum X from the data as bounds seems to be rounded.
for(var i=0; i<satTrack.geometry.components.length; i++) {
    if(satTrack.geometry.components[i].x < minX)
        minX = satTrack.geometry.components[i].x;
}
var pointList = [
    new OpenLayers.Geometry.Point(minX, minY),
    new OpenLayers.Geometry.Point(minX, maxY)
];
var featDateLine = new OpenLayers.Feature.Vector(
    new OpenLayers.Geometry.LineString(pointList)
);

He construido un ejemplo aquí que logró dividir su satélite de la pista en 2 características: http://jsfiddle.net/6XJ5A/

Ahora, para utilizar el WKT con múltiples líneas en su actualización, en lugar de utilizar una línea recta, usted debe ir a través de todo el conjunto de datos y construir su línea de división con todas las coordenadas que ir a través de la línea de cambio de fecha. Mediante la construcción de pequeñas línea dentro de una multilínea, puede dividir en todas las coordenadas que debe ir a través de la línea de cambio de fecha. Aquí está la versión actualizada de ejemplo: http://jsfiddle.net/Jc274/

Y el código:

// Build the splitting line based on the min and max coordinates of the vector to split
var pointList = [];
var lastPoint = satTrack.geometry.components[0];
//Extract the minimum X from the data as bounds seems to be rounded.
for (var i = 1; i < satTrack.geometry.components.length; i++) {
    if (Math.abs(satTrack.geometry.components[i].x - lastPoint.x) > 10000000) {
        pointList.push(satTrack.geometry.components[i]);
    }
    lastPoint = satTrack.geometry.components[i];
}

var lineList = [];
for(var i=0; i<pointList.length; i++) {
    lineList.push(new OpenLayers.Geometry.LineString([
        new OpenLayers.Geometry.Point(pointList[i].x, pointList[i].y-0.00001), 
        new OpenLayers.Geometry.Point(pointList[i].x, pointList[i].y+0.00001)
    ]));
}

var featDateLine = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.MultiLineString(lineList), null, split_style);

Esto devolverá una splitted línea sobre todos los puntos que "cruzar" la línea de cambio de fecha

Tenga en cuenta que yo también bucle a través de las coordenadas para quitar la línea que va a través del mapa para conectar las 2 coordenadas:

for (var i = 0; i < resultsDateLine.length; i++) {
    // Remove the first (or last) point of the line, the one that cross the dateline
    if (Math.abs(resultsDateLine[i].components[0].x - resultsDateLine[i].components[1].x) > 10000000) {
        resultsDateLine[i].removeComponent(resultsDateLine[i].components[0]);
    }
    if (Math.abs(resultsDateLine[i].components[resultsDateLine[i].components.length - 1].x - resultsDateLine[i].components[resultsDateLine[i].components.length - 2].x) > 10000000) {
        resultsDateLine[i].removeComponent(resultsDateLine[i].components[resultsDateLine[i].components.length - 1]);
    }
    features.push(new OpenLayers.Feature.Vector(resultsDateLine[i], null, style_array[i]));
}

Actualización: He actualizado el primer ejemplo sólo hay que añadir la línea que se divide. También he actualizado la explicación en consecuencia. Este enfoque no es a prueba de balas con las 24h de satélite de la pista, pero estoy trabajando en ello.

Actualización 2: He actualizado el segundo ejemplo. Mediante el uso de varias líneas para dividir y recorriendo el resultado para eliminar el exceso de coordenadas añadido por la división, obtenemos un conjunto de características que nunca vaya a través de la línea de cambio de fecha.

2voto

Vasu Puntos 11

He encontrado una gran solución en @Dane 's github. Se llama Arc.js y es que para el cálculo de rutas de Gran radio. No solo eso, sino que también dividir la línea en la línea de cambio de fecha y de proveerle a usted con dos linestrings que se encuentran en la línea de cambio de fecha, que OpenLayers puede asignar fácilmente. Espero que él viene hacia adelante para reclamar la recompensa.

Aquí están mis resultados:

enter image description hereenter image description here

1voto

Bertolt Puntos 213

El splitWith función no sabe acerca de la tierra de la forma 3-dimensional. Únicamente opera en 2 dimensiones mundo. En su caso, todos los de su LINESTRING X coordenadas son entre -180 y 180. Así que a partir de OpenLayers' de dos dimensiones de la perspectiva, la línea de cadena en realidad nunca cruza su división de la geometría (la línea de la fecha) y te lo dice volviendo null.

Creo que vas a tener que escribir código personalizado para hacer la división. Me estoy imaginando un algoritmo que se repite a lo largo de sus vértices, la construcción de línea de salida de cadenas como esta:

  • Para cada par adyacente de los vértices de decidir si el segmento entre ellos cruza la línea de cambio de fecha.
  • Si no, mantener ese segmento, como es y agregar a la "actual" línea de salida de la cadena.
  • Si lo hace, divide el segmento en dos partes. Añadir una parte a la "actual" de la línea de cadena, inicio de una nueva "corriente" de la línea de cadena, y añadir la otra parte a esta nueva.

Una razonable heurística para determinar si un par de vértices cruza la línea de la fecha es para ver si la diferencia entre las coordenadas X es mayor que 180 grados. (Aunque esto puede hacerlo mal, por ejemplo, en las regiones polares. Tal vez tienes la suerte de no tener todas las latitudes altas.)

La operación de dividir un segmento en dos partes podría ser tan simple como la interpolación lineal (si no se preocupan demasiado acerca de la pista de precisión). Cuando se detecta que el segmento cruza la línea de la fecha de realizar una copia de el segundo vértice y mover su coordenada X (sumando o restando 360 grados) y luego interpolar la coordenada.

EDIT: he Aquí un JSFiddle que muestra el algoritmo anterior en sus datos: http://jsfiddle.net/85vjS/

0voto

xenny Puntos 670

Si funciona con Greenwich, esto es debido a que están dentro de los límites de la CRS. Así que me gustaría, en primer lugar, sugieren la misma solución como en el post que se señala a :

var featDateLine = format.read("LINESTRING(179.99 -89, 179.99 89)");

y tal vez

var featDateLine = format.read("LINESTRING(-179.99 -89, -179.99 89)");

por el otro lado .

Otra solución es trabajar en un CRS que no está "fuera de juego" en la línea de cambio de fecha. A continuación, usted debe ser capaz de dividir los datos sin problema.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X