153 lines
4.8 KiB
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);
|
|
// }
|
|
}
|