অনিয়মিত বহুভুজ সেন্ট্রয়েড (লেবেল পয়েন্ট) সন্ধানের জন্য অ্যালগরিদম


13

গুগল ম্যাপে অনিয়মিত আকারের বহুভুজগুলির জন্য আমাকে সেন্ট্রয়েড (বা লেবেল পয়েন্ট) সন্ধান করতে হবে। আমি পার্সেলগুলির জন্য ইনফো উইন্ডো দেখছি এবং তথ্যের পৃষ্ঠায় থাকা গ্যারান্টিযুক্ত ইনফো উইন্ডো অ্যাঙ্কর করার জন্য একটি জায়গা প্রয়োজন। নীচে চিত্র দেখুন।

বিকল্প পাঠ বিকল্প পাঠ

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

আমার প্রথম ধারণাটি ছিল যে "মিথ্যা" সেন্ট্রয়েডের সর্বাধিক ল্যাট এবং এলএনজি নিয়ে এবং এলোমেলোভাবে পয়েন্টগুলি সেখান থেকে বের করে প্লেইন পর্যন্ত আমি বহুভুজকে ছেদ না করে এমন একটি খুঁজে পাই। আমার ইতিমধ্যে পয়েন্ট-ইন-বহুভুজ কোড রয়েছে। এটি আমার কাছে কেবল ভয়ঙ্কর "হ্যাকি" বলে মনে হচ্ছে।

আমার লক্ষ করা উচিত যে জ্যামিতির আউটপুট দেওয়ার জন্য আমার কোনও সার্ভার সাইড কোডের অ্যাক্সেস নেই তাই আমি ST_PointOnSurface (the_geom) এর মতো কিছু করতে পারি না।

উত্তর:


6

দ্রুত এবং নোংরা: যদি "মিথ্যা" সেন্ট্রয়েড বহুভুজের মধ্যে না থাকে তবে সেই বিন্দুটির নিকটতম শীর্ষটি ব্যবহার করুন।


আমি এই সম্পর্কে চিন্তা ছিল না। আদর্শভাবে আমি বহুবর্ষে এই বিন্দুটি পছন্দ করি এবং কিনারায় নয়, তবে এটিই সম্ভবত আমি ফিরে যাব।
জেসন

একবার আপনি একটি প্রান্ত পয়েন্ট পেয়ে গেলে আপনি বহুভুজের সাহায্যে সেই বিন্দুতে কেন্দ্রের একটি ছোট বর্গক্ষেত্র ছেদ করতে পারেন এবং তার পরে ছেদটির সেন্ট্রয়েড চয়ন করতে পারেন। বর্গক্ষেত্রটি যথেষ্ট ছোট হলে এটি একটি অভ্যন্তরীণ পয়েন্ট হওয়ার নিশ্চয়তা দেওয়া হয় (যদিও এটি অবশ্যই একটি প্রান্তের খুব কাছাকাছি থাকবে)।
whuber

@ জেসন যদি আপনি প্রকৃত সেন্ট্রয়েড ব্যবহার করেন তবে আপনি এই সমস্যার মুখোমুখি হতে পারেন। জাভাস্ক্রিপ্টে দ্রুত কোনও কিছুর
ডান্ডি

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

3

আপনি এটি দেখতে চাইতে পারেন: http://github.com/tparkin/Google-Maps-Point-in- পলিগন

এটি একটি র কাস্টিং অ্যালগরিদম ব্যবহার করে বলে মনে হচ্ছে যা আপনার উপস্থাপিত কেসের সাথে মেলে।

এটি সম্পর্কে একটি ব্লগ পোস্ট এখানে আছে। http://appdelegateinc.com/blog/2010/05/16/point-in-polygon-checking/


আপনি যদি সার্ভারের দিক থেকে এটি প্রয়োগ করতে চান তবে জেটিএস (জাভা) এবং জিওস (সি) উভয়ই এই কার্যকারিতাটি বাস্তবায়ন করে।
ডেভিডএফ

হ্যাঁ, আমার সম্ভবত যোগ করা উচিত ছিল যে আমার "গণনা করা" সেন্ট্রয়েড বহুভুজের মধ্যে রয়েছে কিনা তা নির্ধারণ করার জন্য আমার কাছে ইতিমধ্যে কোড রয়েছে। আমি আসলে যা চাই তা সেন্ট্রয়েড তৈরির কিছু উপায় যা বহুভুজের মধ্যে রয়েছে।
জেসন

3

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


1

আমি http://ecname.org.uk/gmap থেকে জনপ্রিয় এপোলি কোডটি প্রসারিত করে আমার সমস্যার সমাধান করেছি । মূলত আমি যা করে শেষ করেছি তা হ'ল:

  • "মিথ্যা সেন্ট্রয়েড" থেকে শুরু হয়ে প্রতিটি কোণ এবং পাশ পর্যন্ত প্রসারিত (8 টি মোট) রশ্মির একটি সিরিজ তৈরি করুন
  • ক্রমান্বয়ে 10,20,30 পয়েন্ট তৈরি করুন ... প্রতিটি রশ্মি নিচে শতাংশ করুন এবং দেখুন যে এই বিন্দুটি আমাদের মূল বহুভুজের মধ্যে রয়েছে কিনা

নীচে বর্ধিত এপোলি কোড:

google.maps.Polygon.prototype.Centroid = function() {
var p = this;
var b = this.Bounds();
var c = new google.maps.LatLng((b.getSouthWest().lat()+b.getNorthEast().lat())/2,(b.getSouthWest().lng()+b.getNorthEast().lng())/2);
if (!p.Contains(c)){
    var fc = c; //False Centroid
    var percentages = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]; //We'll check every 10% down each ray and see if we're inside our polygon
    var rays = [
        new google.maps.Polyline({path:[fc,new google.maps.LatLng(b.getNorthEast().lat(),fc.lng())]}),
        new google.maps.Polyline({path:[fc,new google.maps.LatLng(fc.lat(),b.getNorthEast().lng())]}),
        new google.maps.Polyline({path:[fc,new google.maps.LatLng(b.getSouthWest().lat(),fc.lng())]}),
        new google.maps.Polyline({path:[fc,new google.maps.LatLng(fc.lat(),b.getSouthWest().lng())]}),
        new google.maps.Polyline({path:[fc,b.getNorthEast()]}),
        new google.maps.Polyline({path:[fc,new google.maps.LatLng(b.getSouthWest().lat(),b.getNorthEast().lng())]}),
        new google.maps.Polyline({path:[fc,b.getSouthWest()]}),
        new google.maps.Polyline({path:[fc,new google.maps.LatLng(b.getNorthEast().lat(),b.getSouthWest().lng())]})
    ];
    var lp;
    for (var i=0;i<percentages.length;i++){
        var percent = percentages[i];
        for (var j=0;j<rays.length;j++){
            var ray = rays[j];
            var tp = ray.GetPointAtDistance(percent*ray.Distance()); //Test Point i% down the ray
            if (p.Contains(tp)){
                lp = tp; //It worked, store it
                break;
            }
        }
        if (lp){
            c = lp;
            break;
        }
    }
}
return c;}

এখনও কিছুটা হ্যাকি তবে এটি কাজ করে বলে মনে হচ্ছে না।


এই পদ্ধতিটি কিছু অত্যাশ্চর্য বহুভুজের জন্য ব্যর্থ হবে। উদাহরণস্বরূপ, পলাইন buff {0, 9}, {10, 20}, {9, 9}, {20, 10}, {9, 0}, {20, -10}, {9, -9 buff , {10, -20}, {0, -9}, {-10, -20}, {-9, -9}, {-20, -10}, {-9, 0}, {-20, 10}, {-9, 9}, 10 -10, 20}, {0,9} 1/ 1/2 এর চেয়ে কম দ্বারা। উদাহরণস্বরূপ, এটি ড্যান্ডির QAD পদ্ধতির তুলনায় অদক্ষ।
হোবল

1

এটি করার জন্য আর একটি 'নোংরা' অ্যালগরিদম:


+1 কারণ দ্বিতীয়বারের মতো এটির হিট হওয়ার উপযুক্ত সুযোগ থাকতে পারে। যতক্ষণ না আপনার "এলোমেলো" প্রতিবার ব্যবহারকারীকে বিরক্ত না করার জন্য পুনরায় উত্পাদনের যোগ্য এটি এটি একটি বৈধ সমাধানও। শীঘ্রই কোনও বৈধ পয়েন্টটিকে আঘাত করা না হওয়ার প্রতিক্রিয়াগুলি স্লিম, বিশেষত যদি আপনি ভাল অনুমানের বিন্দু দিয়ে শুরু করেন।
ড্যান্ডি

1
@ ড্যান্ডি: আসলে কিছু ক্ষেত্রে এটি সত্যই দুর্বল অ্যালগরিদম হতে পারে। উদাহরণস্বরূপ একটি সরু তির্যক স্লিভার বিবেচনা করুন। এগুলি বাস্তবে বিদ্যমান (যেমন, রাস্তার সম্মুখভাগের দীর্ঘ পার্সেলগুলি) এবং সহজেই বাউন্ডিং বাক্সের 0.1% এরও কম (কখনও কখনও কম কম) দখল করতে পারে। যুক্তিযুক্তভাবে নিশ্চিত হওয়ার জন্য (95% আত্মবিশ্বাসী) এই কৌশলটির সাথে এই জাতীয় বহুভুজকে আঘাত করার জন্য প্রায় 3,000 পুনরাবৃত্তি প্রয়োজন হবে।
হোবার

@ ভুবার: আপনি যদি কোনও খারাপ শুরুর অবস্থান চয়ন করেন তবে এটি সম্পন্ন হতে কিছুটা সময় নিতে পারে। যদি আপনিও অনুমান করেন যে অনুমিতভাবে 95% ক্লিকগুলি আরও আকাঙ্ক্ষিত জ্যামিতিতে থাকবে এটি কেবল 5% সময়ের সমস্যা হতে পারে। এছাড়াও অন্য জিআইএস.এস প্রশ্নের সাথে যদি পারফরম্যান্সের লক্ষ্য হয় তবে যদি কোনও একক সমাধান না হয় তবে হিউরিস্টিকের ভিত্তিতে কৌশলগুলি পরিবর্তন করা ভাল। এটি 3000 পুনরাবৃত্তির জন্য চালিয়ে যাওয়ার কোনও কারণ নেই। আপনি 10 এর পরে আমার QAD- এর কাছে সর্বদা জামিন দিতে পারেন I আমার ধারণা মনে হয় লোকেশনটি আরও আকাঙ্ক্ষিত হতে পারে বলে কয়েকটি পুনরাবৃত্তির জন্য এটি চেষ্টা করা ভাল হবে।
ড্যান্ডি

@ ড্যান্ডি: তবে আপনার কিএডি সমাধানের বিষয়টি কী? এমনকি বহুভুজের কিছু অভ্যন্তরীণ বাফারে মূল ট্রায়াল লেবেলপয়েন্ট থেকে নিকটতম প্রান্তে চলে গিয়ে আপনি এটি একটি সামান্য বিট পরিবর্তন করতে পারেন: এখনও QAD তবে মূল বৈশিষ্ট্যের অভ্যন্তরীণ স্থানে অবতরণের গ্যারান্টিযুক্ত। বিটিডাব্লু, শিগগিরই জামিন দেওয়ার আপনার কৌশলটি ভাল। আমি যখনই এর মতো এলোমেলো তদন্তটি কোড করি, আমি বৈশিষ্ট্যের ক্ষেত্রের অনুপাতটি তার সীমানা বাক্সের সাথে সংক্ষেপিত করি, সাফল্যের প্রত্যাশিত সময় সন্ধান করতে এটি ব্যবহার করি এবং অবিলম্বে ব্যবহারকারীকে সতর্ক করে দেয় যদি এটি দীর্ঘ হতে পারে।
whuber

@ অঞ্চলটি অনুপাতের হিউরিস্টিক একটি দুর্দান্ত ধারণা কারণ আপনি যখন অঞ্চলটি গণনা করেন তখন সেন্ট্রয়েড গণনা করার সময় আপনি প্রায়। আমার QAD সমাধানের সমস্যা হিসাবে: এটি প্রান্তে। যদি আমি সেই বিন্দুটি বেছে নিই এবং আপনার মতো করে এটি বাফার করি, তবে "ছোট" ব্যাসার্ধটি সংকীর্ণ অংশটি জুড়ে দৈর্ঘ্যের চেয়ে বড় হতে পারে। সর্বদা একটি কোণার কেস আছে। এতদূর বিবেচনা করতে হবে, কেবল এমন একটি বেলুন তৈরি করতে হবে যা ইউআইকে বিশৃঙ্খলা করবে এবং জ্যামিতিটিকে যে কোনওভাবেই অস্পষ্ট করবে। সর্বাধিক বা সর্বনিম্ন শীর্ষটি বেছে নিতে সম্ভবত আরও ভাল better
ড্যান্ডি

1

আপনার সাম্প্রতিক স্পষ্টির আলোকে যে আপনি কঠোরভাবে অভ্যন্তরীণ অবস্থান পছন্দ করবেন, আপনি মেডিটাল এক্সিস ট্রান্সফর্মের কোনও পয়েন্ট নির্বাচন করতে পারেন যা বহুভুজ সীমানায় নয়। (যদি আপনার কাছে এমএএটির জন্য কোড না থাকে তবে আপনি বহুভুজকে নেতিবাচকভাবে বাফার করে এটি আনুমানিক করতে পারেন A একটি বাইনারি বা সেকেন্ড অনুসন্ধানের ফলে খুব শীঘ্রই একটি ছোট অভ্যন্তর বহুভুজ তৈরি হবে যা ম্যাট-এর অংশটিকে প্রায় কাছাকাছি করে; তার সীমানায় যে কোনও পয়েন্ট ব্যবহার করে))


জ্যামিতির প্রান্তটি ব্যবহার করার বিষয়ে আপনি কী বলছিলেন তা আমি বুঝতে পেরেছি যে প্রান্তটি আগ্রহের বহুভুজের অভ্যন্তরের মধ্যে রয়েছে। আমি বুঝতে পারছি না আপনি কীভাবে এই প্রান্তটি / ভারটেক্স তৈরি করতে যাবেন। কেবলমাত্র আমি ভাবতে পারি হ'ল বাছাই করা বিন্দুর অংশটির বিপরীতে অংশের দিকে একটি লম্ব রশ্মি ছেদ করে ভার্চুয়াল ত্রিভুজ তৈরি করা। এই দুটি পয়েন্টের মধ্যবর্তী পয়েন্টটি ভার্চুয়াল ত্রিভুজটির শীর্ষ হতে পারে।
ড্যান্ডি

@ ড্যান্ডি: এটি এটির হৃদয়ঙ্গম হয়। আপনার জিআইএস স্থানীয়ভাবে কী করে তার উপর নির্ভর করে এগুলি চালানোর অনেকগুলি উপায় রয়েছে। উদাহরণস্বরূপ, একবার আপনি একটি রশ্মি খুঁজে পেয়েছেন যা ইতিবাচক দৈর্ঘ্যের একটি সেটে মূল বৈশিষ্ট্যটিকে ছেদ করে, সেই ছেদটি লাইন খণ্ডগুলির বিচ্ছিন্ন ইউনিয়ন হবে। এই বিভাগগুলির যে কোনও একটির কেন্দ্র ব্যবহার করুন। আরেকটি উপায় হ'ল বৈশিষ্ট্যের যে কোনও বিন্দু দিয়ে শুরু করা (সম্ভবত এটির মাঝারিটির নিকটে, যা আপনার QED পদ্ধতিটি সম্পন্ন করেছে), সেখানে একটি ছোট্ট সাধারণ বহুভুজ (উদাহরণস্বরূপ, বর্গক্ষেত্র) তৈরি করুন, মূল বৈশিষ্ট্যটির সাথে ছেদ করুন, অনন্য সংযুক্ত চয়ন করুন উপাদান ...
whuber

(ধারাবাহিকতা) ... প্রারম্ভিক পয়েন্টটি সহ এবং পুনরাবৃত্তভাবে সেই উপাদানটির জন্য একটি কেন্দ্র চয়ন করুন। যখন আপনার জিআইএস আপনাকে বৈশিষ্ট্যের সীমানা বর্ণনা করে এমন শীর্ষ দিকের ক্রমগুলি লুপ করতে দেয় তখন প্রচুর পরিমাণে পদ্ধতি উপলব্ধ থাকে। যদি নেতিবাচক বাফারগুলি সমর্থন করে তবে আপনি পুনরাবৃত্তভাবে সর্বাধিক দূরত্বের অভ্যন্তরীণ পয়েন্টগুলির একটি সেট খুঁজে পেতে পারেন ("কঙ্কাল", যা ম্যাটটির একটি উপসেট)। এটি সামান্য ব্যয়বহুল তবে প্রোগ্রাম করা মোটামুটি সহজ এবং দুর্দান্ত লেবেল পয়েন্ট উত্পাদন করে।
whuber

0

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

এছাড়াও, ইউ আকারগুলি এবং আরও জটিল বিষয়গুলি সম্পর্কে সতর্কতা অবলম্বন করুন। :) সম্ভবত তাদের জন্য, দ্রাঘিমাংশের ডানদিকের জোড়ার গড়টি বেছে নিন (প্রতিটি জুটি বহুভুজের এক স্লাইসের সাথে মিলিত হবে), যেহেতু তথ্য উইন্ডোটি সেভাবেইমুখী?

এটি আপনাকে অবস্থানের উপরেও আরও কিছুটা নিয়ন্ত্রণ দেয়; উদাহরণস্বরূপ, বহুভুজকে আরও দৃশ্যমান রেখে দেওয়ার জন্য তথ্য উইন্ডোটি or 66 বা% 75% উলম্বভাবে অবস্থান করা ভাল হতে পারে। (অথবা এটি নাও হতে পারে! তবে আপনার কাছে টুইট করার মত নক আছে))


0

ব্যবহারকারীর দ্বারা এটি নির্বাচন করার জন্য কীভাবে পয়েন্টটি ব্যবহার করার জন্য ব্যবহারকারী ক্লিক করেছেন, যদি এটি সেই ব্যবহারকারী দ্বারা নির্বাচিত হয়।


এটি একটি মাউস ক্লিক বা স্থান-অ-কোয়েরি দ্বারা নির্বাচন করা যেতে পারে, সুতরাং এটি সর্বদা কার্যকর হয় না।
জেসন

0

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

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

এই প্রান্তবিন্দু থেকে, এক প্রান্তকে দূরে প্রান্তে রেখাগুলি আঁকুন, আপনার শৃঙ্খলাটি যদি শীর্ষস্থানীয় 3 হয় তবে শীর্ষবিন্দু 3 + 2 দেখুন।

আপনার মূল ভার্টেক্স থেকে এই শীর্ষটি পর্যন্ত একটি লাইন তৈরি করুন। যদি নির্মিত লাইন:

  1. অন্য কোন লাইন অতিক্রম করে এবং
  2. এর মিডপয়েন্টটি বহুভুজের বাইরে নয়

তারপরে আপনি বহুভুজের মধ্যে একটি ত্রিভুজ তৈরি করেছেন। যদি সফল প্রান্তটি n + 2 হয়, তবে আপনার ত্রিভুজটি {n, n + 1, n + 2}, যা আমরা {v, v1, v2 refer হিসাবে উল্লেখ করব} যদি তা না হয় তবে পরবর্তী শিখুনটি চেষ্টা করে দেখুন এবং যতক্ষণ পর্যন্ত সমস্ত প্রান্তের চেষ্টা না করা হয় চালিয়ে যান।

যখন আপনি একটি ত্রিভুজ খুঁজে পাবেন, তখন ভার্টেক্স v থেকে v1 এবং v2 এর মাঝের বিন্দুতে একটি লাইন নিয়ে এর কেন্দ্রটি সন্ধান করুন। সেই রেখার মধ্যবিন্দুটি ত্রিভুজের অভ্যন্তরে এবং বহুভুজের অভ্যন্তরে গ্যারান্টিযুক্ত।

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


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.