diff --git a/src/main/java/pl/wat/ms4ds/terrain/BigSquare.java b/src/main/java/pl/wat/ms4ds/terrain/BigSquare.java index 29518aa..43b5a92 100644 --- a/src/main/java/pl/wat/ms4ds/terrain/BigSquare.java +++ b/src/main/java/pl/wat/ms4ds/terrain/BigSquare.java @@ -1,5 +1,8 @@ package pl.wat.ms4ds.terrain; + +import javafx.scene.image.ImageView; + abstract class BigSquare { abstract Square getKwadrat(int x, int y); @@ -9,6 +12,7 @@ abstract class BigSquare { public transient int liczbaZmian = 0; // TODO zamienic na 100 static final int LICZBA_ZMIAN_DO_ZAPISU = 100000; + public ImageView imageView = null; } diff --git a/src/main/java/pl/wat/ms4ds/terrain/GeomUtils.java b/src/main/java/pl/wat/ms4ds/terrain/GeomUtils.java index cc07918..bb79893 100644 --- a/src/main/java/pl/wat/ms4ds/terrain/GeomUtils.java +++ b/src/main/java/pl/wat/ms4ds/terrain/GeomUtils.java @@ -514,7 +514,7 @@ public class GeomUtils { } } - private static final float PRZEKATNA_MK = MapConsts.DL_MK * (float) Math.sqrt(2); + 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 @@ -528,7 +528,7 @@ public class GeomUtils { case SOUTH: case EAST: case WEST: - return MapConsts.DL_MK; + return MapConsts.SS_SIZE; case NORTHEAST: case NORTHWEST: case SOUTHEAST: @@ -860,8 +860,8 @@ public class GeomUtils { float dyf = (float) dy; a = dyf / dxf; // wspolrzedne srodka kwadratu (xp, yp) - int xxp = xp * MapConsts.DL_MK + MapConsts.DL_MK / 2; - int yyp = yp * MapConsts.DL_MK + MapConsts.DL_MK / 2; + 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) { @@ -877,14 +877,14 @@ public class GeomUtils { int xd, xg; int yd, yg; int y1, y2; - xd = (x - 1) * MapConsts.DL_MK; - xg = x * MapConsts.DL_MK; + 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.DL_MK + 1; - y2 = yg / MapConsts.DL_MK + 1; + 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; @@ -1225,7 +1225,7 @@ public class GeomUtils { int yy = p1.y - p2.y; yy *= yy; float odl = (float) Math.sqrt(xx + yy); - odl *= MapConsts.DL_MK; + odl *= MapConsts.SS_SIZE; return odl; } @@ -1245,7 +1245,7 @@ public class GeomUtils { int yy = y1 - y2; yy *= yy; float odl = (float) Math.sqrt(xx + yy); - odl *= MapConsts.DL_MK; + odl *= MapConsts.SS_SIZE; return odl; } @@ -1258,7 +1258,7 @@ public class GeomUtils { */ public static float odleglosc(int dx, int dy) { float odl = (float) Math.sqrt(dx * dx + dy * dy); - odl *= MapConsts.DL_MK; + odl *= MapConsts.SS_SIZE; return odl; } diff --git a/src/main/java/pl/wat/ms4ds/terrain/RightBigSquare.java b/src/main/java/pl/wat/ms4ds/terrain/RightBigSquare.java index 1f38ee4..acacaae 100644 --- a/src/main/java/pl/wat/ms4ds/terrain/RightBigSquare.java +++ b/src/main/java/pl/wat/ms4ds/terrain/RightBigSquare.java @@ -2,111 +2,20 @@ package pl.wat.ms4ds.terrain; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import pl.wat.ms4ds.terrain.konwersja.CoordUtils; import java.io.*; -public class RightBigSquare extends BigSquare implements Serializable { +public class RightBigSquare extends BigSquare { private static final Logger logger = LoggerFactory.getLogger(RightBigSquare.class); - private Square squares[][]; + private Square[][] squares; Square getKwadrat(int ssX, int ssY) { return squares[ssX][ssY]; } - /** - * Funkcja zapisująca do pliku duży kwadrat.
- * Zapis następuje w trybie wskazywanym przez atrybut: RightBigSquare.binary. - * - * @param wymuszony flag informujacy o trybie zapisu pliku - * @param fName nazwa pliku - * @throws IOException generowany wyjątek - */ - void updateFile(boolean wymuszony, String fName) throws IOException { - if (wymuszony) { - if (this.liczbaZmian == 0) { - // nie bylo modyfikacji od ostatniego zapisu - return; - } - this.liczbaZmian = -1; - } - this.liczbaZmian++; - this.liczbaZmian %= LICZBA_ZMIAN_DO_ZAPISU; - if (this.liczbaZmian > 0) { - return; - } - if (fName != null) { - fileName = fName; - } - StringBuilder sb = new StringBuilder(100); - sb.append(MapConsts.KWADRATY_DIR); - sb.append(fileName); - sb.append(".bin"); - ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(sb.toString())); - for (int x = 0; x < MapConsts.SS_PER_BS_X; x++) { - for (int y = 0; y < MapConsts.SS_PER_BS_Y; y++) { - float f = squares[x][y].stopienZalesienia * 100.0f; - int hex = (int) f; - hex = (hex > 100) ? 100 : hex; - hex = (hex < 0) ? 0 : hex; - out.writeByte(hex); - f = squares[x][y].stopienZawodnienia * 100.0f; - hex = (int) f; - hex = (hex > 100) ? 100 : hex; - hex = (hex < 0) ? 0 : hex; - out.writeByte(hex); - f = squares[x][y].stopienZabudowy * 100.0f; - hex = (int) f; - hex = (hex > 100) ? 100 : hex; - hex = (hex < 0) ? 0 : hex; - out.writeByte(hex); - f = squares[x][y].stopienZabagnienia * 100.0f; - hex = (int) f; - hex = (hex > 100) ? 100 : hex; - hex = (hex < 0) ? 0 : hex; - out.writeByte(hex); - out.writeInt(squares[x][y].wysokoscSrednia); - out.writeInt(squares[x][y].roznicaWzniesien); - - hex = 0; - int bit_1 = 1; - for (int i = 0; i < squares[x][y].jestDroga.length; i++) { - // jest odcinek drogi na tym kierunku - if (squares[x][y].jestDroga[i]) { - hex |= bit_1; - } - bit_1 <<= 1; - } - out.writeByte(hex); - - hex = 0; - bit_1 = 1; - for (int i = 0; i < squares[x][y].jestPrzeszkodaWodna.length; i++) { - // jest odcinek przeszkody wodnej na tym kierunku - if (squares[x][y].jestPrzeszkodaWodna[i]) { - hex |= bit_1; - } - bit_1 <<= 1; - } - out.writeByte(hex); - - hex = 0; - bit_1 = 1; - for (int i = 0; i < squares[x][y].jestRow.length; i++) { - // jest odcinek rowu na tym kierunku - if (squares[x][y].jestRow[i]) { - hex |= bit_1; - } - bit_1 <<= 1; - } - out.writeByte(hex); - } - } - out.close(); - logger.debug("Zapisano plik mapy: " + sb.toString()); - } - static final int NORTH = 0; static final int NORTH_EAST = 1; static final int EAST = 2; @@ -124,24 +33,54 @@ public class RightBigSquare extends BigSquare implements Serializable { static final byte WEST_CODE = 64; static final byte NORTH_WEST_CODE = -128; - public void save(String dir) throws IOException { - StringBuilder sb = new StringBuilder(100); - sb.append(dir); + public void saveToFile(String dir) throws IOException { // Utworzenie katalogów, gdyby nie istniały. File directory = new File(dir); directory.mkdirs(); - sb.append(fileName); - sb.append(".bin"); - ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(sb.toString())); - - for (int x = 0; x < MapConsts.SS_PER_BS_X; x++) { - for (int y = 0; y < MapConsts.SS_PER_BS_Y; y++) { - - + String path = dir + fileName + ".bin"; + Square.RawData ss = new Square.RawData(); + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path)); + for (int x = 0; x < squares.length; x++) { + for (int y = 0; y < squares[0].length; y++) { + ss.read(squares[x][y]); + ss.write(out); } } out.close(); - logger.debug("Zapisano nowy plik mapy: " + sb); + logger.debug("Zapisano nowy plik mapy: {}.", path); + } + + /** + * Funkcja zapisująca do pliku duży kwadrat.
+ * + * @param newDir opcjonalna nowa lokalizacja pliku + * @throws IOException generowany wyjątek + */ + void writeToFile(String newDir) throws IOException { + String fn; + if (newDir != null) { + fn = newDir + fileName + ".bin"; + } else { + fn = MapConsts.KWADRATY_DIR + fileName + ".bin"; + } + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fn)); + byte[] buf = new byte[9 * 256]; + int offset = 0; + for (int x = 0; x < squares.length; x++) { + for (int y = 0; y < squares[0].length; y++) { + Square square = squares[x][y]; + offset = square.writeToBuffer(buf, offset); + if (offset >= buf.length) { + out.write(buf); + offset = 0; + } + } + } + if (offset > 0) { + out.write(buf, 0, offset); + } + out.close(); + logger.debug("Zapisano plik mapy: {}", fn); } /** @@ -153,7 +92,7 @@ public class RightBigSquare extends BigSquare implements Serializable { * @throws IOException generowany wyjątek */ public void saveNewFileWithNewScale20m(String dir, int dlmk) throws IOException { - if (MapConsts.DL_MK != 100) { + if (MapConsts.SS_SIZE != 100) { // operacja tylko dla danych terenowych o kwadratach 200m return; } @@ -318,7 +257,8 @@ public class RightBigSquare extends BigSquare implements Serializable { hex = TerrainType.SWAMP.ID; } ss[i][j].terrainType = (byte) hex; - ss[i][j].elevation = (short) squares[x][y].wysokoscSrednia; + // Konwersja [m] -> [0.25m] + ss[i][j].elevation = (short) (squares[x][y].wysokoscSrednia * 4); } } } @@ -327,7 +267,7 @@ public class RightBigSquare extends BigSquare implements Serializable { for (int i = 0; i < m; i++) { for (int y = 0; y < MapConsts.SS_PER_BS_Y; y++) { for (int j = 0; j < m; j++) { - ss_all[x][y][i][j].save(out); + ss_all[x][y][i][j].write(out); } } } @@ -343,8 +283,8 @@ public class RightBigSquare extends BigSquare implements Serializable { * @param dlmk * @throws IOException */ - public void saveNewFileWithNewFormatZero(String dir, int dlmk) throws IOException { - if (MapConsts.DL_MK != 100) { + public void saveNewFileWithNewFormatWithElevetion(String dir, int dlmk) throws IOException { + if (MapConsts.SS_SIZE != 100) { // operacja tylko dla danych terenowych o kwadratach 200m return; } @@ -376,10 +316,11 @@ public class RightBigSquare extends BigSquare implements Serializable { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(sb.toString())); for (int x = 0; x < MapConsts.SS_PER_BS_X; x++) { for (int y = 0; y < MapConsts.SS_PER_BS_Y; y++) { - ss.elevation = (short) squares[x][y].wysokoscSrednia; + // Konwersja [m] -> [0.25m] + ss.elevation = (short) (squares[x][y].wysokoscSrednia * 4); for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { - ss.save(out); + ss.write(out); } } } @@ -388,78 +329,211 @@ public class RightBigSquare extends BigSquare implements Serializable { logger.debug("Zapisano nowy plik mapy: {} dla rozmiaru MK= {}", sb, dlmk); } - void load(String FName) throws IOException { - try { - fileName = FName; - StringBuilder sb = new StringBuilder(100); - sb.append(MapConsts.KWADRATY_DIR); - sb.append(fileName); + /** + * Generuje nowe, wyzerowane kwadraty w danej skali w nowym formacie. + * + * @param dir + * @param dlmk + * @throws IOException + */ + public void writeToFileOldToNewFormatWithElevetion(String dir, int dlmk) throws IOException { + if (MapConsts.SS_SIZE != 100) { + // operacja tylko dla danych terenowych o kwadratach 200m + return; + } + final int m; + String s = ""; + if (dlmk == 100) { + m = 1; + s = "100m/"; + } else if (dlmk == 50) { + m = 2; + s = "50m/"; + } else if (dlmk == 25) { + m = 4; + s = "25m/"; + } else if (dlmk == 20) { + m = 5; + s = "20m/"; + } else { + return; + } + StringBuilder sb = new StringBuilder(100); + sb.append(dir); + sb.append(s); + // Utworzenie katalogów, gdyby nie istniały. + File directory = new File(sb.toString()); + directory.mkdirs(); + sb.append(fileName + ".bin"); + Square.RawData ss = new Square.RawData(); + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(sb.toString())); + byte[] buf = new byte[9 * 256]; + int offset = 0; + for (int x = 0; x < squares.length; x++) { + for (int y = 0; y < squares[0].length; y++) { + Square square = squares[x][y]; + square.elevation = square.wysokoscSrednia; + if (square.elevation > 2660) { + logger.warn("Elevation: {}, fn= {} ", square.elevation, fileName); + } + for (int i = 0; i < m * m; i++) { + offset = square.writeToBuffer(buf, offset); + if (offset >= buf.length) { + out.write(buf); + offset = 0; + } + } + } + } + if (offset > 0) { + out.write(buf, 0, offset); + } + out.close(); + logger.debug("Zapisano plik mapy: {}", fileName); + } + + public void saveFileFromNewToOldFormat(String dir) throws IOException { + StringBuilder sb = new StringBuilder(100); + sb.append(dir); + // Utworzenie katalogów, gdyby nie istniały. + File directory = new File(sb.toString()); + directory.mkdirs(); + sb.append(fileName); + if (fileName.indexOf('.') < 0) { sb.append(".bin"); - Square.RawData ss = new Square.RawData(); - ObjectInputStream in = new ObjectInputStream(new FileInputStream(sb.toString())); + } + Square.RawData ss = new Square.RawData(); + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(sb.toString())); + for (int x = 0; x < squares.length; x++) { + for (int y = 0; y < squares[0].length; y++) { + float f; + int hex = 0; + int hex_s = 0; + int hex_w = 0; + int hex_b = 0; + int hex_f = 0; + switch (squares[x][y].terrainType) { +// case 0, 1, 4: +// hex = 0; +// break; + case 2: + hex_s = 100; + break; + case 3: + hex_w = 100; + break; + case 5: + hex_b = 100; + break; + case 6: + hex_f = 100; + break; + default: + } + out.writeByte(hex_f); + out.writeByte(hex_w); + out.writeByte(hex_b); + out.writeByte(hex_s); + int elevation = (int) squares[x][y].elevation; + out.writeInt(elevation); + out.writeInt(squares[x][y].roznicaWzniesien); + int bit_1; + hex = 0; + bit_1 = 1; + byte[] roads = squares[x][y].roads; + for (int i = 0; i < roads.length; i++) { + // jest odcinek drogi na tym kierunku + if (roads[i] > 0) { + hex |= bit_1; + } + bit_1 <<= 1; + } + out.writeByte(hex); + hex = 0; + bit_1 = 1; + byte[] watercourses = squares[x][y].watercourses; + for (int i = 0; i < watercourses.length; i++) { + // jest odcinek przeszkody wodnej na tym kierunku + if (watercourses[i] > 1) { + hex |= bit_1; + } + bit_1 <<= 1; + } + out.writeByte(hex); + hex = 0; + bit_1 = 1; + for (int i = 0; i < watercourses.length; i++) { + // jest odcinek rowu na tym kierunku + if (watercourses[i] == 1) { + hex |= bit_1; + } + bit_1 <<= 1; + } + out.writeByte(hex); + } + } + out.close(); + logger.debug("Zapisano nowy plik mapy: {}", sb); + } + + void readFromFileNew(String dir) throws IOException { + if (fileName == null) { + return; + } + try { + String fullPath = dir + fileName + ".bin"; + BufferedInputStream in = new BufferedInputStream(new FileInputStream(fullPath), 2 * 8192); + byte[] buffer = new byte[9 * 512]; + int offset = 0; + int count = in.read(buffer); squares = new Square[MapConsts.SS_PER_BS_X][MapConsts.SS_PER_BS_Y]; - int x0 = idX * MapConsts.SS_PER_BS_X; - int y0 = idY * MapConsts.SS_PER_BS_Y; for (int x = 0; x < MapConsts.SS_PER_BS_X; x++) { for (int y = 0; y < MapConsts.SS_PER_BS_Y; y++) { - Square kw = new Square(x0 + x, y0 + y); + Square kw = new Square(x, y); + if (offset >= count) { + count = in.read(buffer); + offset = 0; + } + offset = kw.readFromBuffer(buffer, offset); + if (kw.elevation < -3) { + logger.warn("Elevation: {}, fn= {} ", kw.elevation, fileName); + } + if (kw.elevation > 2660) { + logger.warn("Elevation: {}, fn= {} ", kw.elevation, fileName); + } squares[x][y] = kw; - ss.load(in); - switch (ss.terrainType) { - case 0: - break; - case 1: - break; - case 4: - break; - case 2: - kw.stopienZabagnienia = 1.f; - break; - case 3: - kw.stopienZawodnienia = 1.f; - break; - case 5: - kw.stopienZabudowy = 1.f; - break; - case 6: - kw.stopienZalesienia = 1.f; - break; - } + } + } + in.close(); + logger.debug("Doczytano plik mapy: " + fullPath); + } catch (IOException e) { + squares = null; + throw e; + } + } - kw.wysokoscSrednia = ss.elevation; - kw.roznicaWzniesien = 0; - - int bit_1 = 1; - int hex = ss.majorRoads; - for (int i = 0; i < kw.jestDroga.length; i++) { - // jest odcinek rowu na tym kierunku - if ((hex & bit_1) != 0) { - kw.jestDroga[i] = true; - } - bit_1 <<= 1; + void readFromFile(String dir) throws IOException { + try { + String fullPath = dir + fileName + ".bin"; + Square.RawData ss = new Square.RawData(); +// DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fullPath))); + ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(fullPath))); + squares = new Square[MapConsts.SS_PER_BS_X][MapConsts.SS_PER_BS_Y]; + for (int x = 0; x < MapConsts.SS_PER_BS_X; x++) { + for (int y = 0; y < MapConsts.SS_PER_BS_Y; y++) { + ss.read(in); + Square kw = new Square(x, y, ss); + squares[x][y] = kw; + if (kw.elevation > 2660) { + logger.warn("Elevation: {}, fn={} ", kw.elevation, fileName); } - bit_1 = 1; - hex = ss.rivers; - for (int i = 0; i < kw.jestPrzeszkodaWodna.length; i++) { - // jest odcinek rowu na tym kierunku - if ((hex & bit_1) != 0) { - kw.jestPrzeszkodaWodna[i] = true; - } - bit_1 <<= 1; - } - bit_1 = 1; - hex = ss.drains; - for (int i = 0; i < kw.jestRow.length; i++) { - // jest odcinek rowu na tym kierunku - if ((hex & bit_1) != 0) { - kw.jestRow[i] = true; - } - bit_1 <<= 1; + if (kw.elevation < -3) { + logger.warn("Elevation: {}, fn= {} ", kw.elevation, fileName); } } } in.close(); - logger.debug("Doczytano plik mapy: " + sb.toString()); + logger.debug("Doczytano plik mapy: " + fullPath); } catch (IOException e) { squares = null; throw e; @@ -478,7 +552,7 @@ public class RightBigSquare extends BigSquare implements Serializable { boolean zalesienie, boolean zawodnienie, boolean zabudowa, boolean zabagnienie, boolean wysokosc, boolean roznicaWzniesien, boolean drogi, boolean rzeki, boolean rowy) throws IOException { - if (MapConsts.DL_MK != 200) { + if (MapConsts.SS_SIZE != 200) { // operacja tylko dla danych terenowych o kwadratach 200m return; } @@ -602,20 +676,28 @@ public class RightBigSquare extends BigSquare implements Serializable { public RightBigSquare() { } - // konstruktor ladujacy duzy kwadrat z pliku binarnego - RightBigSquare(String FName) throws IOException { + /** + * konstruktor ladujacy duzy kwadrat z pliku binarnego w starym formacie + * + * @param fname nazwa pliku z danymi + */ + RightBigSquare(String fname, String dir) throws IOException { try { - fileName = FName + ".bin"; + File f = new File(fname); + fileName = f.getName(); + fileName = fileName.substring(0, fileName.lastIndexOf('.')); StringBuilder sb = new StringBuilder(100); - sb.append(MapConsts.KWADRATY_DIR); - sb.append(fileName); + if (dir == null) { + sb.append(MapConsts.KWADRATY_DIR); + } else { + sb.append(dir); + } + sb.append(fileName + ".bin"); ObjectInputStream in = new ObjectInputStream(new FileInputStream(sb.toString())); squares = new Square[MapConsts.SS_PER_BS_X][MapConsts.SS_PER_BS_Y]; - int x0 = idX * MapConsts.SS_PER_BS_X; - int y0 = idY * MapConsts.SS_PER_BS_Y; for (int x = 0; x < MapConsts.SS_PER_BS_X; x++) { for (int y = 0; y < MapConsts.SS_PER_BS_Y; y++) { - Square kw = new Square(x0 + x, y0 + y); + Square kw = new Square(x, y); squares[x][y] = kw; int hex = in.readByte(); kw.stopienZalesienia = (float) hex * (1.0f / 100.f); @@ -626,9 +708,18 @@ public class RightBigSquare extends BigSquare implements Serializable { hex = in.readByte(); kw.stopienZabagnienia = (float) hex * (1.0f / 100.f); kw.wysokoscSrednia = in.readInt(); + if (kw.wysokoscSrednia < -3) { + logger.warn("Elevation: {}, fn= {} ", kw.wysokoscSrednia, fileName); + } + if (kw.wysokoscSrednia > 2660) { + logger.warn("Elevation: {}, fn= {} ", kw.wysokoscSrednia, fileName); + } kw.roznicaWzniesien = in.readInt(); int bit_1 = 1; hex = in.readByte(); + if (kw.jestDroga == null) { + kw.jestDroga = new boolean[8]; + } for (int i = 0; i < kw.jestDroga.length; i++) { // jest odcinek rowu na tym kierunku if ((hex & bit_1) != 0) { @@ -638,6 +729,9 @@ public class RightBigSquare extends BigSquare implements Serializable { } bit_1 = 1; hex = in.readByte(); + if (kw.jestPrzeszkodaWodna == null) { + kw.jestPrzeszkodaWodna = new boolean[8]; + } for (int i = 0; i < kw.jestPrzeszkodaWodna.length; i++) { // jest odcinek rowu na tym kierunku if ((hex & bit_1) != 0) { @@ -647,6 +741,9 @@ public class RightBigSquare extends BigSquare implements Serializable { } bit_1 = 1; hex = in.readByte(); + if (kw.jestRow == null) { + kw.jestRow = new boolean[8]; + } for (int i = 0; i < kw.jestRow.length; i++) { // jest odcinek rowu na tym kierunku if ((hex & bit_1) != 0) { diff --git a/src/main/java/pl/wat/ms4ds/terrain/Square.java b/src/main/java/pl/wat/ms4ds/terrain/Square.java index c9e8454..ba0d33f 100644 --- a/src/main/java/pl/wat/ms4ds/terrain/Square.java +++ b/src/main/java/pl/wat/ms4ds/terrain/Square.java @@ -1,6 +1,7 @@ package pl.wat.ms4ds.terrain; +import java.io.DataInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -8,9 +9,9 @@ import java.io.ObjectOutputStream; public class Square { /** - * The height above the level of the sea. Unit of measure decimeter [m]. + * The height above the level of the sea. Unit of measure meter [m]. */ - float elevation; + public float elevation; /** * Terrain type.
Possible values: @@ -22,21 +23,21 @@ public class Square { * 5 - BUILDINGS * 6 - FOREST */ - short terrainType; + public short terrainType; /** * Type of watercourse (water obstacle) in a given direction. Each index corresponds to a given direction. * Possible values: 0 - no watercourse, 1 - drain, ditch, 2 - canal, stream, 3 - river */ - byte[] watercourses; + public final byte[] watercourses; /** * Type of road in a given direction. Each index corresponds to a given direction. * Possible values: 0 - no road, 1 - small roads, 2 - minor roads, 3 - major roads */ - byte[] roads; + public final byte[] roads; - //////////////////////////////////////// + /// ///////////////////////////////////// /// tymczasowo public float stopienZabudowy; public float stopienZalesienia; @@ -47,11 +48,12 @@ public class Square { public boolean[] jestPrzeszkodaWodna; public int roznicaWzniesien; public int wysokoscSrednia; - //////////////////////////////////////// + + /// ///////////////////////////////////// public static class RawData { /** - * The height above the level of the sea. Unit of measure decimeter [dm]. + * The height above the level of the sea. Unit of measure [0.25m]. */ short elevation; /** @@ -107,7 +109,7 @@ public class Square { rivers = 0; } - public void save(ObjectOutputStream out) throws IOException { + public void write(ObjectOutputStream out) throws IOException { out.writeShort(elevation); out.writeByte(terrainType); out.writeByte(smallRoads); @@ -118,7 +120,7 @@ public class Square { out.writeByte(rivers); } - public void load(ObjectInputStream in) throws IOException { + public void read(ObjectInputStream in) throws IOException { elevation = in.readShort(); terrainType = in.readByte(); smallRoads = in.readByte(); @@ -140,7 +142,7 @@ public class Square { public RawData(Square kw) { terrainType = (byte) kw.terrainType; // Konwersja na decymetry. - elevation = (short) (kw.elevation * 10); + elevation = (short) (kw.elevation * 4); byte bit = 1; for (int i = 0; i < kw.watercourses.length; i++) { switch (kw.watercourses[i]) { @@ -156,10 +158,6 @@ public class Square { default: break; } - bit <<= 1; - } - bit = 1; - for (int i = 0; i < kw.roads.length; i++) { switch (kw.roads[i]) { case 1: smallRoads |= bit; @@ -176,6 +174,43 @@ public class Square { bit <<= 1; } } + + public void read(Square kw) { + terrainType = (byte) kw.terrainType; + // Konwersja na decymetry. + elevation = (short) (kw.elevation * 4); + byte bit = 1; + for (int i = 0; i < kw.watercourses.length; i++) { + switch (kw.watercourses[i]) { + case 1: + drains |= bit; + break; + case 2: + streams |= bit; + break; + case 3: + rivers |= bit; + break; + default: + break; + } + switch (kw.roads[i]) { + case 1: + smallRoads |= bit; + break; + case 2: + minorRoads |= bit; + break; + case 3: + majorRoads |= bit; + break; + default: + break; + } + bit <<= 1; + } + } + } public static final Square EMPTY = new Square(-1, -1); @@ -189,13 +224,122 @@ public class Square { this.y = y; roads = new byte[8]; watercourses = new byte[8]; - // Brak danych o wysokości. - elevation = -1000; } public Square(int x, int y, RawData rawData) { - this(x, y); - elevation = rawData.elevation / 10.f; + this.x = x; + this.y = y; + roads = new byte[8]; + watercourses = new byte[8]; + // Konwersja na metry a[0.25m] -> b[m] + elevation = (float) (rawData.elevation) / 4; + terrainType = rawData.terrainType; + int bit = 1; + for (int i = 0; i < 8; i++) { + int b1 = ((rawData.majorRoads & bit) > 0) ? 3 : 0; + int b2 = ((rawData.minorRoads & bit) > 0) ? 2 : 0; + int b3 = ((rawData.smallRoads & bit) > 0) ? 1 : 0; + roads[i] = (byte) (b1 + b2 + b3); + b1 = ((rawData.rivers & bit) > 0) ? 3 : 0; + b2 = ((rawData.streams & bit) > 0) ? 2 : 0; + b3 = ((rawData.drains & bit) > 0) ? 1 : 0; + watercourses[i] = (byte) (b1 + b2 + b3); + bit <<= 1; + } + } + + public int writeToBuffer(byte[] buffer, int offset) { + // Konwersja [m] -> [0.25m]. + int elev = (short) (elevation * 4); + byte bit = 1; + byte drains = 0; + byte streams = 0; + byte rivers = 0; + byte smallRoads = 0; + byte minorRoads = 0; + byte majorRoads = 0; + for (int i = 0; i < watercourses.length; i++) { + switch (watercourses[i]) { + case 1: + drains |= bit; + break; + case 2: + streams |= bit; + break; + case 3: + rivers |= bit; + break; + default: + break; + } + switch (roads[i]) { + case 1: + smallRoads |= bit; + break; + case 2: + minorRoads |= bit; + break; + case 3: + majorRoads |= bit; + break; + default: + break; + } + bit <<= 1; + } + byte b1 = (byte) (elev & 0xFF); + elev >>= 8; + byte b0 = (byte) (elev & 0xFF); + if (b0 == -1 && b1 == -4) { + System.out.println("a"); + } + buffer[offset + 1] = b1; + buffer[offset] = b0; + buffer[offset + 2] = (byte) terrainType; + buffer[offset + 3] = smallRoads; + buffer[offset + 4] = minorRoads; + buffer[offset + 5] = majorRoads; + buffer[offset + 6] = drains; + buffer[offset + 7] = streams; + buffer[offset + 8] = rivers; + return offset + 9; + } + + public int readFromBuffer(byte[] buffer, int offset) { + int elev = buffer[offset] & 0xFF; + elev = (elev << 8) + (buffer[offset + 1] & 0xFF); + short v = (short) elev; + // Konwersja na metry a[0.25m] -> b[m] + elevation = (float) (v) / 4; + if (elevation > 2660) { + System.out.println("h=" + elevation); + } + terrainType = buffer[offset + 2]; + byte smallRoads = buffer[offset + 3]; + byte minorRoads = buffer[offset + 4]; + byte majorRoads = buffer[offset + 5]; + byte drains = buffer[offset + 6]; + byte streams = buffer[offset + 7]; + byte rivers = buffer[offset + 8]; + int bit = 1; + // 8 kierunków geograficznych (0 - NORTH, 1 - NORTH_EAST, ...) + for (int i = 0; i < 8; i++) { + int b1 = ((majorRoads & bit) > 0) ? 3 : 0; + int b2 = ((minorRoads & bit) > 0) ? 2 : 0; + int b3 = ((smallRoads & bit) > 0) ? 1 : 0; + roads[i] = (byte) (b1 + b2 + b3); + b1 = ((rivers & bit) > 0) ? 3 : 0; + b2 = ((streams & bit) > 0) ? 2 : 0; + b3 = ((drains & bit) > 0) ? 1 : 0; + watercourses[i] = (byte) (b1 + b2 + b3); + bit <<= 1; + } + return offset + 9; + } + + void read(RawData rawData) { + // Konwersja na metry a[0.25m] -> b[m] + elevation = (float) (rawData.elevation) / 4; terrainType = rawData.terrainType; int bit = 1; for (int i = 0; i < 8; i++) { @@ -213,12 +357,6 @@ public class Square { public final int x; public final int y; - public double sumaWysokosci; - public int count = 1; - public double ell; - public double nll; - public double eur; - public double nur; @Override @@ -250,7 +388,7 @@ public class Square { }; linia.append(c); linia.append(' '); - String s = String.format("%5.1f", elevation); + String s = String.format("%7.2f", elevation); linia.append(s); linia.append(' '); for (byte road : roads) { diff --git a/src/main/java/pl/wat/ms4ds/terrain/Teren.java b/src/main/java/pl/wat/ms4ds/terrain/Teren.java index 5f96522..01535e5 100644 --- a/src/main/java/pl/wat/ms4ds/terrain/Teren.java +++ b/src/main/java/pl/wat/ms4ds/terrain/Teren.java @@ -41,17 +41,16 @@ public class Teren { private static double maxKatNachylTerenuNaPrzelaj; /** - * Jawne wywolanie zapisu do pliku bufora zmian terenu + * Jawne wywolanie zapisu do pliku bufora zmian terenu. Zapisane zostaną aktywne/załadowane duże kwadraty. */ - public static void zapisBuforaMapyDoPliku() { + public static void saveToFiles(String dir) { for (int i = 0; i < bigSquares.length; i++) { for (int j = 0; j < bigSquares[i].length; j++) { BigSquare bs = bigSquares[i][j]; - if (null != bs && bs instanceof RightBigSquare) { - RightBigSquare rbs = (RightBigSquare) bigSquares[i][j]; + if (bs instanceof RightBigSquare rbs) { try { - rbs.liczbaZmian++; - rbs.updateFile(true, null); + rbs.writeToFile(dir); + bigSquares[i][j] = null; } catch (IOException e) { LOGGER.warn("Błąd zapisu pliku mapy: " + rbs.fileName); } @@ -73,107 +72,6 @@ public class Teren { System.gc(); } - /** - * Funkcja zamienia reprezentację w postaci (stopnie, minuty, sekundy) długości geograficznej WGS-84 - * na wartość w milisekundach. - * - * @param wspolrzedneUtm - * @return - */ - public static int zamienWspSMSNaWspXms(String wspolrzedneUtm) { - String d = wspolrzedneUtm.substring(8, 10); - int ms = Integer.parseInt(d) * MapConsts.DEG_MS; - d = wspolrzedneUtm.substring(10, 12); - ms += Integer.parseInt(d) * 60000; - d = wspolrzedneUtm.substring(12, 14); - ms += Integer.parseInt(d) * 1000; - if (wspolrzedneUtm.charAt(14) == 'W') { - ms = -ms; - } - ms += 180 * MapConsts.DEG_MS; - return ms; - } - - /** - * Funkcja zamienia reprezentację w postaci (stopnie, minuty, sekundy) szerokości geograficznej WGS-84 - * na wartość w milisekundach. - * - * @param wspolrzedneUtm - * @return - */ - public static int zamienWspSMSNaWspYms(String wspolrzedneUtm) { - String d = wspolrzedneUtm.substring(0, 2); - int ms = Integer.parseInt(d) * MapConsts.DEG_MS; - d = wspolrzedneUtm.substring(2, 4); - ms += Integer.parseInt(d) * 60000; - d = wspolrzedneUtm.substring(4, 6); - ms += Integer.parseInt(d) * 1000; - if (wspolrzedneUtm.charAt(6) == 'S') { - ms = -ms; - } - ms += 90 * MapConsts.DEG_MS; - return ms; - } - - /** - * Zamienia współrzędne geograficzne WGS-84 w milisekundach (xms,yms) na reprezentację stopnie, minuty, sekundy. - * - * @param xms - * @param yms - * @return - */ - public static String zamienWspXmsYmsNaWspSMS(long xms, long yms) { - char cx = 'E'; - // stopnie dlugosci geograficznej - long x_st = xms / MapConsts.DEG_MS - 180; - if (x_st < 0) { - x_st = -x_st; - cx = 'W'; - } - long reszta = xms % MapConsts.DEG_MS; - // minuty dlugosci geograficznej - long x_m = reszta / 60000; - // sekundy dlugosci geograficznej - long x_s = reszta % 60000; - x_s /= 1000; - - char cy = 'N'; - // stopnie szerokosci geograficznej - long y_st = yms / MapConsts.DEG_MS - 90; - if (y_st < 0) { - y_st = -y_st; - cy = 'S'; - } - reszta = yms % MapConsts.DEG_MS; - // minuty szerokosci geograficznej - long y_m = reszta / 60000; - // sekundy szerokosci geograficznej - long y_s = reszta % 60000; - y_s /= 1000; - - return String.format( - "%1$02d%2$02d%3$02d%4$c%5$03d%6$02d%7$02d%8$c", y_st, y_m, y_s, cy, x_st, x_m, x_s, cx); - } - - // funkcja wyznacza wspolrzedne UTM ze wspolrzednych dziesietnych - // Zalozenie: wspolrzedne w zakresie dlugosc wschodnia do 100 stopni, szerokosc polnocna - public static String zamienWspGeoDziesietnieNaWspSMS(float lon, float lat) { - int x_st = (int) lon; - int y_st = (int) lat; - - float s = (lon - x_st) * 3600; - int x_s = (int) s; - int x_m = x_s / 60; - x_s = x_s % 60; - - s = (lat - y_st) * 3600; - int y_s = (int) s; - int y_m = y_s / 60; - y_s = y_s % 60; - - return String.format("%1$02d%2$02d%3$02dN%4$03d%5$02d%6$02dE", y_st, y_m, y_s, x_st, x_m, x_s); - } - /** * Zwraca nazwę pliku na podstawie współrzędnych geograficznych. * @@ -182,17 +80,14 @@ public class Teren { * @return Nazwa zwracanego pliku z danymi (null - gdy niepoprawne współrzędne). */ public static String getFileName(double lat, double lon) { - int idX = Coord.zamienDlugoscGeoNaIdKwadratuX(lon); - int idY = Coord.zamienSzerokoscGeoNaIdKwadratuY(lat); + int idX = Coord.zamienDlugoscGeoNaIdKwadratuX(lon); + int idY = Coord.zamienSzerokoscGeoNaIdKwadratuY(lat); int bigX = idX / MapConsts.SS_PER_BS_X; int bigY = idY / MapConsts.SS_PER_BS_Y; return getFileName(bigX, bigY); } private static String getFileName(int bsX, int bsY) { - if ((bsX < 0) || (bsY < 0)) { - return null; - } int x_stop = MapConsts.X_REF + bsX / MapConsts.BS_PER_DEG_X - 180; char cLon = (x_stop < 0) ? 'W' : 'E'; if (x_stop < 0) { @@ -200,7 +95,6 @@ public class Teren { } int dx = bsX % MapConsts.BS_PER_DEG_X; char cx = LITERALS.charAt(dx); - int y_stop = MapConsts.Y_REF + bsY / MapConsts.BS_PER_DEG_Y - 90; char cLat = (y_stop < 0) ? 'S' : 'N'; if (y_stop < 0) { @@ -209,14 +103,12 @@ public class Teren { int dy = bsY % MapConsts.BS_PER_DEG_Y; char cy = LITERALS.charAt(dy); // przykładowa nazwa pliku: E024B_N50F - + // StringBuilder sb = new StringBuilder(); -// sb.append(MapConsts.KWADRATY_DIR); sb.append(cLon); - if (x_stop < 100) { - sb.append('0'); - } if (x_stop < 10) { + sb.append("00"); + } else if (x_stop < 100) { sb.append('0'); } sb.append(x_stop); @@ -231,21 +123,22 @@ public class Teren { return sb.toString(); } - private static BigSquare loadArea(int bsX, int bsY) { - String fName = getFileName(bsX, bsY); + private static BigSquare loadAreaOld(int bsX, int bsY) { + String fName = getFileName(bsX, bsY) + ".bin"; try { - return new RightBigSquare(fName); + return new RightBigSquare(fName, null); } catch (IOException e) { LOGGER.warn("Brak pliku mapy: {}{}{}", MapConsts.KWADRATY_DIR, fName, ".bin"); return EmptyBigSquare.EMPTY_BIG_SQUARE; } } - private static BigSquare loadAreaNew(int bsX, int bsY) { + private static BigSquare loadArea(int bsX, int bsY) { String fName = getFileName(bsX, bsY); try { RightBigSquare bs = new RightBigSquare(); - bs.load(fName); + bs.fileName = fName; + bs.readFromFile(MapConsts.KWADRATY_DIR); return bs; } catch (IOException e) { LOGGER.warn("Brak pliku mapy: {}{}{}", MapConsts.KWADRATY_DIR, fName, ".bin"); @@ -262,48 +155,53 @@ public class Teren { } public static Square getKwadrat(double lat, double lon) { - int idX = Coord.zamienDlugoscGeoNaIdKwadratuX(lon); - int idY = Coord.zamienSzerokoscGeoNaIdKwadratuY(lat); + int idX = Coord.zamienDlugoscGeoNaIdKwadratuX(lon); + int idY = Coord.zamienSzerokoscGeoNaIdKwadratuY(lat); return getKwadrat(idX, idY); } - public static Square getKwadrat(int idX, int idY) { - if (idX < 0 || idY < 0) { + /** + * Zwraca kwadrat o podanych współrzędnych siatki (grida). + * + * @param x współrzędna pozioma (indeks kolumny) + * @param y współrzędna pionowa (indeks wiersza) + * @return obiekt reprezentujący charakterystyki fragmentu terenu + */ + public static Square getKwadrat(int x, int y) { + if (x < 0 || y < 0) { return EMPTY; } // wspolrzędna x dużego kwadratu - int bsX = idX / MapConsts.SS_PER_BS_X; + int bsX = x / MapConsts.SS_PER_BS_X; // wspolrzędna y dużego kwadratu - int bsY = idY / MapConsts.SS_PER_BS_Y; + int bsY = y / MapConsts.SS_PER_BS_Y; if (bsX < 0 || bsX >= BIG_X_MAX || bsY < 0 || bsY >= BIG_Y_MAX) { return EMPTY; } // wspolrzędna x małego kwadratu w ramach dużego kwadratu - int ssX = idX % MapConsts.SS_PER_BS_X; + int ssX = x % MapConsts.SS_PER_BS_X; // wspolrzędna y małego kwadratu w ramach dużego kwadratu - int ssY = idY % MapConsts.SS_PER_BS_Y; + int ssY = y % MapConsts.SS_PER_BS_Y; synchronized (bsSynch) { if (bigSquares[bsX][bsY] == null) { makeRoom(bsX, bsY); bigSquares[bsX][bsY] = loadArea(bsX, bsY); -// bigSquares[bsX][bsY] = loadAreaNew(bsX, bsY); } } return bigSquares[bsX][bsY].getKwadrat(ssX, ssY); } - private static Coord.Grid[] history = new Coord.Grid[MapConsts.MAX_BIG_SQUARES_IN_MEMORY]; + private static Coord.Grid[] history = new Coord.Grid[MapConsts.MAX_BIG_SQUARES_IN_MEMORY]; private static int bigSquaresInMemory = 0; private static void makeRoom(int bigX, int bigY) { if (bigSquaresInMemory >= MapConsts.MAX_BIG_SQUARES_IN_MEMORY) { // najpierw zapisuję w pliku dokonane zmiany - if (bigSquares[history[0].x][history[0].y] instanceof RightBigSquare) { - RightBigSquare rbs = (RightBigSquare) bigSquares[history[0].x][history[0].y]; + if (bigSquares[history[0].x][history[0].y] instanceof RightBigSquare rbs) { try { //!! dla potrzeb generowania danych rbs.liczbaZmian = 1; - rbs.updateFile(true, null); + rbs.writeToFile(null); } catch (IOException e) { e.printStackTrace(); } @@ -332,8 +230,8 @@ public class Teren { private static final double TANG_ALFA_MAX_NA_DRODZE; private static final double TANG_ALFA_MIN_NA_DRODZE; - private static double a1; - private static double b1; + private static final double a1; + private static final double b1; /** * Funkcja opisujaca zmianę stopnia przejezdności podczas ruchu na drodze dla kątów w przedziale <22.5, 45> @@ -352,8 +250,8 @@ public class Teren { private static final double TANG_ALFA_MAX_NA_PRZELAJ; private static final double TANG_ALFA_MIN_NA_PRZELAJ; - private static double a2; - private static double b2; + private static final double a2; + private static final double b2; /** * Funkcja opisujaca zmianę stopnia przejezdności podczas ruchu na przełaj dla kątów w przedziale <22.5, 45> @@ -378,7 +276,7 @@ public class Teren { static { for (int i = 0; i < history.length; i++) { - history[i] = new Coord.Grid(); + history[i] = new Coord.Grid(); } przejezdnoscZawsze = MapConsts.ustawienia.getProperty("przejezdnosc_zawsze").equals("on"); minStopienPrzejezd = Double.parseDouble(MapConsts.ustawienia.getProperty("minimalny_stopien_przejezdnosci")); @@ -496,19 +394,40 @@ public class Teren { LOGGER.debug("start"); // Teren.normalizujDanePokrycia(); - String dir = "C:/users/jrulka/Workspace/_data/new/"; - Square kw = getKwadrat(1500, 2100); + String newDir = "D:/work/kwadraty_nmt/temp/25/"; + String dir1 = "D:/work/nowe/25m/"; + String inDir = "D:/work/kwadraty_nmt/withElevation/25m/"; + String dir2 = "C:/Workspace/_data/swdt/ms4ds/teren/kwadraty/100m/"; + +// Square kw = getKwadrat(1500, 2100); // System.out.println(kw); // kw = getKwadrat(2100, 1500); // System.out.println(kw); + Set