2011-06-22 10 views
7

Wdrażam raytracer, a ja jestem w trakcie wdrażania samplerów. Próbnik jest generatorem losowych punktów ponad kwadratem x = 0: 1, y = 0: 1. Każdy próbnik zawiera wiele zestawów "losowych" próbek, a każdy zestaw zawiera określoną liczbę próbek.Zabezpieczanie przetasowania i blokowania NRooków

Teraz jednym z samplerów jest NRooks. Dzieli on powierzchnię w blokach n x n, wybiera bloki wzdłuż przekątnej, w każdym przekątnym bloku wyodrębnia losowy punkt, a na koniec tasuje najpierw między sobą x, a następnie y.

enter image description here

To wszystko jest ładne i czyste. Jednakże, gdy nadszedł czas na wyodrębnienie punktów, książka, którą obserwuję, proponuje te dodatkowe wymagania, aby zerwać korelacje między kolejnymi pikselami i próbkami. Pierwszym wymaganiem jest to, że za każdym razem, gdy zestaw jest wyczerpany, losowo wybierany jest nowy zestaw próbek. Kod wprowadzone do osiągnięcia tego celu jest następująca:

Point2D Sampler::sample_unit_square(void) { 
    if (count % num_samples == 0) jump = (rand_int() % num_sets) * num_samples; 
    return (samples[jump + count++ % num_samples] 
} 

gdzie samples jest wektorem Point2D wielkości num_samples*num_sets (jest linearyzowany). Za każdym razem, gdy jeden piksel jest zrobiony (liczba jest podzielna przez num_samples), nowy skok jest wyodrębniany i używany do wskazania liniowej tablicy dla początku nowego zestawu.

Ponieważ używam Python, moja strategia sprawia, że ​​korzystanie z iteratorów:

def __iter__(self): 

    while True: 
     for sample_set in random.choice(self._samples_sets): 
      for sample in sample_set: 
       yield sample 

to jest trywialne, i działa OK.

Drugą potrzebą jest przetasowanie indeksów i tu jest moje pytanie. Książka zmienia kod następująco

Point2D Sampler::sample_unit_square(void) { 
    if (count % num_samples == 0) jump = (rand_int() % num_sets) * num_samples; 
    return (samples[jump + shuffled_indices[ jump + count++ % num_samples]] 
} 

gdzie tasowane indeksów jest tablicą obliczana następująco

void Sampler::setup_shuffled_indices(void) { 
    shuffled_indices.reserve(num_samples*num_sets); 
    vector<int> indices; 

    for (int j=0; j<num_samples; j++) indices.push_back(j); 

    for (int p=0; p<num_sets; p++) { 
      random_shuffle(indices.begin(), indices.end()); 
      for (int j=0; j<num_samples; j++) { 
       shuffled_indices.push_back(indices[j]); 
      } 
    } 
} 

co jest bardzo C++ sposobu podejmowania listę numerów od 1 do n, a ich losowego. Chciałem zaimplementować następujący kod w Pythonie

def __iter__(self): 

    while True: 
     sample_set = random.choice(self._samples_sets): 
     shuffled_set = sample_set[:] 
     random.shuffle(shuffled_set) 
     for sample in shuffled_set: 
      yield sample 

mogę również realizować losową iterator że iteracje na planie, oszczędzając liście kopiowania, ale to nie o to chodzi. Moje pytanie wynika z następującej frazy w książce:

... Inną możliwością [usunięcia korelacji] jest użycie ostatecznego shuffle na próbkach każdego zestawu, ale to niszczy warunek n-rooks [. ..]. Najlepszym sposobem jest losowe przetasowanie indeksów używanych w sample_unit_square, dla każdego zestawu, ale zagwarantowanie, że wszystkie próbki są używane.

Czego nie rozumiem, to: dlaczego mówi się, że ostateczne przetasowanie na próbkach każdego zestawu łamie n-gawrony? chodzi o to, że używa pośredniego indeksowania do tablicy punktów. Ten indeks pośredni powstaje z przetasowania wszystkich indeksów od 1 do liczby zestawów, ale jest to odpowiednik przetasowania wszystkich próbek w każdym zestawie. Będąc odpowiednikiem IMHO, nie rozumiem, dlaczego pierwsze sformułowanie powinno złamać n-gawrony i dlaczego drugie nie.

Książka, dla przypomnienia, to "Ray śledzący od podstaw" autorstwa Kevina Suffern'a.

+0

Wygląda na to, że autor jest zdezorientowany co do kombinatoryki. Na przykład, przy konstruowaniu układu n-gawronów, dlaczego mieszamy na * obu x i y? Tasowanie na x już dociera do wszystkich n! aranżacje wież; nie powinno też być potrzeby tasowania. –

+0

Czy to możliwe, że autor oznacza przetasowanie całego zestawu, a nie tylko indeksów? tj. z powyższym przykładem 4x4, aby wymieszać wszystkie 16 skrzynek? To by zniszczyło n-gawrony ... – tugs

+0

@tugs: Nie widzę powodu, dla którego powinno. Tasowanie lub użycie indeksu pośredniego, pozwala na wyjście jednego punktu przed drugim. Nie zmienia rozkładu punktów na planszy. –

Odpowiedz

1

To mi wygląda

... użyć ostatecznej SHUFFLE na próbkach każdego zestawu ..

sugeruje shuffle każdy niezależnie ustawić po zestawy tasuje.

def __iter__(self): 

    while True: 
     for sample_set in random.choice(self._samples_sets): 
      for sample in random.choice(sample_set): 
       yield sample 

Tak jak w przypadku. Nie jestem ekspertem od Pythona, więc wybacz każdy błąd kodu. To by złamało n-gawrony, choć może to po prostu zły pomysł. To zależy od tego, do czego zmierzasz.

Powiązane problemy