Skip to content

Commit

Permalink
Merge pull request #13 from adtewa/feature/5_given_two_coordinates_de…
Browse files Browse the repository at this point in the history
…termine_visibility

Feature/5 given two coordinates determine visibility
  • Loading branch information
dodie authored Oct 17, 2021
2 parents f7e65ed + 27246e8 commit 6a0b719
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 5 deletions.
18 changes: 18 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,21 @@ java -jar target/hgt-map-renderer-0.0.1-SNAPSHOT.jar "contour" "<path-to-hgt-dat
```

![Contour lines](https://github.com/dodie/hgt-map-renderer/blob/master/docs/contour.png "Contour lines")

## Can-See Calculation

The "cansee" command tells you if a point in the 3D space is visible from the viewpoint.
The inputs are the two coordinates with height data: Viewpoint(lat, lon, height), WatchedPoint(lat, lon, height) in this order.

In the following example we try to see a point at 500m above Pásztó from 500m above Verpelét unsuccessfully because Kékes blocks the view:
```
java -jar target/hgt-map-renderer-0.0.1-SNAPSHOT.jar "cansee" "<path-to-hgt-data>" "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" "<path-to-hgt-data>" "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.
36 changes: 32 additions & 4 deletions src/main/java/hu/awm/srtm/cli/CliApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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]);
Expand All @@ -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]);
Expand All @@ -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.");
}

Expand Down
14 changes: 14 additions & 0 deletions src/main/java/hu/awm/srtm/data/hgt/Tile.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/hu/awm/srtm/tools/cansee/CanSeeCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
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 Vector3D from;
private Vector3D to;
private TileMap tileMap;

public CanSeeCalculator() {

}

public void setCoordinates(Double fromLat, Double fromLon, Double fromHeight, Double toLat, Double toLon, Double toHeight) {
this.from = new Vector3D(fromLat, fromLon, fromHeight);
this.to = new Vector3D(toLat, toLon, toHeight);
}

public void setTileMap(TileMap tileMap) {
this.tileMap = tileMap;
}

public Sight calculateSight() {
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();
}
}
44 changes: 44 additions & 0 deletions src/main/java/hu/awm/srtm/tools/cansee/Sight.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package hu.awm.srtm.tools.cansee;

public class Sight {
private Vector3D startCoordinate;
private Vector3D endCoordinate;
private Vector3D looseSightCoordinate;

public Sight() {
}

public Sight(Vector3D startCoordinate, Vector3D endCoordinate, Vector3D looseSightCoordinate) {
this.startCoordinate = startCoordinate;
this.endCoordinate = endCoordinate;
this.looseSightCoordinate = looseSightCoordinate;
}

public Vector3D getStartCoordinate() {
return startCoordinate;
}

public void setStartCoordinate(Vector3D startCoordinate) {
this.startCoordinate = startCoordinate;
}

public Vector3D getEndCoordinate() {
return endCoordinate;
}

public void setEndCoordinate(Vector3D endCoordinate) {
this.endCoordinate = endCoordinate;
}

public Vector3D getLooseSightCoordinate() {
return looseSightCoordinate;
}

public void setLooseSightCoordinate(Vector3D looseSightCoordinate) {
this.looseSightCoordinate = looseSightCoordinate;
}

public boolean hasBlocker() {
return this.looseSightCoordinate != null;
}
}
64 changes: 64 additions & 0 deletions src/main/java/hu/awm/srtm/tools/cansee/Vector3D.java
Original file line number Diff line number Diff line change
@@ -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();
}
}

0 comments on commit 6a0b719

Please sign in to comment.