อัลกอริทึมสำหรับการแพร่กระจายฉลากในวิธีที่ดึงดูดสายตาและใช้งานง่าย


24

เวอร์ชั่นสั้น

มีรูปแบบการออกแบบสำหรับการกระจายฉลากยานพาหนะในแบบที่ไม่ทับซ้อนกันวางไว้ใกล้กับยานพาหนะที่พวกเขาอ้างถึงมากที่สุดหรือไม่? ถ้าไม่มีวิธีใดที่ฉันแนะนำให้ปฏิบัติได้? คุณจะใช้สิ่งนี้ด้วยตนเองอย่างไร?

รุ่นขยาย

ในเกมที่ฉันเขียนฉันมีวิสัยทัศน์ที่ชัดเจนจากยานพาหนะทางอากาศของฉัน ฉันมีป้ายเล็ก ๆ ติดกับคีย์ข้อมูลเกี่ยวกับยานพาหนะแต่ละคันด้วย นี่เป็นภาพหน้าจอจริง:

รถสองคันที่มีฉลาก

ตอนนี้เนื่องจากยานพาหนะสามารถบินในระดับความสูงที่แตกต่างกันไอคอนของพวกเขาอาจทับซ้อนกัน อย่างไรก็ตามฉันไม่ต้องการให้ป้ายกำกับของพวกเขาซ้อนทับกัน (หรือป้ายกำกับจากยานพาหนะ 'A' ทับไอคอนรถถัง 'B')

ขณะนี้ฉันสามารถตรวจสอบการชนกันระหว่างสไปรท์และผมก็ผลักดันออกไปป้ายที่กระทำผิดในทิศทางตรงข้ามกับผีสางมิฉะนั้นการที่คาบเกี่ยวกัน สิ่งนี้ใช้ได้ในสถานการณ์ส่วนใหญ่ แต่เมื่อน่านฟ้าหนาแน่นผู้คนสามารถขับป้ายได้ไกลจากยานพาหนะแม้ว่าจะมีทางเลือก "ฉลาด" ทางเลือก ตัวอย่างเช่นฉันได้รับ:

  B - label
A -----------label
  C - label

มันจะดีกว่า (= ฉลากใกล้กับยานพาหนะ) เพื่อรับ:

          B - label
label - A
          C - label

แก้ไข:มันจะต้องได้รับการพิจารณาว่าข้างตัวถังรถที่ทับซ้อนกันอาจจะมีการกำหนดค่าอื่น ๆ ที่labellab'labelสามารถทับซ้อนกัน (ตัวอย่าง ASCII-art แสดงตัวอย่างรถสามคันที่อยู่ใกล้กันมากซึ่งฉลากของAจะทับไอคอนของBและC)

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

สำหรับสิ่งที่คุ้มค่าต่อไปนี้เป็นสองแนวคิดที่ฉันคิด

Slot-isation ของพื้นที่ฉลาก

ในสถานการณ์นี้ฉันจะแบ่งหน้าจอทั้งหมดเป็น "ช่อง" สำหรับป้ายกำกับ จากนั้นยานพาหนะแต่ละคันจะมีป้ายของมันวางไว้ในที่ว่างเปล่าที่ใกล้เคียงที่สุดเสมอ (ว่าง = ไม่มีสไปรต์อื่น ๆ ที่ตำแหน่งนั้น

การค้นหาที่น่าสนใจ

จากตำแหน่งของยานพาหนะบนหน้าจอฉันพยายามวางป้ายในมุมที่เพิ่มขึ้นและเพิ่มรัศมีจนกระทั่งพบตำแหน่งที่ไม่ทับซ้อนกัน บางสิ่งบางอย่างลงไปที่:

try 0°, 10px
try 10°, 10px
try 20°, 10px
...
try 350°, 10px
try 0°, 20px
try 10°, 20px
...

1
มีเครื่องบินหลายลำที่ซ้อนทับกันในคราวเดียว?
wangburger

1
@wangburger - ไม่เคยคิดว่ามันจะเกี่ยวข้อง (จะสนใจที่จะรู้เพิ่มเติมเกี่ยวกับแนวความคิดของคุณ) แต่คำตอบคือ: มันขึ้นอยู่กับกลยุทธ์ของเกมของผู้เล่น ในทางเทคนิคโลกอาจมียานเกราะ 24 คันซ้อนทับกัน แต่ตัวเลขที่สมจริงในสภาพเกมส่วนใหญ่คือ 3-4
แม็

3
มันสับสนหรือไม่ที่จะมีการเคลื่อนไหวของฉลากที่สัมพันธ์กับระนาบมากกว่าการซ้อนทับกัน แต่คงที่ในระยะเวลาที่เหมาะสมใช่หรือไม่
Maik Semder

3
คุณอาจสนใจen.wikipedia.org/wiki/… - นี่ไม่ใช่ปัญหาง่าย ๆ ในการแก้ไข อย่าคาดหวังว่าจะหาทางออกที่สมบูรณ์แบบ
Blecki

2
GraphVizเป็นชุดเครื่องมือสำหรับการจัดทำกราฟในลักษณะที่น่าพึงพอใจโดยมีแนวโน้มที่จะหลีกเลี่ยงการทับซ้อนกันในฉลาก แม้ว่ามันอาจจะไม่สามารถใช้งานได้โดยตรง แต่คุณสามารถรวบรวมข้อมูลบางอย่างจากเอกสารหรือซอร์สโค้ดของพวกเขาเกี่ยวกับอัลกอริทึมชนิดใดที่พวกเขาใช้ในการจัดวางกราฟของพวกเขา พวกเขาดูเหมือนจะมีทั้งรุ่นที่ใช้พลังงานและรุ่นที่ใช้สปริงเป็นตัวอย่าง
Lars Viklund

คำตอบ:


14

โดยพื้นฐานแล้วปัญหานี้คล้ายกับปัญหาการหลีกเลี่ยงการชนกันของข้อมูล ใช่เครื่องบินสามารถบินได้ที่ระดับความสูงต่างกัน แต่ฉลากของพวกเขาจะมีระดับความสูงเท่ากัน

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

หากคุณดูที่พฤติกรรมการเตือนเตือนภัยคุณต้องการใช้ "กฎ" แรกของการเตือนความจำ: การผลักช่วงสั้น ๆ อย่างไรก็ตามแทนที่จะ "หมุนพวงมาลัย" ในทิศทางที่อยู่ห่างจากประเทศเพื่อนบ้านที่ใกล้ที่สุดคุณจะใช้เวกเตอร์ "ออกไป" เป็นตำแหน่งสำหรับป้ายกำกับของคุณ

ตัวอย่างเช่น:

ป้อนคำอธิบายรูปภาพที่นี่

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

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

ดังนั้นเมื่อใช้ตัวอย่างของคุณด้านบนฉันคิดว่าสิ่งนี้จะให้ผลเช่น

            - label
           / 
          B 
label - A
          C 
           \
            - label

การใช้วิธีนี้มีบางสถานการณ์ที่คุณจะต้องสร้างเคสพิเศษสำหรับเช่นสามระนาบแนวตั้ง:

          - label       label -
          |                   |
          B                   B
  label - A                   A - label
          C                   C
          |                   |
          - label       label -

ป้ายกำกับทั้งสามสามารถพลิกจากด้านขวาไปซ้ายขึ้นอยู่กับการกำหนดมุมฉลากของคุณ โดยทั่วไปคุณจะต้องระวังมุมรอบวงกลมที่ป้ายของคุณสามารถเปลี่ยนมุมที่พวกเขาวาดจาก: 0, 90, 180, 270

ป้อนคำอธิบายรูปภาพที่นี่

ฉันคิดว่าในท้ายที่สุดมันจะดูเรียบร้อยและดูฉลากหลีกเลี่ยงซึ่งกันและกัน หากมันทำให้เสียสมาธิมากเกินไปบางทีคุณสามารถปัดเศษเป็น 10 องศาที่ใกล้เคียงที่สุดเพื่อให้เคลื่อนไหวน้อยลง

ขออภัยสำหรับรายละเอียดแปลก ๆ สิ่งนี้ส่วนใหญ่ที่ฉันคิดเกี่ยวกับเมื่อฉันทำเมนูรัศมีสำหรับเกมของฉัน แต่ฉันคิดว่าในรูปแบบ "แบบไดนามิก" มันจะทำงานได้ค่อนข้างดี


1
อันที่จริงตัวอย่างของฉันไม่ได้คำนึงถึงระนาบที่อยู่ด้านบนของกันและกันโดยตรงเช่นในพิกัด x และ z ของพวกเขาตรงกันทุกประการ (แต่ถ้าคุณกำลังใช้โฟลตนี้น่าจะไม่เกิดขึ้น) ตัวอย่างที่ฉันให้นั้นเป็นระนาบใกล้กัน นอกจากนี้คุณอาจคิดว่าจุดสีดำในภาพด้านบนเป็นป้ายกำกับอื่น ๆ
MichaelHouse

1
โอ้ดูเหมือนว่าคุณได้ลบความคิดเห็นของคุณ?
MichaelHouse

1
สิ่งที่ฉันหมายถึงด้วยความเห็นก่อนหน้านี้ [สูตรที่ไม่ดีและทำให้ถูกลบออกไปแล้ว] คือคุณอาจมีสถานการณ์ที่ป้ายกำกับ "ติดกับดัก / ล้อมรอบ" โดยสไปรต์อื่นที่ไม่สามารถเคลื่อนย้ายได้ ในกรณีนี้ป้ายกำกับอาจ "กระโดด" นอกวงกลมล้อมรอบ แต่ก็ไม่ชัดเจนสำหรับฉันว่าจะเกิดอะไรขึ้น BTW: ตอนแรกฉันคิดว่าจุดสีเขียวของรูปภาพของคุณคือเครื่องบินหลายลำซ้อนกันอยู่ด้านบนของอีกด้านหนึ่ง แต่หลังจากความคิดเห็นของคุณฉันรู้ว่าฉันผิดฉันขอโทษ ... )
mac

1
อ่าฉันเข้าใจแล้ว ดังนั้นคุณจะถือว่าจุดดำเป็นทั้งระนาบและฉลาก หากตำแหน่งที่พบโดยการทำซ้ำครั้งแรกไม่ดีให้เพิ่มรัศมีเป็นสองเท่าและตรวจสอบอีกครั้ง หรือคุณมีเวกเตอร์ที่ชี้ให้เห็นจากฝูงชนส่วนใหญ่แล้วคุณสามารถติดตามได้จนกว่าคุณจะพบที่ทำงาน อย่างไรก็ตามฉันคิดว่าวิธีแรกจะได้ผลลัพธ์ที่ดีกว่า
MichaelHouse

9

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

เหตุผลก็คือว่าByte56วิธีการของความต้องการการดูแลเป็นพิเศษสำหรับเงื่อนไขบางอย่างในขณะที่การค้นหาลอยไม่ได้และมันรหัสในทางที่มีขนาดกะทัดรัดจริงๆ นอกจากนี้การค้นหา spriralling ยังเน้นการค้นหาจุดที่อยู่ใกล้กับยานพาหนะเพื่อวางฉลากซึ่ง IMO เป็นปัจจัยหลักในการทำให้แผนที่อ่านได้

อย่างไรก็ตามโปรดตอบคำถามของเขาต่อไปเรื่อย ๆ เนื่องจากไม่เพียงมีประโยชน์เท่านั้น แต่ยังเขียนได้ดีมาก!

นี่คือภาพหน้าจอของผลลัพธ์ที่ทำได้ด้วยรหัสวนวน:

ป้อนคำอธิบายรูปภาพที่นี่

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

def place_tags(self):
    for tag in self.tags:
        start_angle = tag.angle
        while not tag.place() or is_colliding(tag):  #See note n.1
            tag.angle = (tag.angle + angle_step) % 360
            if tag.angle == start_angle:
                tag.radius += radius_step
        tag.connector.update()                       #See note n.2

Note 1 - tag.place()ผลตอบแทนจริงถ้าแท็กทั้งหมดในพื้นที่ที่มองเห็นของหน้าจอ / เรดาร์ ดังนั้นบรรทัดนั้นจะอ่านว่า "วนไปเรื่อย ๆ ถ้าแท็กอยู่นอกเรดาร์หรือทับซ้อนกันอย่างอื่น ... "

หมายเหตุ 2 - tag.connector.updateเป็นวิธีการที่วาดเส้นเชื่อมต่อไอคอนเครื่องบินไปยังฉลาก / แท็กด้วยข้อมูลข้อความ


ทำได้ดีมากกะทัดรัด ขอบคุณสำหรับการสรรเสริญ นอกจากนี้ขอขอบคุณสำหรับการโพสต์เกี่ยวกับสิ่งที่คุณทำมันมีประโยชน์เสมอสำหรับผู้ที่ค้นหาคำตอบในภายหลัง จากภาพหน้าจอดูเหมือนว่ามันทำงานได้ดีมาก! ตรวจสอบให้แน่ใจว่ายอมรับคำตอบของคุณเพราะเป็นสิ่งที่คุณจะต้องทำ
MichaelHouse

@ Byte56 - ขอบคุณสำหรับ "retro-สรรเสริญ";) ฉันกำลังรอการเลือกคำตอบที่ได้รับการยอมรับเพราะฉันยังต้องการรหัสโซลูชันของคุณด้วยและเปรียบเทียบผลลัพธ์ สำหรับหนึ่งฉันสงสัยว่าวิธีการแก้ปัญหาของคุณอาจส่งผลในอีกต่อไป แต่ยังเร็วกว่ารหัสในการดำเนินการ นอกจากนี้ฉันอยากจะดูว่าการเปรียบเทียบทั้งสองในเครื่องบินที่อัดแน่นมาก ... ยังมีโอกาสที่ฉันจะปล่อยรหัสด้วยอัลกอริทึมของคุณ ดูพื้นที่นี้! ;)
mac

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