3D 복셀 기반 실내가 효율적으로 밀봉되는지 확인하는 방법


10

큰 방이 복셀 기반 3D 방에 밀봉되어 있는지 효율적으로 결정하는 데 문제가 있습니다. 나는 도움을 요청하지 않고 문제를 해결하기 위해 최선을 다했지만 포기하지 않을 정도로 도움을 요청하는 시점에 있습니다.

명확히하기 위해, 방에 구멍이 없다는 것을 밀봉하십시오. 실내가 밀폐되어 있는지 확인하고 산소 입력 레벨에 따라 밀봉하는 산소 실러가 있습니다.

지금, 이것이 내가하는 일입니다.

  • 실러 타일 위의 블록에서 시작하여 (통풍구가 실러의 윗면에 있음) 6 개의 인접한 모든 방향으로 반복적으로 반복합니다.
  • 인접한 타일이 진공이 아닌 전체 타일 인 경우 루프를 계속 진행하십시오.
  • 인접한 타일이 가득 차지 않았거나 진공 타일 인 경우 인접한 블록이 재귀 적으로 있는지 확인하십시오.
  • 타일을 확인할 때마다 카운터를 줄입니다.
  • 카운트가 0에 도달하면 마지막 블록이 진공 타일에 인접 해 있으면 해당 영역이 봉인되지 않았 음을 반환합니다.
  • 카운트가 0에 도달하고 마지막 블록이 진공 타일이 아니거나 카운터가 0이되기 전에 재귀 루프가 종료되면 (진공 타일이 남지 않음) 영역이 밀봉됩니다

영역이 봉인되지 않은 경우 몇 가지 변경 사항을 적용하여 루프를 다시 실행하십시오.

  • 진공 타일 대신 "통기성 공기"타일이 있는지 인접 블록 점검
  • 감소하는 카운터를 사용하는 대신 인접한 "호흡 가능한 공기"타일이 없을 때까지 계속하십시오.
  • 루프가 완료되면 체크 된 각 블록을 진공 타일로 설정하십시오.

사용중인 코드는 다음과 같습니다. http://pastebin.com/NimyKncC

문제 :

3 초 마다이 검사를 실행하고 때로는 실러가 수백 개의 블록을 통과해야하며 많은 산소 실러가있는 큰 세계가 있습니다. 몇 초마다 여러 개의 재귀 루프가 CPU에서 매우 어려울 수 있습니다.

최적화에 대한 경험이 많은 사람이 나에게 도움을 줄 수 있는지 또는 적어도 올바른 방향으로 나를 가리킬 수 있는지 궁금합니다. 무리 감사.


상황이 언제 변하는 지 확인하는 것이 시작일 것입니다. 복셀이 언제 바뀌어 봉인을 깨뜨릴 수 있는지 알기 때문에 3 초마다 점검하는 것은 과도한 것으로 보입니다. 밀폐 된 방을 구성하는 복셀이 변경되면 해당 방을 다시 확인하도록 표시 할 수 있습니다. 그렇지 않으면 귀찮게하지 마십시오.
MichaelHouse

3 초 동안 수백 개의 복셀이 변경 될 수 있기 때문에 근처에서 무언가가 바뀌 었는지 확인하는 것보다는 정기적으로하는 것이 더 효율적이라고 생각했습니다. 그래도 실험 해 보겠습니다.
NigelMan1010

오, 수백 개의 복셀이 3 초 동안 변경 될 수 있다면 성능에 많은 문제가있을 수 있습니다. 비 효율성을 찾기 위해 코드 프로파일 링을 시작하십시오. 행운을 빕니다!
MichaelHouse

답변:


3

최상의 솔루션은 예상되는 방의 크기와 같은 여러 가지 요소에 의존합니다.

  1. 실제로 변경되는 경우에만이 검사를 수행하십시오.

접근법 1 :

A *를 사용하여 통풍구에서 통풍구 위의 타일 또는 통풍구 자체 또는 진공이라고 알려진 타일까지의 경로를 찾을 수 있습니다. 경로가 발견되면 방이 봉인되지 않은 것입니다. 이것은 현재 접근 방식과 크게 다르지 않지만 더 빠릅니다. 일단 발견되면, "홍수 채우기"를 만들어 타일을 진공으로 설정하십시오.

접근법 2 :

어쩌면 외부 구조가 덜 보완 적 일 수 있습니다-방이있는 곳에 표면이 있다고 생각하면 6 방향으로 모두 움직일 필요가 없으므로 표면을 따라 여행해야하며 모든 타일을 진공으로 표시해야합니다.


0

재귀 검색을 할 때 같은 복셀을 여러 번 확인하지 않습니까? 알고리즘을 설명하는 방식을 알 수는 없지만 복셀을 이미 재귀 적으로 확장했는지 여부를 나타내는 플래그가 있어야하므로 두 번 이상 수행하지 마십시오.

그리고 Byte56이 말했듯이, 상황이 바뀔 때만 누출을 확인해야합니다. 이렇게하면 변경 빈도에 따라 작업량을 크게 최소화 할 수 있습니다. 연속적인 알고리즘 호출 사이에 정보를 캐시 할 수도 있습니다. 첫 번째 호출 후 수행하는 계산량을 사소하게 만들 수 있습니다.

편집하다:

나는 당신의 코드 중 일부를 보았습니다. 첫 번째 단락에서와 같이 복셀이 이미 확인되었는지 표시하기 위해 LinkedList를 사용하고있는 것 같습니다. 이것을 위해 LinkedList 이외의 것을 사용하면 더 나은 결과를 얻을 수 있습니다. 아마도 HashSet 또는 무언가를 시도해보십시오. 이는 검사 방법의 복잡성을 O (n)에서 O (1)로 줄여야합니다.


예, "checked"라는 LinkedList에 추가 한 다음 목록을 확인하기 전에 해당 목록에 위치가 포함되어 있는지 확인합니다. 3 초 내에 수백 개의 복셀이 변경되었을 수 있기 때문에 변경된 것이 있는지 확인하는 것이 CPU를 많이 사용한다고 생각했습니다. 그러나이 상황에서 해시 세트가 링크 된 목록과 어떻게 비교되는지 볼 수 있습니다. 감사합니다.
NigelMan1010
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.