2 ডি-তে, আমি কীভাবে দক্ষতার সাথে একটি বিন্দুর নিকটতম বস্তুটি খুঁজে পেতে পারি?


35

আমার একটি বিশাল গেম ইঞ্জিন রয়েছে এবং আমি নিকটস্থ পয়েন্টের তালিকার সন্ধানের জন্য একটি বৈশিষ্ট্য চাই।

আমি প্রতিটি দূরত্ব খুঁজে পেতে এবং সর্বনিম্ন একটি চয়ন করতে পাইথাগোরিয়ান উপপাদকে সহজভাবে ব্যবহার করতে পারি, তবে এর মধ্যে সমস্তটির মধ্য দিয়ে পুনরুক্তি প্রয়োজন।

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

পয়েন্ট এবং আকারগুলির তালিকার উপর ভিত্তি করে কোন অবজেক্টটি সবচেয়ে নিকটে রয়েছে তা সনাক্ত করতে আমি কি দক্ষ এবং নির্ভুল কিছু ব্যবহার করতে পারি?


এক্স এবং ওয়াই পজিশনের স্কোয়ার্ড সংস্করণগুলি সংরক্ষণ করুন যাতে আপনি ব্যয়বহুল স্কয়ারটি শেষে না করে পাইথাগোরাস উপপাদ্যটি করতে পারেন।
জোনাথন কনেল 15

3
একে নিকটতম প্রতিবেশী অনুসন্ধান বলা হয় । এটি সম্পর্কে ইন্টারনেটে প্রচুর লেখা রয়েছে। সাধারণ সমাধানটি হ'ল কিছু ধরণের স্থান-বিভাজনযুক্ত গাছ ব্যবহার করা।
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

উত্তর:


38

নিকটতম-প্রতিবেশী অনুসন্ধানে কোয়াড / অষ্টমীর সমস্যা হ'ল নিকটতম বস্তুটি নোডের মধ্যে বিভাজন জুড়ে বসে থাকতে পারে। সংঘর্ষের জন্য, এটি ঠিক আছে, কারণ এটি যদি নোডে না থাকে তবে আমরা এটির যত্ন নিই না। তবে এই 2 ডি উদাহরণটিকে চতুর্ভুজ সহ বিবেচনা করুন:

চতুষ্পদ উদাহরণ

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

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

উইকিপিডিয়া থেকে একটি দুর্দান্ত এবং তথ্যমূলক অ্যানিমেশন: কেডি-ট্রি নিকটতম প্রতিবেশী অনুসন্ধান

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

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


1
দুর্দান্ত উত্তর, ছোট বিবরণ "আপনার গাছে থাকা প্রতিটি জিনিসই কেবলমাত্র আপনার গাছে থাকা নিকটতম-প্রতিবেশীকে কেবলমাত্র ছোট ছোট নোডে রাখার গ্যারান্টি দেয়" আমার উত্তরটির অর্থ একই এবং প্রতিবেশী নোডের সমস্ত আইটেমগুলি পুনরাবৃত্তি হয়, সুতরাং আপনি 10 এর পরিবর্তে লুপ করুন you 10.000।
রায় টি।

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

আমি লক্ষ করতে চেয়েছিলাম যে আমি এমন একটি বাস্তবায়ন করেছি যা কালো সবুজ নীল সমস্যা নিয়ে কাজ করে। নীচে পরীক্ষা করুন।
clankill3r

18

sqrt() অ-নেতিবাচক আর্গুমেন্টগুলির জন্য একঘেয়ে বা অর্ডার-সংরক্ষণযোগ্য so

sqrt(x) < sqrt(y) iff x < y

এবং বিপরীতভাবে.

সুতরাং আপনি যদি কেবল দুটি দূরত্বের তুলনা করতে চান তবে তাদের আসল মানগুলির প্রতি আগ্রহী না হন তবে আপনি কেবল sqrt()আপনার পাইথাগোরাস-স্টাফ থেকে ধাপটি বের করতে পারেন:

pseudoDistanceB = (A.x - B.x + (A.y - B.y
pseudoDistanceC = (A.x - C.x + (A.y - C.y
if (pseudoDistanceB < pseudoDistanceC)
{
    A is closest to B!
}
else
{
    A is closest to C!
}

এটি অক্ট ট্রি গাছের মতো দক্ষ নয়, তবে এটি কার্যকর করা সহজ এবং গতি কমপক্ষে কিছুটা সামান্য চাপিয়ে দেয়


1
সেই মেট্রিককে স্কোয়ারড ইউক্লিডিয়ান দূরত্বও বলা হয় ।
মূইলিপ

10

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

এক্ষেত্রে নিকটতম অবজেক্টটি আপনার নিজের জায়গার সমস্ত বস্তুর উপরে প্রথমে পুনরাবৃত্তি করে সেখানে কোনটি নিকটবর্তী তা সন্ধান করতে পারে। সেখানে যদি কেউ না থাকে তবে আপনি আপনার প্রথম প্রতিবেশীদের চেক করতে পারবেন, যদি কেউ না থাকে তবে আপনি তাদের প্রতিবেশী ইত্যাদি পরীক্ষা করতে পারেন ...

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

যথারীতি উইকিপিডিয়া নিবন্ধটিও দেখুন: http://en.wikedia.org/wiki/Octree


7
@ মাল্টিফিনিটাস এটি যুক্ত করতে: আপনার গেমটি 2 ডি হয় তবে আপনি অক্টোবরের পরিবর্তে কোয়াডট্রি ব্যবহার করতে পারেন।
ট্র্যাভিসজি

1

আপনার স্থানিক তথ্যটি আরটিআরগুলিতে সংগঠিত করার চেষ্টা করুন, যা মহাকাশে স্টাফের জন্য বিট্রির মতো এবং "নিকটবর্তী এন প্রতিবেশী" ইত্যাদির মতো প্রশ্নের অনুমতি দেয় ... http://en.wikedia.org/wiki/Rtree


0

কোয়াডট্রি থেকে নিকটতমটি পেতে এখানে আমার জাভা বাস্তবায়ন। এটি dlras2 যে সমস্যাটি বর্ণনা করছে তা নিয়ে কাজ করে:

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

আমি মনে করি অপারেশনটি সত্যিই দক্ষ। এটি কোয়াডের দূরত্বের ভিত্তিতে বর্তমানের নিকটতম কোয়াডগুলিতে আরও অনুসন্ধান করা এড়াতে।

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

public T getClosest(float x, float y) {

    Closest closest = new Closest();
    getClosest(x, y, closest);

    return closest.item;
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

protected void getClosest(float x, float y, Closest closestInfo) {


    if (hasQuads) {

        // we have no starting point yet
        // so get one
        if (closestInfo.item == null) {
            // check all 4 cause there could be a empty one
            for (int i = 0; i < 4; i++) {
                quads[i].getClosest(x, y, closestInfo);
                if (closestInfo.item != null) {
                    // now we have a starting point
                    getClosest(x, y, closestInfo);
                    return;
                }

            }
        }
        else {

            // we have a item set as closest
            // we should check if this quad is
            // closer then the current closest distance
            // let's start with the closest from index

            int closestIndex = getIndex(x, y);

            float d = quads[closestIndex].bounds.distToPointSQ(x, y);

            if (d < closestInfo.dist) {
                quads[closestIndex].getClosest(x, y, closestInfo);
            }

            // check the others
            for (int i = 0; i < 4; i++) {
                if (i == closestIndex) continue;

                d = quads[i].bounds.distToPointSQ(x, y);

                if (d < closestInfo.dist) {
                    quads[i].getClosest(x, y, closestInfo);
                }

            }

        }

    }
    else {

        for (int i = 0; i < items.size(); i++) {

            T item = items.get(i);

            float dist = distSQ(x, y, getXY.x(item), getXY.y(item));

            if (dist < closestInfo.dist) {
                closestInfo.dist = dist;
                closestInfo.item = item;
                closestInfo.tree = this;
            }

        }
    }

}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


class Closest {

    QuadTree<T> tree;
    T item;
    float dist = Float.MAX_VALUE;

}

PS আমি এখনও কেডি-ট্রি বা অন্য কিছু ব্যবহার করা ভাল বলে মনে করি তবে এটি লোকেদের সহায়তা করতে পারে।
clankill3r

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