Shapefile을 구성하면 모든 피처의 정점이 일정량만큼 이동했다고 가정 해 보겠습니다. 임의 의 이동으로 모든 기능 ( 정점 의 (x, y) 위치 )을 가장 쉽게 이동하는 방법은 무엇입니까 ? 이 수정 사항을 적용 할 파일이 많으므로 Bash / OGR 답변이 선호됩니다. :)
마지막으로, 나는 멋진 기능을 가지고 있기 때문에 Spatialite를 사용했습니다 ShiftCoords. 그러나 스레드는 매우 유익했습니다! 모두 감사합니다!
Shapefile을 구성하면 모든 피처의 정점이 일정량만큼 이동했다고 가정 해 보겠습니다. 임의 의 이동으로 모든 기능 ( 정점 의 (x, y) 위치 )을 가장 쉽게 이동하는 방법은 무엇입니까 ? 이 수정 사항을 적용 할 파일이 많으므로 Bash / OGR 답변이 선호됩니다. :)
마지막으로, 나는 멋진 기능을 가지고 있기 때문에 Spatialite를 사용했습니다 ShiftCoords. 그러나 스레드는 매우 유익했습니다! 모두 감사합니다!
답변:
JEQL 사용하기 세 줄로 가능하다 :
ShapefileReader t file: "shapefile.shp";
out = select * except (GEOMETRY), Geom.translate(GEOMETRY,100,100) from t;
ShapefileWriter out file: "ahapefile_shift.shp";
이런 종류의 처리를 간단하게하기 위해 Fiona (OGR 래퍼)를 설계했습니다 .
from fiona import collection
import logging
log = logging.getLogger()
# A few functions to shift coords. They call eachother semi-recursively.
def shiftCoords_Point(coords, delta):
# delta is a (delta_x, delta_y [, delta_y]) tuple
return tuple(c + d for c, d in zip(coords, delta))
def shiftCoords_LineString(coords, delta):
return list(shiftCoords_Point(pt_coords, delta) for pt_coords in coords)
def shiftCoords_Polygon(coords, delta):
return list(
shiftCoords_LineString(ring_coords, delta) for ring_coords in coords)
# We'll use a map of these functions in the processing code below.
shifters = {
'Point': shiftCoords_Point,
'LineString': shiftCoords_LineString,
'Polygon': shiftCoords_Polygon }
# Example 2D shift, 1 unit eastward and northward
delta = (1.0, 1.0)
with collection("original.shp", "r") as source:
# Create a sink for processed features with the same format and
# coordinate reference system as the source.
with collection(
"shifted.shp",
"w",
driver=source.driver,
schema=source.schema,
crs=source.crs
) as sink:
for rec in source:
try:
g = rec['geometry']
g['coordinates'] = shifters[g['type']](
g['coordinates'], delta )
rec['geometry'] = g
sink.write(rec)
except Exception, e:
log.exception("Error processing record %s:", rec)
업데이트 : http://sgillies.net/blog/1128/geoprocessing-for-hipsters-translating-features 에이 스크립트의 다른 더 엄격한 버전을 넣었습니다 .
그리고 게시물에 파이썬으로 태그가 지정되었지만 JEQL이 이미 언급되었으므로 JavaScript ( GeoScript 사용)의 예가 있습니다.
/**
* Shift all coords in all features for all layers in some directory
*/
var Directory = require("geoscript/workspace").Directory;
var Layer = require("geoscript/layer").Layer;
// offset for all geometry coords
var dx = dy = 10;
var dir = Directory("./data");
dir.names.forEach(function(name) {
var orig = dir.get(name);
var shifted = Layer({
schema: orig.schema.clone({name: name + "-shifted"})
});
orig.features.forEach(function(feature) {
var clone = feature.clone();
clone.geometry = feature.geometry.transform({dx: dx, dy: dy});
shifted.add(clone);
});
dir.add(shifted);
});
GRASS GIS v.edit 모듈 :
일치하는 투영의 기존 위치 및 맵 세트가 가정됩니다.
쉘 스크립트에서 :
#!/bin/bash
for file in `ls | grep \.shp$ | sed 's/\.shp$//g'`
do
v.in.ogr dsn=./${file}.shp output=$file
v.edit map=$file tool=move move=1,1 where="1=1"
v.out.ogr input=$file type=point,line,boundary,area dsn=./${file}_edit.shp
done
또는 파이썬 스크립트에서 :
#!/usr/bin/env python
import os
from grass.script import core as grass
for file in os.listdir("."):
if file.endswith(".shp"):
f = file.replace(".shp","")
grass.run_command("v.in.ogr", dsn=file, output=f)
grass.run_command("v.edit", map=f, tool="move", move="1,1", where="1=1")
grass.run_command("v.out.ogr", input=f, type="point,line,boundary,area", dsn="./%s_moved.shp" % f)
또 다른 옵션은 ogr2ogr에서 재 투영 옵션을 사용하는 것입니다. JEQL, Fiona 또는 GeoScript 접근 방식보다 해커 접근 방식이지만, 그럼에도 불구하고 효과적입니다. s_srs와 t_srs에 사용 된 투영 사이에 잘못된 이스트와 노스 링이 변경되는 한, 시작 및 투영은 실제로 원본 모양 파일의 실제 투영 일 필요는 없습니다. 이 예에서는 Google Mercator를 사용하고 있습니다. 기본으로 사용할 훨씬 간단한 좌표계가 있다고 확신하지만 복사 / 붙여 넣기가 바로 앞에 있습니다.
ogr2ogr -s_srs EPSG:900913 -t_srs 'PROJCS["Google Mercator",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137.0,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0.0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.017453292519943295],AXIS["Geodetic latitude",NORTH],AXIS["Geodetic longitude",EAST],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["semi_minor",6378137.0],PARAMETER["latitude_of_origin",0.0],PARAMETER["central_meridian",0.0],PARAMETER["scale_factor",1.0],PARAMETER["false_easting",1000.0],PARAMETER["false_northing",1000.0],UNIT["m",1.0],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","900913"]]' -f "ESRI Shapefile" shift.shp original.shp
또는 입력 / 붙여 넣기를 저장하려면 다음을 저장하십시오 projcs.txt(위와 동일하지만 작은 따옴표를 제거).
-s_srs EPSG:900913
-t_srs PROJCS["Google Mercator",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137.0,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0.0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.017453292519943295],AXIS["Geodetic latitude",NORTH],AXIS["Geodetic longitude",EAST],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["semi_minor",6378137.0],PARAMETER["latitude_of_origin",0.0],PARAMETER["central_meridian",0.0],PARAMETER["scale_factor",1.0],PARAMETER["false_easting",1000.0],PARAMETER["false_northing",1000.0],UNIT["m",1.0],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","900913"]]
그런 다음 다음을 실행하십시오.
ogr2ogr --optfile projcs.txt shifted.shp input.shp
--optfile(예 :) ogr2ogr --optfile projcs.txt shifted.shp input.shp. 대답으로 접겠습니다.
패키지 maptools 및 해당 elide 함수를 사용하는 R 옵션 :
shift.xy <- c(1, 2)
library(maptools)
files <- list.files(pattern = "shp$")
for (fi in files) {
xx <- readShapeSpatial(fi)
## update the geometry with elide arguments
shifted <- elide(xx, shift = shift.xy)
## write out a new shapfile
writeSpatialShape(shifted, paste("shifted", fi, sep = ""))
}
지오 함수에서 shapefile 구문 분석기를 사용하면 XSLT를 사용하여 프로세스를 수행 할 수 있습니다. 물론 나중에 shapefile로 다시 변환해야합니다 :-).
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0" xmlns:gml="http://www.opengis.net/gml">
<xsl:param name="x_shift" select="0.0"/>
<xsl:param name="y_shift" select="0.0"/>
<!-- first the identity transform makes sure everything gets copied -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- for any element with coordinate strings, apply the translation factors -->
<!-- note that a schema-aware processor could use the schema type names to simplify -->
<xsl:template match="gml:pos|gml:posList|gml:lowerCorner|gml:upperCorner">
<xsl:copy>
<!-- this xpath parses the ordinates, assuming x y ordering (shapefiles), applies translation factors -->
<xsl:value-of select="
for $i in tokenize(.,'\s+') return
if ($i[(position() mod 2) ne 0]) then
number($i)+$x_shift
else
number($i)+$y_shift
"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
다음은 Groovy GeoScript 버전입니다.
import geoscript.workspace.Directory
import geoscript.layer.Layer
int dx = 10
int dy = 10
def dir = new Directory("./data")
dir.layers.each{name ->
def orig = dir.get(name)
def shifted = dir.create("${name}-shifted", orig.schema.fields)
shifted.add(orig.cursor.collect{f ->
f.geom = f.geom.translate(dx, dy)
f
})
}
여기 OGR 버전이 있습니다
드라이버 = ogr.GetDriverByName ( "ESRI Shapefile")
데프 이동 (dx, dy, dz) :
dataSource = driver.Open(path,1)
layer = dataSource.GetLayer(0)
for feature in layer:
get_poly = feature.GetGeometryRef()
get_ring = get_poly.GetGeometryRef(0)
points = get_ring.GetPointCount()
set_ring = ogr.Geometry(ogr.wkbLinearRing)
for p in xrange(points):
x,y,z = get_ring.GetPoint(p)
x += dx
y += dy
z += dz
set_ring.AddPoint(x,y)
print x,y,z
set_poly = ogr.Geometry(ogr.wkbPolygon)
set_poly.AddGeometry(set_ring)
feature.SetGeometry(set_poly)
layer.SetFeature(feature)
del layer
del feature
del dataSource