PostGIS এ একটি নন-নোড ছেদ করা সমস্যাটি কীভাবে সেরা করা যায়?


38

আমি একটি PL/Rফাংশন ব্যবহার করছি এবং PostGISপয়েন্টের একটি সেট প্রায় ভোরোনাই বহুভুজ উত্পাদন করতে। আমি যে ফাংশনটি ব্যবহার করছি তা এখানে সংজ্ঞায়িত করা হয়েছে । আমি যখন কোনও নির্দিষ্ট ডেটাসেটে এই ফাংশনটি ব্যবহার করি তখন আমি নিম্নলিখিত ত্রুটি বার্তাটি পাই:

Error : ERROR:  R interpreter expression evaluation error
DETAIL:  Error in pg.spi.exec(sprintf("SELECT %3$s AS id,   
st_intersection('SRID='||st_srid(%2$s)||';%4$s'::text,'%5$s') 
AS polygon FROM %1$s WHERE st_intersects(%2$s::text,'SRID='||st_srid(%2$s)||';%4$s');",  
:error in SQL statement : Error performing intersection: TopologyException: found non-noded 
intersection between LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465 
264611, 594406 286813) at 568465.05533706467 264610.82749605528
CONTEXT:  In R support function pg.spi.exec In PL/R function r_voronoi

ত্রুটি বার্তার এই অংশটি পরীক্ষা করা থেকে:

Error performing intersection: TopologyException: found non-noded intersection between
LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465 264611, 594406 286813) 
at 568465.05533706467 264610.82749605528

উপরের তালিকাভুক্ত সমস্যাটি দেখতে এই জাতীয়:

এখানে চিত্র বর্ণনা লিখুন

আমি প্রথমে ভেবেছিলাম যে এই বার্তাটি অভিন্ন পয়েন্টগুলির অস্তিত্বের কারণে ঘটতে পারে st_translate()এবং নিম্নলিখিত পদ্ধতিতে ব্যবহৃত ফাংশনটি ব্যবহার করে এটি সমাধান করার চেষ্টা করেছি :

ST_Translate(geom, random()*20, random()*20) as geom 

এটি সমস্যার সমাধান করে তবে আমার উদ্বেগটি হ'ল আমি এখন সমস্ত পয়েন্টগুলি এক্স / ওয়াইয়ের দিক থেকে 20 মিলিয়ন ডলার পর্যন্ত অনুবাদ করছি। একটি উপযুক্ত অনুবাদ পরিমাণ কী প্রয়োজন তা আমিও বলতে পারি না। উদাহরণস্বরূপ, এই ডেটাসেটে ট্রায়াল এবং ত্রুটির মাধ্যমে একটি 20m * random numberঠিক আছে, তবে এটি আরও বড় হওয়া দরকার কিনা আমি কীভাবে বলতে পারি?

উপরের চিত্রটির উপর ভিত্তি করে আমি মনে করি সমস্যাটি হ'ল বিন্দুটি রেখার সাথে ছেদ করছে যখন অ্যালগরিদমটি একটি বহুভুজ দিয়ে বিন্দুকে ছেদ করার চেষ্টা করছে। আমি নিশ্চিত নই যে বিন্দুটি একটি রেখার সাথে ছেদ করার পরিবর্তে বহুভুজের মধ্যে রয়েছে তা নিশ্চিত করার জন্য আমার কী করা উচিত। এই লাইনে ত্রুটি ঘটছে:

"SELECT 
  %3$s AS id, 
  st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'') AS polygon 
FROM 
  %1$s 
WHERE 
  st_intersects(%2$s::text,''SRID=''||st_srid(%2$s)||'';%4$s'');"

আমি এই পূর্ববর্তী প্রশ্নের মাধ্যমে পড়েছি, "ননডোড মোড়" কী? এই সমস্যাটি আরও ভালভাবে বোঝার চেষ্টা করার জন্য, এবং এটি সমাধান করার জন্য কীভাবে সেরা কোনও পরামর্শের প্রশংসা করব।


আপনার ইনপুটগুলি শুরু করার জন্য বৈধ না হলে সেগুলিতে ST_MakeValid () চালান। যদি সেগুলি বৈধ হয় তবে এনট্রপি যুক্ত করা যেমনটি আপনি করছেন, এটিই পরবর্তী কৌশলটি উপলভ্য এবং সম্ভবত আপাতত শেষ কৌশল।
পল রামসে

হ্যাঁ, আমি WHERE ST_IsValid(p.geom)প্রাথমিকভাবে পয়েন্টগুলি ফিল্টার করতে ব্যবহার করছি ।
djq

উত্তর:


30

আমার অভিজ্ঞতায় প্রায়শই এই সমস্যাটি ঘটে:

  1. আপনার স্থানাঙ্কগুলিতে উচ্চ স্পষ্টতা (43.231499999999996), এর সাথে মিলিত
  2. লাইনগুলি প্রায় কাকতালীয় তবে অভিন্ন নয়

ST_Bufferসমাধানগুলির "নজ" পদ্ধতির সাহায্যে আপনাকে # 2 দিয়ে দূরে সরে যেতে দেওয়া হয়, তবে এই অন্তর্নিহিত কারণগুলি সমাধান করতে আপনি যা কিছু করতে পারেন, আপনার জ্যামিতিটি 1-6 গ্রিডে ছড়িয়ে দেওয়ার মতো করে আপনার জীবনকে সহজ করে তুলবে। বাফার জ্যামিতিগুলি ওভারল্যাপের মতো মধ্যবর্তী গণনাগুলির জন্য সাধারণত সূক্ষ্ম হয় তবে আপনি সেগুলি ধরে রাখার বিষয়ে যত্নবান হতে চাইবেন কারণ তারা আপনার ঘনিষ্ঠ-তবে-না-যথেষ্ট সমস্যা দীর্ঘতর পাল্লায় ফেলে দিতে পারে।

পোস্টগ্র্যাস এসকিউএল এর ব্যতিক্রম হ্যান্ডলিং ক্ষমতা আপনাকে এই বিশেষ ক্ষেত্রে পরিচালনা করতে মোড়ক ফাংশন লিখতে দেয়, যখন প্রয়োজন হয় কেবল বাফারিং করে। এখানে উদাহরণস্বরূপ ST_Intersection; আমি একই ধরণের ফাংশন ব্যবহার করি ST_Difference। আপনার পরিস্থিতিতে খালি বহুভুজটির বাফারিং এবং সম্ভাব্য প্রত্যাবর্তন গ্রহণযোগ্য কিনা তা আপনাকে সিদ্ধান্ত নিতে হবে।

CREATE OR REPLACE FUNCTION safe_isect(geom_a geometry, geom_b geometry)
RETURNS geometry AS
$$
BEGIN
    RETURN ST_Intersection(geom_a, geom_b);
    EXCEPTION
        WHEN OTHERS THEN
            BEGIN
                RETURN ST_Intersection(ST_Buffer(geom_a, 0.0000001), ST_Buffer(geom_b, 0.0000001));
                EXCEPTION
                    WHEN OTHERS THEN
                        RETURN ST_GeomFromText('POLYGON EMPTY');
    END;
END
$$
LANGUAGE 'plpgsql' STABLE STRICT;

এই পদ্ধতির সাথে আরেকটি সুবিধা হ'ল আপনি এমন জ্যামিতিগুলি চিহ্নিত করতে পারেন যা আসলে আপনার সমস্যার কারণ হতে পারে; কেবলমাত্র ব্লকে WKT আউটপুট বা অন্য কোনও কিছুতে RAISE NOTICEস্টেটমেন্ট যুক্ত করুন EXCEPTIONযা আপনাকে সমস্যার সমাধান করতে সহায়তা করবে।


এটি একটি চতুর ধারণা। আমি প্রায়শই খুঁজে পেয়েছি যে আন্তঃনগর সমস্যাগুলি ইউনিয়ন, পার্থক্য, বাফার ইত্যাদির সংমিশ্রনের সময় উপস্থিত লাইনস্ট্রিংগুলি থেকে আসে যা সমস্ত কিছু বাফার করে বা সমস্ত কিছু ডাম্পিং করে এবং কেবল পলিগনস / মিটলিপলিগনগুলি নির্বাচন করে স্থির করা যায়। এটি একটি আকর্ষণীয় পদ্ধতির।
জন পাওয়েল

আপনি জ্যামিতিটি 1e-6 গ্রিডে ছড়িয়ে দেওয়ার কথা উল্লেখ করেছেন, তবে আমি এখানে বসে ভাবছি যে 2 এর শক্তিতে ঝাঁপিয়ে পড়া আরও ভাল হবে কিনা। ভাসমান পয়েন্ট সংখ্যা ব্যবহার করে পোস্টজিআইএস (এবং জিইওএস), সুতরাং 10 এর শক্তিতে ঝোলানো সম্ভবত স্থানাঙ্কগুলি খুব বেশি ছাঁটাইতে পারে না কারণ সংখ্যার সীমাবদ্ধ দৈর্ঘ্যের বাইনারি উপস্থাপনা নাও থাকতে পারে। তবে আপনি যদি 2 ^ -16 বলতে যান তবে আমি বিশ্বাস করি যে কোনও ভগ্নাংশের অংশটি কেবল 2 বাইটে ছাঁটাই করার নিশ্চয়তা দেওয়া হবে। নাকি আমি ভুল ভাবছি?
jpmc26

12

প্রচুর পরীক্ষার এবং ত্রুটির মধ্য দিয়ে আমি অবশেষে বুঝতে পেরেছিলাম যে non-noded intersectionএকটি আত্ম-ছেদ সমস্যা থেকে এসেছিল। আমি একটি থ্রেড পেয়েছি যা ব্যবহার ST_buffer(geom, 0)করে সমস্যার সমাধানের জন্য ব্যবহার করা যেতে পারে (যদিও এটি সামগ্রিকভাবে এটি অনেক ধীর করে তোলে)। আমি তখন ব্যবহার করার চেষ্টা করেছি ST_MakeValid()এবং যখন অন্য কোনও ফাংশনের আগে সরাসরি জ্যামিতিতে প্রয়োগ করা হয়। এটি সমস্যাটিকে দৃust়রূপে সমাধান করবে বলে মনে হচ্ছে।

ipoint <- pg.spi.exec(
        sprintf(
            "SELECT 
                    %3$s AS id, 
                    st_intersection(ST_MakeValid(''SRID=''||st_srid(%2$s)||'';%4$s''::text), ST_MakeValid(''%5$s'', 0)) AS polygon 
            FROM %1$s 
            WHERE 
                ST_Intersects(ST_MakeValid(%2$s::text),ST_MakeValid(''SRID=''||st_srid(%2$s)||'';%4$s''));",
            arg1,
            arg2,
            arg3,
            curpoly,
            buffer_set$ewkb[1]
        )
    )

আমি এটিকে উত্তর হিসাবে চিহ্নিত করেছি কারণ মনে হচ্ছে এটিই একমাত্র পদ্ধতির যা আমার সমস্যার সমাধান করে।


11

আমি এই একই সমস্যায় পড়েছি (পোস্টগ্রিস 9.1.4, পোস্টজিআইএস 2.1.1), এবং আমার পক্ষে কাজ করা একমাত্র জিনিসটি খুব ছোট বাফার দিয়ে জ্যামিতিটি মোড়ানো ছিল rap

SELECT ST_Intersection(
    (SELECT geom FROM table1), ST_Union(ST_Buffer(geom, 0.0000001))
) FROM table2

ST_MakeValidআমার জন্য কাজ করে না, কিংবা সমন্বয় করেনি ST_Nodeএবং ST_Dump। বাফারের পারফরম্যান্সে কোনও ক্ষয় হওয়ার ফলস্বরূপ মনে হয়নি, তবে আমি যদি এটি আরও ছোট করে তুলি তবে আমি এখনও একটি ননডেড ছেদযুক্ত ত্রুটি পেয়েছি।

কুরুচিপূর্ণ, কিন্তু এটি কার্যকর।

হালনাগাদ:

এস 07 বাফার কৌশলটি ভালভাবে কাজ করছে বলে মনে হচ্ছে, তবে আমি এমন একটি সমস্যায় পড়েছিলাম যেখানে ভূগোলের জ্যামিতিটি কাস্ট করার সময় এটি ত্রুটি সৃষ্টি করেছিল। উদাহরণস্বরূপ, যদি কোনও বিন্দুটি মূলত -90.0 এ থাকে এবং এটি 0.0000001 দ্বারা বাফার হয় তবে এটি এখন -90.0000001 এ রয়েছে যা একটি অবৈধ ভূগোল।

এর অর্থ যে যদিও ST_IsValid(geom)ছিল t, ST_Area(geom::geography)ফিরে NaNঅনেক বৈশিষ্ট্য জন্য।

ননডেড ছেদকৃত সমস্যাটি এড়াতে বৈধ ভূগোল বজায় রাখার সময় আমি এ জাতীয় ব্যবহার করে শেষ ST_SnapToGridকরেছি

SELECT ST_Union(ST_MakeValid(ST_SnapToGrid(geom, 0.0001))) AS geom, common_id
    FROM table
    GROUP BY common_id;

6

পোস্টগিজে এস T_ নোডের চৌরাস্তাগুলিতে একটি ধারাবাহিক রেখা ভেঙে দেওয়া উচিত, যা নন-নোডেড ছেদটি সমস্যার সমাধান করবে। এস এসডাম্প এ এটি মোড়ানো ভাঙ্গা লাইনগুলির সম্মিলিত অ্যারে উত্পন্ন করে।

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


এটি একটি দুর্দান্ত উপস্থাপনা (ধন্যবাদ @ পলর্যামসে)। আমি কিভাবে ব্যবহার করা উচিত ST_Nodeএবং ST_Dump? আমি ধারণা করি ফাংশনের এই অংশটির কাছে আমার তাদের ব্যবহার করা উচিত, তবে নিশ্চিত নয়: st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'')ইন
ডিজেকিউ

হুমম আমি লক্ষ্য করিনি যে দুটি লাইনের একটি অভিন্ন সমন্বয় ছিল, যা ঠিক হওয়া উচিত। যদি আপনি সেগুলি স্থানাঙ্কের চৌবাচ্চাটি ছেদ করেন তবে মোড় থেকে প্রায় 18 সেন্টিমিটার দূরে। আসলেই সমাধান নয়, কেবল একটি পর্যবেক্ষণ।
ওল্ফড্রেড

আমি st_nodeএখানে কীভাবে ব্যবহার করব সে সম্পর্কে সম্পূর্ণ পরিষ্কার নয় - আমি কি এটি আগে ব্যবহার করতে পারি st_intersection?
djq

1
উপস্থাপনা আর উপলব্ধ নেই। আমি একই সমস্যার সাথে আটকে আছি, এস এস-ক্লিপ করার চেষ্টা করার সময় (রাস্ট, বহুভুজ)
জ্যাকি

1
@ জ্যাকি: আমি উত্তরটিতে উপস্থাপনাটির লিঙ্কটি ঠিক করেছি: পোস্টজিআইএস: বিদ্যুৎ ব্যবহারকারীর জন্য টিপস
পিট

1

আমার অভিজ্ঞতায়, আমি St_SnapToGrid ফাংশনটি non-noded intersectionব্যবহার করে আমার ত্রুটিটি সমাধান করেছি যা বহুভুজগুলির ভার্টেক্সের স্থানাঙ্কগুলিতে উচ্চ নির্ভুলতার সমস্যাটি সমাধান করেছে।

SELECT dissolve.machine, dissolve.geom FROM (
        SELECT machine, (ST_Dump(ST_Union(ST_MakeValid(ST_SnapToGrid(geom,0.000001))))).geom 
        FROM cutover_automatique
        GROUP BY machine) as dissolve
WHERE ST_isvalid(dissolve.geom)='t' AND ST_GeometryType(dissolve.geom) = 'ST_Polygon';
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.