ओवरलैप न करने वाली संस्थाओं को कैसे बेतरतीब ढंग से जगह दें?


11

मैं एक गेम के लिए एक बेतरतीब ढंग से उत्पन्न वातावरण बना रहा हूं जो मैं विकसित कर रहा हूं। में उपयोग OpenGLऔर कोडिंग कर रहा हूँ Java

मैं अपनी दुनिया में बेतरतीब ढंग से पेड़ लगाने की कोशिश कर रहा हूं (जंगल बनाने के लिए), लेकिन मैं नहीं चाहता कि मॉडल ओवरलैप हों (जो तब होता है जब दो पेड़ एक-दूसरे के बहुत करीब रखे जाते हैं)। यहाँ मैं क्या बात कर रहा हूँ की एक तस्वीर है:

यहाँ छवि विवरण दर्ज करें

यदि आवश्यक हो तो मैं और अधिक कोड प्रदान कर सकता हूं, लेकिन यहां आवश्यक स्निपेट्स हैं। मैं एक में मेरी वस्तुओं के भंडारण कर रहा हूँ ArrayListके साथ List<Entity> entities = new ArrayList<Entity>();। मैं उस सूची का उपयोग कर रहा हूँ:

Random random = new Random();
for (int i = 0; i < 500; i++) {
    entities.add(new Entity(tree, new Vector3f(random.nextFloat() * 800 - 400, 
    0, random.nextFloat() * -600), 0, random.nextFloat() * 360, 0, 3, 3, 3);
}

जहां प्रत्येक Entityनिम्नलिखित सिंटैक्स का अनुसरण करता है:

new Entity(modelName, positionVector(x, y, z), rotX, rotY, rotZ, scaleX, scaleY, scaleZ);

rotXएक्स-एक्सिस के साथ घुमाव है, और scaleXएक्स-दिशा में पैमाने है, आदि।

आप देख सकते हैं कि मैं इन पेड़ों को बेतरतीब ढंग random.nextFloat()से xऔर zपदों के लिए रख रहा हूं , और सीमा को बांधे ताकि पेड़ वांछित स्थान पर दिखाई दें। हालाँकि, मैं किसी भी तरह इन पदों को नियंत्रित करना चाहूंगा, ताकि अगर यह पहले से रखे गए पेड़ के बहुत करीब पेड़ लगाने की कोशिश करे, तो यह एक नए यादृच्छिक स्थिति की पुनरावृत्ति करेगा। मैं सोच रहा था कि प्रत्येक पेड़ के Entityपास एक और क्षेत्र हो सकता है, जैसे कि treeTrunkGirth, और यदि एक पेड़ को दूसरे पेड़ के स्थान के बीच की दूरी पर रखा जाता है और वह है treeTrunkGirth, तो यह एक नई स्थिति को पुनर्गणना करेगा। क्या इसको मदद देने का कोई तरीका है?

मुझे अधिक कोड स्निपेट और आवश्यक रूप से विवरण जोड़ने में खुशी हो रही है।


3
पॉइसन डिस्क नमूना काम करना चाहिए। नहीं जानते कि क्या यह इसके लिए सबसे अच्छा है और इसे वास्तव में कभी लागू नहीं किया / उपयोग किया, लेकिन कम से कम एक अच्छी शुरुआत के रूप में लगता है। इस लेख की जाँच करें: devmag.org.za/2009/05/03/poisson-disk-sampling
मंगल

@Mars वाह, यह लिंक सुपर सहायक है, धन्यवाद। मैं देखूंगा कि मैं क्या कर सकता हूं, और शायद अपने खुद के जवाब के साथ वापस आऊं।

@Pikalek हाँ, मुझे लगता है कि आपके द्वारा जोड़ा गया प्रश्न एक डुप्लिकेट है। क्या मैं xz-plane का उपयोग "स्टार मैप" के क्षेत्र के रूप में करूँगा , जैसे दूसरे प्रश्न में?
19

हां, अपने मामले में xz विमान का उपयोग करें । इसके अलावा, treeTrunkGirthएक निरंतर के बजाय एक पेड़ रखने के लिए न्यूनतम दूरी निर्धारित करने के लिए उपयोग करें यदि उन्हें अलग करने की आवश्यकता हो।
पिकालेक

@Pikalek यदि आप एक उत्तर में सभी जोड़ते हैं, तो मैं इसे सर्वश्रेष्ठ के रूप में चुनूँगा। सहायता के लिए धन्यवाद।
21

जवाबों:


15

एक पॉइसन-डिस्क नमूना वितरण आपको यादृच्छिक बिंदुओं को न्यूनतम दूरी के अलावा चुनने की अनुमति देगा। आपकी स्थिति इस प्रश्न के समान है , लेकिन चूंकि आपके पेड़ आदर्श अंक नहीं हैं, इसलिए आपको दूरी की जाँच निम्नानुसार करनी होगी: एक संभावित नए पेड़ और एक मौजूदा पेड़ के बीच की दूरी, उनकी त्रिज्या के योग से कम होनी चाहिए ।

ब्रिडसन के एल्गोरिथ्म कुशलता से ओ (एन) में समस्या को हल कर सकते हैं, लेकिन यह चर दूरी के लिए इसे ट्वीड करने के लिए थोड़ा सा हो सकता है। यदि आपके पैरामीटर कम हैं और / या आप अपने इलाके को प्री-कॉम्पट्यूट कर रहे हैं, तो एक ब्रूट फोर्स सॉल्यूशन आपकी सेवा कर सकता है। यहां कुछ सैंपल कोड दिए गए हैं, जो सभी पूर्व में रखे गए पेड़ों के खिलाफ हर संभावित नए पेड़ के स्थान की जांच करके समस्या को हल करते हैं:

public static class SimpleTree{
    float x;
    float z;
    float r;

    public SimpleTree(Random rng, float xMax, float zMax, float rMin, float rMax){
        x = rng.nextFloat() * xMax;
        z = rng.nextFloat() * zMax;
        r = rng.nextFloat() * (rMax-rMin) + rMin;
    }
}

private static ArrayList<SimpleTree> buildTreeList(float xMax, float zMax, 
        float rMin, float rMax, int maxAttempts, Random rng) {
    ArrayList<SimpleTree> result = new ArrayList<>();

    SimpleTree currentTree = new SimpleTree(rng, xMax, zMax, rMin, rMax);
    result.add(currentTree);

    boolean done = false;
    while(!done){
        int attemptCount = 0;
        boolean placedTree = false;
        Point nextPoint = new Point();
        SimpleTree nextTree = null;
        while(attemptCount < maxAttempts && !placedTree){
            attemptCount++;
            nextTree = new SimpleTree(rng, xMax, zMax, rMin, rMax);
            if(!tooClose(nextTree, result)){
                placedTree = true;
            }
        }
        if(placedTree){
            result.add(nextTree);
        }
        else{
            done = true;
        }
    }

    return result;
}

private static boolean tooClose(SimpleTree tree, ArrayList<SimpleTree> treeList) {
    for(SimpleTree otherTree : treeList) {
        float xDiff = tree.x - otherTree.x;
        float zDiff = tree.z - otherTree.z;

        float dist = (float)Math.sqrt((xDiff * xDiff) + (zDiff * zDiff));
        if(dist < tree.r + otherTree.r){
            return true;
        }
    }        
    return false;
}

निम्नलिखित मापदंडों के साथ:

 maxAttempts = 500;
 width = 300;
 height = 200;
 minSize = 2;
 maxSize = 15;

मैं बेतरतीब ढंग से जगह बना सका और 400-450 पेड़ों के बीच एक सेकेंड में रेंडर कर पाया। यहाँ एक उदाहरण है: यहाँ छवि विवरण दर्ज करें


क्या यह पॉइसन डिस्क नमूना का उपयोग कर रहा है?
वकहार्ट

हां, मैंने इसे स्पष्ट करने के लिए संपादित किया है।
पिकालेक

Math.sqrt के स्थान पर math.pow tree.r + other tree.r, 2 का उपयोग करने का प्रयास करें , sqrt आमतौर पर pow से धीमा है
Ferrybig

1
@ फेरीबग की तुलना चुकता दूरी तेज है, लेकिन यह इस तथ्य को नहीं बदलता है कि यह एक क्रूर बल एल्गोरिथ्म है और अभी भी ओ (एन ^ 2) होगा। यदि तेज समाधान की आवश्यकता है, तो ब्रिडसन के एल्गोरिथ्म का उपयोग करें। साथ ही, यहां चर्चा के रूप में Math.pow(x,2)उपयोग करने की तुलना में किसी भी बेहतर / अलग का उपयोग करना जरूरी नहीं हैx*x
पिकालेक

1
मैंने इलाके के साथ एक समान मुद्दा रखा है और कुछ अच्छे प्रसार और ओवरलैप को सुनिश्चित करना है। मैंने वास्तव में एक बदलाव किया था, मेरे संस्करण में ट्रेस / ब्रश इलाके के इलाके में बेतरतीब ढंग से फैले हुए हैं। मैं तब एक समारोह पोस्ट चलाता हूं ताकि एक-दूसरे के खिलाफ हर वस्तु की दूरी की जांच कर सकें, जहां वे बहुत करीब थे मैंने उन्हें अलग धकेल दिया। यह हालांकि क्षेत्र के अन्य पेड़ों पर संभवतः लगाया जाएगा। मैंने इसे तब तक दोहराया जब तक मेरे पास कोई टक्कर नहीं थी। यह धीमा है, लेकिन मेरे पास बोनस के रूप में जो चीजें थीं, वे क्लीयरिंग (हर जगह नहीं है!) जैसी चीजें थीं और पेड़ का घनत्व अधिक "दिलचस्प" लग रहा था।
एर्नीडिंगो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.