อัลกอริธึมการกระจัดกลาง


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.lighthouse3d.com/opengl/terrain/index.php?mpd2สำหรับการสร้างภูมิประเทศแบบเศษส่วนฉันจะ ขอบคุณพวกเขาเป็นความคิดเห็นด้วย

แก้ไข:

MDP

นี่คือภาพใหม่ตามคำแนะนำของ Fabians (ty) อย่างไรก็ตามมันยังมีนิสัยแปลก ๆ อยู่ซึ่งคุณควรเห็นได้ทันที ('ลักยิ้ม' เล็ก ๆ ทุกที่)

สิ่งที่อาจทำให้เกิดพฤติกรรมที่แปลกประหลาดนี้? อัปเดตซอร์สโค้ด: http://www.pastie.org/1924223

แก้ไข:

ขอบคุณมากเฟเบียนในการค้นหาข้อผิดพลาดการตรวจสอบขอบเขตสำหรับผู้ที่สนใจนี่คือทางออกปัจจุบันเป็น 512x512 png และซอร์สโค้ดปัจจุบัน (แก้ไขโดยเฟเบียน)(แก้ไขโดยเฟเบียน) MDP

แก้ไข (หลายปีต่อมา): Python เวอร์ชั่นhttps://gist.github.com/dcousens/5573724#file-mdp-py


ในภาพดูเหมือนว่าแต่ละจุดมีความสูงเท่ากัน มุมที่ความสูงเท่ากันหรือไม่?
deft_code

1
สำหรับสิ่งที่คุ้มค่าภาพของคุณดูสวยมาก :)
ChrisE

scrand (): ฉันไม่แน่ใจทั้งหมดที่ฉันเข้าใจ - นี่ควรจะส่งคืนอักขระที่มีลายเซ็นในช่วงเวลา (-r / 2, r / 2] หรือไม่ลักยิ้มสำหรับฉันยังไงก็ตามดูเหมือนว่าผลลัพธ์ ของพื้นที่มากเกินไปพื้นที่ใกล้เคียงดูเหมือนจะยิงสีดำแล้วปีนกลับขึ้นไปเป็นสีขาวโดยรวมแล้วมันดูเหมือนว่ามีแถบที่แหลมคมอีกครั้งแนะนำให้ฉันรู้ว่า ความแม่นยำที่สูงขึ้น (พูดจำนวนเต็ม) จากนั้นทำการหนีบค่าให้อยู่ในช่วง [0,256] หรือ [-128,127]?
ChrisE

ปัญหาได้รับการแก้ไขด้านล่างมันเป็นเพราะฉันถูกตรวจสอบขอบเขตกับช่วงของค่าสุ่มไม่ใช่ค่าจริง Scrand () เป็นฟังก์ชั่น 'สัญญาณรบกวน' ชั่วคราวที่ส่งคืน [-128, 127]
deceleratedcaviar

อ๊ะ! ดีใจที่ได้ยินว่ามันใช้งานได้แล้ว
ChrisE

คำตอบ:


12

อัลกอริทึมเพิ่มค่าซ้ำ แต่ค่าสามารถบวกหรือลบ (ปกติ + -1 / (2 ^ ระดับแปดเสียง))

หากคุณเริ่มต้นที่ศูนย์และเพิ่มค่าบวกเท่านั้นคุณสามารถขึ้นไปได้และนั่นคือเหตุผลที่คุณเห็นจุดยอดลง

ลองเริ่มที่ 127 แทนที่จะเป็นศูนย์สำหรับมุมทั้งสี่และลองลงชื่อด้วยถ่าน (จากนั้นตรวจสอบขอบเขตของคุณทั้งด้านบนและด้านล่าง)

แก้ไข

ดังนั้นอีกสองสิ่งที่จำเป็นต้องเปลี่ยนใน main (64 >> i) เพื่อให้ได้เอฟเฟกต์ครึ่งหนึ่งในแต่ละอ็อกเทฟและฟังก์ชั่นเอาต์พุตของคุณ (อันที่แมปสุดท้าย [] [] tp the imgdta [] คุณ จำเป็นต้องใส่

imgdta [(i * n) + j] = 128+ final [i] [j];

มากกว่าบล็อก if else

อีกสิ่งหนึ่งฉันไม่แน่ใจว่าทำไม แต่การตรวจสอบขอบเขตของคุณล้มเหลว (นั่นคือบรรทัดที่ 38 และ 65) หากคุณลบการตรวจสอบออกโดยสิ้นเชิงคุณสังเกตว่ามี blobs สีเข้มใหม่อยู่ด้วยดังนั้นฉันจึงคิดว่าคุณอาจจำเป็นต้องส่งเสริม ก่อนที่จะทำการตรวจสอบขอบเขตถ้าคุณต้องการภาพที่มีเสียงดังมากขึ้นคุณจะได้รับด้วย "64 / i"

แก้ไขอีกต่อไป

เพิ่งค้นพบว่ามันคืออะไรคุณกำลังเปรียบเทียบกับ 'r' ไม่ใช่ 'rv' ในการตรวจสอบขอบเขต นี่คือรหัสคงที่: http://pastie.org/1927076


นี่เป็นวิธีที่ดีกว่าที่จะไปเกี่ยวกับเรื่องนี้ แต่ไม่มีซิการ์ในตอนนี้ดูเหมือนว่าภาพของฉันยังคงมี 'นิสัยใจคอ' ฉันได้อัปเดตโพสต์ดั้งเดิม
deceleratedcaviar

ไม่แน่ใจ แต่บรรทัด 93 ดูผิด, 64 / i อาจต้องเป็น 64 >> i (ในขณะที่คุณมีเอฟเฟกต์ครึ่งละหนึ่งคู่)
Richard Fabian

Ahhh !! ขอบคุณมากฉันไม่อยากจะเชื่อเลยว่าฉันรู้ว่ามันเป็นสิ่งที่โง่สำหรับปัญหาที่สอง ชอบรหัส TGA ชั่วคราวของคุณขอโทษฉันควรจะช่วยคุณแก้ปัญหาและวางส่วนหัว
deceleratedcaviar

3

สองสิ่งที่โดดเด่น:

  1. คุณมีเหตุผลที่น่าสนใจในการทำเช่นนี้ในจุดคงที่หรือไม่? ไม่มีอะไรผิดปกติกับมันและมีเหตุผลมากมายที่จะใช้มัน (ความต้องการหน่วยความจำที่สะดุดตาที่สุดถ้าคุณกำลังวางแผนที่จะขึ้นสู่แผนที่ขนาดใหญ่) แต่ฉันจะเริ่มต้นด้วยอัลกอริธึมรุ่นทศนิยม และแปลงเป็นจุดคงที่หลังจากที่คุณได้ทำงานแล้ว หากไม่มีสิ่งอื่นใดควรกำจัดแหล่งที่มาของข้อผิดพลาดที่เป็นไปได้ (โดยเฉพาะฉันสงสัยว่าการหนีบของคุณอาจทำให้เกิดปัญหาและเงื่อนไขสำหรับการเพิ่ม / substract rv)
  2. แม้ว่าจะยากที่จะบอกจากโค้ดที่ฉันเห็น แต่ดูเหมือนว่าการกำจัดความสูงแบบสุ่มของคุณจะปรับตามระดับและการรวมกับปัญหาใน (1) อาจทำให้เกิดปัญหาบางอย่าง - คุณไม่ควร แทนที่ด้วยจำนวนเดียวกันในแต่ละระดับ

โอ้และสิ่งหนึ่งที่ไม่ใช่อัลกอริทึม: ฉันขอแนะนำไม่ให้ทำการจัดสรรในฟังก์ชัน mdp () ของคุณ ส่งผ่านสองอาร์เรย์ที่จัดสรรไว้แล้วและทำ 'in-place' ซ้ำแล้ววนซ้ำจากที่หนึ่งไปอีกที่หนึ่ง หากไม่มีสิ่งอื่นใดสิ่งนี้จะช่วยให้คุณปิงปองไปมาในขณะที่คุณเล่นเลเยอร์แทนที่จะต้องจัดสรรอาร์เรย์ใหม่ทุกครั้ง


บางจุดที่ดีเห็นได้ชัดว่าฉันแค่พยายามที่จะทำให้อัลกอริทึมถูกต้องการใช้งานอยู่ไกลจากอุดมคติฉันไม่ได้ทำความสะอาดหน่วยความจำ ณ จุดนี้: P
ชะลอตัวลง

ณ จุดนี้การปรับสเกลผ่านเป็น 64 / i แน่นอนว่าฉันจะเปลี่ยนในภายหลัง แต่มันไม่ได้อธิบายถึงผลกระทบของลักยิ้มที่มีอยู่ในปัจจุบัน : S
deceleratedcaviar

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;

ฉันรู้มากเกี่ยวกับวิธีการล้างหน่วยความจำ แต่เมื่อเห็นว่านี่เป็นต้นแบบของอัลกอริทึมเท่านั้นและจะถูกเขียนใหม่เพื่อใช้เวกเตอร์ฉันแค่อยากให้แน่ใจว่ามันถูกต้อง
ชะลอตัวลง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.