2016-05-09 70 views
2

我在OL3應用程序中工作,用戶可以通過WFS-T繪製,修改和刪除多邊形並將更改保存到GeoServer。openlayers3 wfs-t保存繪圖

對於起點,我已經使用了這裏的解決方案:wfs-t example app 我已經將代碼稍微更改爲使用GeoServer中的多邊形圖層。繪製,修改和刪除多邊形功能工作得非常好,如果我修改或刪除一個多邊形,它也會被保存,但新的多邊形創建不會被保存,我找不到原因。原來的應用程序沒有任何問題。

我希望有人也試圖使用這個應用程序作爲一個起點,並解決了這個問題。有人能告訴我什麼問題?

臨屋的代碼的最重要的部分:

var dirty = {}; 
var formatWFS = new ol.format.WFS(); 
var formatGML = new ol.format.GML({ 
    featureNS: 'http://www.openplans.org/topp', 
    featureType: 'poly', 
    srsName: 'EPSG:3857' 
    }); 
var transactWFS = function(p,f) { 
    switch(p) { 
    case 'insert': 
     node = formatWFS.writeTransaction([f],null,null,formatGML); 
     break; 
    case 'update': 
     node = formatWFS.writeTransaction(null,[f],null,formatGML); 
     break; 
    case 'delete': 
     node = formatWFS.writeTransaction(null,null,[f],formatGML); 
     break; 
    } 
    s = new XMLSerializer(); 
    str = s.serializeToString(node); 
    $.ajax('http://localhost:8080/geoserver/wfs',{ 
     type: 'POST', 
     dataType: 'xml', 
     processData: false, 
     contentType: 'text/xml', 
     data: str 
     }).done(); 
} 

$('.btn-floating').hover(
     function() { 
      $(this).addClass('darken-2');}, 
     function() { 
      $(this).removeClass('darken-2');} 
     ); 

$('.btnMenu').on('click', function(event) { 
    $('.btnMenu').removeClass('orange'); 
    $(this).addClass('orange'); 
    map.removeInteraction(interaction); 
    select.getFeatures().clear(); 
    map.removeInteraction(select); 
    switch($(this).attr('id')) { 

    case 'btnSelect': 
     interaction = new ol.interaction.Select({ 
      style: new ol.style.Style({ 
       stroke: new ol.style.Stroke({color: '#f50057', width: 2}) 
       }) 
     }); 
     map.addInteraction(interaction); 
     interaction.getFeatures().on('add', function(e) { 
      props = e.element.getProperties(); 
      if (props.status){$('#popup-status').html(props.status);}else{$('#popup-status').html('n/a');} 
      if (props.tiendas){$('#popup-tiendas').html(props.tiendas);}else{$('#popup-tiendas').html('n/a');} 
      coord = $('.ol-mouse-position').html().split(','); 
      overlayPopup.setPosition(coord); 
      }); 
     break; 

    case 'btnEdit': 
     map.addInteraction(select); 
     interaction = new ol.interaction.Modify({ 
      features: select.getFeatures() 
      }); 
     map.addInteraction(interaction); 

     snap = new ol.interaction.Snap({ 
      source: layerVector.getSource() 
      }); 
     map.addInteraction(snap); 

     dirty = {}; 
     select.getFeatures().on('add', function(e) { 
      e.element.on('change', function(e) { 
       dirty[e.target.getId()] = true; 
       }); 
      }); 
     select.getFeatures().on('remove', function(e) { 
      f = e.element; 
      if (dirty[f.getId()]){ 
       delete dirty[f.getId()]; 
       featureProperties = f.getProperties(); 
       delete featureProperties.boundedBy; 
       var clone = new ol.Feature(featureProperties); 
       clone.setId(f.getId()); 
       transactWFS('update',clone); 
       } 
      }); 
     break; 

    case 'btnDrawPoly': 
     interaction = new ol.interaction.Draw({ 
      type: 'Polygon', 
      source: layerVector.getSource() 
     }); 
     map.addInteraction(interaction); 
     interaction.on('drawend', function(e) { 
      transactWFS('insert',e.feature); 
     }); 
     break; 

    case 'btnDelete': 
     interaction = new ol.interaction.Select(); 
     map.addInteraction(interaction); 
     interaction.getFeatures().on('change:length', function(e) { 
      transactWFS('delete',e.target.item(0)); 
      interaction.getFeatures().clear(); 
      selectPointerMove.getFeatures().clear(); 
     }); 
     break; 

    default: 
     break; 
    } 
    }); 

我使用一個形狀文件作爲數據存儲。

完成多邊形後到GeoServer的請求:

<Transaction xmlns="http://www.opengis.net/wfs" service="WFS" version="1.1.0" xsi:schemaLocation="http 
    ://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" xmlns:xsi="http://www.w3.org/2001 
    /XMLSchema-instance"><Insert><poly xmlns="http://www.openplans.org/topp"><geometry><Polygon xmlns="http 
    ://www.opengis.net/gml"><exterior><LinearRing><posList>2274170.418847337 5923526.286802612 2329612.7433635183 
    5979783.939620501 2373640.4716557795 5936979.203780803 2330835.735816081 5891728.483035979 2274170.418847337 
    5923526.286802612</posList></LinearRing></exterior></Polygon></geometry></poly></Insert></Transaction 
    > 

從GeoServer的響應:

<?xml version="1.0" encoding="UTF-8"?><wfs:TransactionResponse xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:sf="http://www.openplans.org/spearfish" xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http 
://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" 
xmlns:tiger="http://www.census.gov" xmlns:topp="http://www.openplans.org/topp" xmlns:xlink="http://www 
.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation 
="http://www.opengis.net/wfs http://localhost:8080/geoserver/schemas/wfs/1.1.0/wfs.xsd"><wfs:TransactionSummary 
><wfs:totalInserted>1</wfs:totalInserted><wfs:totalUpdated>0</wfs:totalUpdated><wfs:totalDeleted>0</wfs 
:totalDeleted></wfs:TransactionSummary><wfs:TransactionResults/><wfs:InsertResults><wfs:Feature><ogc 
:FeatureId fid="new0"/></wfs:Feature></wfs:InsertResults></wfs:TransactionResponse> 
+0

要回答這個問題,我們需要知道*至少*發送到服務器的插入,使用的是什麼錯誤是什麼類型的數據存儲的XML記錄在GeoServer日誌文件中。 –

+0

我已經添加了更多detials的描述。 –

回答

1

的GeoServer實際上是正確處理您的請求,問題是,你正在嘗試do不被底層數據存儲所允許。 Shapefiles必須具有幾何屬性,稱爲the_geom,因此當您發送稱爲poly的幾何時,shapefile編寫器在編寫該要素時會忽略它。如果您使用的是數據庫(例如PostGIS),那麼一切都會好起來的。

+0

我已經將多邊形導入PostGIS數據庫。所以現在我使用postgis數據存儲,但它仍然無法正常工作。當我創建一個多邊形時,它將新的記錄添加到表格中,但沒有幾何圖形。 –

+0

您可以將圖層上的describeFeature請求的響應添加到您的問題中嗎? –

+0

< xsd:sequence

1

該代碼示例看起來很熟悉......我在很久以前寫了這個代碼,感到驚訝,這個代碼仍然有效,以後有多少人使用過它。我很確定問題在於幾何列不稱爲幾何。我相信這總是被稱爲幾何。自從使用Geoserver 2.8和OpenLayers 3.16後,我已經更新了這個例子。

在我的設置中,我在Postgis表中使用了一個簡單的幾何字段。這不是生產環境,但允許您將所有類型的幾何體(點,線,多邊形)放在同一個表中。我沒有在這裏定義EPSG代碼,但我總是在開發過程中使用EPSG:3857。如果您像這樣設置表格,則可以測試WFS-T帖子是否工作。

CREATE TABLE wfs_geom 
(
    id bigint NOT NULL, 
    geometry geometry, 
    CONSTRAINT wfs_geom_pkey PRIMARY KEY (id) 
) 
WITH (
    OIDS=FALSE 
); 
ALTER TABLE wfs_geom 
    OWNER TO geoserver; 

這是在一個新的jsfiddle,但我也可以把它放在一個stackoverflow代碼片段。

https://jsfiddle.net/goldrydigital/13Lwsfmf/

var formatWFS = new ol.format.WFS(); 
 

 
var formatGML = new ol.format.GML({ 
 
    featureNS: 'https://geolytix.net/wfs', 
 
    featureType: 'wfs_geom', 
 
    srsName: 'EPSG:3857' 
 
}); 
 

 
var xs = new XMLSerializer(); 
 

 
var sourceWFS = new ol.source.Vector({ 
 
    loader: function (extent) { 
 
     $.ajax('https://maps.geolytix.net/geoserver/geolytix.wfs/wfs', { 
 
      type: 'GET', 
 
      data: { 
 
       service: 'WFS', 
 
       version: '1.1.0', 
 
       request: 'GetFeature', 
 
       typename: 'wfs_geom', 
 
       srsname: 'EPSG:3857', 
 
       bbox: extent.join(',') + ',EPSG:3857' 
 
      } 
 
     }).done(function (response) { 
 
      sourceWFS.addFeatures(formatWFS.readFeatures(response)); 
 
     }); 
 
    }, 
 
    //strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ()), 
 
    strategy: ol.loadingstrategy.bbox, 
 
    projection: 'EPSG:3857' 
 
}); 
 

 
var layerWFS = new ol.layer.Vector({ 
 
    source: sourceWFS 
 
}); 
 

 
var interaction; 
 

 
var interactionSelectPointerMove = new ol.interaction.Select({ 
 
    condition: ol.events.condition.pointerMove 
 
}); 
 

 
var interactionSelect = new ol.interaction.Select({ 
 
    style: new ol.style.Style({ 
 
     stroke: new ol.style.Stroke({ 
 
      color: '#FF2828' 
 
     }) 
 
    }) 
 
}); 
 

 
var interactionSnap = new ol.interaction.Snap({ 
 
    source: layerWFS.getSource() 
 
}); 
 

 
var map = new ol.Map({ 
 
    target: 'map', 
 
    controls: [], 
 
    interactions: [ 
 
     interactionSelectPointerMove, 
 
     new ol.interaction.MouseWheelZoom(), 
 
     new ol.interaction.DragPan() 
 
    ], 
 
    layers: [ 
 
     new ol.layer.Tile({ 
 
      source: new ol.source.OSM({ 
 
       url: 'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/dark_nolabels/{z}/{x}/{y}.png', 
 
       opaque: false, 
 
       attributions: [] 
 
      }) 
 
     }), 
 
     layerWFS 
 
    ], 
 
    view: new ol.View({ 
 
     center: ol.proj.fromLonLat([-1.7, 53.2]), 
 
     zoom: 6 
 
    }) 
 
}); 
 

 
//wfs-t 
 
var dirty = {}; 
 
var transactWFS = function (mode, f) { 
 
    var node; 
 
    switch (mode) { 
 
     case 'insert': 
 
      node = formatWFS.writeTransaction([f], null, null, formatGML); 
 
      break; 
 
     case 'update': 
 
      node = formatWFS.writeTransaction(null, [f], null, formatGML); 
 
      break; 
 
     case 'delete': 
 
      node = formatWFS.writeTransaction(null, null, [f], formatGML); 
 
      break; 
 
    } 
 
    var payload = xs.serializeToString(node); 
 
    $.ajax('https://maps.geolytix.net/geoserver/geolytix.wfs/wfs', { 
 
     type: 'POST', 
 
     dataType: 'xml', 
 
     processData: false, 
 
     contentType: 'text/xml', 
 
     data: payload 
 
    }).done(function() { 
 
     sourceWFS.clear(); 
 
    }); 
 
}; 
 

 
$('button').click(function() { 
 
    $(this).siblings().removeClass('btn-active'); 
 
    $(this).addClass('btn-active'); 
 
    map.removeInteraction(interaction); 
 
    interactionSelect.getFeatures().clear(); 
 
    map.removeInteraction(interactionSelect); 
 

 
    switch ($(this).attr('id')) { 
 

 
     case 'btnEdit': 
 
      map.addInteraction(interactionSelect); 
 
      interaction = new ol.interaction.Modify({ 
 
       features: interactionSelect.getFeatures() 
 
      }); 
 
      map.addInteraction(interaction); 
 
      map.addInteraction(interactionSnap); 
 
      dirty = {}; 
 
      interactionSelect.getFeatures().on('add', function (e) { 
 
       e.element.on('change', function (e) { 
 
        dirty[e.target.getId()] = true; 
 
       }); 
 
      }); 
 
      interactionSelect.getFeatures().on('remove', function (e) { 
 
       var f = e.element; 
 
       if (dirty[f.getId()]) { 
 
        delete dirty[f.getId()]; 
 
        var featureProperties = f.getProperties(); 
 
        delete featureProperties.boundedBy; 
 
        var clone = new ol.Feature(featureProperties); 
 
        clone.setId(f.getId()); 
 
        transactWFS('update', clone); 
 
       } 
 
      }); 
 
      break; 
 

 
     case 'btnPoint': 
 
      interaction = new ol.interaction.Draw({ 
 
       type: 'Point', 
 
       source: layerWFS.getSource() 
 
      }); 
 
      map.addInteraction(interaction); 
 
      interaction.on('drawend', function (e) { 
 
       transactWFS('insert', e.feature); 
 
      }); 
 
      break; 
 

 
     case 'btnLine': 
 
      interaction = new ol.interaction.Draw({ 
 
       type: 'LineString', 
 
       source: layerWFS.getSource() 
 
      }); 
 
      map.addInteraction(interaction); 
 
      interaction.on('drawend', function (e) { 
 
       transactWFS('insert', e.feature); 
 
      }); 
 
      break; 
 

 
     case 'btnArea': 
 
      interaction = new ol.interaction.Draw({ 
 
       type: 'Polygon', 
 
       source: layerWFS.getSource() 
 
      }); 
 
      interaction.on('drawend', function (e) { 
 
       transactWFS('insert', e.feature); 
 
      }); 
 
      map.addInteraction(interaction); 
 
      break; 
 

 
     case 'btnDelete': 
 
      interaction = new ol.interaction.Select(); 
 
      interaction.getFeatures().on('add', function (e) { 
 
       transactWFS('delete', e.target.item(0)); 
 
       interactionSelectPointerMove.getFeatures().clear(); 
 
       interaction.getFeatures().clear(); 
 
      }); 
 
      map.addInteraction(interaction); 
 
      break; 
 

 
     default: 
 
      break; 
 
    } 
 
});
html, 
 
body { 
 
    height: 100%; 
 
    width: 100%; 
 
    padding: 0; 
 
    margin: 0; 
 
    border: 0; 
 
} 
 

 
.map { 
 
    height: 100%; 
 
    width: 100%; 
 
} 
 

 
#btnPoint { 
 
    position: absolute; 
 
    top: 10px; 
 
    left: 10px; 
 
} 
 

 
#btnLine { 
 
    position: absolute; 
 
    top: 10px; 
 
    left: 80px; 
 
} 
 

 
#btnArea { 
 
    position: absolute; 
 
    top: 10px; 
 
    left: 150px; 
 
} 
 

 
#btnEdit { 
 
    position: absolute; 
 
    top: 10px; 
 
    left: 220px; 
 
} 
 

 
#btnDelete { 
 
    position: absolute; 
 
    top: 10px; 
 
    left: 290px; 
 
} 
 

 
.btn-active { 
 
    background-color: #0d47a1 !important; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.16.0/ol.css" type="text/css"> 
 
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> 
 
    <link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.indigo-pink.min.css"> 
 
    <script src="https://code.getmdl.io/1.1.3/material.min.js"></script> 
 
</head> 
 
<body> 
 
    <div id="map" class="map"></div> 
 
    <button id="btnPoint" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored"> 
 
     <i class="material-icons">add_location</i> 
 
    </button> 
 
    <button id="btnLine" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored"> 
 
     <i class="material-icons">timeline</i> 
 
    </button> 
 
    <button id="btnArea" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored"> 
 
     <i class="material-icons">signal_cellular_null</i> 
 
    </button> 
 
    <button id="btnEdit" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored"> 
 
     <i class="material-icons">build</i> 
 
    </button> 
 
    <button id="btnDelete" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored"> 
 
     <i class="material-icons">delete</i> 
 
    </button> 
 
</body> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.14/proj4.js"></script> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.16.0/ol.js"></script> 
 
</html>