From b7ec5f05a7e8853b9ad93e49535eaf5f0ad6170f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Simon?= Date: Tue, 12 Oct 2021 18:55:05 +0200 Subject: [PATCH 1/2] Resolves #5 - Basic structure for new feature. - Next is adding the math. --- .../java/hu/awm/srtm/cli/CliApplication.java | 36 +++++++++++++-- .../srtm/tools/cansee/CanSeeCalculator.java | 33 ++++++++++++++ .../java/hu/awm/srtm/tools/cansee/Sight.java | 44 +++++++++++++++++++ .../java/hu/awm/srtm/tools/cansee/Xyz.java | 25 +++++++++++ 4 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java create mode 100644 src/main/java/hu/awm/srtm/tools/cansee/Sight.java create mode 100644 src/main/java/hu/awm/srtm/tools/cansee/Xyz.java diff --git a/src/main/java/hu/awm/srtm/cli/CliApplication.java b/src/main/java/hu/awm/srtm/cli/CliApplication.java index d1ad41a..da1293e 100644 --- a/src/main/java/hu/awm/srtm/cli/CliApplication.java +++ b/src/main/java/hu/awm/srtm/cli/CliApplication.java @@ -9,6 +9,7 @@ import hu.awm.srtm.map.contour.ContourRenderer; import hu.awm.srtm.map.reliefmap.ReliefMapRenderer; import hu.awm.srtm.presentation.JFramePresenter; +import hu.awm.srtm.tools.cansee.CanSeeCalculator; public class CliApplication { @@ -19,11 +20,11 @@ public static void main(String[] args) { String type = args[0]; String hgtFiles = args[1]; - Position coordinates = new Position( - Double.parseDouble(args[2]), - Double.parseDouble(args[3])); if (type.equals("relief")) { + Position coordinates = new Position( + Double.parseDouble(args[2]), + Double.parseDouble(args[3])); int fromLat = Integer.parseInt(args[4]); int fromLon = Integer.parseInt(args[5]); int toLat = Integer.parseInt(args[6]); @@ -33,6 +34,9 @@ public static void main(String[] args) { TileMap tileMap = tileReader.readHgtFiles(fromLat, fromLon, toLat, toLon); new JFramePresenter("Relief map", ReliefMapRenderer.render(tileMap, coordinates)).display(); } else if (type.equals("contour")) { + Position coordinates = new Position( + Double.parseDouble(args[2]), + Double.parseDouble(args[3])); final double fromDeg = Double.parseDouble(args[4]); final double toDeg = Double.parseDouble(args[5]); final double resolution = Double.parseDouble(args[6]); @@ -48,7 +52,31 @@ public static void main(String[] args) { ContourCalculator.getContours(tileMap, coordinates, fromDeg, toDeg, resolution); new JFramePresenter("Contours", ContourRenderer.renderContours(contours)).display(); - } else { + } else if (type.equals("cansee")) { + int tileFromLat = Integer.parseInt(args[2]); + int tileFromLon = Integer.parseInt(args[3]); + int tileToLat = Integer.parseInt(args[4]); + int tileToLon = Integer.parseInt(args[5]); + + TileReader tileReader = new TileReader(hgtFiles); + TileMap tileMap = tileReader.readHgtFiles(tileFromLat, tileFromLon, tileToLat, tileToLon); + + Double fromLat = Double.parseDouble(args[6]); + Double fromLon = Double.parseDouble(args[7]); + Double fromHeight = Double.parseDouble(args[8]); + Double toLat = Double.parseDouble(args[9]); + Double toLon = Double.parseDouble(args[10]); + Double toHeight = Double.parseDouble(args[11]); + + CanSeeCalculator canSeeCalculator = new CanSeeCalculator(); + canSeeCalculator.setTileMap(tileMap); + canSeeCalculator.setCoordinates(fromLat, fromLon, fromHeight, toLat, toLon, toHeight); + System.out.println( + canSeeCalculator.calculateBoolean() + ? "Points are visible to each other." + : "Points aren't visible to each other."); + } + else { throw new IllegalArgumentException("Unknown map type: " + type + ". Type should be one of the following: relief, contour."); } diff --git a/src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java b/src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java new file mode 100644 index 0000000..32843e7 --- /dev/null +++ b/src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java @@ -0,0 +1,33 @@ +package hu.awm.srtm.tools.cansee; + +import hu.awm.srtm.data.hgt.TileMap; + +public class CanSeeCalculator { + + private Xyz from; + private Xyz to; + private TileMap tileMap; + + public CanSeeCalculator() { + + } + + public void setCoordinates(Double fromLat, Double fromLon, Double fromHeight, Double toLat, Double toLon, Double toHeight) { + this.from = new Xyz(fromLat, fromLon, fromHeight); + this.to = new Xyz(toLat, toLon, toHeight); + } + + public void setTileMap(TileMap tileMap) { + this.tileMap = tileMap; + } + + public Sight calculateSight() { + // TODO: Replace this with the correct math. + return new Sight(null, null, null); + } + + public boolean calculateBoolean() { + Sight sight = calculateSight(); + return !sight.hasBlocker(); + } +} diff --git a/src/main/java/hu/awm/srtm/tools/cansee/Sight.java b/src/main/java/hu/awm/srtm/tools/cansee/Sight.java new file mode 100644 index 0000000..9c02f84 --- /dev/null +++ b/src/main/java/hu/awm/srtm/tools/cansee/Sight.java @@ -0,0 +1,44 @@ +package hu.awm.srtm.tools.cansee; + +public class Sight { + private Xyz startCoordinate; + private Xyz endCoordinate; + private Xyz looseSightCoordinate; + + public Sight() { + } + + public Sight(Xyz startCoordinate, Xyz endCoordinate, Xyz looseSightCoordinate) { + this.startCoordinate = startCoordinate; + this.endCoordinate = endCoordinate; + this.looseSightCoordinate = looseSightCoordinate; + } + + public Xyz getStartCoordinate() { + return startCoordinate; + } + + public void setStartCoordinate(Xyz startCoordinate) { + this.startCoordinate = startCoordinate; + } + + public Xyz getEndCoordinate() { + return endCoordinate; + } + + public void setEndCoordinate(Xyz endCoordinate) { + this.endCoordinate = endCoordinate; + } + + public Xyz getLooseSightCoordinate() { + return looseSightCoordinate; + } + + public void setLooseSightCoordinate(Xyz looseSightCoordinate) { + this.looseSightCoordinate = looseSightCoordinate; + } + + public boolean hasBlocker() { + return this.looseSightCoordinate != null; + } +} diff --git a/src/main/java/hu/awm/srtm/tools/cansee/Xyz.java b/src/main/java/hu/awm/srtm/tools/cansee/Xyz.java new file mode 100644 index 0000000..63dc391 --- /dev/null +++ b/src/main/java/hu/awm/srtm/tools/cansee/Xyz.java @@ -0,0 +1,25 @@ +package hu.awm.srtm.tools.cansee; + +public class Xyz { + private Double x; + private Double y; + private Double z; + + public Xyz(Double x, Double y, Double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public Double getX() { + return x; + } + + public Double getY() { + return y; + } + + public Double getZ() { + return z; + } +} From 27246e897688cb9a8921f0a970fc47f8a7395e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Simon?= Date: Sat, 16 Oct 2021 13:39:07 +0200 Subject: [PATCH 2/2] Resolves #5 - Modified Tile to have a function to get height by double lat/lon. - Renamed Xyz to Vector3D and added some useful functions to it. - Implemented the main calculation for CanSeeCalculator. - Added examples to readme. --- readme.md | 18 ++++++ src/main/java/hu/awm/srtm/data/hgt/Tile.java | 14 ++++ .../srtm/map/contour/ContourCalculator.java | 2 +- .../srtm/tools/cansee/CanSeeCalculator.java | 38 +++++++++-- .../java/hu/awm/srtm/tools/cansee/Sight.java | 20 +++--- .../hu/awm/srtm/tools/cansee/Vector3D.java | 64 +++++++++++++++++++ .../java/hu/awm/srtm/tools/cansee/Xyz.java | 25 -------- 7 files changed, 139 insertions(+), 42 deletions(-) create mode 100644 src/main/java/hu/awm/srtm/tools/cansee/Vector3D.java delete mode 100644 src/main/java/hu/awm/srtm/tools/cansee/Xyz.java diff --git a/readme.md b/readme.md index ad622f0..6817c1c 100644 --- a/readme.md +++ b/readme.md @@ -91,3 +91,21 @@ java -jar target/hgt-map-renderer-0.0.1-SNAPSHOT.jar "contour" "" "44" "16" "48" "22" "47.84907" "20.19078" "500" "47.91870" "19.70804" "500" +``` + +Int the next example the viewpoint is on the lookout tower in Kékes, and the target is the reservoir in Nagyréde. +The point is visible. +``` +java -jar target/hgt-map-renderer-0.0.1-SNAPSHOT.jar "cansee" "" "44" "16" "48" "22" "47.87231" "20.00913" "1050" "47.78333" "19.83700" "200" +``` + +Warning! This method does not yet calculate with the Earth's curve. \ No newline at end of file diff --git a/src/main/java/hu/awm/srtm/data/hgt/Tile.java b/src/main/java/hu/awm/srtm/data/hgt/Tile.java index c73b823..f4564d8 100644 --- a/src/main/java/hu/awm/srtm/data/hgt/Tile.java +++ b/src/main/java/hu/awm/srtm/data/hgt/Tile.java @@ -77,6 +77,20 @@ public double getMaxElevation() { return maxElevation; } + public double elevationByExactCoordinates(final double lat, final double lon) { + if (lat < this.lat || lat >= this.lat + 1 || lon < this.lon || lon >= this.lon + 1) { + throw new IllegalArgumentException("{lat: " + lat + " lon: " + lon + "} is not in tile of {lat: " + + this.lat + " lon: " + this.lon + "}"); + } + double latDelta = lat - this.lat; + double lonDelta = lon - this.lon; + + int row = (int)(RESOLUTION * latDelta); + int col = (int)(RESOLUTION * lonDelta); + + return elevation(row, col); + } + private static String createExceptionMessage(int row, int col) { return "Query: " + row + "/" + col; } diff --git a/src/main/java/hu/awm/srtm/map/contour/ContourCalculator.java b/src/main/java/hu/awm/srtm/map/contour/ContourCalculator.java index c87d19f..2e7b568 100644 --- a/src/main/java/hu/awm/srtm/map/contour/ContourCalculator.java +++ b/src/main/java/hu/awm/srtm/map/contour/ContourCalculator.java @@ -107,7 +107,7 @@ else if (eyeHeight < targetVisibleHeight) { } //Based on https://github.com/dizzib/earthcalc. - static double calculateTargetHiddenHeight(double eyeHeight, int targetDistance) { + public static double calculateTargetHiddenHeight(double eyeHeight, double targetDistance) { final int EARTH_RADIUS_KM = 6371; final double eyeHeightKm = eyeHeight * 0.001; final double targetDistanceKm = targetDistance * 0.001; diff --git a/src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java b/src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java index 32843e7..be646a2 100644 --- a/src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java +++ b/src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java @@ -1,11 +1,13 @@ package hu.awm.srtm.tools.cansee; +import hu.awm.srtm.data.hgt.Tile; import hu.awm.srtm.data.hgt.TileMap; +import hu.awm.srtm.map.contour.ContourCalculator; public class CanSeeCalculator { - private Xyz from; - private Xyz to; + private Vector3D from; + private Vector3D to; private TileMap tileMap; public CanSeeCalculator() { @@ -13,8 +15,8 @@ public CanSeeCalculator() { } public void setCoordinates(Double fromLat, Double fromLon, Double fromHeight, Double toLat, Double toLon, Double toHeight) { - this.from = new Xyz(fromLat, fromLon, fromHeight); - this.to = new Xyz(toLat, toLon, toHeight); + this.from = new Vector3D(fromLat, fromLon, fromHeight); + this.to = new Vector3D(toLat, toLon, toHeight); } public void setTileMap(TileMap tileMap) { @@ -22,12 +24,36 @@ public void setTileMap(TileMap tileMap) { } public Sight calculateSight() { - // TODO: Replace this with the correct math. - return new Sight(null, null, null); + Vector3D loseSightCoordinate = null; + Vector3D directionVector = to.subtract(from); + double stepCount = Math.max(Math.abs(to.getLat() - from.getLat()) * Tile.RESOLUTION, + Math.abs(to.getLon() - from.getLon()) * Tile.RESOLUTION) * 2; + Vector3D stepVector = directionVector.getInstanceResizedToLength(directionVector.length() / stepCount); + + for (Vector3D i = from.newInstance(); i.lengthTo(to) > stepVector.length(); i = i.add(stepVector)) { + if (!isPointVisible(i)) { + loseSightCoordinate = i.newInstance(); + break; + } + } + if (loseSightCoordinate == null) { + if (!isPointVisible(to)) { + loseSightCoordinate = to.newInstance(); + } + } + return new Sight(from, to, loseSightCoordinate); } public boolean calculateBoolean() { Sight sight = calculateSight(); return !sight.hasBlocker(); } + + private boolean isPointVisible(Vector3D pointToCheck) { + int tileLat = pointToCheck.getLat().intValue(); + int tileLon = pointToCheck.getLon().intValue(); + Tile tile = tileMap.getByLatLon(tileLat, tileLon); + double height = tile.elevationByExactCoordinates(pointToCheck.getLat(), pointToCheck.getLon()); + return height <= pointToCheck.getHeight(); + } } diff --git a/src/main/java/hu/awm/srtm/tools/cansee/Sight.java b/src/main/java/hu/awm/srtm/tools/cansee/Sight.java index 9c02f84..2b7aa44 100644 --- a/src/main/java/hu/awm/srtm/tools/cansee/Sight.java +++ b/src/main/java/hu/awm/srtm/tools/cansee/Sight.java @@ -1,40 +1,40 @@ package hu.awm.srtm.tools.cansee; public class Sight { - private Xyz startCoordinate; - private Xyz endCoordinate; - private Xyz looseSightCoordinate; + private Vector3D startCoordinate; + private Vector3D endCoordinate; + private Vector3D looseSightCoordinate; public Sight() { } - public Sight(Xyz startCoordinate, Xyz endCoordinate, Xyz looseSightCoordinate) { + public Sight(Vector3D startCoordinate, Vector3D endCoordinate, Vector3D looseSightCoordinate) { this.startCoordinate = startCoordinate; this.endCoordinate = endCoordinate; this.looseSightCoordinate = looseSightCoordinate; } - public Xyz getStartCoordinate() { + public Vector3D getStartCoordinate() { return startCoordinate; } - public void setStartCoordinate(Xyz startCoordinate) { + public void setStartCoordinate(Vector3D startCoordinate) { this.startCoordinate = startCoordinate; } - public Xyz getEndCoordinate() { + public Vector3D getEndCoordinate() { return endCoordinate; } - public void setEndCoordinate(Xyz endCoordinate) { + public void setEndCoordinate(Vector3D endCoordinate) { this.endCoordinate = endCoordinate; } - public Xyz getLooseSightCoordinate() { + public Vector3D getLooseSightCoordinate() { return looseSightCoordinate; } - public void setLooseSightCoordinate(Xyz looseSightCoordinate) { + public void setLooseSightCoordinate(Vector3D looseSightCoordinate) { this.looseSightCoordinate = looseSightCoordinate; } diff --git a/src/main/java/hu/awm/srtm/tools/cansee/Vector3D.java b/src/main/java/hu/awm/srtm/tools/cansee/Vector3D.java new file mode 100644 index 0000000..07fce78 --- /dev/null +++ b/src/main/java/hu/awm/srtm/tools/cansee/Vector3D.java @@ -0,0 +1,64 @@ +package hu.awm.srtm.tools.cansee; + +public class Vector3D { + private Double lat; + private Double lon; + private Double height; + + public Vector3D(Double lat, Double lon, Double height) { + this.lat = lat; + this.lon = lon; + this.height = height; + } + + public Vector3D newInstance() { + return new Vector3D(this.lat, this.lon, this.height); + } + + public Double getLat() { + return lat; + } + + public Double getLon() { + return lon; + } + + public Double getHeight() { + return height; + } + + public Vector3D getInstanceResizedToLength(Double newLength) { + Double ratio = newLength / length(); + return new Vector3D(lat * ratio, lon * ratio, height * ratio); + } + + public Double length() { + return Math.sqrt(Math.pow(lat, 2.0) + + Math.pow(lon, 2.0) + + Math.pow(height, 2.0)); + } + + public static Vector3D subtract(Vector3D from, Vector3D what) { + return from.subtract(what); + } + + public Vector3D subtract(Vector3D what) { + return new Vector3D(this.lat - what.getLat(), + this.lon - what.getLon(), + this.height - what.getHeight()); + } + + public static Vector3D add(Vector3D to, Vector3D what) { + return to.add(what); + } + + public Vector3D add(Vector3D what) { + return new Vector3D(this.lat + what.getLat(), + this.lon + what.getLon(), + this.height + what.getHeight()); + } + + public double lengthTo(Vector3D what) { + return what.subtract(this).length(); + } +} diff --git a/src/main/java/hu/awm/srtm/tools/cansee/Xyz.java b/src/main/java/hu/awm/srtm/tools/cansee/Xyz.java deleted file mode 100644 index 63dc391..0000000 --- a/src/main/java/hu/awm/srtm/tools/cansee/Xyz.java +++ /dev/null @@ -1,25 +0,0 @@ -package hu.awm.srtm.tools.cansee; - -public class Xyz { - private Double x; - private Double y; - private Double z; - - public Xyz(Double x, Double y, Double z) { - this.x = x; - this.y = y; - this.z = z; - } - - public Double getX() { - return x; - } - - public Double getY() { - return y; - } - - public Double getZ() { - return z; - } -}