मिडपॉइंट विस्थापन एल्गोरिथम


14

MDPMDP

यह सवाल मुख्य रूप से सरासर हताशा से बाहर आया है , कई घंटे बिताने के बाद समस्या का पता लगाने की कोशिश कर रहा है।

यदि आप ऊपर की तस्वीर के लिए अपनी आँखें डालते हैं, तो आपको देखना चाहिए कि मेरा मिडपॉइंट विस्थापन एल्गोरिथ्म एल्गोरिथ्म सफलतापूर्वक (कुछ हद तक) काम कर रहा है; कुछ हद तक सुसंगत शोर पैटर्न के उत्पादन में।

हालांकि, यह छवि पर एक काले बिंदीदार ग्रिड को पीछे छोड़ रहा है, और मुझे नहीं पता कि क्यों। मैं इसे गणित में एक मुद्दा होने की उम्मीद कर सकता हूं, लेकिन मैं इसे देख नहीं सकता; न ही यह संभव मुद्दे के रूप में किसी भी ऑनलाइन संसाधनों में बताया गया था; तो इस बग को शिकार करने के लिए किसी भी मदद की सराहना की जाएगी।

unsigned char** mdp(unsigned char** base, unsigned base_n, unsigned char r) {
    size_t n = (2 * base_n) - 1;

    unsigned char** map = new unsigned char*[n];
    for (unsigned i = 0; i < n; ++i) map[i] = new unsigned char[n];

    // Resize
    // 1 0 1
    // 0 0 0
    // 1 0 1
    for (size_t i = 0; i < n; i += 2) {
        for (size_t j = !(i % 2 == 0); j < n; j += 2) {
            map[i][j] = base[i / 2][j / 2];
        }
    }

    // Diamond algorithm
    // 0 0 0
    // 0 X 0
    // 0 0 0
    for (size_t i = 1; i < n; i += 2) {
        for (size_t j = 1; j < n; j += 2) {
            unsigned char& map_ij = map[i][j];

            unsigned char a = map[i - 1][j - 1];
            unsigned char b = map[i - 1][j + 1];
            unsigned char c = map[i + 1][j - 1];
            unsigned char d = map[i + 1][j + 1];
            map_ij = (a + b + c + d) / 4;

            unsigned char rv = std::rand() % r;
            if (map_ij + r < 255) map_ij += rv; // EDIT: <-- thanks! the bug! `map_ij + rv`, not `r`
            else map_ij = 255;
        }
    }

    // Square algorithm
    // 0 1 0
    // 1 0 1
    // 0 1 0
    for (size_t i = 0; i < n; ++i) {
        for (size_t j = (i % 2 == 0); j < n; j += 2) {
            unsigned char& map_ij = map[i][j];

            // get surrounding values
            unsigned char a = 0, b = a, c = a, d = a;
            if (i != 0) a = map[i - 1][j];
            if (j != 0) b = map[i][j - 1];
            if (j + 1 != n) c = map[i][j + 1];
            if (i + 1 != n) d = map[i + 1][j];

            // average calculation
            if (i == 0) map_ij = (b + c + d) / 3;
            else if (j == 0) map_ij = (a + c + d) / 3;
            else if (j + 1 == n) map_ij = (a + b + d) / 3;
            else if (i + 1 == n) map_ij = (a + b + c) / 3;
            else map_ij = (a + b + c + d) / 4;

            unsigned char rv = std::rand() % r;
            if (map_ij + r < 255) map_ij += rv;
            else map_ij = 255;
        }

    }

    return map;
}

यदि आपके पास http://www.gameprogrammer.com/fractal.html और http://www.lIIIouse3d.com/opengl/terrain/index.php?mpd2 के अलावा कोई अन्य सुझाव है , तो भग्न आधारित भू-निर्माण पीढ़ी के लिए, मैं करूँगा उन्हें टिप्पणी के रूप में भी सराहना करते हैं।

संपादित करें:

MDP

फैबियंस के सुझाव (ty) के अनुसार यह नई छवि है, हालांकि इसमें अभी भी कुछ अजीब विचित्रताएं हैं, जिन्हें आपको सीधे (छोटे 'डिम्पल') हर जगह देखने में सक्षम होना चाहिए।

इस अजीब व्यवहार के कारण क्या हो सकता है? अपडेटेड सोर्स कोड: http://www.pastie.org/1924223

संपादित करें:

सीमा की जाँच में त्रुटि ढूंढने में फ़ेबियन के लिए बहुत धन्यवाद, दिलचस्पी रखने वालों के लिए, यहाँ मौजूदा समाधान 512x512 png है। और वर्तमान स्रोत कोड (फैबियन द्वारा संशोधित)MDP

संपादित करें (वर्षों बाद): पायथन संस्करण https://gist.github.com/dcousens/5573724#file-mdp-py


तस्वीरों में, ऐसा लग रहा है कि प्रत्येक बिंदु एक ही ऊंचाई पर है। क्या कोनों समान ऊंचाई पर हैं?
deft_code

1
इसके लायक क्या है, आपकी छवियां बहुत सुंदर लगती हैं। :)
क्रिस

स्कैंड (): मुझे पूरी तरह से यकीन नहीं है कि मैं समझता हूं - क्या यह अंतराल (-r / 2, r / 2] पर एक हस्ताक्षरित चरित्र को वापस करने वाला है? डिम्पल, मुझे वैसे भी, परिणाम की तरह लगते हैं? अतिप्रवाह। आसन्न क्षेत्र अचानक काले शूट करने लगते हैं, और फिर वापस सफेद पर चढ़ जाते हैं। कुल मिलाकर, ऐसा लगता है कि तेज बैंडिंग है, फिर से मुझे सुझाव दिया कि आप अतिप्रवाह कर रहे हैं, शायद आप गणित करने में मन लगाएंगे। उच्च परिशुद्धता (कहना, पूर्णांक), और उसके बाद मानों को श्रेणी में बंद करना [0,256] या [-128 -127]
क्रिस

समस्या नीचे हल की गई थी, यह इसलिए था क्योंकि मैं यादृच्छिक मूल्य की सीमा के खिलाफ जाँच कर रहा था, न कि इसका वास्तविक मूल्य। Scrand () एक अस्थायी 'शोर' समारोह आदर्श लौटने था [-128, 127]
deceleratedcaviar

आह कूल! खुशी है कि अब यह काम कर रहा है।
क्रिस

जवाबों:


12

एल्गोरिदम पुनरावर्ती रूप से एक मान जोड़ता है, लेकिन मान सकारात्मक या नकारात्मक हो सकता है (सामान्य रूप से + -1 / (2 ^ ऑक्टेव))

यदि आप शून्य पर शुरू करते हैं और केवल सकारात्मक मूल्यों को जोड़ते हैं, तो आप केवल ऊपर जा सकते हैं, और यही कारण है कि आप नीचे खींचे गए सिरों को देख रहे हैं।

चार कोनों के लिए शून्य के बजाय 127 पर शुरू करने की कोशिश करें, और हस्ताक्षरित चार की कोशिश भी करें (फिर ऊपर और नीचे दोनों तरफ से अपनी सीमा की जांच करें)

संपादित करें

इसलिए, दो और चीजों को मुख्य रूप में बदलने की आवश्यकता है (64 >> i) प्रत्येक अष्टक पर आधा प्रभाव प्राप्त करने के लिए, और आपके आउटपुट फ़ंक्शन (अंतिम को मैप करने वाला एक [] [] tp imgdta [], आप बस अंदर डालने की जरूरत है

imgdta [(i * n) + j] = 128 + अंतिम [i] [j];

इसके बजाय अगर और ब्लॉक।

एक और बात, मुझे यकीन नहीं है कि क्यों, लेकिन आपका बाउंड चेक फेल हो रहा है (जो कि लाइनें 38 और 65 है) यदि आप पूरी तरह से चेक को हटाते हैं, तो आपको कुछ नए डार्क ब्लब्स भी दिखाई देते हैं, इसलिए मुझे लगता है कि आपको बड़े प्रकार को बढ़ावा देने की आवश्यकता हो सकती है सीमा जाँच करने से पहले यदि आप "64 / i" के साथ अधिक शोर वाली तस्वीर चाहते हैं।

पुराने संस्करण

बस पता चला कि यह क्या था, आप 'आर' के खिलाफ तुलना कर रहे हैं, 'आरवी' नहीं, सीमा की जांच में। यहाँ निश्चित कोड है: http://pastie.org/1927076


यह निश्चित रूप से इसके बारे में जाने का सबसे अच्छा तरीका था, लेकिन अभी तक कोई सिगार नहीं है, ऐसा लगता है कि मेरी छवि अभी भी कुछ 'quirks' है, मैंने मूल पोस्ट को अपडेट किया।
deceleratedcaviar

यकीन नहीं है, लेकिन रेखा 93 गलत दिखती है, 64 / i को 64 >> i की आवश्यकता हो सकती है (जैसा कि आप प्रत्येक प्रभाव को आधा करते हैं)
रिचर्ड फैबियन

आह !! बहुत बहुत धन्यवाद, मैं विश्वास नहीं कर सकता कि, मुझे पता था कि यह उस दूसरी समस्या के लिए कुछ बेवकूफ होगा। आपका अस्थायी TGA कोड पसंद आया, क्षमा करें, मुझे आपको परेशानी से बचाना चाहिए था और हेडर लगाना चाहिए था।
deceleratedcaviar

3

दो चीजें जो बाहर कूदती हैं:

  1. क्या आपके पास निश्चित-बिंदु में ऐसा करने के लिए एक सम्मोहक कारण है? वहाँ प्रति इसके साथ कुछ भी गलत नहीं है, और इसका उपयोग करने के लिए बहुत सारे कारण हैं (यदि आप एक विशाल मानचित्र की ओर जाने की योजना बना रहे हैं, तो विशेष रूप से स्मृति की आवश्यकताएं हैं), लेकिन मैं निश्चित रूप से एल्गोरिथ्म के फ्लोटिंग-पॉइंट संस्करण के साथ शुरू करूंगा। और इसे काम करने के बाद इसे नियत-बिंदु में बदल दें; यदि कुछ और नहीं, तो त्रुटियों के एक प्रशंसनीय स्रोत को समाप्त करें (विशेष रूप से, मुझे संदेह है कि आपके क्लैम्पिंग से समस्याएं पैदा हो सकती हैं, और आरवी को कब / कहां जोड़ना / कैसे करना है) के लिए शर्तें।
  2. हालांकि मुझे जो कोड दिखाई दे रहा है, उससे बताना मुश्किल है, ऐसा नहीं लगता है कि आपका यादृच्छिक ऊंचाई विस्थापन स्तर के साथ स्केलिंग कर रहा है, और उस मुद्दे के साथ संयुक्त (1) कुछ समस्याओं का कारण हो सकता है - आपको नहीं होना चाहिए प्रत्येक स्तर पर एक ही राशि से विस्थापित करना।

ओह, और एक गैर-एल्गोरिदमिक चीज़: मैं दृढ़ता से आपके mdp () फ़ंक्शन में आवंटन नहीं करने की सलाह देता हूं; दो अलग-अलग पहले से आवंटित सरणियों में पास करें और पुनरावृत्ति 'इन-प्लेस' करें, एक से दूसरे में जा रहे हैं। यदि और कुछ नहीं है, तो यह आपको पिंग-पॉन्ग को आगे और पीछे कर देगा क्योंकि आप नए टाइम को आउट करने के बजाय एक नया एरे आवंटित करने के बजाय लेयर्स करते हैं।


कुछ अच्छे बिंदु, जाहिर है मैं सिर्फ एल्गोरिदम को सही करने की कोशिश कर रहा हूं, कार्यान्वयन आदर्श से बहुत दूर है, मैं इस बिंदु पर स्मृति को भी साफ नहीं करता हूं: पी।
deceleratedcaviar

इस बिंदु पर, पासिंग स्केलिंग 64 / i है, जाहिर है मैं बाद में इसे बदल दूंगा, लेकिन यह वास्तव में वर्तमान में अनुभव किए गए डिम्पल प्रभाव की व्याख्या नहीं करता है। : एस
डेक्लेरेटेडकविर

0

उपरोक्त से आगे, आप वर्तमान में उस मेमोरी को नहीं हटा रहे हैं जिसे आप आवंटित कर रहे हैं। इसे मापने के लिए, लाइन 104 को निम्न से बदलें:

for (unsigned i = 1; i < 6; ++i) final = mdp(final, n, 64 / i);

सेवा

for (unsigned i = 1; i < 6; ++i) {
  signed char** new_final = mdp(final, n, 64 / i);
  for (unsigned i = 0; i < n; ++i)
    delete[] final[i];
  delete[] final;
  final = new_final;
}

और इसे tga फ़ाइल में लिखने के बाद जोड़ें:

for (unsigned i = 0; i < n; ++i)
  delete[] final[i];
delete[] final;

मैं स्मृति को साफ करने के तरीके के बारे में बहुत जागरूक हूं, लेकिन यह देखते हुए कि यह केवल एक एल्गोरिथम प्रोटोटाइप था, और वैक्टर का उपयोग करने के लिए फिर से लिखा जाएगा, मैं सिर्फ यह सुनिश्चित करना चाहता था कि यह सही था।
deceleratedcaviar
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.