Domanda

Ho bisogno di un chiarimento con algoritmo di generare valori casuali per il mio animaletto ray-tracer.
I emettono raggi da un punto. E ho il problema con la distribuzione di questi raggi: ho bisogno la distribuzione essere uniforme, ma non è ...

Il problema che affronto ora è che la distribuzione uniforme essere inizialmente non è uniforme dopo le mie distorsioni dello spazio dei risultati.

Così, per esempio, ho generare r e t angoli se il sistema di coordinate polari. La distribuzione non è uniforme e non può essere uniforme: spazio vicino ad ogni polo è molto più densità di risultati rispetto, ad esempio, vicino all'equatore. Il motivo è abbastanza chiaro: convertire i punti uniformemente distribuiti dallo spazio cilindrico alla sferica. E io alterare i risultati. Lo stesso problema è che se io normalizzare punti generati in modo casuale nel cubo.

La mia idea ora è questa: Voglio creare un tetraedro, normalizzare i suoi vertici, dividere ciascuna faccia (triangolo) con il punto nel mezzo, normalizzare e ripetere in modo ricorsivo fino a quando non ho abbastanza punti. Poi ho "distorco" questi punti un po '. Poi li ho normalizzare di nuovo. Questo è tutto.

Mi rendo conto che questo metodo non è pura matematica metodo Monte-Carlo stesso, perché io non uso distribuzione casuale in qualsiasi punto tranne l'ultimo. E non mi piace questa soluzione per questa complessità.

Qualcuno può suggerire qualcosa di più semplice, ma ancora

  • casuale
  • uniforme
  • veloce
  • semplice

Grazie!

Modifica
Ho bisogno di un metodo veloce, non solo quella corretta. È per questo che sto chiedendo in merito a Monte-Carlo. Le risposte fornite sono corrette, ma non veloce. Il metodo con il tetraedro è veloce, ma non molto "random" => errato.
Ho davvero bisogno di qualcosa di più adatto.

È stato utile?

Soluzione

Ecco un algoritmo che permette di generare i punti distribuiti sulla sfera unitaria.

Altri suggerimenti

Ecco un'implementazione Java che ho usato in passato:

public static double[] randomPointOnSphere(Random rnd)
{
    double x, y, z, d2;
    do {
        x = rnd.nextGaussian();
        y = rnd.nextGaussian();
        z = rnd.nextGaussian();
        d2 = x*x + y*y + z*z;
    } while (d2 <= Double.MIN_NORMAL);
    double s = Math.sqrt(1.0 / d2);
    return new double[] {x*s, y*s, z*s};
}

Avete veramente bisogno di distribuzione casuale o una distribuzione uniforme sulla sfera?

Poi vorrei suggerire angoli ZCW, equamente distribuiti in tutta la sfera e veloci da calcolare. Altri metodi sono TheSydneyOperaHouse (SOPHE) e repulsione. (Ricerca di repulsion.c) Il metodo di repulsione è abbastanza buona ma lenta: Distribuisce iterativo punti in modo uniforme su una sfera. Fortunatamente deve essere fatto solo una volta.

Questo è usato in cristallografia e NMR, perché per i modelli in polvere è più veloce di utilizzare una distribuzione uniforme rispetto a distribuzione casuale (è necessario meno punti).

Qui è un'implementazione di Python per ZCW.

Maggiori dettagli in questi documenti:

A meno che non si sta raytracing solo scene banali, sarà il vostro tempo di rendering davvero essere dominato da campione tempo raccogliendo? In caso contrario, è probabilmente non vale la pena ottimizzare ancora, però vale la pena di leggere e capire le tecniche di campionamento uniformi riportati nelle altre risposte.

Inoltre, i campioni non devono essere molto casuale per produrre una buona stima di qualsiasi funzione che stai campionamento. Si consiglia di indagare usando una sequenza numerica quasirandom come il sequenza di Halton . La tua idea tetraedro suddivisione non è male. Essa dovrebbe comportare bei punti ben distribuiti che dovrebbe essere migliore di campioni pseudocasuali uniformi per la maggior parte delle scene, anche se potrebbe causare difetti terribili in alcune circostanze.

In ogni caso davvero si consiglia di consultare il forum a ompf.org. Ha ottenuto alcuni nerds raytracing hardcore laggiù.

Per un sezioni sferiche generano l'angolo in modo uniforme in phi (l'angolo polare) e cos(theta) (per theta l'angolo azimutale) fra i propri limiti.

In pseudo-codice:

phi = phi_low_limit        + rand()*(phi_high_limit       - phi_low_limit)
ct = cos(theta_high_limit) + rand()*(cos(theta_low_limit) - cos(theta_high_limit))
// The order is inverted here because cos heads down for increasing theta
theta = arccos(ct)

Questo è un caso particolare della regola che dice che invertire la Jacobiano e generare in modo uniforme quello spazio di quelli coordinate.

Nota: Si noti che sto usando la convenzione opposto per phi e theta dalla linea di David Norman

.

Si noti inoltre: Questo non è in realtà il metodo più veloce, ma piuttosto uno che illustra il principio generale

.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top