Wie kann man eine Poisson Disc Sampler?

Ich hab jetzt jetzt einen code geschrieben, aber benötige vom Vector2 das sqrMagnitude. Ich weiß nicht wie ich das machen soll.
[CODE lang="java" title="Der Code fürs Poisson Disc Sampling"]public static List<Vector2> GeneratePoints(float radius, Vector2 sampleRegionSize, int numSamplesBeforeRejection)
{
float cellSize = (float) (radius / Math.sqrt(2));

int[][] grid = new int[(int) Math.ceil(sampleRegionSize.x / cellSize)][(int) Math.ceil(sampleRegionSize.y / cellSize)];
List<Vector2> points = new ArrayList<Vector2>();
List<Vector2> spawnPoints = new ArrayList<Vector2>();

spawnPoints.add(sampleRegionSize.div(2));
while (spawnPoints.size() > 0)
{
int spawnIndex = Utils.getRandom(0, spawnPoints.size());
Vector2 spawnCentre = spawnPoints.get(spawnIndex);
boolean candidateAccepted = false;

for (int i = 0; i < numSamplesBeforeRejection; i++)
{
float angle = (float) (new Random().nextFloat() * Math.PI * 2);
Vector2 dir = new Vector2(Math.sin(angle), Math.cos(angle));
Vector2 candidate = spawnCentre.add(dir.mul(Utils.getRandom(radius, 2 * radius)));
if (IsValid(candidate, sampleRegionSize, cellSize, radius, points, grid))
{
points.add(candidate);
spawnPoints.add(candidate);
grid[(int)(candidate.x / cellSize)][(int)(candidate.y / cellSize)] = points.size();
candidateAccepted = true;
break;
}
}
if (!candidateAccepted)
{
spawnPoints.remove(spawnIndex);
}

}

return points;
}

static boolean IsValid(Vector2 candidate, Vector2 sampleRegionSize, float cellSize, float radius, List<Vector2> points, int[][] grid)
{
if (candidate.x >= 0 && candidate.x < sampleRegionSize.x && candidate.y >= 0 && candidate.y < sampleRegionSize.y)
{
int cellX = (int)(candidate.x / cellSize);
int cellY = (int)(candidate.y / cellSize);
int searchStartX = Math.max(0, cellX - 2);
int searchEndX = Math.min(cellX + 2, grid.length - 1);
int searchStartY = Math.max(0, cellY - 2);
int searchEndY = Math.min(cellY + 2, grid.length - 1);

for (int x = searchStartX; x <= searchEndX; x++)
{
for (int y = searchStartY; y <= searchEndY; y++)
{
int pointIndex = grid[x][y] - 1;
if (pointIndex != -1)
{
float sqrDst = (candidate.sub(points.get(pointIndex))).sqrMagnitude;
if (sqrDst < radius * radius)
{
return false;
}
}
}
}
return true;
}
return false;
}[/CODE]
 
In diesem Code:
Java:
float sqrDst = (candidate.sub(points.get(pointIndex))).sqrMagnitude;
if (sqrDst < radius * radius) {
  ...
}
steht das "sqr" in `sqrDst` für "square" (also ein Wert zum Quadrat) und "Dst" steht hier in diesem Kontext für "Distance".
Also: Das Quadrat der Distanz.
Und hier ist damit einfach die euklidische Distanz/Länge des Vektors, zum Quadrat, gemeint.
Dieser Wert wird ja dann auch mit dem Radius zum Quadrat verglichen.
Die Länge zum Quadrat statt der eigentlichen euklidischen Distanz zu verwenden ist ein berühmter Trick, um die Laufzeit von einer Quadratwurzel zu sparen, weil man die Werte nur komparativ vergleichen will.
Das heisst, du brauchst hier nur das innere/skalar-Produkt des Vektors auszurechnen.
 
Nein. Woher soll ich denn wissen, ob ein Instanzfeld namens "magnitude" überhaupt auf dem statischen Typ des Ausdrucks existiert?
Und ausserdem: Wenn dieses Instanzfeld (genauso wie sqrMagnitude) existiert, dann ist es eine ziemlich schlechte/ineffiziente Implementierung eines Vektors, weil ja bei jeder Erzeugung einer neuen Vektor-Instanz dieses Feld berechnet werden müsste. Und wenn es soetwas wie ein "magnitude" Instanzfeld gäbe, müsste hier auch jedesmal die Quadratwurzel berechnet werden. Das will der eigentliche Code ja gerade vermeiden, nehme ich an.
Wir wissen also gar nicht, von welchen Klassen hier überhaupt die Rede ist...
 
Hab es jetzt hingekriegt. Vector2 hält einfach nur zwei floats, X, Y

[CODE lang="java" title="PoissonDiscSampling"]import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PoissonDiscSampling {

public static List<Vector2> GeneratePoints(float radius, final Vector2 sampleRegionSize, int numSamplesBeforeRejection)
{
float cellSize = (float) (radius / Math.sqrt(2));

int[][] grid = new int[(int) (sampleRegionSize.x / cellSize)][(int) (sampleRegionSize.y / cellSize)];
List<Vector2> points = new ArrayList<Vector2>();
List<Vector2> spawnPoints = new ArrayList<Vector2>();

spawnPoints.add(new Vector2(sampleRegionSize.x / 2, sampleRegionSize.y / 2));
while (spawnPoints.size() > 0)
{
int spawnIndex = Utils.getRandom(0, spawnPoints.size() - 1);
Vector2 spawnCentre = spawnPoints.get(spawnIndex);
boolean candidateAccepted = false;

for (int i = 0; i < numSamplesBeforeRejection; i++)
{
float angle = (float) (new Random().nextFloat() * Math.PI * 2);
Vector2 dir = new Vector2(Math.sin(angle), Math.cos(angle));
Vector2 candidate = spawnCentre.add(dir.mul(Utils.getRandom(radius, 2 * radius)));

if (IsValid(candidate, sampleRegionSize, cellSize, radius, points, grid))
{
points.add(candidate);
spawnPoints.add(candidate);
try {
grid[(int)(candidate.x / cellSize)][(int)(candidate.y / cellSize)] = points.size();
} catch (Exception e) {}
candidateAccepted = true;
break;
}
}
if (!candidateAccepted)
{
spawnPoints.remove(spawnIndex);
}

}

return points;
}

static boolean IsValid(Vector2 candidate, Vector2 sampleRegionSize, float cellSize, float radius, List<Vector2> points, int[][] grid)
{
if (candidate.x >= 0 && candidate.x < sampleRegionSize.x && candidate.y >= 0 && candidate.y <= sampleRegionSize.y)
{
int cellX = (int)(candidate.x / cellSize);
int cellY = (int)(candidate.y / cellSize);
int searchStartX = Math.max(0, cellX - 2);
int searchEndX = Math.min(cellX + 2, grid.length - 2);
int searchStartY = Math.max(0, cellY - 2);
int searchEndY = Math.min(cellY + 2, grid.length - 2);
for (int x = searchStartX; x <= searchEndX; x++)
{
for (int y = searchStartY; y <= searchEndY; y++)
{
int pointIndex = -1;
try {
pointIndex = grid[x][y] - 1;
} catch (Exception e) {}
if (pointIndex != -1)
{
float sqrDst = (candidate.sub(points.get(pointIndex))).magnitude();
sqrDst = (float) Math.sqrt(sqrDst);
if (sqrDst < radius * radius)
{
return false;
}
}
}
}
return true;
}
return false;
}
}[/CODE]

[CODE lang="java" title="Meine Magnitude Lösung"]public float magnitude()
{
return (float)Math.sqrt(x*x + y*y);
}[/CODE]
 

Zurück
Oben