Bir vektör veri kümesindeki tüm özellikler nasıl kolayca değiştirilir?


33

Diyelim ki bir Shapefile hazırladım ve tüm özelliklerin köşeleri sabit bir miktarda kaydırılıyor. Tüm özellikleri (bu nedenle (x, y) konumlarını) (isteğe bağlı bir kayma ile) değiştirmenin en kolay yolu nedir ? Bu düzeltmeyi uygulayacağım çok fazla dosyam var, bu yüzden Bash / OGR cevabı tercih edilir :)

Sonunda, güzel işlevi olduğu için bunun için Spatialite kullandım ShiftCoords. Ancak, konu çok bilgilendirici oldu! Herkese teşekkürler!


Ben sadece bu girişi seviyorum. Bu sayfanın tamamı doğru giden soru ve cevapların mükemmel bir örneği. Basit ve net bir şekilde tanımlanmış bir soru ve her cevap benzersiz, geçerli ve eksiksiz bir çözüm sunar. Bu güzel. Her birini kendi yararına övdü.
matt wilkie

@Jose Bu yazının, GDAL kütüphanesinin nispeten yeni gelişmeleri nedeniyle biraz güncellenmesi gerekiyor. Şimdi bir liner çözümü var (aşağıdaki cevaba bakınız)! SpatiaLite ShiftCoords işlevini doğrudan ogr2ogr yardımcı programıyla kullanmak mümkündür.
Antonio Falciano

Yanıtlar:


21

JEQL kullanma Bu üç satırla yapılabilir:

ShapefileReader t file: "shapefile.shp";
out = select * except (GEOMETRY), Geom.translate(GEOMETRY,100,100) from t;
ShapefileWriter out file: "ahapefile_shift.shp";

keskin kenar! Güzel!
WolfOdrade

Güzel David. Bu sıkı.
sgillies

1
Sadece şunu belirtmeliyim ... "ahapefile?"
WolfOdrade

Burada önerdiğin gibi Spatialite'nin tercüme işlevini kullandım.
Jose

30

Fiona'yı (OGR sarmalayıcısı) bu tür işlemlerin basitleştirilmesi için tasarladım .

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)

Güncelleme : Bu betiğin farklı ve daha sıkı bir versiyonunu http://sgillies.net/blog/1128/geoprocessing-for-hipsters-translating-features adresinde yazdım .


2
"Yenilikçiler için Geoprocessing" Keşke bu harika oyun için 10 kat daha fazla
kazanabilseydim

13

Mesaj, python ile etiketlenmiş olmasına rağmen, JEQL zaten belirtilmiş olduğundan, işte JavaScript ( GeoScript kullanarak ) örneği .

/**
 * 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);
});

13

SQLAL ve SpatiaLite ile derlenmiş GDAL> = 1.10.0 kullanarak:

ogr2ogr data_shifted.shp data.shp -dialect sqlite -sql "SELECT ShiftCoords(geometry,1,10) FROM data"

burada shiftX = 1 ve shiftY = 10.


1
Brilliant - basit bir satır CLI çözümü.
Dave X

kısa ve kolay!
Kurt

8

GRASS GIS v.edit modülü :

Eşleşen projeksiyonda mevcut bir konum ve harita kümesi kabul edilir.

Bir kabuk komut dosyasında:

#!/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

veya bir Python betiğinde:

#!/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)

8

Başka bir seçenek de reprojection seçeneklerini sadece ogr2ogr'da kullanmak, kesinlikle JEQL, Fiona ya da GeoScript yaklaşımlarından daha hacimli bir yaklaşım olsa da hiç de etkili değil. Ssrs ve t_srs'da kullanılan projeksiyonlar arasında değişen tek şey, yanlış doğu ve kuzey yönü olduğu sürece, başlangıçtan projeksiyonlara gerçekten orijinal şekil dosyasının gerçek projeksiyonu olması gerekmediğine dikkat edin. Bu örnekte sadece Google Mercator kullanıyorum. Temel olarak kullanmak için çok daha basit bir koordinat sistemi olduğundan eminim, ama bu kopya / yapıştırma tam önümdeydi.

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

Veya yazma / yapıştırma işleminden tasarruf etmek için aşağıdakini kaydedin projcs.txt(yukarıdakiyle aynı, ancak tek tırnak işaretleri hariç):

-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"]]

ve sonra çalıştırın:

ogr2ogr --optfile projcs.txt shifted.shp input.shp

2
Geo-script golfüne dönüşüyor! Sonraki adım, uzun edebi PROJCS ortadan kaldırmak için EPSG tabloyu kesmek olacaktır;)
sgillies

@sgillies, epsg hackine gerek yok, sadece projcs dosyasını bir dosyaya kaydedin ve kullanın --optfile, örn ogr2ogr --optfile projcs.txt shifted.shp input.shp. Cevabın içine katlayacağım.
matt wilkie

7

Paket maptools ve elide işlevini kullanan bir R seçeneği:

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 = ""))
}

4

Shapefile ayrıştırıcısını coğrafi işlevlerde kullanarak, işlemi gerçekleştirmek için XSLT kullanabilirsiniz. Tabii ki daha sonra tekrar shapefile dönüştürmeniz gerekecek :-).

<?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>

4

İşte bir Groovy GeoScript sürümü:

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
    })
}  

0

İşte OGR versiyonu

driver = ogr.GetDriverByName ("ESRI Shapefile")

def hamle (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   
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.