Tenía el mismo problema y no encontré ninguna herramienta que me diera la solución, así que lo que hice fue tomar el LineString (que no es el feature
pero la geometría de la característica => feature.geometry
), obtener sus vértices y almacenarlos en un array ( points
)
function onFeatureSelectLineString(event) {
var feature = event.feature;
var points = feature.geometry.getVertices();
entonces almaceno cualquier dato del segmento que considere relevante (distancia, velocidad, horas de inicio/fin [la mía es una aplicación de seguimiento]) en una matriz bidimensional segmentdataArray[segmentCount][attribute]
o, si sólo quieres distancia, segmentdataArray[segmentCount]
. dependiendo del número de puntos totales puede o no ser necesario guardar los datos en la matriz (pocos puntos, no hay necesidad de molestarse, un poco de sobrecarga no será un problema grave).
var segmentdataArray = new Array(points.length-1);
for (var i=0;i<(points.length);i++) { //skip first point
segmentdataArray[i-1] = point[i-1].distanceTo(point[i-1]); // start at segmentdataArray[0]
}
Así que, ahora que tenemos nuestros datos, necesitamos saber en qué segmento hizo clic el usuario. desafortunadamente, no he encontrado ningún método, función o propiedad nativa que dé esta información (por favor, por favor, corrígeme si estoy equivocado).
mi enfoque era almacenar la posición actual del ratón en variables "globales" (declaradas fuera de function init()
disponible para todas las funciones javascript de ese script).
var mouseLat, mouseLon;
una vez dentro del onFeatureSelect()
creo un punto a partir de la lat + lon global (posición del ratón en el momento de hacer clic, que está CERCA pero no necesariamente SOBRE la LineString) y calculo el distanceTo
la geometría LineString
var clickPoint = new OpenLayers.Geometry.Point(mouseLon, mouseLat);
// shortest distance from clicked point to LineString geometry
var distance = feature.geometry.distanceTo(clickPoint);
entonces creo un LineString* de 4 lados, "cuadrado" lineStringTemp
alrededor del clic del ratón y la intersección ( splitWIth
) el original feature.geometry
(LineString). el resultado de una división es un array nulo (si las geometrías no se tocan), o un array con al menos 2 geometrías, pero normalmente 3 linestrings, ya que mi caja divide el LineString original en 2 linestrings grandes y uno muy pequeño que está "dentro" de mi cuadrado.
var splitFeatures = feature.geometry.splitWith(lineStringTemp);
si su caja es demasiado grande, tendrá más de 3 segmentos, se crea uno por cada punto adicional en el que se cruzan ambas geometrías. puede o no invertir tiempo en la verificación del resultado (vuelva a dividir con una caja más pequeña si obtiene más de 4 geometrías como resultado de una división).
para el 99% de los casos, un cuadrado alrededor del punto de clic del ratón con lados 1,42 veces ("vete a jugar con tus triángulos, euclides") la distancia más pequeña entre el clic del ratón y la cadena de líneas funcionará bien. el único problema es que hay que convertir la distancia a grados para poder crear este cuadrado.
las latitudes son paralelas y la distancia entre cada grado es siempre de 111,2 km. en cuanto a la longitud, 1 grado de longitud puede representar más de 9000 km en el ecuador, frente a unos pocos centímetros cuando se está "en" cualquiera de los polos (norte o sur).
// distance between degrees Lat = 111.2km (constant - lats are parallel to each other)
var latDegreeKm = 111.2;
// distance between degrees Lon vary (much smaller closer to poles)
var pointTemp = new OpenLayers.Geometry.Point((mouseLon+1), mouseLat);
var lonDegreeKm = pointTemp.distanceTo(clickPoint);
// 1.42:1 = approx relation between legs / hypothenuse in isosceles rectangle (90-45-45) triangle
var degreesLat = 1.42 * distance / latDegreeKm;
var degreesLon = 1.42 * distance / lonDegreeKm;
var lineStringTemp = new OpenLayers.Geometry.LineString([
new OpenLayers.Geometry.Point((mouseLon+lonDegreeKm), (mouseLat+degreesLat)),
new OpenLayers.Geometry.Point((mouseLon-lonDegreeKm), (mouseLat+degreesLat)),
new OpenLayers.Geometry.Point((mouseLon-lonDegreeKm), (mouseLat-degreesLat)),
new OpenLayers.Geometry.Point((mouseLon+lonDegreeKm), (mouseLat-degreesLat))
]);
entonces tomo la primera cadena de líneas dividida ( splitFeatures[0]
) y contar sus puntos. Ahora sé dónde se produjo la división ( pointsTemp.length - 2
es el puntero a segmentdataArray[]
(si lo usas, en este ejemplo no lo hago)
var splitFeatures = feature.geometry.splitWith(lineStringTemp);
if (splitFeatures) {
var attributes = {name: "FirstSegment", type: "LineString"};
var pointsTemp = splitFeatures[0].getVertices();
var pointsTempCount = pointsTemp.length;
var lineStringSegment = new OpenLayers.Geometry.LineString([points[pointsTempCount-2], points[pointsTempCount-1] ]);
var lineStringSegmentLength = lineStringSegment.getLength();
var featureTemp = new OpenLayers.Feature.Vector(lineStringSegment, attributes);
//var featureTemp = new OpenLayers.Feature.Vector(splitFeatures[0], attributes); // alternate splits linestring and shows first part
layerTemp.addFeatures(featureTemp);
content += "\n\n Segment Length: "+lineStringSegmentLength+"\n splitFeatures count: "+splitFeatures.length+"\n\n featureTemp.geometry: "+featureTemp.geometry+"\n\n feature.geometry: "+feature.geometry;
popup = new OpenLayers.Popup.FramedCloud("chicken",
featureTemp.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(100,100),
content,
null, true, onFeatureUnselect);
popup.setBackgroundColor('white');
featureTemp.popup = popup;
map.addPopup(popup);
} else {
alert( "no SPLIT OCCURED");
}
atención, si empieza a dividir y mostrar líneas, obtendrá una matriz poblada de geometrías que deben ser convertidas en características, antes de ser colocadas en una capa y mostradas en el mapa como se ve arriba en:
var featureTemp = new OpenLayers.Feature.Vector(splitFeatures[0], attributes);
layerTemp.addFeatures(featureTemp);
nota 2 auto: ver código zMapaAlunosCaminho06a.php