package pl.wat.ms4ds.terrain; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.wat.ms4ds.common.EGeoDirection; import java.util.ArrayList; public class GeomUtils { private static final Logger logger = LoggerFactory.getLogger(GeomUtils.class); /** *

Wyznacznik macierzy (kwadratowej stopnia 3) * [[p.x, p.y, 1], * [q.x, q.y, 1] * [r.x, r.y, 1]] *

* Pozwala na określenie położenie punktu względem wektora. * * @param p Wsp poczatku wektora * @param q Wsp konca wektora * @param r Wsp testowanego punktu * @return det3 == 0, gdy punkt jest wpolliniowy, det3 wieksze od 0, gdy punkt lezy po lewej stronie wektora, * det3 mniejsze od 0, gdy punkt lezy po prawej stronie wektora, */ public static long det3(Coord.Grid p, Coord.Grid q, Coord.Grid r) { return p.x * (q.y - r.y) + q.x * (r.y - p.y) + r.x * (p.y - q.y); } /** *

Wyznacznik macierzy (kwadratowej stopnia 3) * [[p.x, p.y, 1], * [q.x, q.y, 1] * [r.x, r.y, 1]] *

* Pozwala na określenie położenie punktu względem wektora. * * @param px Wsp x poczatku wektora * @param py Wsp y poczatku wektora * @param qx Wsp x końca wektora * @param qy Wsp y końca wektora * @param rx Wsp x testowanego punktu * @param ry Wsp y testowanego punktu * @return det3 == 0, gdy punkt jest wspolliniowy, det3 wieksze od 0, gdy punkt lezy po lewej stronie wektora, * det3 mniejsze od 0, gdy punkt lezy po prawej stronie wektora, */ public static long det3(int px, int py, int qx, int qy, int rx, int ry) { return px * (qy - ry) + qx * (ry - py) + rx * (py - qy); } /** * Sprawdza, czy punkt r należy do odcinka p-q * * @param p Poczatek odcinka * @param q Koniec odcinka * @param r Punkt testowany * @return true, jesli punkt r lezy na odcinku */ public static boolean include(Coord.Grid p, Coord.Grid q, Coord.Grid r) { return det3(p, q, r) == 0 && Math.min(p.x, q.x) <= r.x && r.x <= Math.max(p.x, q.x) && Math.min(p.y, q.y) <= r.y && r.y <= Math.max(p.y, q.y); } /** * Sprawdza, czy punkt r należy do odcinka p-q * * @param px Wsp x poczatku wektora * @param py Wsp y poczatku wektora * @param qx Wsp x końca wektora * @param qy Wsp y końca wektora * @param rx Wsp x testowanego punktu * @param ry Wsp y testowanego punktu * @return true, jesli punkt r lezy na odcinku */ public static boolean include(int px, int py, int qx, int qy, int rx, int ry) { return det3(px, py, qx, qy, rx, ry) == 0 && Math.min(px, qx) <= rx && rx <= Math.max(px, qx) && Math.min(py, qy) <= ry && ry <= Math.max(py, qy); } /** * Sprawdza, czy punkt r należy do poziomego odcinka p-q * * @param p Poczatek odcinka * @param q Koniec odcinka * @param r Punkt testowany * @return true, jeśli punkt r należy do odcinka p-q */ public static boolean includeHorizontaly(Coord.Grid p, Coord.Grid q, Coord.Grid r) { return p.y == r.y && Math.min(p.x, q.x) <= r.x && r.x <= Math.max(p.x, q.x); // return det3(p, q, r) == 0 && // Math.min(p.x, q.x) <= r.x && // r.x <= Math.max(p.x, q.x) && // Math.min(p.y, q.y) <= r.y && // r.y <= Math.max(p.y, q.y); } /** * Sprawdza, czy punkt r należy do poziomego odcinka p-q * * @param px Wsp x poczatku wektora * @param py Wsp y poczatku wektora * @param qx Wsp x końca wektora * @param qy Wsp y końca wektora * @param rx Wsp x testowanego punktu * @param ry Wsp y testowanego punktu * @return true, jeśli punkt r należy do odcinka p-q */ public static boolean includeHorizontaly(int px, int py, int qx, int qy, int rx, int ry) { return py == ry && Math.min(px, qx) <= rx && rx <= Math.max(px, qx); } /** * Określenie znaku liczby * * @param x Testowana liczba * @return 0, gdy x == 0, 1 gdy x wieksze od 0, -1 gdy x mniejsze od 0 */ public static int sgn(long x) { if (x == 0) { return 0; } if (x > 0) { return 1; } return -1; } /** * Sprawdza, czy odcinki p-q i r-s przecinają się wewnetrznie tzn. * mają dokładnie jeden punkt wspólny różny od każdego z konców odcinków. * * @param p punkt początkowy pierwszego odcinka * @param q punkt końcowy pierwszego odcinka * @param r punkt początkowy drugiego odcinka * @param s punkt końcowy drugiego odcinka * @return true, jeśli odcinki przecinają się wewnętrznie */ public static boolean cross(Coord.Grid p, Coord.Grid q, Coord.Grid r, Coord.Grid s) { long det3_pqr = det3(p, q, r); long det3_pqs = det3(p, q, s); long det3_rsp = det3(r, s, p); long det3_rsq = det3(r, s, q); return sgn(det3_pqr) != sgn(det3_pqs) && sgn(det3_rsp) != sgn(det3_rsq) && det3_pqr != 0 && det3_pqs != 0 && det3_rsp != 0 && det3_rsq != 0; // return sgn(det3(p, q, r)) != sgn(det3(p, q, s)) && // sgn(det3(r, s, p)) != sgn(det3(r, s, q)) && // !include(p, q, r) && // !include(p, q, s) && // !include(r, s, p) && // !include(r, s, q); } /** * Sprawdza, czy odcinki p-q i r-s przecinają się wewnetrznie tzn. * mają dokładnie jeden punkt wspólny różny od każdego z konców odcinków. * * @param px wsp x punktu początkowego pierwszego odcinka * @param py wsp y punktu początkowego pierwszego odcinka * @param qx wsp x punktu końcowego pierwszego odcinka * @param qy wsp y punktu końcowego pierwszego odcinka * @param rx wsp x punktu początkowego drugiego odcinka * @param ry wsp y punktu początkowego drugiego odcinka * @param sx wsp x punktu końcowego drugiego odcinka * @param sy wsp y punktu końcowego drugiego odcinka * @return true, jeśli odcinki przecinają się wewnętrznie */ public static boolean cross(int px, int py, int qx, int qy, int rx, int ry, int sx, int sy) { long det3_pqr = det3(px, py, qx, qy, rx, ry); long det3_pqs = det3(px, py, qx, qy, sx, sy); long det3_rsp = det3(rx, ry, sx, sy, px, py); long det3_rsq = det3(rx, ry, sx, sy, qx, qy); return sgn(det3_pqr) != sgn(det3_pqs) && sgn(det3_rsp) != sgn(det3_rsq) && det3_pqr != 0 && det3_pqs != 0 && det3_rsp != 0 && det3_rsq != 0; // return sgn(det3(p, q, r)) != sgn(det3(p, q, s)) && // sgn(det3(r, s, p)) != sgn(det3(r, s, q)) && // !include(p, q, r) && // !include(p, q, s) && // !include(r, s, p) && // !include(r, s, q); } /** * Sprawdza, czy odcinki p-q i r-s mają dowolną część wspólną. * * @param p punkt początkowy pierwszego odcinka * @param q punkt końcowy pierwszego odcinka * @param r punkt początkowy drugiego odcinka * @param s punkt końcowy drugiego odcinka * @return true, jeśli odcinki mają część wspólną */ public static boolean intersection(Coord.Grid p, Coord.Grid q, Coord.Grid r, Coord.Grid s) { long det3_pqr = det3(p, q, r); long det3_pqs = det3(p, q, s); long det3_rsp = det3(r, s, p); long det3_rsq = det3(r, s, q); return (sgn(det3_pqr) != sgn(det3_pqs) && sgn(det3_rsp) != sgn(det3_rsq)) || (det3_pqr == 0 && det3_pqs == 0 && ((Math.min(p.x, q.x) <= r.x && r.x <= Math.max(p.x, q.x) && Math.min(p.y, q.y) <= r.y && r.y <= Math.max(p.y, q.y)) || (Math.min(p.x, q.x) <= s.x && s.x <= Math.max(p.x, q.x) && Math.min(p.y, q.y) <= s.y && s.y <= Math.max(p.y, q.y)))); } /** * Sprawdza, czy punkt należy do wielokata w ogólnym przypadku (boki wielokata bez samoprzecięć). * * @param polygon Kolejne wierzchołki wielokata. * @param p Testowany punkt. * @return true, jeśli testowany punkt leży wewnątrz wielokąta */ public static boolean insidePolygon(Coord.Grid[] polygon, Coord.Grid p) { // sprawdzenie czy punkt p należy do jednego z boków wielokąta for (int i = 0; i < polygon.length; i++) { int i_plus_1 = (i + 1) % polygon.length; if (include(polygon[i], polygon[i_plus_1], p)) { return true; } } // punkty p i p1 wyznaczają półprostą równoległą do osi OX // współrzędna X punktu p1 musi być większa od największej // współrzędnej X wśród wszystkich wierzchołków wielokąta Coord.Grid p1 = new Coord.Grid(p.x + 1, p.y); for (int i = 0; i < polygon.length; i++) { p1.x = Math.max(polygon[i].x, p1.x); } p1.x++; // licznik przecięć int cross_count = 0; // przechodzenie po wszystkich bokach int i = 0; while (i < polygon.length) { int i_plus_1 = (i + 1) % polygon.length; int i_plus_2 = (i + 2) % polygon.length; int i_minus_1 = (i + polygon.length - 1) % polygon.length; int sgn_det3_i_minus_1 = sgn(det3(p, p1, polygon[i_minus_1])); int sgn_det3_i_plus_1 = sgn(det3(p, p1, polygon[i_plus_1])); int sgn_det3_i_plus_2 = sgn(det3(p, p1, polygon[i_plus_2])); if (includeHorizontaly(p, p1, polygon[i])) { // polprosta p-p1 zawiera wierzchołek w(i) if (includeHorizontaly(p, p1, polygon[i_plus_1])) { // polprosta p-p1 zawiera bok w(i)w(i+1) if (sgn_det3_i_minus_1 != sgn_det3_i_plus_2) { // punkt wczesniejszy w(i-1) i dalszy w(i+2) testowanego boku wielokata // leza po przeciwnych stronach polprostej p-p1, zatem ilosc przeciec +1 cross_count++; } // pomijamy nastepny wierzcholek i++; } else { // polprosta p-p1 zawiera TYLKO wierzchołek w(i) if (sgn_det3_i_minus_1 != 0 && sgn_det3_i_minus_1 != sgn_det3_i_plus_1) { // wierzcholki sasiadujace z wierzchołkiem w(i) tj. w(i-1) i w(i+1) // leza po przeciwnych stronach polprostej p-p1, zatem ilosc przeciec +1 cross_count++; } } } else { // sprawdzenie czy polprosta p-p1 // przecina bok w(i)w(i+1) wielokąta wewnatrz odcinka if (cross(p, p1, polygon[i], polygon[i_plus_1])) { cross_count++; } } i++; } // obliczenie wyniku (nieparzysty oznacza należenie punktu do wielokata) return (cross_count % 2) == 1; } /** * Sprawdza, czy punkt należy do wielokata w ogólnym przypadku (boki wielokata bez samoprzecięć). * * @param polygon Kolejne wierzchołki wielokata. * @param px Wsp. x testowanego punktu. * @param py Wsp. y testowanego punktu. * @return true, jeśli testowany punkt leży wewnątrz wielokąta */ public static boolean insidePolygon(Coord.Grid[] polygon, int px, int py) { // sprawdzenie czy punkt p nie należy do jednego z boków wielokąta for (int i = 0; i < polygon.length; i++) { int i_plus_1 = (i + 1) % polygon.length; if (include(polygon[i].x, polygon[i].y, polygon[i_plus_1].x, polygon[i_plus_1].y, px, py)) { return true; } } // punkty p i p1 wyznaczają półprostą równoległą do osi OX // współrzędna X punktu p1 musi być większa od największej // współrzędnej X wśród wszystkich wierzchołków wielokąta Coord.Grid p1 = new Coord.Grid(px + 1, py); for (int i = 0; i < polygon.length; i++) { p1.x = Math.max(polygon[i].x, p1.x); } p1.x++; // licznik przecięć int cross_count = 0; // przechodzenie po wszystkich bokach int i = 0; while (i < polygon.length) { int i_plus_1 = (i + 1) % polygon.length; int i_plus_2 = (i + 2) % polygon.length; int i_minus_1 = (i + polygon.length - 1) % polygon.length; int sgn_det3_i_minus_1 = sgn(det3(px, py, p1.x, p1.y, polygon[i_minus_1].x, polygon[i_minus_1].y)); if (includeHorizontaly(px, py, p1.x, p1.y, polygon[i].x, polygon[i].y)) { // polprosta p-p1 zawiera wierzchołek w(i) if (includeHorizontaly(px, py, p1.x, p1.y, polygon[i_plus_1].x, polygon[i_plus_1].y)) { int sgn_det3_i_plus_2 = sgn(det3(px, py, p1.x, p1.y, polygon[i_plus_2].x, polygon[i_plus_2].y)); // polprosta p-p1 zawiera bok w(i)w(i+1) if (sgn_det3_i_minus_1 != sgn_det3_i_plus_2) { // punkt wczesniejszy w(i-1) i dalszy w(i+2) testowanego boku wielokata // leza po przeciwnych stronach polprostej p-p1, zatem ilosc przeciec +1 cross_count++; } // pomijamy nastepny wierzcholek i++; } else { int sgn_det3_i_plus_1 = sgn(det3(px, py, p1.x, p1.y, polygon[i_plus_1].x, polygon[i_plus_1].y)); // polprosta p-p1 zawiera TYLKO wierzchołek w(i) if (sgn_det3_i_minus_1 != 0 && sgn_det3_i_minus_1 != sgn_det3_i_plus_1) { // wierzcholki sasiadujace z wierzchołkiem w(i) tj. w(i-1) i w(i+1) // leza po przeciwnych stronach polprostej p-p1, zatem ilosc przeciec +1 cross_count++; } } } else { // sprawdzenie czy polprosta p-p1 // przecina bok w(i)w(i+1) wielokąta wewnatrz odcinka if (cross(px, py, p1.x, p1.y, polygon[i].x, polygon[i].y, polygon[i_plus_1].x, polygon[i_plus_1].y)) { cross_count++; } } i++; } // obliczenie wyniku (nieparzysty oznacza należenie punktu do wielokata) return (cross_count % 2) == 1; } /** * Wyznacza kierunek przeciwny dla zadanego, przy założeniu, że kierunki geograficzne numerowane są od 0 do 7 * * @param kierunek zadany kierunek * @return kierunek przeciwny dla zadanego */ public static int kierunekPrzeciwny(int kierunek) { int kierPrzeciwny = (kierunek + 4) % 8; return kierPrzeciwny; } // tangens kąta alfa = 22.5 stopnia static final double TANG_22_5_DEG = Math.tan(Math.PI / 8); // tangens kąta alfa = 22.5 stopnia static final double TANG_67_5_DEG = Math.tan(3 * Math.PI / 8); /** * Wyznacza najbliższy kierunek geograficzny dla zadanego wektora. * * @param start kwadrat początkowy wektora * @param stop kwadrat końcowy wektora * @return kierunek geograficzny klasy EGeoDirection */ public static EGeoDirection kierunek(Coord.Grid start, Coord.Grid stop) { if (start.x == stop.x && start.y == stop.y) { return EGeoDirection.UNDEFINED; } // polnoc-poludnie if (start.x == stop.x) { if (start.y < stop.y) { return EGeoDirection.NORTH; //na polnoc OK } else { // Start.Y >= Stop.Y return EGeoDirection.SOUTH; //na poludnie OK } } // wschod-zachod if (start.y == stop.y) { if (start.x < stop.x) { return EGeoDirection.EAST; //na wschod OK } else { // Start.X >= Stop.X return EGeoDirection.WEST; //na zachod OK } } // pozostale kierunki double dx = stop.x - start.x; double dy = stop.y - start.y; if (dx > 0) { double tgAlfa = dy / dx; if (tgAlfa >= TANG_67_5_DEG) { return EGeoDirection.NORTH; } else if (tgAlfa >= TANG_22_5_DEG) { return EGeoDirection.NORTHEAST; } else if (tgAlfa >= -TANG_22_5_DEG) { return EGeoDirection.EAST; } else if (tgAlfa >= -TANG_67_5_DEG) { return EGeoDirection.SOUTHEAST; } else { return EGeoDirection.SOUTH; } } else { double tgAlfa = dy / -dx; if (tgAlfa >= TANG_67_5_DEG) { return EGeoDirection.NORTH; } else if (tgAlfa >= TANG_22_5_DEG) { return EGeoDirection.NORTHWEST; } else if (tgAlfa >= -TANG_22_5_DEG) { return EGeoDirection.WEST; } else if (tgAlfa >= -TANG_67_5_DEG) { return EGeoDirection.SOUTHWEST; } else { return EGeoDirection.SOUTH; } } } /** * Funkcja zwraca kierunek geograficzny dla wektora opisanego na sasiednich kwadratach. * * @param start współrzędne (X, Y) siatki kwadratu początkowego * @param stop współrzędne (X, Y) siatki kwadratu końcowego * @return kierunek geograficzny klasy EGeoDirection dla wektora zadanego przez kwadrat początkowy * i końcowy lub UNDEFINED dla kwadratów niesąsiednich */ public static EGeoDirection kierunekDlaSasiada(Coord.Grid start, Coord.Grid stop) { int d = Math.abs(start.x - stop.x) + Math.abs(start.y - stop.y); if (d == 1 || d == 2) { if (start.x == stop.x) { if (start.y < stop.y) { return EGeoDirection.NORTH; } return EGeoDirection.SOUTH; } if (start.y == stop.y) { if (start.x < stop.x) { return EGeoDirection.EAST; } return EGeoDirection.WEST; } if (start.x < stop.x) { if (start.y < stop.y) { return EGeoDirection.NORTHEAST; } return EGeoDirection.SOUTHEAST; } if (start.y < stop.y) { return EGeoDirection.NORTHWEST; } return EGeoDirection.SOUTHWEST; } else { return EGeoDirection.UNDEFINED; } } /** * Funkcja zwraca kierunek geograficzny dla wektora opisanego na sasiednich kwadratach. * * @param xStart współrzędne X siatki kwadratu początkowego * @param yStart współrzędne Y siatki kwadratu początkowego * @param xStop współrzędne X siatki kwadratu końcowego * @param yStop współrzędne Y siatki kwadratu końcowego * @return kierunek geograficzny dla wektora zadanego przez kwadrat początkowy i końcowy lub UNDEFINED dla kwadratów niesąsiednich */ public static EGeoDirection kierunekDlaSasiada(int xStart, int yStart, int xStop, int yStop) { int d = Math.abs(xStart - xStop) + Math.abs(yStart - yStop); if (d == 1 || d == 2) { if (xStart == xStop) { if (yStart < yStop) { return EGeoDirection.NORTH; } return EGeoDirection.SOUTH; } if (yStart == yStop) { if (xStart < xStop) { return EGeoDirection.EAST; } return EGeoDirection.WEST; } if (xStart < xStop) { if (yStart < yStop) { return EGeoDirection.NORTHEAST; } return EGeoDirection.SOUTHEAST; } if (yStart < yStop) { return EGeoDirection.NORTHWEST; } return EGeoDirection.SOUTHWEST; } else { return EGeoDirection.UNDEFINED; } } private static final float PRZEKATNA_MK = MapConsts.SS_SIZE * (float) Math.sqrt(2); /** * Funkcja wyznacza odległość między środkami kwadratów sąsiednich na zadanym kierunku * * @param kierunek zadany kierunek sąsiedztwa * @return odległość między środkami kwadratów sąsiednich [m] */ public static float odlegloscKwadratowSasiednich(EGeoDirection kierunek) { switch (kierunek) { case NORTH: case SOUTH: case EAST: case WEST: return MapConsts.SS_SIZE; case NORTHEAST: case NORTHWEST: case SOUTHEAST: case SOUTHWEST: return PRZEKATNA_MK; default: return 0.0f; } } /** * Funkcja wyznacza sumaryczną długość drogi podanej jako ciąg sąsiednich kwadratów * * @param road droga jako ciąg sąsiednich kwadratów * @return sumaryczna długość drogi [m] */ public static float dlugoscDrogiPoKwadratch(Coord.Grid[] road) { float dl = 0; for (int i = 1; i < road.length; i++) { dl += Coord.Grid.distance(road[i - 1], road[i]); } return dl; } /** * Funkcja wyznacza tablicę kwadratów leżących na łamanej. * * @param punktyLamanej tablica wspolrzednych tworzących łamaną * @return kwadratyWyj kolekcja kwadratów leżących na łamanej */ public static ArrayList kwadratyLamanej(Coord.Grid[] punktyLamanej) { ArrayList kwadratyWyj = new ArrayList(); if (punktyLamanej.length == 2) { Coord.Grid[] kwadraty = kwadratyOdcinka(punktyLamanej[0], punktyLamanej[1]); for (int i = 0; i < kwadraty.length; i++) { kwadratyWyj.add(kwadraty[i]); } return kwadratyWyj; } for (int i = 0; i < punktyLamanej.length - 1; i++) { Coord.Grid[] kwadraty = kwadratyOdcinka(punktyLamanej[i], punktyLamanej[i + 1]); int lko; if (i < punktyLamanej.length - 2) { // odcinek lamanej nie jest ostatni, zatem bez ostatniego kwadratu odcinka, // gdyz powtorzy sie jako pierwszy w nastepnym odcinku lamanej lko = kwadraty.length - 1; } else { lko = kwadraty.length; } for (int j = 0; j < lko; j++) { kwadratyWyj.add(kwadraty[j]); } } return kwadratyWyj; } /** * Funkcja wyznacza tablicę kwadratów leżących na łamanej. * * @param punktyLamanej tablica wspolrzednych odcinków tworzących łamaną * @return tablica (ciąg) sąsiednich kwadratów leżących na łamanej */ public static Coord.Grid[] kwadratyLamanej2(Coord.Grid[] punktyLamanej) { Coord.Grid[] kwadratyWyj; if (punktyLamanej.length == 2) { kwadratyWyj = kwadratyOdcinka(punktyLamanej[0], punktyLamanej[1]); return kwadratyWyj; } int maxLen = 0; for (int i = 0; i < punktyLamanej.length - 1; i++) { maxLen += Math.abs(punktyLamanej[i].x - punktyLamanej[i + 1].x) + Math.abs(punktyLamanej[i].y - punktyLamanej[i + 1].y) + 1; } Coord.Grid[] helpTab = new Coord.Grid[maxLen]; int lastLen = 0; for (int i = 0; i < punktyLamanej.length - 1; i++) { Coord.Grid[] kwadraty = kwadratyOdcinka(punktyLamanej[i], punktyLamanej[i + 1]); // liczba kwadratów bieżącego odcinka do zapamietania int lko; if (i < punktyLamanej.length - 2) { // odcinek lamanej nie jest ostatni, zatem bez ostatniego kwadratu odcinka, // gdyz powtorzy sie jako pierwszy w nastepnym odcinku lamanej lko = kwadraty.length - 1; } else { // ostatni odcinek łamanej, zatem wszystkie kwadraty odcinka lko = kwadraty.length; } System.arraycopy(kwadraty, 0, helpTab, lastLen, lko); // for (int j = 0; j < lko; j++) { // helpTab[lastLen] = kwadraty[j]; // lastLen++; // } } kwadratyWyj = new Coord.Grid[lastLen]; System.arraycopy(helpTab, 0, kwadratyWyj, 0, lastLen); // for (int i = 0; i < lastLen; i++) { // kwadratyWyj[i] = helpTab[i]; // } return kwadratyWyj; } /** * Funkcja wyznacza tablice (ciąg) sąsiednich kwadratow na odcinku zadanym przez wspolrzedne jego koncow. * * @param pocz wspolrzedna poczatku odcinka * @param kon wspolrzedna konca odcinka * @return tablica sąsiednich kwadratow lezacych na odcinku */ public static Coord.Grid[] kwadratyOdcinka(Coord.Grid pocz, Coord.Grid kon) { return kwadratyOdcinka(pocz.x, pocz.y, kon.x, kon.y); } /** * Funkcja wyznacza tablice (ciąg) sąsiednich kwadratow na odcinku zadanym przez wspolrzedne jego koncow. * * @param xp wspolrzedna x poczatku * @param yp wspolrzedna y poczatku * @param xk wspolrzedna x konca * @param yk wspolrzedna y konca * @return tablica sąsiednich kwadratow lezacych na odcinku */ public static Coord.Grid[] kwadratyOdcinka(int xp, int yp, int xk, int yk) { Coord.Grid[] kwadraty; if ((xp == xk) && (yp == yk)) { // odcinek skladajacy sie z jednego kwadratu kwadraty = new Coord.Grid[1]; kwadraty[0] = new Coord.Grid(xp, yp); return kwadraty; } if (xp == xk) { // odcinek pionowy kwadraty = kwadratyOdcinkaPionowego(xp, yp, xk, yk); return kwadraty; } if (yp == yk) { // odcinek poziomy kwadraty = kwadratyOdcinkaPoziomego(xp, yp, xk, yk); return kwadraty; } int dx = Math.abs(xk - xp); int dy = Math.abs(yk - yp); if (dx == dy) { // odcinek na przekatnej duzego kwadratu kwadraty = kwadratyOdcinkaNaPrzekatnej(xp, yp, xk, yk); } else { // odcinek na przekatnej duzego prostokata kwadraty = kwadratyOdcinkaDowolnego(xp, yp, xk, yk); } return kwadraty; } /** * Funkcja pomocnicza. * Funkcja zwraca kwadraty odcinka/wektora zorientowanego względem osi OX pod katem 90 stop. lub 270 stop. * * @param xp wspolrzedna x poczatku * @param yp wspolrzedna y poczatku * @param xk wspolrzedna x konca * @param yk wspolrzedna y konca * @return tablica kwadratow lezacych na odcinku */ private static Coord.Grid[] kwadratyOdcinkaPionowego(int xp, int yp, int xk, int yk) { Coord.Grid[] kwadraty = new Coord.Grid[Math.abs(yp - yk) + 1]; if (yp < yk) { // zorientowanie wektora do gory for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp, yp + i); } } else { // zorientowanie wektora do dolu for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp, yp - i); } } return kwadraty; } /** * Funkcja pomocnicza. * Funkcja zwraca kwadraty odcinka/wektora zorientowanego względem osi OX pod katem 0 stop. lub 180 stop.. * * @param xp wspolrzedna x poczatku * @param yp wspolrzedna y poczatku * @param xk wspolrzedna x konca * @param yk wspolrzedna y konca * @return tablica kwadratow lezacych na odcinku */ private static Coord.Grid[] kwadratyOdcinkaPoziomego(int xp, int yp, int xk, int yk) { Coord.Grid[] kwadraty = new Coord.Grid[Math.abs(xp - xk) + 1]; if (xp < xk) { // zorientowanie wektora w prawo for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp + i, yp); } } else { // zorientowanie wektora w lewo for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp - i, yp); } } return kwadraty; } /** * Funkcja pomocnicza. * Zwraca kwadraty leżące na odcinku/wektorze zorientowanym względem osi OX pod kątem innym niż: 0, 90, 180, 270. * * @param xp wspolrzedna x poczatku * @param yp wspolrzedna y poczatku * @param xk wspolrzedna x konca * @param yk wspolrzedna y konca * @return tablica kwadratow lezacych na odcinku */ private static Coord.Grid[] kwadratyOdcinkaDowolnego(int xp, int yp, int xk, int yk) { int x = xp; int y = yp; int dx = xk - xp; int dy = yk - yp; Coord.Grid[] tab; int abs_dx = Math.abs(dx); int abs_dy = Math.abs(dy); if (abs_dx > abs_dy) { // przypadek, gdy poruszamy sie po osi OX // wyznaczenie wspolczynnikow prostej zawierającej odcinek na podstawie środków kwadratów double a = (double) dy / (double) dx; double b = yp + 0.5 - a * (xp + 0.5); tab = new Coord.Grid[abs_dx + 1]; int i = 0; tab[i] = new Coord.Grid(x, y); if (dx > 0) { // idziemy w prawo w kierunku rosnacych wartosci x if (dy > 0) { // prosta zaierająca odcinek jest funkcją rosnącą while (x < xk) { x++; int yy_ref = y + 1; double yy_l_test = a * x + b; double yy_h_test = a * (x + 1) + b; double dy_l = Math.abs(yy_ref - yy_l_test); double dy_h = Math.abs(yy_ref - yy_h_test); if (dy_l <= dy_h) { y++; } i++; tab[i] = new Coord.Grid(x, y); } } else { // prosta zawierająca odcinek jest funkcją malejącą while (x < xk) { x++; int yy_ref = y; double yy_l_test = a * x + b; double yy_h_test = a * (x + 1) + b; double dy_l = Math.abs(yy_ref - yy_l_test); double dy_h = Math.abs(yy_ref - yy_h_test); if (dy_l <= dy_h) { y--; } i++; tab[i] = new Coord.Grid(x, y); } } } else { // idziemy w lewo w kierunku malejacych wartosci x if (dy > 0) { // prosta zaierająca odcinek jest funkcją malejącą while (x > xk) { x--; int yy_ref = y + 1; double yy_l_test = a * x + b; double yy_h_test = a * (x + 1) + b; double dy_l = Math.abs(yy_ref - yy_l_test); double dy_h = Math.abs(yy_ref - yy_h_test); if (dy_l >= dy_h) { y++; } i++; tab[i] = new Coord.Grid(x, y); } } else { // prosta zaierająca odcinek jest funkcją rosnącą while (x > xk) { x--; int yy_ref = y; double yy_l_test = a * x + b; double yy_h_test = a * (x + 1) + b; double dy_l = Math.abs(yy_ref - yy_l_test); double dy_h = Math.abs(yy_ref - yy_h_test); if (dy_l >= dy_h) { y--; } i++; tab[i] = new Coord.Grid(x, y); } } } } else { // przypadek, gdy poruszamy sie po osi OY // zamiana wspolrzednych koncow odcinka tab = kwadratyOdcinkaDowolnego(yp, xp, yk, xk); // zamiana wspolrzednych x <-> y for (int i = 0; i < tab.length; i++) { int temp = tab[i].x; tab[i].x = tab[i].y; tab[i].y = temp; } } return tab; } /** * Funkcja pomocnicza. * Zwraca kwadraty lezace na odcinku zorientowanaym pod dowolnym katem wzgledem osi OX. * * @param xp wspolrzedna x poczatku * @param yp wspolrzedna y poczatku * @param xk wspolrzedna x konca * @param yk wspolrzedna y konca * @return tablica kwadratow lezacych na odcinku */ private static Coord.Grid[] kwadratyOdcinkaDowolnego2(int xp, int yp, int xk, int yk) { int dx = xk - xp; int dy = yk - yp; if (Math.abs(dx) > Math.abs(dy)) { // przypadek, gdy poruszamy sie po osi OX // wyznaczenie wspolczynnikow prostej (wartosci w metrach) float a; float b; float dxf = (float) dx; float dyf = (float) dy; a = dyf / dxf; // wspolrzedne srodka kwadratu (xp, yp) int xxp = xp * MapConsts.SS_SIZE + MapConsts.SS_SIZE / 2; int yyp = yp * MapConsts.SS_SIZE + MapConsts.SS_SIZE / 2; b = yyp - a * xxp; if (dx > 0) { // idziemy w prawo w kierunku rosnacych wartosci x Coord.Grid[] temp = new Coord.Grid[Math.abs(dx) + Math.abs(dy) + 1]; int dl = 0; temp[dl] = new Coord.Grid(); temp[dl].x = xp; temp[dl].y = yp; dl++; for (int x = xp + 1; x <= xk - 1; x++) { // wspolrzedne wierzcholkow kwadratu w metrach int xd, xg; int yd, yg; int y1, y2; xd = (x - 1) * MapConsts.SS_SIZE; xg = x * MapConsts.SS_SIZE; float ydf = a * xd + b; float ygf = a * xg + b; yd = (int) ydf; yg = (int) ygf; y1 = yd / MapConsts.SS_SIZE + 1; y2 = yg / MapConsts.SS_SIZE + 1; temp[dl] = new Coord.Grid(); temp[dl].x = x; temp[dl].y = y1; dl++; if (y1 != y2) { temp[dl] = new Coord.Grid(); temp[dl].x = x; temp[dl].y = y2; dl++; } } temp[dl] = new Coord.Grid(); temp[dl].x = xk; temp[dl].y = yk; dl++; Coord.Grid[] kwadraty = new Coord.Grid[dl]; System.arraycopy(temp, 0, kwadraty, 0, dl); // for (int i = 0; i < kwadraty.length; i++) { // // przepisanie referencji na wspolrzedne kwadratow // kwadraty[i] = temp[i]; // } return kwadraty; } else { // idziemy w lewo w kierunku malejacych wartosci x // zamiana koncow odcinka Coord.Grid[] temp = kwadratyOdcinkaDowolnego2(xk, yk, xp, yp); Coord.Grid[] kwadraty = new Coord.Grid[temp.length]; for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = temp[kwadraty.length - 1 - i]; } return kwadraty; } } else { // przypadek, gdy poruszamy sie po osi OY // zamiana wspolrzednych koncow odcinka Coord.Grid[] kwadraty = kwadratyOdcinkaDowolnego2(yp, xp, yk, xk); // przepisanie wspolrzednych do nowej tablicy // z zamiana wspolrzednych for (int i = 0; i < kwadraty.length; i++) { int temp_x = kwadraty[i].x; kwadraty[i].x = kwadraty[i].y; kwadraty[i].y = temp_x; } return kwadraty; } } /** * Funkcja pomocnicza. * Zwraca kwadraty lezace na odcinku zorientowanaym pod katem 45 lub 135 stop. wzgledem osi OX. * * @param xp wspolrzedna x poczatku * @param yp wspolrzedna y poczatku * @param xk wspolrzedna x konca * @param yk wspolrzedna y konca * @return tablica kwadratow lezacych na odcinku */ private static Coord.Grid[] kwadratyOdcinkaNaPrzekatnej(int xp, int yp, int xk, int yk) { int dx = xk - xp; int dy = yk - yp; Coord.Grid[] kwadraty = new Coord.Grid[Math.abs(dx) + 1]; if ((dx > 0) && (dy > 0)) { // wektor typu "/" do gory for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp + i, yp + i); } } else if ((dx > 0) && (dy < 0)) { // wektor typu "\" do dolu for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp + i, yp - i); } } else if ((dx < 0) && (dy < 0)) { // wektor typu "/" do dolu for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp - i, yp - i); } } else { // wektor typu "\" do gory for (int i = 0; i < kwadraty.length; i++) { kwadraty[i] = new Coord.Grid(xp - i, yp + i); } } return kwadraty; } /** * Funkcja wyznacza ograniczenie dolne wspolrzednych rejonu * * @param rejon * @return ograniczenie dolne wspolrzednych rejonu */ public static Coord.Grid wspXYOgranDolne(Coord.Grid[] rejon) { if (rejon == null) { return null; } Coord.Grid kw_min = new Coord.Grid(); kw_min.x = rejon[0].x; kw_min.y = rejon[0].y; for (int i = 1; i < rejon.length; i++) { if (kw_min.x > rejon[i].x) { kw_min.x = rejon[i].x; } if (kw_min.y > rejon[i].y) { kw_min.y = rejon[i].y; } } return kw_min; } /** * Funkcja wyznacza ograniczenie górne wspolrzednych rejonu * * @param rejon * @return ograniczenie górne wspolrzednych rejonu */ public static Coord.Grid wspXYOgranGorne(Coord.Grid[] rejon) { if (rejon == null) { return null; } Coord.Grid kw_max = new Coord.Grid(); kw_max.x = rejon[0].x; kw_max.y = rejon[0].y; for (int i = 1; i < rejon.length; i++) { if (kw_max.x < rejon[i].x) { kw_max.x = rejon[i].x; } if (kw_max.y < rejon[i].y) { kw_max.y = rejon[i].y; } } return kw_max; } /** * Funkcja bada należenie punktu do prostokąta zorientowanego równolegle do osi współrzędnych * * @param xMin minimalna współrzędna X prostokąta (lewego dolnego rogu) * @param yMin minimalna współrzędna Y prostokąta (lewego dolnego rogu) * @param xMax maksymalna współrzędna X prostokąta (prawego górnego rogu) * @param yMax maksymalna współrzędna Y prostokąta (prawego górnego rogu) * @param xTest współrzędna X punktu testowanego * @param yTest współrzędna Y punktu testowanego * @return true, jeśli testowany punkt należy do prostokąta */ public static boolean nalezyDoProstokata(int xMin, int yMin, int xMax, int yMax, int xTest, int yTest) { if (xTest < xMin || xTest > xMax) { return false; } if (yTest < yMin || yTest > yMax) { return false; } return true; } /** * Funkcja usuwa z tablicy wejściowej rejon wierzchołków obszaru powtarzające się sąsiednie wierzchołki * * @param rejon tablica wierzchołków obszaru * @return poprawioną tablicę wierzchołków obszaru */ public static Coord.Grid[] poprawRejon(Coord.Grid[] rejon) { if ((rejon == null) || (rejon.length <= 0)) { return null; } int j = 0; Coord.Grid[] rejon_temp = new Coord.Grid[rejon.length]; rejon_temp[j] = rejon[j]; for (int i = j + 1; i < rejon.length; i++) { if (!rejon[i].equals(rejon_temp[j])) { if (i == rejon.length - 1) { if (rejon[i].equals(rejon_temp[0])) { break; } } j++; rejon_temp[j] = rejon[i]; } } if ((j > 0) && (rejon_temp[0].equals(rejon_temp[j]))) { j--; } Coord.Grid[] rejon_popr = new Coord.Grid[j + 1]; System.arraycopy(rejon_temp, 0, rejon_popr, 0, rejon_popr.length); // for (int k = 0; k < rejonPopr.length; k++) { // rejonPopr[k] = rejon_temp[k]; // } return rejon_popr; } /** * Funkcja wyznacza tablice (kolekcję) kwadratow należących do zadanego obszaru * * @param rej kolejne wierzchołki obszaru zadawane prawoskretnie * @return tablica kwadratów należących do zadanego obszaru */ public static Coord.Grid[] kwadratyObszaru(Coord.Grid[] rej) { if (rej == null) { return null; } Coord.Grid[] kwadraty = null; Coord.Grid[] rejon = poprawRejon(rej); if (rejon.length == 1) { //TODO Tu raczej jest blad kwadraty = new Coord.Grid[1]; return kwadraty; } if (rejon.length == 2) { return kwadratyOdcinka(rejon[0].x, rejon[0].y, rejon[1].x, rejon[1].y); } Coord.Grid kw_min = wspXYOgranDolne(rejon); Coord.Grid kw_max = wspXYOgranGorne(rejon); int dl = (kw_max.x - kw_min.x + 1) * (kw_max.y - kw_min.y + 1); Coord.Grid[] kwadraty_temp = new Coord.Grid[dl]; // sprawdzenie kazdego kwadratu z duzego obszaru // (prostokat opisany na rejonie) dl = 0; for (int x = kw_min.x; x <= kw_max.x; x++) { for (int y = kw_min.y; y <= kw_max.y; y++) { if (insidePolygon(rejon, x, y)) { // if (nalezyDoObszaru(rejon, i, j)) { // kwadrat o indeksach (i,j) nalezy do obszaru kwadraty_temp[dl] = new Coord.Grid(x, y); dl++; } } } kwadraty = new Coord.Grid[dl]; System.arraycopy(kwadraty_temp, 0, kwadraty, 0, dl); // for (int i = 0; i < kwadraty.length; i++) { // kwadraty[i] = new Coord.GridCoord(); // kwadraty[i].x = kwadraty_temp[i].x; // kwadraty[i].y = kwadraty_temp[i].y; // } return kwadraty; } /** * Funkcja wyznacza srodek zadanego odcinka * * @param odc odcinek wejściowy * @return współrzędne środka zadanego odcinka */ public static Coord.Grid srodekOdcinka(Coord.Grid[] odc) { Coord.Grid srodek = null; int xsr = 0, ysr = 0; if ((odc != null) && (odc.length > 0)) { srodek = new Coord.Grid(); for (int j = 0; j < odc.length; j++) { xsr = xsr + odc[j].x; ysr = ysr + odc[j].y; } srodek.x = (int) xsr / odc.length; srodek.y = (int) ysr / odc.length; } return srodek; } /** * Funkcja wyznacza srodek zadanego odcinka * * @param pocz początek wejściowego odcinka * @param kon koniec wejsciowego odcinka * @return współrzędne środka zadanego odcinka */ public static Coord.Grid srodekOdcinka(Coord.Grid pocz, Coord.Grid kon) { Coord.Grid srodek = null; int xsr = 0, ysr = 0; if ((pocz == null) || (kon == null)) { return srodek; } xsr = (pocz.x + kon.x) / 2; ysr = (pocz.y + kon.y) / 2; srodek = new Coord.Grid(xsr, ysr); return srodek; } /** * Funkcja wyznacza ważony środek odcinka * * @param pocz początek wejściowego odcinka * @param kon koniec wejsciowego odcinka * @param waga waga współrzędnych początku odcinka * @return ważone współrzędne środka zadanego odcinka */ public static Coord.Grid srodekOdcinkaWazony(Coord.Grid pocz, Coord.Grid kon, float waga) { Coord.Grid srodek = null; if ((waga < 0.0f) || (waga > 1.0f)) { return srodek; } int xsr = 0, ysr = 0; if ((pocz == null) || (kon == null)) { return srodek; } float f_xsr = pocz.x * waga + kon.x * (1.0f - waga); float f_ysr = pocz.y * waga + kon.y * (1.0f - waga); xsr = (int) f_xsr; ysr = (int) f_ysr; srodek = new Coord.Grid(xsr, ysr); return srodek; } /** * Funkcja wyznacza pozostałą długość drogi odcinka od zadanego punktu tej drogi do jej końca * * @param droga zadana droga * @param pocz punkt od którego liczona pozostała długość drogi * @return pozostała długość odcinka od punktu pocz [m] */ public static float wyznaczPozostalaDlugoscDrogi(ArrayList droga, int pocz) { if ((droga == null) || (droga.size() == 0) || (pocz < 0) || (pocz >= droga.size())) { return 0.0f; } double dl = 0.0f; Coord.Grid idkw1 = droga.get(pocz); Coord.Grid idkw2; for (int j = pocz + 1; j < droga.size() - 1; j++) { idkw2 = droga.get(j); dl += Coord.Grid.distance(idkw1.x, idkw1.y, idkw2.x, idkw2.y); idkw1 = idkw2; } return (float) dl; } /** * Funkcja zwraca odleglosc miedzy srodkami malych kwadratow [m]. * * @param p1 współrzędna malego kwadratu pocz. * @param p2 współrzędna malego kwadratu konc. * @return Odległość między środkami małych kwadratów [m]. */ public static float odleglosc(Coord.Grid p1, Coord.Grid p2) { // odleglosc miedzy srodkami malych kwadratow if (null == p1 || null == p2) { return -1.0f; } int xx = p1.x - p2.x; xx *= xx; int yy = p1.y - p2.y; yy *= yy; float odl = (float) Math.sqrt(xx + yy); odl *= MapConsts.SS_SIZE; return odl; } /** * Funkcja zwraca odległość między środkami małych kwadratów [m]. * * @param x1 Wsp X id malego kwadratu pocz. * @param y1 Wsp Y id malego kwadratu pocz. * @param x2 Wsp X id malego kwadratu konc. * @param y2 Wsp Y id malego kwadratu konc. * @return Odległość miedzy srodkami malych kwadratow [m]. */ public static float odleglosc(int x1, int y1, int x2, int y2) { // odleglosc miedzy srodkami malych kwadratow int xx = x1 - x2; xx *= xx; int yy = y1 - y2; yy *= yy; float odl = (float) Math.sqrt(xx + yy); odl *= MapConsts.SS_SIZE; return odl; } /** * Funkcja zwraca odległość między środkami małych kwadratów [m]. * * @param dx odległość w kwadratach na osi OX. * @param dy odległość w kwadratach na osi OY. * @return Odległość miedzy srodkami malych kwadratow [m]. */ public static float odleglosc(int dx, int dy) { float odl = (float) Math.sqrt(dx * dx + dy * dy); odl *= MapConsts.SS_SIZE; return odl; } // ===================================================================== public static void main(String[] args) { double odl = Coord.Grid.distance(1, 1, 2, 2); double odl2 = Coord.Grid.distanceApprox(1, 1, 2, 2); logger.debug("dist = {}, dist2 = {}, DELTA = {}, delta = {}", odl, odl2, odl - odl2, (odl - odl2) / odl); odl = Coord.Grid.distance(1, 1, 21, 21); odl2 = Coord.Grid.distanceApprox(1, 1, 21, 21); logger.debug("dist = {}, dist2 = {}, DELTA = {}, delta = {}", odl, odl2, odl - odl2, (odl - odl2) / odl); odl = Coord.Grid.distance(1, 1, 1, 21); odl2 = Coord.Grid.distanceApprox(1, 1, 1, 21); logger.debug("dist = {}, dist2 = {}, DELTA = {}, delta = {}", odl, odl2, odl - odl2, (odl - odl2) / odl); odl = Coord.Grid.distance(1, 1, 10, 21); odl2 = Coord.Grid.distanceApprox(1, 1, 10, 21); logger.debug("dist = {}, dist2 = {}, DELTA = {}, delta = {}", odl, odl2, odl - odl2, (odl - odl2) / odl); odl = Coord.Grid.distance(1, 1, 100, 210); odl2 = Coord.Grid.distanceApprox(1, 1, 100, 210); logger.debug("dist = {}, dist2 = {}, DELTA = {}, delta = {}", odl, odl2, odl - odl2, (odl - odl2) / odl); odl = Coord.Grid.distance(1, 1, 5, 210); odl2 = Coord.Grid.distanceApprox(1, 1, 5, 210); logger.debug("dist = {}, dist2 = {}, DELTA = {}, delta = {}", odl, odl2, odl - odl2, (odl - odl2) / odl); Coord.Grid p = new Coord.Grid(4, 6); Coord.Grid q = new Coord.Grid(8, 2); Coord.Grid r = new Coord.Grid(6, 4); Coord.Grid s = new Coord.Grid(8, 6); Coord.Grid startCoord = new Coord.Grid(10, 10); Coord.Grid stopCoord = new Coord.Grid(); for (int y = 20; y >= 0; y--) { for (int x = 0; x <= 20; x++) { stopCoord.set(x, y); EGeoDirection kier = kierunek(startCoord, stopCoord); switch (kier) { case NORTH: System.out.print('|'); break; case NORTHEAST: System.out.print('/'); break; case EAST: System.out.print('-'); break; case SOUTHEAST: System.out.print('\\'); break; case SOUTH: System.out.print('|'); break; case SOUTHWEST: System.out.print('/'); break; case WEST: System.out.print('-'); break; case NORTHWEST: System.out.print('\\'); break; case UNDEFINED: System.out.print('O'); break; } } System.out.println(); } System.out.println(); EGeoDirection kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(10, 15)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(10, 5)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 10)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 10)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(9, 15)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(11, 15)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(9, 5)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(11, 5)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 9)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 11)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 9)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 11)); System.out.println(kier); // Kierunki pośrednie: PLN-WSC, PLD-WSC, PLN-ZAC, PLD-ZAC kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 15)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 5)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 15)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 5)); System.out.println(kier); // PLN-WSC kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 16)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 14)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(16, 15)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(14, 15)); System.out.println(kier); // PLD-WSC kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 6)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(15, 4)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(16, 5)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(14, 5)); System.out.println(kier); //PLN-ZAC kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 16)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 14)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(6, 15)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(4, 15)); System.out.println(kier); // PLD-ZAC kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 6)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(5, 4)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(6, 5)); System.out.println(kier); kier = kierunek(new Coord.Grid(10, 10), new Coord.Grid(4, 5)); System.out.println(kier); boolean przeciecie = intersection(p, q, r, s); r.set(8, 2); s.set(11, 5); przeciecie = intersection(p, q, r, s); r.set(6, 4); s.set(7, 3); przeciecie = intersection(p, q, r, s); r.set(6, 4); s.set(10, 0); przeciecie = intersection(p, q, r, s); r.set(4, 4); s.set(6, 6); przeciecie = intersection(p, q, r, s); r.set(4, 8); s.set(6, 10); przeciecie = intersection(p, q, r, s); r.set(2, 8); s.set(1, 9); przeciecie = intersection(p, q, r, s); Coord.Grid[] lamana = {new Coord.Grid(8, 8), new Coord.Grid(3, 4), new Coord.Grid(6, 11)}; Coord.Grid[] tab = kwadratyLamanej2(lamana); long det = det3(1, 0, 4, 0, 2, 2); det = det3(1, 0, 4, 0, 2, -2); det = det3(1, 1, 1, 4, 0, 2); det = det3(1, 1, 1, 4, 2, 2); det = det3(1, 1, 4, 4, 4, 3); det = det3(1, 1, 4, 4, 3, 4); // Coord.GridCoord[] polygon = new Coord.GridCoord[21]; // polygon[0] = new Coord.GridCoord(12, 18); // polygon[1] = new Coord.GridCoord(16, 18); // polygon[2] = new Coord.GridCoord(18, 13); // polygon[3] = new Coord.GridCoord(21, 13); // polygon[4] = new Coord.GridCoord(22, 9); // polygon[5] = new Coord.GridCoord(20, 7); // polygon[6] = new Coord.GridCoord(17, 7); // polygon[7] = new Coord.GridCoord(15, 9); // polygon[8] = new Coord.GridCoord(13, 7); // polygon[9] = new Coord.GridCoord(15, 5); // polygon[10] = new Coord.GridCoord(17, 5); // polygon[11] = new Coord.GridCoord(14, 2); // polygon[12] = new Coord.GridCoord(8, 8); // polygon[13] = new Coord.GridCoord(9, 3); // polygon[14] = new Coord.GridCoord(6, 4); // polygon[15] = new Coord.GridCoord(3, 4); // polygon[16] = new Coord.GridCoord(2, 10); // polygon[17] = new Coord.GridCoord(6, 11); // polygon[18] = new Coord.GridCoord(6, 13); // polygon[19] = new Coord.GridCoord(7, 15); // polygon[20] = new Coord.GridCoord(10, 13); // // // // przesunięcie wielokata o wektor // for (int k = 0; k < polygon.length; k++) { // polygon[k].x += 1000; // polygon[k].y += 1000; // } // Coord.GridCoord p = new Coord.GridCoord(); // for (int j = 20; j >= 0; j--) { // for (int i = 0; i < 25; i++) { // p.x = i + 1000; // p.y = j + 1000; // char c = ' '; // if (insidePolygon(polygon, p)) { // c = 'O'; // } // for (int k = 0; k < polygon.length; k++) { // if (polygon[k].equals(p)) { // c = 'X'; // break; // } // } // System.out.print(c); // System.out.print(' '); // } // System.out.println(); // } // int lp = args.length / 2; // for (int i = 0; i < lp; i++) { // p.x = Integer.parseInt(args[2 * i]); // p.y = Integer.parseInt(args[2 * i + 1]); // if (insidePolygon(polygon, p)) { // System.out.println("Punkt " + p + " leży wewnatrz"); // } else { // System.out.println("Punkt " + p + " leży na zewnatrz"); // } // } // float odl = odleglosc(5000, 4000, 2, 2); // odl = odleglosc(1, 1000, 3999, 3); // odl = odleglosc(5, 1, 27, 11); // odl = odleglosc(10, 1, 2, 20); // odl = odleglosc(1, 1, 2, 2); // // Coord.GridCoord[] rejon = new Coord.GridCoord[4]; // rejon[0] = new Coord.GridCoord(20, 18); // rejon[1] = new Coord.GridCoord(27, 9); // rejon[2] = new Coord.GridCoord(9, 1); // rejon[3] = new Coord.GridCoord(2, 15); // // ArrayList< Coord.GridCoord> kwadraty = kwadratyLamanej(rejon); // System.out.println(kwadraty); // try { // BufferedWriter wyj = new BufferedWriter(new FileWriter("A.txt")); // if (args.length == 5 ) { // int xp = Integer.parseInt(args[1]); // int yp = Integer.parseInt(args[2]); // int xk = Integer.parseInt(args[3]); // int yk = Integer.parseInt(args[4]); /* * int xp = 50000; int yp = 8000; int xk = 20; int yk = 1; */ // Coord.GridCoord[] rejon = new Coord.GridCoord[4]; // rejon[0] = new Coord.GridCoord(); // rejon[0].x = 20; // rejon[0].y = 18; // rejon[1] = new Coord.GridCoord(); // rejon[1].x = 27; // rejon[1].y = 9; // rejon[2] = new Coord.GridCoord(); // rejon[2].x = 9; // rejon[2].y = 1; // rejon[3] = new Coord.GridCoord(); // rejon[3].x = 2; // rejon[3].y = 15; // Coord.GridCoord[] kwadraty = kwadratyObszaru(rejon); /* * WspXY[] kwadraty = kwadratyOdcinka(xp, yp, xk, yk); * wyj.write("pocz: ("); wyj.write(Integer.toString(xp)); * wyj.write(", "); wyj.write(Integer.toString(yp)); wyj.write(")"); * wyj.newLine(); wyj.write("kon: ("); * wyj.write(Integer.toString(xk)); wyj.write(", "); * wyj.write(Integer.toString(yk)); wyj.write(")"); wyj.newLine(); */ // wyj.write(Integer.toString(kwadraty.length)); // wyj.newLine(); // for (int i = 0; i < kwadraty.length; i++) { // wyj.write("("); // wyj.write(Integer.toString(kwadraty[i].x)); // wyj.write(", "); // wyj.write(Integer.toString(kwadraty[i].y)); // wyj.write(")"); // wyj.newLine(); // } // // wyj.close(); // } catch (IOException e) { // e.printStackTrace(); // } } }