পোস্টজিআইএস-এ নির্দিষ্ট দূরত্বে পয়েন্টগুলির মধ্যে রেখা আঁকুন?


9

রাস্তার পাশে আমার কাছে পয়েন্টগুলির একটি ডেটা রয়েছে, আমি সেই বিন্দুগুলিকে সাধারণ রঙিন লাইনে পরিণত করতে চাই। কোনও সমস্যা নির্দেশক যা এই সমস্যাটি বলা হতে পারে বা কোনও অ্যালগরিদম যা আমাকে এটি সমাধান করতে সহায়তা করতে পারে? রাস্তার পাশের পয়েন্টগুলি আমি লাইনে পরিণত করতে চাই।

আমি এটি করার জন্য PostGISফাংশনগুলি ব্যবহার করার আশা করছিলাম তবে আমি পরামর্শগুলির জন্য উন্মুক্ত, এটি কোনও .shpফাইলের একটি ডেটা ।

সম্পাদনা 1: এই সমস্যার আদর্শ সমাধান প্রদর্শনের জন্য ছবি আপডেট করেছে।

লাইন অঙ্কন করা নির্ভুলভাবে এই পয়েন্টগুলির মধ্যে দূরত্বের ভিত্তিতে হবে, আমি এগুলিকে গ্রুপ করার জন্য আর কিছুই করতে পারি না। আদর্শভাবে এটি প্রজেক্ট লাইন বরাবর সর্বাধিক নির্দিষ্ট দূরত্বে পয়েন্ট হতে পারে? এবং অভিক্ষিপ্ত রেখার দ্বারা আমার অর্থ 1 ম পয়েন্টটি খুঁজে তারপরের নিকটবর্তী পরবর্তীটি একটি লাইন প্রজেক্ট করুন এবং লাইনটিতে থাকা ইতিমধ্যে যে কোনওটির থেকে সর্বোচ্চ দূরত্বে এই লাইনের কোনও পয়েন্ট রয়েছে কিনা তা পরীক্ষা করুন।


1
আপনি কোন সফ্টওয়্যার ব্যবহার করার পরিকল্পনা করছেন?
আরমোরার

আপনি এগুলি ফুটপাতে পরিণত করার চেষ্টা করছেন?
ডিপিএসএসপিশিয়াল

আমি এটি করার জন্য পোস্টজিআইএস ফাংশন ব্যবহার করার আশা করছিলাম তবে আমি পরামর্শগুলির জন্য উন্মুক্ত, এটি একটি .shp ফাইলের একটি ডেটা।
মহাকাল

1
আপনি কোন অঙ্কনটি আপনার অঙ্কন বা অন্য কোনও অঙ্কনে সংযোগ করতে চান তা ঠিক দেখাতে পারেন? এটি কি একবারে মাত্র দুটি পয়েন্ট? নাকি তিনটি? যে পয়েন্টগুলির মধ্যে সর্বদা সংযুক্ত হওয়া উচিত তার মধ্যবর্তী দূরত্বটি কি এটি নির্দিষ্ট দোরের নীচে "ঠিক"?
পিটার হর্সবুল মোলার

1
@ ডাবস্টন এবং মারহফ উভয়ের জন্য অনেক ধন্যবাদ, আমার এপ্রিলের শেষ অবধি আপনার ধারণাগুলি পরীক্ষা করার সময় হবে না, আমি আশা করি যে আমি এর মধ্যে অনুগ্রহ বিভক্ত করতে পারব তবে আপনার 1 জনকে আমি এটি প্রদান করতে হবে এবং ডাবস্টন আমাকে কিছু প্রশ্নও দিয়েছেন যাতে আমাকে তদন্ত করতে হবে সুতরাং আমি তার প্রতিক্রিয়া গ্রহণ করব। উত্তর দেওয়ার জন্য সময় নিয়েছেন সবাই! গ্রেট সম্প্রদায় :-) এর অংশ হওয়ার জন্য
মহাকাল

উত্তর:


8

আপনি যে লাইনগুলি তৈরি করতে চান তার প্রতিটি সনাক্ত করা প্রান্ত থেকে শুরু করে প্রতিটি পয়েন্টের নিকটতম প্রতিবেশীর অন্বেষণ করতে আপনি পুনরাবৃত্ত ক্যোয়ারী ব্যবহার করতে পারেন ।

পূর্বশর্ত : আপনার পয়েন্ট সহ একটি পোস্টগিজ স্তর এবং অন্য একটিতে আপনার রাস্তাগুলি সহ একক মাল্টি-লাস্টারিং বস্তু প্রস্তুত করুন। দুটি স্তর অবশ্যই একই সিআরএসে থাকা উচিত। আমি তৈরি করা টেস্ট ডেটা-সেটটির কোড এখানে, দয়া করে এটি প্রয়োজনীয় হিসাবে সংশোধন করুন। (পোস্টগ্রিস ৯.২ এবং পোস্টগ্রিস ২.১ এ পরীক্ষিত)

WITH RECURSIVE
points as (SELECT id, st_transform((st_dump(wkb_geometry)).geom,2154) as geom, my_comment as com FROM mypoints),
roads as (SELECT st_transform(ST_union(wkb_geometry),2154) as geom from highway),

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

পদক্ষেপ এখানে :

  1. প্রতিটি পয়েন্টের জন্য প্রতিবেশী এবং তাদের দূরত্বের তালিকা তৈরি করুন যা এই তিনটি মাপদণ্ড পূরণ করে।

    • ব্যবহারকারীকে নির্ধারিত প্রান্তিকের চেয়ে দূরত্ব অবশ্যই অতিক্রম করতে হবে না (এটি বিচ্ছিন্ন বিন্দুর সাথে সংযোগ এড়াতে পারবে) এখানে চিত্র বর্ণনা লিখুন
      graph_full as (
      SELECT a.id, b.id as link_id, a.com, st_makeline(a.geom,b.geom) as geom, st_distance(a.geom,b.geom) as distance
      FROM points a
      LEFT JOIN points b ON a.id<>b.id
      WHERE st_distance(a.geom,b.geom) <= 15
      ),
    • সরাসরি পথ অবশ্যই কোনও রাস্তা অতিক্রম করবে না cross এখানে চিত্র বর্ণনা লিখুন
      graph as (
      SELECt graph_full.*
      FROM graph_full RIGHT JOIN
      roads ON st_intersects(graph_full.geom,roads.geom) = false
      ),
    • দূরত্বটি অবশ্যই নিকটবর্তী প্রতিবেশী থেকে দূরত্বের ব্যবহারকারীর সংজ্ঞায়িত অনুপাতের বেশি হওয়া উচিত নয় (এটি নির্ধারিত দূরত্বের তুলনায় অনিয়মিত ডিজিটালাইজেশনের সাথে আরও ভালভাবে সংযোজন করা উচিত) এই অংশটি বাস্তবায়নের পক্ষে আসলে খুব কঠিন ছিল, স্থির অনুসন্ধানের ব্যাসার্ধের সাথে সংযুক্ত

    এই টেবিলটিকে "গ্রাফ" বলি

  2. গ্রাফটিতে যোগদান করে এবং গ্রাফের ঠিক একটি প্রবেশ রয়েছে এমন পয়েন্ট রেখে লাইনের পয়েন্টের শেষটি নির্বাচন করুন Select এখানে চিত্র বর্ণনা লিখুন

    eol as (
    SELECT points.* FROM
    points  JOIN
    (SELECT id, count(*) FROM graph 
    GROUP BY id
    HAVING count(*)= 1) sel
    ON points.id = sel.id),

    আসুন এই টেবিলটিকে "ইওল" (লাইনের শেষ) বলি
    ? যে দুর্দান্ত গ্রাফ করার জন্য পুরষ্কার পাবে কিন্তু পরের ধাপে জিনিসগুলি হোল্ড-অন করবে crazy

  3. একটি পুনরাবৃত্তি ক্যোয়ারী সেট আপ করুন যা প্রতি ইওল থেকে প্রতিবেশী থেকে প্রতিবেশীদের কাছাকাছি চলে এখানে চিত্র বর্ণনা লিখুন

    • ইওল টেবিল ব্যবহার করে এবং পুনর্গঠন ক্যোয়ারি প্রারম্ভিক করুন গভীরতার জন্য একটি কাউন্টার, পথের জন্য একগ্রিগেটর এবং লাইনগুলি তৈরি করতে জ্যামিতি নির্মাণকারী
    • গ্রাফটি ব্যবহার করে নিকটতম প্রতিবেশী স্যুইচ করে এবং পথটি ব্যবহার করে আপনি কখনই পিছিয়ে যাবেন না তা পরীক্ষা করে পরবর্তী পুনরাবৃত্তিতে যান
    • পুনরাবৃত্তি সমাপ্ত হওয়ার পরে প্রতিটি প্রারম্ভিক পয়েন্টের জন্য কেবল দীর্ঘতম পথ রাখুন (যদি আপনার ডেটাসেটে প্রত্যাশিত লাইনের মধ্যে সম্ভাব্য ছেদ অন্তর্ভুক্ত থাকে তবে অংশটির আরও শর্ত প্রয়োজন হবে)
    recurse_eol (id, link_id, depth, path, start_id, geom) AS (--initialisation
    SELECT id, link_id, depth, path, start_id, geom FROM (
        SELECT eol.id, graph.link_id,1 as depth,
        ARRAY[eol.id, graph.link_id] as path,
        eol.id as start_id,
        graph.geom as geom,
        (row_number() OVER (PARTITION BY eol.id ORDER BY distance asc))=1 as test
        FROM eol JOIn graph ON eol.id = graph.id 
        ) foo
    WHERE test = true
    
    UNION ALL ---here start the recursive part
    
    SELECT id, link_id, depth, path, start_id, geom  FROM (
        SELECT graph.id, graph.link_id, r.depth+1 as depth,
        path || graph.link_id as path,
        r.start_id,
        ST_union(r.geom,graph.geom) as geom,
        (row_number() OVER (PARTITION BY r.id ORDER BY distance asc))=1 as test
        FROM recurse_eol r JOIN graph ON r.link_id = graph.id AND NOT graph.link_id = ANY(path)) foo
    WHERE test = true AND depth < 1000), --this last line is a safe guard to stop recurring after 1000 run adapt it as needed

    আসুন এই টেবিলটিকে "recurse_eol" বলি

  4. প্রতিটি শুরুর পয়েন্টের জন্য কেবল দীর্ঘতম লাইন রাখুন এবং প্রতিটি সঠিক সদৃশ পথ সরান উদাহরণস্বরূপ: 1,2,3,5 এবং 5,3,2,1 পথ দুটি পৃথক "লাইনের শেষ" দ্বারা আবিষ্কার করা একই লাইন

    result as (SELECT start_id, path, depth, geom FROM
    (SELECT *,
    row_number() OVER (PARTITION BY array(SELECT * FROM unnest(path) ORDER BY 1))=1 as test_duplicate,
    (max(depth) OVER (PARTITION BY start_id))=depth as test_depth
    FROM recurse_eol) foo
    WHERE  test_depth = true AND test_duplicate = true)
    
    SELECT * FROM result
  5. ম্যানুয়ালি অবশিষ্ট ত্রুটিগুলি পরীক্ষা করে (বিচ্ছিন্ন পয়েন্টগুলি, ওভারল্যাপিং লাইনগুলি, অদ্ভুত আকারের রাস্তায়)


প্রতিশ্রুতি অনুসারে আপডেট হয়েছে, আমি এখনও বুঝতে পারি না যে কখনও কখনও পুনরাবৃত্ত হওয়া ক্যোয়ারী একই লাইনের বিপরীত ইওল থেকে শুরু করার সময় কেন একই ফলাফল দেয় না যাতে কিছু সদৃশ এখনকার ফলাফলের স্তরে থাকতে পারে।

বিনা দ্বিধায় আমি সম্পূর্ণরূপে এই কোডটি আরও মন্তব্য প্রয়োজন যে পেতে। এখানে পূর্ণ জিজ্ঞাসা:

WITH RECURSIVE
points as (SELECT id, st_transform((st_dump(wkb_geometry)).geom,2154) as geom, my_comment as com FROM mypoints),
roads as (SELECT st_transform(ST_union(wkb_geometry),2154) as geom from highway),

graph_full as (
    SELECT a.id, b.id as link_id, a.com, st_makeline(a.geom,b.geom) as geom, st_distance(a.geom,b.geom) as distance
    FROM points a
    LEFT JOIN points b ON a.id<>b.id
    WHERE st_distance(a.geom,b.geom) <= 15
    ),

graph as (
    SELECt graph_full.*
    FROM graph_full RIGHT JOIN
    roads ON st_intersects(graph_full.geom,roads.geom) = false
    ),

eol as (
    SELECT points.* FROM
    points  JOIN
        (SELECT id, count(*) FROM graph 
        GROUP BY id
        HAVING count(*)= 1) sel
    ON points.id = sel.id),


recurse_eol (id, link_id, depth, path, start_id, geom) AS (
    SELECT id, link_id, depth, path, start_id, geom FROM (
        SELECT eol.id, graph.link_id,1 as depth,
        ARRAY[eol.id, graph.link_id] as path,
        eol.id as start_id,
        graph.geom as geom,
        (row_number() OVER (PARTITION BY eol.id ORDER BY distance asc))=1 as test
        FROM eol JOIn graph ON eol.id = graph.id 
        ) foo
    WHERE test = true

UNION ALL
    SELECT id, link_id, depth, path, start_id, geom  FROM (
        SELECT graph.id, graph.link_id, r.depth+1 as depth,
        path || graph.link_id as path,
        r.start_id,
        ST_union(r.geom,graph.geom) as geom,
        (row_number() OVER (PARTITION BY r.id ORDER BY distance asc))=1 as test
        FROM recurse_eol r JOIN graph ON r.link_id = graph.id AND NOT graph.link_id = ANY(path)) foo
    WHERE test = true AND depth < 1000),

result as (SELECT start_id, path, depth, geom FROM
    (SELECT *,
    row_number() OVER (PARTITION BY array(SELECT * FROM unnest(path) ORDER BY 1))=1 as test_duplicate,
    (max(depth) OVER (PARTITION BY start_id))=depth as test_depth
    FROM recurse_eol) foo
WHERE  test_depth = true AND test_duplicate = true)

SELECT * FROM result

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

একটি কার্যনির্বাহী স্ক্রিপ্ট পেয়েছেন, এখানে পূর্বরূপ দেখুন qgiscloud.com/MarHoff/test_qgiscloud_ ডি- সদৃশকরণের জন্য একটি ছোট সতর্কতা রয়ে গেছে ... আমার অনুমান নেই আরও অনুগ্রহ হবে না, আর চাপ দেওয়া হবে না, তাই আমি যখন মুক্তি পাব তখনই মুক্তি দেব। যদিও এই ধাঁধাটি মজাদার ছিল
মারহফ

আপনাকে ধন্যবাদ! মারহফ, আমি যদি এই অনুগ্রহকে বিভক্ত করতে পারতাম তবে আমি আপনাকে কোন পয়েন্ট দিয়ে কীভাবে পুরষ্কার দিতে পারি তা দেখতে পাচ্ছি না, তবে এটি এবং আপনার প্রমাণ অনুসন্ধান করার জন্য আপনাকে ধন্যবাদ thanks খাঁটি মনে হচ্ছে :)
মহাকাল

সম্পন্ন. ধাঁধার জন্য ধন্যবাদ, এবং রেটিংয়ের জন্য দুঃখিত। যদি অন্য উত্তর এটি আপনার জন্য করে থাকে তবে এটি পুরোপুরি ঠিক আছে এককালের সবচেয়ে সহজ সেরা ... আমার উত্তর সম্ভবত এটি কিছুটা ওভারচিন্স করে। যদিও সিটিই + রিকার্সিভ ক্যোয়ারী + উইন্ডোজ ফাংশন + একক ক্যোয়ারীতে পোস্টজিস ব্যবহারের দুর্দান্ত উদাহরণ;)
মারহফ

8

@ ফেলিক্সআইপি হিসাবে উল্লেখ করা হয়েছে যে, প্রথম পদক্ষেপটি প্রতিটি লাইন তৈরি করবে এমন পয়েন্টগুলি সন্ধান করা। আপনি সর্বাধিক বিচ্ছেদ দূরত্ব সহ ST_ClusterWithin কল করে এটি করতে পারেন :

SELECT
  row_number() OVER () AS cid, 
  (ST_Dump(geom)).geom 
FROM (
  SELECT unnest(st_clusterwithin(geom, 0.05)) AS geom 
  FROM inputs) sq

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

SELECT 
  ST_MakeLine(geom ORDER BY ST_Y(geom)) AS geom
FROM (
  SELECT row_number() OVER () AS cid, 
  (ST_Dump(geom)).geom FROM (
    SELECT unnest(st_clusterwithin(geom, 0.05)) AS geom 
    FROM inputs) sq) ssq 
GROUP BY cid

যাওয়ার উপায় তবে ওয়াই-মনোোটোন (বা এমনকি এক্স / ওয়াই-মোনোটোনগুলির মধ্যে স্যুইচ করা) পদ্ধতির যদি ডেটা-সেটে বাঁকানো রাস্তা থাকে তবে ভাল কাজ করবে না। এটা কি ঘটনা? অর্ডারিং অ্যালগরিদম এই প্রশ্নের আইএমএইচওর শক্ততম অংশ।
মারহফ

@ মারহফ: হ্যাঁ বাঁকা রাস্তাগুলি একটি সমস্যা হয়ে দাঁড়াবে, তবে আমি বেশিরভাগ ডেটা স্বয়ংক্রিয়ভাবে রূপান্তরিত করার চেষ্টা করছি এবং বাকিটি ম্যানুয়ালি করা দরকার। অথবা সমাধান বের করার জন্য আমি আরও বিষয়ের খনন চালিয়ে যাব তবে কাউকে বাকী ডেটা ঠিক করতে আরও বেশি সময় লাগতে পারে। আমাকে সিদ্ধান্ত নিতে সক্ষম হতে ফলাফলগুলি মূল্যায়ন করতে হবে। এটি নির্দেশ করার জন্য THX!
মহাকাল

স্ট্যাটুট টিউন করা আমি কেবল একটি কৌশল সম্পর্কে চিন্তা করেছিলাম যা আমার চেক করা দরকার ...
মারহফ

এটি করার কোনও শক্তিশালী উপায় আছে যা পয়েন্টগুলির সমস্ত সম্ভাব্য ক্রমগুলি চেষ্টা করে না এবং কোনটি সবচেয়ে কম দৈর্ঘ্যের দেয় তা সন্ধান করে?
dbaston

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