পোস্টগিসে একটি বহুভুজের অভ্যন্তরে নিয়মিত পয়েন্ট গ্রিড কীভাবে তৈরি করবেন?


31

বহুভুজের অভ্যন্তরে কীভাবে পোস্টগিসে পয়েন্ট স্পেস x, y এর নিয়মিত গ্রিড তৈরি করবেন? উদাহরণটি পছন্দ করুন:

বিকল্প পাঠ


আমি এই কোডটিকে "পোস্টজিআইএস ইন অ্যাকশন" ডাইটিং কোডের সাথে মার্পিং বহুভুজগুলি ক্লিপিং করার চেষ্টা করেছি তবে কেবল একটি বহুভুজ তৈরি হয়েছে ... আমি কি কিছু ভুলে গেছি? ফাংশন মেকগ্রিড তৈরি বা পুনঃস্থাপন (জ্যামিতি, পূর্ণসংখ্যা, পূর্ণসংখ্যার) জ্যামিতি প্রত্যাবর্তন করুন 'নির্বাচন করুন স্টিল-ইনটারেকশন (g1.geom1, g2.geom2) হিসাবে জিওআম থেকে জিওআর 1 (নির্বাচন করুন 1 জেনো 1) জিন 1 আন্তঃ যোগদান করুন (স্টেটস্রেডস সিড (সিএস 2 (সিএসএক্স_কেন্দ্র) নির্বাচন করুন) ST_Point (x, y), $ 3), st_setsrid (ST_Point (x + $ 2, y + $ 2), omet 3)) জ্যামিতি হিসাবে), $ 3) জিরোম 2 FROM জেনারেট_সরিজ হিসাবে (মেঝে (st_xmin ($ 1)) :: অবধি, সিলিং ( st_xmax ($ 1)) :: int, $ 2) x হিসাবে, জেনারেট_সেসরিজ (মেঝে (st_ymin ($ 1)) :: :: int, সিলিং (st_ymax (
অরেল_সিএন

আমার বিস্তারিত উত্তর দেখুন।
মুহাম্মদ ইমরান সিদ্দিক

উত্তর:


30

আপনি জেনারেট_সরিজ দিয়ে এটি করেন।

আপনি যদি গ্রিডটি শুরু করতে এবং থামাতে যেখানে ম্যানুয়ালি লিখতে চান না, তবে একটি ফাংশন তৈরি করা সবচেয়ে সহজ।

আমি নীচে সঠিকভাবে পরীক্ষা করিনি, তবে আমার মনে হয় এটি কার্যকর করা উচিত:

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;

যেখানে প্রথম যুক্তি হ'ল বহুভুজ আপনি গ্রিডটি চান এবং দ্বিতীয় যুক্তিটি গ্রিডের পয়েন্টগুলির মধ্যে দূরত্ব।

আপনি যদি প্রতি সারিতে একটি পয়েন্ট চান তবে আপনি কেবল এসT_ডাম্প ব্যবহার করুন:

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

আছে HTH

Nicklas


2
আপনাকে st_setSRID () যুক্ত করতে হবে_ 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;

আশা করি এটি কারও জন্য উপকারী হবে।

অ্যালেক্স


গৃহীত উত্তরটি এসআরআইডি ত্রুটির কারণে আমার ডেটা নিয়ে কাজ করে না। এই পরিবর্তনটি আরও ভাল কাজ করে।
ভিটালি ইসাইভ

বহুভুজ এন্টিমিডারডিয়ান অতিক্রম করার সময় আপনি কিছু যুক্ত করতে চান? আমি ভাবতে পারি এটি xmin / xmax এর সাথে সমস্যার সৃষ্টি করবে।
টমাস

2
এটি আমার পক্ষে কাজ করে নি। পোস্টগ্রিস 9.6 এবং পোস্টজিআইএস 2.3.3 ব্যবহার করে। জেনারেট_সরিজ কলের অভ্যন্তরে, আমি এটি দ্বিতীয় প্যারামিটার হিসাবে "সিলিং (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 পয়েন্ট সংগ্রহ করতে সক্ষম করবে যা বেশিরভাগ সময় এমনকি জ্যামিতি নিজেই ছেদ করে না ... => খালি ফলাফল!

আমার সমস্যাটি হ'ল আমি জেনারেট_সরিজগুলি () ভাসমান সংখ্যায় যেমন ডাব্লুএসজি 84 এর দশমিক দূরত্বে ব্যবহার করতে পারি না বলে মনে হয় ... এই কারণেই এটি ফাংশনটি যেভাবেই হোক কাজ করতে আমি টুইট করেছিলাম:

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 দিয়ে গুণ এবং ভাগ করে নেওয়া।

এটি অর্জনের জন্য অবশ্যই আরও ভাল সমাধান রয়েছে। ++,


এটি একটি স্মার্ট workaround। আপনি ফলাফল চেক করেছেন? তারা কি সামঞ্জস্যপূর্ণ?
পাবলো

হাই। হ্যাঁ পাবলো। আমি এখন পর্যন্ত ফলাফল নিয়ে খুশি। মাটির উপরে আপেক্ষিক উচ্চতার সাথে কিছু বহুভুজ তৈরি করা আমার দরকার ছিল needed (আমি প্রতিটি গ্রিড পয়েন্টের জন্য যে উচ্চতা চাই তা গণনা করতে আমি এসআরটিএম ব্যবহার করি)। বহুভুজের ঘেরেও যে পয়েন্ট রয়েছে সেগুলি অন্তর্ভুক্ত করার জন্য আমি এখন কেবল একটি উপায় মিস করছি। বর্তমানে রেন্ডার আকারটি প্রান্তে কিছুটা কাটা হয়েছে।
জুলিয়েন গার্সিয়া

কাজ করেছে, যখন অন্য সকলের সমাধান ব্যর্থ হয়, ধন্যবাদ!
জর্দান আর্সেনো

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

যেখানে 'বহুভুজ' বহুভুজ এবং 'রেজোলিউশন' প্রয়োজনীয় গ্রিড রেজোলিউশন।

পোস্টজিআইএসে এটি বাস্তবায়নের জন্য, নিম্নলিখিত ফাংশনগুলির প্রয়োজন হতে পারে:

শুভকামনা!


1
মনে রাখবেন যে আপনার যদি বৃহত জটিল বহুভুজ অঞ্চল (যেমন আমার উপকূলরেখা বাফার আছে) থাকে তবে এই পদ্ধতির কোনওটি অনুকূল নয়।
জাকএল

তারপরে, আপনি এর পরিবর্তে কী প্রস্তাব করবেন?
জুলিয়েন

4

বিভিন্ন পদ্ধতি ব্যবহার করে তিনটি অ্যালগরিদম।

গিথুব রেপো লিঙ্ক

  1. এক্স এবং ওয়াইয়ের দিক থেকে স্থানাঙ্কগুলির প্রকৃত পৃথিবীর দূরত্ব ব্যবহার করে সহজ এবং সর্বোত্তম পন্থা। অ্যালগোরিদম যে কোনও এসআরআইডি দিয়ে কাজ করে, অভ্যন্তরীণভাবে এটি ডাব্লুজিএস 1984 (ইপিএসজি: 4326) এর সাথে কাজ করে এবং ফলাফল এসআরআইডি-এ ফিরে রূপান্তরিত করে।

ফাংশন ================================================== ==================

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. নিক্লাস আভান অ্যালগরিদমের উপর ভিত্তি করে দ্বিতীয় ফাংশন । যে কোনও এসআরআইডি হ্যান্ডেল করার জন্য আমি এটি বাড়িয়েছি।

    অ্যালগরিদমে নিম্নলিখিত পরিবর্তনগুলি আপগ্রেড করেছেন।

    1. পিক্সেল আকারের জন্য x এবং y দিকের জন্য পৃথক ভেরিয়েবল,
    2. গোলক বা উপবৃত্তাকার দূরত্ব গণনা করতে নতুন পরিবর্তনশীল।
    3. যে কোনও এসআরআইডি ইনপুট করুন, ফাংশনটি জিওমকে স্পেরয়েড বা এলিপসয়েড ডেটামের কর্ম পরিবেশে রূপান্তর করুন, তারপরে প্রতিটি দিকে দূরত্ব প্রয়োগ করুন, ফলাফল পাবেন এবং এসআরআইডি ইনপুটটিতে রূপান্তর করুন।

ফাংশন ================================================== ==================

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 ব্যবহার করে আকৃতিটি পোস্টজিআইএসে আমদানি করা হয়েছিল। কী কারণে সমস্যা সৃষ্টি হতে পারে সে সম্পর্কে কোনও ধারণা নেই, srs wgs84 তে সেট করা আছে।
মিশাল জিম্মারম্যান

3

এখানে আরও একটি পদ্ধতি যা বোঝার জন্য দ্রুত এবং সহজ is

উদাহরণস্বরূপ 1000 মি বাই 1000 মি গ্রিডের জন্য:

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

এছাড়াও মূল এসআরআইডি সংরক্ষণ করা হয়।

এই স্নিপেট বহুভুজের জ্যামিতিকে একটি খালি রাস্টার রূপান্তর করে, তারপরে প্রতিটি পিক্সেলকে একটি বিন্দুতে রূপান্তর করে। সুবিধা: মূল বহুভুজনটি পয়েন্টগুলি ছেদ করে কিনা তা আমাদের আবার পরীক্ষা করতে হবে না।

ঐচ্ছিক:

আপনি প্যারামিটার গ্রিডেক্স এবং গ্রিডির সাহায্যে গ্রিড অ্যালিজেনমেন্ট যুক্ত করতে পারেন। তবে যেহেতু আমরা প্রতিটি পিক্সেলের সেন্ট্রয়েড ব্যবহার করি (এবং কোনও কোণ নয়) সঠিক মান গণনা করার জন্য আমাদের একটি মডুলো ব্যবহার করতে হবে:

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

জ্যামিতিকে কোনও নির্দিষ্ট এসআরআইডি (EPSG: 3857 এর মত) রূপান্তর করা কি স্কেল ফ্যাক্টরের দ্বারা গুণনের চেয়ে ভাল হবে না?
নিকোলাস ক্রিশমার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.