无法获取要素坐标,因此我可以获得最接近的要素

Cannot get feature coordinates so I can get its closest feature

我在 Openlayers 3.9.0 中有一个矢量图层。 Geoserver 从 PostGIS 获取数据,我用 ol.source.Vector.

抓取图层

返回数据的GeoJSON格式为

    {"type":"FeatureCollection","totalFeatures":422,"features":
[{"type":"Feature","id":"myLayer.709","geometry":{"type":"Point","coordinates":
[2391735.8907621,4695330.8039257005]},"geometry_name":"myLayer_geom","properties"
:{"myLayer_name":"Hello"....next feature

所以我通过它的ID得到第一个特征,并尝试根据它的坐标找到它最近的特征。这是我的代码

var bb = (sourceVector.getFeatureById('myLayer.709')).getCoordinates()
var aa = getClosestFeatureToCoordinate(bb);
console.log(aa);

我收到 Cannot read property 'getCoordinates' of null 错误。

这是为什么?我错过了什么?

另外,getFeatureById implies that the id must be a number, but in my case is a string (myLayer.709). On the other hand, a feature的API可以得到一个字符串作为ID,在读取数据时可以设置ID。

编辑

这是全部代码(图层切换器模块here

var textent = ol.proj.transformExtent([2297128.5, 4618333, 2459120.25, 4763120], 'EPSG:900913', 'EPSG:3857');

    var layer = new ol.layer.Tile({
        source: new ol.source.OSM({})});

    var bingMapsAerial = new ol.layer.Tile({
        source: new ol.source.BingMaps({
            key: 'aaaa',
            imagerySet:'AerialWithLabels'
        })
    });       

    var ait = new ol.layer.Tile({
    source: new ol.source.TileWMS({
      url: 'http://localhost:8080/geoserver/mymap/wms?',
       params: {'LAYERS': 'mymap:polygons, mymap:lines', 'TILED': true,  'VERSION': '1.3.0','FORMAT': 'image/png' ,'CRS': 'EPSG:900913'},
       serverType: 'geoserver'
     })
   })

var sourceVector = new ol.source.Vector({
    format: new ol.format.GeoJSON(),
    useSpatialIndex : true,
    loader: function (extent) {
        $.ajax('http://localhost:5550/geoserver/mymap/wfs?service=WFS&version=1.0.0&request=GetFeature&typeName=mymap:mylayer&outputFormat=application/json&BBOX='+extent.join(','), 
        {type: 'GET'})
        .done(      
         function(response) {
                    var geojsonFormat = new ol.format.GeoJSON({});
                    sourceVector.addFeatures(geojsonFormat.readFeatures(response,{dataProjection : projection,featureProjection : projection}));
                })
        .fail(function () {alert("no");});
    },

    strategy: ol.loadingstrategy.bbox
});


var fill = new ol.style.Fill({
color: 'rgba(0,0,0,0.2)'
});

var stroke = new ol.style.Stroke({
color: 'rgba(0,0,0,0.4)'
});

var circle = new ol.style.Circle({
radius: 6,
fill: fill,
stroke: stroke
});

layerVector = new ol.layer.Vector({
    source: sourceVector,
    style: new ol.style.Style({
        fill: fill,
        stroke: stroke,
        image: circle
      })
});

    layer.set('title','a');
    layer.set('type','base');
    bingMapsAerial.set('title','b');
    bingMapsAerial.set('type','base');
    ait.set('title','ait');
    ait.set('type','base');

    var kbz = new ol.interaction.KeyboardZoom();
    var dr = new ol.interaction.DragRotateAndZoom();
    var control = new ol.control.FullScreen();
    var ext = new ol.control.ZoomToExtent({extent: textent});   
    var center = ol.proj.transform([21.54967, 38.70250], 'EPSG:4326', 'EPSG:3857');

    var view = new ol.View({
        center: center,
        zoom: 6,
        extent : textent,
        maxZoom:20
    });

    var map = new ol.Map({
        target: 'map',
        layers:[bingMapsAerial, layer, ait, layerVector],
        view: view
    });

    map.getView().fit(textent, map.getSize()); 
    map.addInteraction(kbz);
    map.addInteraction(dr);
    map.addControl(control);
    map.addControl(ext);
    var layerSwitcher = new ol.control.LayerSwitcher();
    map.addControl(layerSwitcher);

        var bb = sourceVector.getFeatureById('mylayer.709').getGeometry().getCoordinates();
    var aa = sourceVector.getClosestFeatureToCoordinate(bb);
    console.log(aa); 

更新

在控制台中,如果我点击 map.getLayers(),我会得到矢量图层和一个包含所有特征的 idIndex_ 数组(也是 709)。但是在我的代码中,如果我这样做 var cc = sourceVector.getFeatures(); console.log(cc); 我得到 [ ] ,只有两个空括号。这是否意味着在我尝试通过 ID 获取功能之前功能尚未完成加载?

更新 2 如果我删除

var bb=sourceVector.getFeatureById('mylayer.709').getGeometry().getCoordinates();
var aa = sourceVector.getClosestFeatureToCoordinate(bb);
console.log(aa); 

放在读取特征的响应函数中,wfs请求后就可以了

.done(      
function(response) {
var geojsonFormat = new ol.format.GeoJSON({});
sourceVector.addFeatures(geojsonFormat.readFeatures(response,{dataProjection :projection,featureProjection : projection}));

    //-------------add the following

    var bb=sourceVector.getFeatureById('mylayer.709').getGeometry().getCoordinates();
    var aa = sourceVector.getClosestFeatureToCoordinate(bb);
    console.log(aa); 
                        })

这是否意味着这是我唯一的选择?为什么我不能设置我的矢量图层、获取特征、设置我的地图和访问特征?在真实场景中,加载完成后,用户选择一个随机特征并靠近。不可能知道id。在阅读特征的同时玩弄特征是不切实际的,也没有意义。有什么想法吗?

谢谢

应该是:

var bb = (sourceVector.getFeatureById('myLayer.709'))
    .getGeometry().getCoordinates();
var aa = sourceVector.getClosestFeatureToCoordinate(bb);
console.log(aa);

ol.Feature#id 始终 (https://github.com/openlayers/ol3/blob/v3.9.0/src/ol/source/vectorsource.js#L694) 被视为字符串。

更新 - http://jsfiddle.net/jonataswalker/fn721xdk/

在阅读您的 json 功能时告诉 OL3 您的 data projection

var features = new ol.format.GeoJSON().readFeatures(geojsonObject, {
    dataProjection: 'EPSG:3857',
    featureProjection: 'EPSG:3857'
});

是的,Jonatas Walker 是对的,我必须等待 Ajax 完成加载矢量图层上的所有特征,然后我才能玩特征。

所以,为了知道 Ajax 何时完成,我保留了与 OP 中相同的代码,但我添加了。

       function(response) {
                    var geojsonFormat = new ol.format.GeoJSON({});
                    sourceVector.addFeatures(geojsonFormat.readFeatures(response,{dataProjection : projection,featureProjection : projection}));
                    ww();//<---added this to the existing response function
                })

所以,当它全部完成时,所有功能都已加载,现在可以访问它们了。我调用一个函数

所以,在添加到地图控件和交互之后,我替换了这个

var bb = sourceVector.getFeatureById('mylayer.709').getGeometry().getCoordinates();
    var aa = sourceVector.getClosestFeatureToCoordinate(bb);
    console.log(aa); 

有了这个

 function ww(){
    var rr = sourceVector.getFeatureById('mylayer.709').getGeometry().getCoordinates();
    var hh = sourceVector.getClosestFeatureToCoordinate(rr);
    console.log("The name of the closest feature is : "+hh.get("mylayer_name"));
    }

但是,mylayer.709是一个点。因此,如果地图也有线和多边形,并且用户可以单击任何要素,而您不是在寻找固定要素(您事先不知道 id)

在ww函数后面加上这个就可以了

 var select = new ol.interaction.Select();//simple click interaction
 map.addInteraction(select);//add it to the map

 select.on('select', function(e) {//on every select (=click)

   //get the extent of the first selected feature (from the e.selected array)
    var aa = e.selected[0].getGeometry().getExtent();

   //in case of line or polygon get the center of that extent (=just a point)
    var oo = ol.extent.getCenter(aa);

   //use that center (=point) to get the name of the closest feature
   console.log((sourceVector.getClosestFeatureToCoordinate(oo)).get("mylayer_name")) ;
 });

编辑

我很抱歉。原来有一个错误。在这种情况下

如果我单击多边形,我会得到最近要素的名称,但是如果我单击这些点,我会得到那个点的名称,所以如果我单击 "testpoint9",我会得到 "testpoint9" 但我应该得到 "8" 或 "u" 或 "e" 或其他东西。所以我想和积分有关。

我把函数的内容改成了

    var closestType = e.selected[0].getGeometry().getType();
    var oo;
    if (closestType === 'Point'){
        oo = e.selected[0].getGeometry().getCoordinates();
    }
    else{
        var aa = e.selected[0].getGeometry().getExtent();
        oo = ol.extent.getCenter(aa);
    }

    console.log("---------------------------------------------------");
    console.log("Name of closest : "+sourceVector.getClosestFeatureToCoordinate(oo).get('mylayer_name'));

但还是一样的错误。有小费吗?谢谢