จะเปลี่ยนคุณสมบัติทั้งหมดในชุดข้อมูลเวกเตอร์ได้อย่างไร


33

สมมุติว่าฉันรวม Shapefile เข้าด้วยกันและฟีเจอร์ทั้งหมดจะเปลี่ยนจุดยอดเป็นจำนวนคงที่ อะไรคือวิธีที่ง่ายที่สุดในการเปลี่ยนฟีเจอร์ทั้งหมด (x, y)ของจุดยอด) โดยการเลื่อนตามอำเภอใจ? ฉันมีไฟล์มากมายที่ฉันจะใช้การแก้ไขนี้กับดังนั้นคำตอบ Bash / OGR จะเป็นที่ต้องการ :)

สุดท้ายผมสิ้นสุดการใช้ Spatialite ShiftCoordsนี้มันมีฟังก์ชั่นที่ดี อย่างไรก็ตามด้ายมีข้อมูลมาก! ขอบคุณทุกคน!


ฉันรักรายการนี้ ทั้งหน้านี้เป็นตัวอย่างที่ยอดเยี่ยมของคำถาม & คำตอบที่ถูกต้อง คำถามที่อธิบายอย่างตรงไปตรงมาอย่างชัดเจนและทุกคำตอบมอบวิธีการแก้ไขที่ไม่ซ้ำใครถูกต้องและสมบูรณ์ มันสวย. ฉัน upvoted ทุกคนแต่ละคนในบุญของตัวเอง
matt wilkie

@Jose โพสต์นี้ต้องการการอัปเดตเล็กน้อยเนื่องจากการปรับปรุงล่าสุดของไลบรารี GDAL มีวิธีแก้ปัญหาแบบหนึ่งตอนนี้ (ดูคำตอบด้านล่าง)! เป็นไปได้ที่จะใช้ฟังก์ชัน SpatiaLite ShiftCoords โดยตรงด้วยยูทิลิตี้ ogr2ogr
Antonio Falciano

คำตอบ:


21

การใช้JEQLสามารถทำได้สามบรรทัด:

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

คมตัด! ดี!
WolfOdrade

นิสัยดีเดวิด นั่นคับ
sgillies

1
ต้องชี้ให้เห็น ... "ahapefile?"
WolfOdrade

ฉันลงเอยด้วยการใช้ฟังก์ชั่นแปลของ Spatialite ซึ่งคล้ายกับสิ่งที่คุณแนะนำที่นี่
Jose

30

ฉันได้ออกแบบFiona (wrapper 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


2
"การประมวลผลทางภูมิศาสตร์สำหรับ hipsters" ฉันหวังว่าฉันจะสามารถ upvote ที่ 10x สำหรับชื่อที่น่ากลัวนั้น
Ragi Yaser Burhum

13

และแม้ว่าโพสต์จะถูกแท็กด้วย python เนื่องจาก 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);
});

13

การใช้ GDAL> = 1.10.0 คอมไพล์ด้วย SQLite และ SpatiaLite:

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

โดยที่ shiftX = 1 และ shiftY = 10


1
Brilliant - โซลูชัน CLI บรรทัดเดียวแบบง่าย
Dave X

สั้นและง่าย!
เคิร์ต

8

โมดูล GRASS GIS v.edit :

มีการสันนิษฐานตำแหน่งและ mapset ที่มีอยู่ในโปรเจคชั่นการจับคู่

ในเชลล์สคริปต์:

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

หรือในสคริปต์ Python:

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

อีกทางเลือกหนึ่งคือใช้ตัวเลือกการคัดลอกใน 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

2
มันกลายเป็นกอล์ฟสคริปต์ทางภูมิศาสตร์! ขั้นตอนต่อไปคือการแฮ็กตาราง EPSG ของคุณเพื่อกำจัด PROJCS ที่มีตัวอักษรยาว)
sgillies

@sgillies ไม่จำเป็นต้องตัด EPSG เพียงบันทึก projcs ไปยังแฟ้มและการใช้งานเช่น--optfile ogr2ogr --optfile projcs.txt shifted.shp input.shpฉันจะพับมันเป็นคำตอบ
matt wilkie

7

ตัวเลือก R โดยใช้แพ็คเกจ maptools และฟังก์ชั่น elide:

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 ในตำแหน่งทางภูมิศาสตร์คุณสามารถใช้ 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>

4

นี่คือเวอร์ชั่น 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
    })
}  

0

นี่คือเวอร์ชั่น OGR

ไดรเวอร์ = ogr.GetDriverByName ("ESRI Shapefile")

def move (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   
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.