2014-02-11 140 views
5

注意:我知道還有另一個類似於這個問題,但它沒有得到回答,我需要知道如何處理混合投影與GeoJSON和OSM。Openlayers投影與OSM樣式的地圖和GeoJSON矢量圖層

我很困惑。我在Android上使用OSMDroid API進行映射,並希望使用OpenLayers和GeoExt進行復制,但我在包含GeoJSON節點和動作事件時遇到了投影問題。

我的圖集是基於OSM的,並且駐留在與此HTML/JS相同的Web服務器上。在下面看到它。我意識到我的界限不起作用,我的預測可能完全錯誤。我一直在測試不同的組合。

問題是我的地圖顯示正確並居中良好。但是:

  1. 我的GeoJSON功能節點離開地圖。他們處於不同的投影長/緯度,但我不知道如何設置或將GeoJSON long/lat轉換爲當前的地圖投影。

  2. 我的mapCtrl不起作用。當我點擊它lonlat是另一個投影(OSM的投影COORDS),我似乎無法將它們轉換)

  3. 的程度/界限是如何工作的將是任何提示,不勝感激

有人可以請一些投影建議幫忙嗎?嘆息......我對此沒有耐心。

enter image description here

這裏是我的全JS,如:

var mapPanel, store, gridPanel, mainPanel, nodePop, mapPop; 

Ext.onReady(function() { 

    var map, mapLayer, vecLayer; 
    var lon = -70.885610; 
    var lat = 38.345822; 
    var zoom = 17; 
    var maxZoom = 18; 

var toProjection = new OpenLayers.Projection("EPSG:4326"); 
var fromProjection = new OpenLayers.Projection("EPSG:900913"); 
    var extent = new OpenLayers.Bounds(-1.32,51.71,-1.18,51.80).transform(fromProjection, toProjection); 

    // Setup the node layer feature store and push it all into a vector layer 
    vecLayer = new OpenLayers.Layer.Vector("vector"); 
    store = new GeoExt.data.FeatureStore({ 
     layer: vecLayer, 
     fields: [ 
      {name: 'name', type: 'string'}, 
      {name: 'status', type: 'string'} 
     ], 
     proxy: new GeoExt.data.ProtocolProxy({ 
      protocol: new OpenLayers.Protocol.HTTP({ 
       url: "data/sa.json", 
       format: new OpenLayers.Format.GeoJSON() 
      }) 
     }), 
     autoLoad: true 
    }); 

    // Setup the basic map layer using OSM style tile retreival to pull tiles 
    // from the same server hosting this service 
    map = new OpenLayers.Map(
     'map', { 
      controls:[ 
       new OpenLayers.Control.Navigation(), 
       new OpenLayers.Control.PanZoomBar(), 
       new OpenLayers.Control.Attribution(), 
       new OpenLayers.Control.ScaleLine()], 
      projection: toProjection, 
      displayProjection: fromProjection, 
      numZoomLevels: 20, 
      fractionalZoom: true 
     }); 

    mapLayer = new OpenLayers.Layer.OSM(
     "Local Tiles", 
     "tiles/${z}/${x}/${y}.png", 
     { 
      zoomOffset: 17, 
      resolutions: [1.194328566741945,0.5971642833709725,0.2985821416854863] // Zoom level 17 - 19 
     }); 

    map.addLayers([mapLayer, vecLayer]); 

    // Create a map panel 
    mapPanel = new GeoExt.MapPanel({ 
      title: "Map", 
      region: "center", 
      map: map, 
      xtype: "gx_mappanel", 
      center: new OpenLayers.LonLat(lon, lat), 
      zoom: zoom 
    }); 

    // Create a grid panel for listing nodes 
    gridPanel = new Ext.grid.GridPanel({ 
      title: "Nodes", 
      region: "east", 
      store: store, 
      width: 275, 
      columns: [{ 
       header: "Name", 
       width: 200, 
       dataIndex: "name" 
      }, { 
       header: "Status", 
       width: 75, 
       dataIndex: "status" 
      }], 
      sm: new GeoExt.grid.FeatureSelectionModel({ 
       autoPanMapOnSelection: true 
       }) 
    }); 

    // Create the main view port 
    new Ext.Viewport({ 
     layout: "border", 
     items: [{ 
      region: "north", 
      contentEl: "title", 
      height: 150 
     }, mapPanel, gridPanel] 
    }); 
    var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); 
    map.setCenter(lonLat, zoom); 


    // Attach all the event driven stuff here... 
    // Create a node selection pop up control 
    function nodeAction(feature) { 
     nodePop = new GeoExt.Popup({ 
      title: 'Node selected', 
      location: feature, 
      width: 200, 
      html: "", 
      maximizable: true, 
      collapsible: true 
     }); 
     nodePop.on({ 
      close: function() { 
       if(OpenLayers.Util.indexOf(vectorLayer.selectedFeatures, this.feature) > -1) { 
        selectCtrl.unselect(this.feature); 
       } 
      } 
     }); 
     nodePop.show(); 
    }; 

    // Attach the pop to node/feature selection events 
    var selectCtrl = new OpenLayers.Control.SelectFeature(vecLayer); 
    vecLayer.events.on({ 
     featureselected: function(e) { 
      nodeAction(e.feature); 
     } 
    }); 

    // Create map selection pop up control 
    function mapAction(lonlat) { 
     mapPop = new GeoExt.Popup({ 
      title: 'Map selected', 
      location: lonlat, 
      width: 200, 
      html: "You clicked on (" + lonlat.lon.toFixed(2) + ", " + lonlat.lat.toFixed(2) + ")", 
      maximizable: true, 
      collapsible: true, 
      map: mapPanel.map, 
      anchored: true 
     }); 
     mapPop.doLayout(); 
     mapPop.show(); 
    }; 

    var mapCtrl = new OpenLayers.Control.Click({ 
     trigger: function(evt) { 
      var lonlat = mapPanel.map.getLonLatFromViewPortPx(evt.xy); 
      lonlat.transform(new OpenLayers.Projection("EPSG:4326"), mapPanel.map.getProjectionObject()); 

      //.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); 

      mapAction(lonlat); 
     } 
    }); 
    mapPanel.map.addControl(mapCtrl); 
    mapCtrl.activate(); 
}); 

// A control to handle user clicks on the map 
OpenLayers.Control.Click = OpenLayers.Class(
    OpenLayers.Control, { 
     defaultHandlerOptions: { 
      single: true, 
      double: false, 
      pixelTolerance: 0, 
      stopSingle: true 
     }, 
     initialize: function(options) { 
      this.handlerOptions = OpenLayers.Util.extend(
       options && options.handlerOptions || {}, 
       this.defaultHandlerOptions 
      ); 
      OpenLayers.Control.prototype.initialize.apply(
       this, arguments 
      ); 
      this.handler = new OpenLayers.Handler.Click(
       this, 
       { click: this.trigger }, 
       this.handlerOptions 
      ); 
     }, 
     CLASS_NAME: "OpenLayers.Control.Click" 
    } 
); 

這裏的GeoJSON的我使用:

{ 
    "type": "FeatureCollection", 
    "features": [ 
    { 
     "geometry": { 
     "type": "Point", 
     "coordinates": [ 
      -70.3856, 
     38.3458 
     ] 
     }, 
     "type": "Feature", 
     "properties": { 
     "name": "Node0", 
     "status": "Active", 
     "externalGraphic": "img/node2.png", 
     "graphicHeight": 75, "graphicWidth": 75 
     }, 
     "id": 100 
    }, 
    { 
     "geometry": { 
     "type": "Point", 
     "coordinates": [ 
      -70.885810, 
     38.344722 
     ] 
     }, 
     "type": "Feature", 
     "properties": { 
     "name": "Node1", 
     "status": "Active", 
     "externalGraphic": "img/node2.png", 
     "graphicHeight": 75, "graphicWidth": 75 
     }, 
     "id": 101 
    } 
    ] 
} 

回答

1

好吧,這裏是我如何處理這個問題:

  1. 我在後端使用了嵌入式Jetty Web服務器,但無論如何,我創建了一個使用GeoJSON格式數據響應的servlet。 每個特徵位置lon/lat在投影之間轉換。 (例如,EPSG:4326到EPSG:900913)

  2. 長/投影對話利用GeoTools Java API。 這個博客文章是特別有幫助 (http://ariasprado.name/2012/08/13/quick-and-dirty-coordinate-transforming-using-geotools.html) 請注意,你需要經過一定的試驗和錯誤,如果 你只想包括轉換你的 預測所需的罐子。 GeoTools很大,做了很多,並且有一些 罐子。

現在,當GeoExt.data.ProtocolProxy加載我的GeoJSON內容時,它已經在OSM兼容的EPSG:900913中。我希望完全在GeoExt/OpenLayer中處理這個問題,但似乎並不容易。我會承認,GeoExt和OpenLayers沒有超強的參考文檔。

我會收錄我的GeoTools代碼,但上面的「Arias Prado GIS Ramblings」博客文章比我做得更好。同樣,請注意,你必須嘗試和錯誤的罐子。投影編碼器是動態加載的,而它們又具有來自其他罐子的類相關性。

相關問題