Files
terrain-utilities/src/main/java/pl/wat/ms4ds/terenfunkcje/Bresenham.java

153 lines
4.8 KiB
Java

package pl.wat.ms4ds.terenfunkcje;
/**
* Klasa algorytmiczna do wyznaczania kwadratów odcinka (dyskretyzacja odcinka kwadratami/pikselami).
*/
public class Bresenham {
static int sign(int a) {
if (a > 0)
return 1;
if (a < 0)
return -1;
return 0;
}
/**
* Metoda generuje tablicę współrzędnych gridowych kolejnych punktów/kwadratów podanego odcinka.
* <p>
* Wykorzystuje algorytm Bresenhama.
*
* @param x1 współrzędna x początku
* @param y1 współrzędna y początku
* @param x2 współrzędna x końca
* @param y2 współrzędna y końca
* @return tablicę kolejnych kwadratów tworzących odcinek o zadanych końcach
*/
public static GridCoord[] generateSegment(int x1, int y1, int x2, int y2) {
int x = x1;
int y = y1;
int dx = x2 - x1;
int dy = y2 - y1;
final int sx = sign(dx);
final int sy = sign(dy);
if (dx < 0) {
dx = -dx;
}
if (dy < 0) {
dy = -dy;
}
final int ddx = 2 * dx;
final int ddy = 2 * dy;
int p;
if (dx >= dy) {
// poruszamy się po x
p = ddy - dx;
GridCoord[] res = new GridCoord[dx + 1];
for (int i = 0; i <= dx; i++) {
res[i] = new GridCoord(x, y);
if (p > 0) {
y += sy;
p -= ddx;
}
x += sx;
p += ddy;
}
return res;
} else {
// poruszamy sie po y
p = ddx - dy;
GridCoord[] res = new GridCoord[dy + 1];
for (int i = 0; i <= dy; i++) {
res[i] = new GridCoord(x, y);
if (p > 0) {
x += sx;
p -= ddy;
}
y += sy;
p += ddx;
}
return res;
}
}
static void print(GridCoord[] segment) {
StringBuilder sb = new StringBuilder(300);
sb.append('[');
int last = segment.length - 1;
for (int i = 0; i < segment.length; i++) {
sb.append('(');
sb.append(segment[i].x);
sb.append(',');
sb.append(segment[i].y);
sb.append(')');
if (i < last) {
sb.append('|');
}
}
sb.append(']');
System.out.println(sb);
}
// public static void main(String[] args) {
//
// var segment = generateSegmentSquares(10, 3, 1, 6);
// var segment2 = generateSegmentSquares(1, 6, 10, 3);
// var line = generateSegmentSquares(2, 1, 5, 8);
// var line1 = generateSegmentSquares(5, 8, 2, 1);
// var line2 = generateSegmentSquares(1, 6, 6, 11);
// var line3 = generateSegmentSquares(11, 6, 6, 1);
//
// final int low = 300;
// final int xHigh = 2000;
// final int yHigh = 1000;
// final int TRIAL_LENGTH = 100;
// System.out.println("Start trial 1");
// long t0 = System.nanoTime();
// long sumLen = 0;
// for (int i = 0; i < TRIAL_LENGTH; i++) {
// int x1 = low + RandomStream.uniformInt(-20, 20);
// int y1 = low + RandomStream.uniformInt(-20, 20);
// int x2 = low + RandomStream.uniformInt(-20, 20);
// int y2 = low + RandomStream.uniformInt(-20, 20);
// int dx = Math.abs(x2 - x1);
// int dy = Math.abs(y2 - y1);
// if (dx == dy) {
// continue;
// }
// var seg1 = generateSegmentSquares(x1, y1, x2, y2);
// print(seg1);
// }
// long dt = System.nanoTime() - t0;
// dt /= 1_000_000;
// System.out.println("Czas = " + dt + " [ms]");
// sumLen = 0;
// System.out.println("Start trial 2");
// t0 = System.nanoTime();
// for (int i = 0; i < TRIAL_LENGTH * 10000; i++) {
// int x1 = low + RandomStream.uniformInt(50);
// int y1 = low + RandomStream.uniformInt(50);
// int x2 = 2 * xHigh + RandomStream.uniformInt(1000);
// int y2 = 2 * yHigh + RandomStream.uniformInt(2000);
// int dx = Math.abs(x2 - x1);
// int dy = Math.abs(y2 - y1);
// if (dx == dy) {
// continue;
// }
//
// var seg1 = generateSegmentSquares(x1, y1, x2, y2);
//
// sumLen += seg1.length;
// }
// dt = System.nanoTime() - t0;
// dt /= 1_000_000;
// System.out.println("Czas = " + dt + " [ms] - len=" + sumLen);
//
//// var seg1 = generateSegment(1, 1, 3, 5);
//// var seg2 = generateSegment(14, 4, 3, 8);
//// System.out.println(seg1);
// }
}