पोस्टगिस में एक बहुभुज के अंदर नियमित बिंदु ग्रिड कैसे बनाएं?


31

कैसे बनाएं, बहुभुज के अंदर, बिंदु स्पेस एक्स का नियमित ग्रिड, वाई पोस्टगिस में? उदाहरण की तरह:

वैकल्पिक शब्द


मैंने इस कोड को "एक्शन में पोस्टजीआईएस" के साथ कोडिंग पॉलीगॉन बनाने की कोशिश की, लेकिन कोडिंग में केवल एक बहुभुज ही बनता है ... क्या मैं कुछ भूल गया? क्रीएट या रिप्लाई फेस मेकग्रिड (ज्यामिति, पूर्णांक, पूर्णांक) RETURNS ज्यामिति के रूप में 'SELECT st_intersection (g1.geom1, g2.geom2) AS geom FROM (SELECT $ 1 AS geom1) AS g1 INNER JOIN (एसटीएसटीएसटी (CAST) (CAST (ST) ST_Point (x, y), $ 3), st_setsrid (ST_Point (x + $ 2, y + $ 2), $ 3)) ज्यामिति के रूप में), $ 3) geom2 के रूप में उत्पन्न_से (मंजिल (st_xmin ($ 1)) :: int, छत ( st_xmax ($ 1)) :: पूर्णांक, $ 2) के रूप में एक्स, generate_series (मंजिल (st_ymin ($ 1)) :: पूर्णांक, छत (st_ymax (
aurel_nc

मेरे विस्तृत जवाब को देखो।
मुहम्मद इमरान सिद्दीकी

जवाबों:


30

आप इसे Gener_series के साथ करते हैं।

यदि आप मैन्युअल रूप से नहीं लिखना चाहते हैं कि ग्रिड कहां से शुरू और बंद करना है, तो सबसे आसान है कि एक फ़ंक्शन बनाएं।

मैंने नीचे ठीक से परीक्षण नहीं किया है, लेकिन मुझे लगता है कि यह काम करना चाहिए:

CREATE OR REPLACE FUNCTION makegrid(geometry, integer)
RETURNS geometry AS
'SELECT ST_Collect(ST_POINT(x,y)) FROM 
generate_series(floor(st_xmin($1))::int, ceiling(st_xmax($1)-st_xmin($1))::int, $2) as x
,generate_series(floor(st_ymin($1))::int, ceiling(st_ymax($1)-st_ymin($1))::int,$2) as y 
where st_intersects($1,ST_POINT(x,y))'
LANGUAGE sql

इसका उपयोग करने के लिए आप कर सकते हैं:

SELECT makegrid(the_geom, 1000) from mytable;

पहला तर्क वह बहुभुज है जिसमें आप ग्रिड चाहते हैं, और दूसरा तर्क ग्रिड में बिंदुओं के बीच की दूरी है।

यदि आप प्रति पंक्ति एक बिंदु चाहते हैं तो आप ST_Dump का उपयोग करें:

SELECT (ST_Dump(makegrid(the_geom, 1000))).geom as the_geom from mytable;

HTH

Nicklas


2
आपको st_pointSRID () को st_point फ़ंक्शन में जोड़ने की आवश्यकता हो सकती है, अन्यथा st_intersects काम नहीं करता है।
जाकल

अलग-अलग उत्तर के रूप में मेरे परीक्षण किए गए संस्करण को जोड़ा।
जाकल

12

मैंने निकलैस एवन मेकग्रिड फंक्शन कोड उठाया है और इसे बहुभुज ज्यामिति से श्रीड को पढ़कर और उपयोग करके इसे थोड़ा और सामान्य बना दिया है। अन्यथा एक परिभाषित श्रीड के साथ बहुभुज का उपयोग करना, एक त्रुटि देगा।

कार्यक्रम:

CREATE OR REPLACE FUNCTION makegrid(geometry, integer)
RETURNS geometry AS
'SELECT ST_Collect(ST_SetSRID(ST_POINT(x,y),ST_SRID($1))) FROM 
generate_series(floor(st_xmin($1))::int, ceiling(st_xmax($1)-st_xmin($1))::int, $2) as x
,generate_series(floor(st_ymin($1))::int, ceiling(st_ymax($1)-st_ymin($1))::int,$2) as y 
where st_intersects($1,ST_SetSRID(ST_POINT(x,y),ST_SRID($1)))'
LANGUAGE sql

फ़ंक्शन का उपयोग करने के लिए ठीक वैसा ही किया जाता है जैसा कि निकल्स एवन ने लिखा था:

SELECT makegrid(the_geom, 1000) from mytable;

या यदि आप प्रति पंक्ति एक अंक चाहते हैं:

SELECT (ST_Dump(makegrid(the_geom, 1000))).geom as the_geom from mytable;

आशा है कि यह किसी के लिए उपयोगी होगा।

एलेक्स


स्वीकृत उत्तर SRID त्रुटियों के कारण मेरे डेटा के साथ काम नहीं करता है। यह संशोधन बेहतर काम करता है।
विटाली येशेव

आप कुछ जोड़ना चाह सकते हैं जब बहुभुज एंटीमेडिडियन को पार कर रहा है? मैं कल्पना कर सकता हूँ कि यह xmin / xmax के साथ समस्या पैदा करेगा।
थॉमस

2
यह मेरे लिए काम नहीं किया। Postgres 9.6 और PostGIS 2.3.3 का उपयोग करना। Gener_series कॉल के अंदर, मुझे इसे दूसरे पैरामीटर "छत (st_xmax ($ 1)) :: int" के बजाय "छत (st_xmax ($ 1)) -st_xmin ($ 1) :: int", और "छत" के रूप में रखना था st_ymax ($ 1)) :: int "" सीलिंग के बजाय "(st_ymax ($ 1) -st_ymin ($ 1) :: int"
Vitor Sapucaia

मैं पिछली टिप्पणी को मंजूरी देता हूं; जेनरेट_सरीज की ऊपरी सीमा अधिकतम की छत होनी चाहिए, न कि अंतर की छत (अधिकतम - मिनट)।
आर। बॉर्गेन

10

एक wgs84 ज्यामिति का उपयोग करने वाले लोगों को संभवतः इस फ़ंक्शन से परेशानी होगी

generate_series(floor(st_xmin($1))::int, ceiling(st_xmax($1))::int,$2) as x
,generate_series(floor(st_ymin($1))::int, ceiling(st_ymax($1))::int,$2) as y 

केवल पूर्णांक वापस करें। बहुत बड़े ज्यामितीय देशों को छोड़कर (जैसे कि कई लेट, लैंग डिग्री पर लेटते हैं), यह केवल 1 बिंदु को इकट्ठा करने का कारण होगा जो कि अधिकांश समय ज्यामिति को खुद भी नहीं काट रहा है ... => खाली परिणाम!

मेरी परेशानी यह थी कि मैं उन WSG84 जैसे फ़्लोटिंग नंबरों पर एक दशमलव दूरी के साथ जनरेट_रेज़ () का उपयोग नहीं कर सकता ... यही कारण है कि मैंने इसे वैसे भी काम करने के लिए फ़ंक्शन को ट्विक किया:

SELECT ST_Collect(st_setsrid(ST_POINT(x/1000000::float,y/1000000::float),st_srid($1))) FROM 
  generate_series(floor(st_xmin($1)*1000000)::int, ceiling(st_xmax($1)*1000000)::int,$2) as x ,
  generate_series(floor(st_ymin($1)*1000000)::int, ceiling(st_ymax($1)*1000000)::int,$2) as y 
WHERE st_intersects($1,ST_SetSRID(ST_POINT(x/1000000::float,y/1000000::float),ST_SRID($1)))

मूल रूप से बिल्कुल वैसा ही। बस जरूरत पड़ने पर खेल में दशमलव को 1000000 से गुणा करना और विभाजित करना।

निश्चित रूप से इसे प्राप्त करने के लिए एक बेहतर समाधान है। ++


यह एक स्मार्ट वर्कअराउंड है। क्या आपने परिणामों की जाँच की है? क्या वे लगातार हैं?
पाब्लो

नमस्ते। हाँ पाब्लो मैं अब तक के परिणामों से खुश हूं। मुझे जमीन के ऊपर सापेक्ष ऊंचाई के साथ कुछ बहुभुज बनाने की आवश्यकता थी। (मैं हर ग्रिड बिंदु के लिए वांछित ऊंचाई की गणना करने के लिए SRTM का उपयोग करता हूं)। मुझे अब केवल उन बिंदुओं को शामिल करने का एक तरीका याद आ रहा है जो बहुभुज की परिधि पर भी हैं। वर्तमान में प्रदान की गई आकृति को कुछ हद तक किनारे पर काट दिया गया है।
जूलियन गार्सिया

काम किया, जब अन्य सभी समाधान विफल हो गए, धन्यवाद!
जॉर्डन आर्सेनो

7

यह एल्गोरिथ्म ठीक होना चाहिए:

createGridInPolygon(polygon, resolution) {
    for(x=polygon.xmin; x<polygon.xmax; x+=resolution) {
       for(y=polygon.ymin; y<polygon.ymax; y+=resolution) {
          if(polygon.contains(x,y)) createPoint(x,y);
       }
    }
}

जहाँ 'बहुभुज' बहुभुज है और 'रिज़ॉल्यूशन' आवश्यक ग्रिड रिज़ॉल्यूशन है।

PostGIS में इसे लागू करने के लिए, निम्नलिखित कार्यों की आवश्यकता हो सकती है:

  • बहुभुज का न्यूनतम और अधिकतम निर्देशांक प्राप्त करने के लिए ST_XMin , ST_XMax , ST_YMin और ST_YMax
  • बहुभुज में बिंदु होने पर परीक्षण करने के लिए ST_Contains ,
  • और एक बिंदु बनाने के लिए ST_Point

सौभाग्य!


1
ध्यान दें कि यदि आपके पास बड़े जटिल बहुभुज क्षेत्र हैं (जैसे कि मुझे तटरेखा बफर है), तो यह दृष्टिकोण काफी इष्टतम नहीं है।
जाकल

फिर, आप इसके बजाय क्या प्रस्ताव करते हैं?
जूलियन

4

विभिन्न तरीकों का उपयोग करते हुए तीन एल्गोरिदम।

जीथब रेपो लिंक

  1. X और y दिशा से निर्देशांक की वास्तविक पृथ्वी दूरी का उपयोग करते हुए सरल और सर्वोत्तम दृष्टिकोण। एल्गोरिथ्म किसी भी SRID के साथ काम करता है, आंतरिक रूप से यह WGS 1984 (EPSG: 4326) के साथ काम करता है और परिणाम वापस इनपुट SRID में बदल जाता है।

समारोह ================================================================ ==================

CREATE OR REPLACE FUNCTION public.I_Grid_Point_Distance(geom public.geometry, x_side decimal, y_side decimal)
RETURNS public.geometry AS $BODY$
DECLARE
x_min decimal;
x_max decimal;
y_max decimal;
x decimal;
y decimal;
returnGeom public.geometry[];
i integer := -1;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
    geom := ST_SetSRID(geom, srid);
        ----RAISE NOTICE 'No SRID Found.';
    ELSE
        ----RAISE NOTICE 'SRID Found.';
END CASE;
    input_srid:=st_srid(geom);
    geom := st_transform(geom, srid);
    x_min := ST_XMin(geom);
    x_max := ST_XMax(geom);
    y_max := ST_YMax(geom);
    y := ST_YMin(geom);
    x := x_min;
    i := i + 1;
    returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
<<yloop>>
LOOP
IF (y > y_max) THEN
    EXIT;
END IF;

CASE i WHEN 0 THEN 
    y := ST_Y(returnGeom[0]);
ELSE 
    y := ST_Y(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), y_side, radians(0))::geometry);
END CASE;

x := x_min;
<<xloop>>
LOOP
  IF (x > x_max) THEN
      EXIT;
  END IF;
    i := i + 1;
    returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
    x := ST_X(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), x_side, radians(90))::geometry);
END LOOP xloop;
END LOOP yloop;
RETURN
ST_CollectionExtract(st_transform(ST_Intersection(st_collect(returnGeom), geom), input_srid), 1);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;

एक साधारण क्वेरी के साथ फ़ंक्शन का उपयोग करें, ज्यामिति वैध और बहुभुज, बहु-बहुभुज या लिफाफा प्रकार होना चाहिए

SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;

परिणाम ================================================= =====================

यहां छवि विवरण दर्ज करें

  1. निकल्स एवन एल्गोरिथ्म पर आधारित दूसरा समारोह । मैंने इसे किसी भी SRID को संभालने के लिए बढ़ाया।

    एल्गोरिथ्म में निम्नलिखित परिवर्तनों को अपग्रेड किया है।

    1. पिक्सेल आकार के लिए x और y दिशा के लिए अलग चर,
    2. गोलाकार या दीर्घवृत्त में दूरी की गणना करने के लिए नया चर।
    3. किसी भी SRID को इनपुट करें, फ़ंक्शन को गोलाकार या एलीपोसिड डेटम के काम के माहौल में परिवर्तित करें, फिर प्रत्येक पक्ष पर दूरी लागू करें, परिणाम प्राप्त करें और इनपुट SRID में परिवर्तित करें।

समारोह ================================================================ ==================

CREATE OR REPLACE FUNCTION I_Grid_Point(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$ 
DECLARE
x_max decimal; 
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer; 
BEGIN
CASE st_srid(geom) WHEN 0 THEN
  geom := ST_SetSRID(geom, srid);
  RAISE NOTICE 'SRID Not Found.';
    ELSE
        RAISE NOTICE 'SRID Found.';
    END CASE;

    CASE spheroid WHEN false THEN
        RAISE NOTICE 'Spheroid False';
        srid := 4326;
        x_side := x_side / 100000;
        y_side := y_side / 100000;
    else
        srid := 900913;
        RAISE NOTICE 'Spheroid True';
    END CASE;
    input_srid:=st_srid(geom);
    geom := st_transform(geom, srid);
    x_max := ST_XMax(geom);
    y_max := ST_YMax(geom);
    x_min := ST_XMin(geom);
    y_min := ST_YMin(geom);
RETURN QUERY
WITH res as (SELECT ST_SetSRID(ST_MakePoint(x, y), srid) point FROM
generate_series(x_min, x_max, x_side) as x,
generate_series(y_min, y_max, y_side) as y
WHERE st_intersects(geom, ST_SetSRID(ST_MakePoint(x, y), srid))
) select ST_TRANSFORM(ST_COLLECT(point), input_srid) from res;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;

एक साधारण क्वेरी के साथ इसका उपयोग करें।

SELECT I_Grid_Point(geom, 22, 15, false) from polygons;

परिणाम ================================================= ==================यहां छवि विवरण दर्ज करें

  1. श्रृंखला जनरेटर पर आधारित कार्य।

समारोह ================================================= =================

CREATE OR REPLACE FUNCTION I_Grid_Point_Series(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
x_series DECIMAL;
y_series DECIMAL;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
  geom := ST_SetSRID(geom, srid);
  RAISE NOTICE 'SRID Not Found.';
    ELSE
        RAISE NOTICE 'SRID Found.';
    END CASE;

    CASE spheroid WHEN false THEN
        RAISE NOTICE 'Spheroid False';
    else
        srid := 900913;
        RAISE NOTICE 'Spheroid True';
    END CASE;
    input_srid:=st_srid(geom);
    geom := st_transform(geom, srid);
    x_max := ST_XMax(geom);
    y_max := ST_YMax(geom);
    x_min := ST_XMin(geom);
    y_min := ST_YMin(geom);

    x_series := CEIL ( @( x_max - x_min ) / x_side);
    y_series := CEIL ( @( y_max - y_min ) / y_side );
RETURN QUERY
SELECT st_collect(st_setsrid(ST_MakePoint(x * x_side + x_min, y*y_side + y_min), srid)) FROM
generate_series(0, x_series) as x,
generate_series(0, y_series) as y
WHERE st_intersects(st_setsrid(ST_MakePoint(x*x_side + x_min, y*y_side + y_min), srid), geom);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;

एक साधारण क्वेरी के साथ इसका उपयोग करें।

SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons; परिणाम ================================================= =========================

यहां छवि विवरण दर्ज करें


3

तो मेरा निश्चित संस्करण:

CREATE OR REPLACE FUNCTION makegrid(geometry, integer, integer)
RETURNS geometry AS
'SELECT ST_Collect(st_setsrid(ST_POINT(x,y),$3)) FROM 
  generate_series(floor(st_xmin($1))::int, ceiling(st_xmax($1))::int,$2) as x
  ,generate_series(floor(st_ymin($1))::int, ceiling(st_ymax($1))::int,$2) as y 
where st_intersects($1,st_setsrid(ST_POINT(x,y),$3))'
LANGUAGE sql

उपयोग:

SELECT (ST_Dump(makegrid(the_geom, 1000, 3857))).geom as the_geom from my_polygon_table

1
नमस्ते, मुझे मेकग्रिड फ़ंक्शन के साथ खाली परिणाम मिलता है। शेपफाइल को shp2pgsql का उपयोग करके PostGIS में आयात किया गया था। पता नहीं क्या परेशानी पैदा कर सकता है, srs wgs84 पर सेट है।
मिशाल ज़िम्मरमैन

3

यहाँ एक और दृष्टिकोण है जो निश्चित रूप से तेज़ और समझने में आसान है।

1000 मीटर ग्रिड द्वारा 1000 मीटर के लिए उदाहरण के लिए:

SELECT (ST_PixelAsCentroids(ST_AsRaster(the_geom,1000.0,1000.0))).geom 
FROM the_polygon

इसके अलावा मूल SRID संरक्षित है।

यह स्निपेट बहुभुज की ज्यामिति को एक खाली रेखापुंज में परिवर्तित करता है, फिर प्रत्येक पिक्सेल को एक बिंदु में परिवर्तित करता है। लाभ: यदि मूल बहुभुज अंक को काटता है तो हमें फिर से जांच करने की आवश्यकता नहीं है।

वैकल्पिक:

आप पैरामीटर ग्रिड और ग्रिड के साथ ग्रिड संरेखण को भी जोड़ सकते हैं। लेकिन चूंकि हम प्रत्येक पिक्सेल (और एक कोने नहीं) के केंद्रक का उपयोग करते हैं, हमें सही मूल्य की गणना करने के लिए एक मोडुलो का उपयोग करने की आवश्यकता होती है:

SELECT (ST_PixelAsCentroids(ST_AsRaster(the_geom,1000.0,1000.0,mod(1000/2,100),mod(1000/2,100)))).geom 
FROM the_polygon

साथ में mod(grid_size::integer/2,grid_precision)

यहाँ पोस्टग्रेज फंक्शन है:

CREATE OR REPLACE FUNCTION st_makegrid(geometry, float, integer)
RETURNS SETOF geometry AS
'SELECT (ST_PixelAsCentroids(ST_AsRaster($1,$2::float,$2::float,mod($2::int/2,$3),mod($2::int/2,$3)))).geom'
LANGUAGE sql;

कैनबे के साथ प्रयोग किया जाता है:

SELECT makegrid(the_geom,1000.0,100) as geom from the_polygon  
-- makegrid(the_geom,grid_size,alignement)

1

पिछले उत्तरों के लिए एक छोटा संभावित अपडेट - wgs84 के लिए पैमाने के रूप में तीसरा तर्क (या सामान्य लोगों के लिए 1 का उपयोग करें), और कोड के अंदर भी गोलाई ताकि कई आकृतियों पर स्केल किए गए बिंदु गठबंधन किए गए हों।

आशा है कि यह मदद करता है, मार्टिन

CREATE OR REPLACE FUNCTION makegrid(geometry, integer, integer)
RETURNS geometry AS



/*geometry column , integer: distance between points, integer: scale factor for distance (useful for wgs84, e.g. use there 50000 as distance and 1000000 as scale factor*/

'
SELECT ST_Collect(st_setsrid(ST_POINT(x/$3::float,y/$3::float),st_srid($1))) FROM 
  generate_series(
                (round(floor(st_xmin($1)*$3)::int/$2)*$2)::int, 
                (round(ceiling(st_xmax($1)*$3)::int/$2)*$2)::int,
                $2) as x ,
  generate_series(
                (round(floor(st_ymin($1)*$3)::int/$2)*$2)::int, 
                (round(ceiling(st_ymax($1)*$3)::int/$2)*$2)::int,
                $2) as y 
WHERE st_intersects($1,ST_SetSRID(ST_POINT(x/$3::float,y/$3::float),ST_SRID($1)))
'

LANGUAGE sql

ज्यामिति को एक विशिष्ट SRID में बदलना नहीं होगा (जैसे EPSG: 3857) केवल एक स्केल फैक्टर से गुणा करने से बेहतर होगा?
निकोलस क्रिस्मर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.