diff --git a/src/main/java/io/github/js0ny/ilp_coursework/data/RegionDto.java b/src/main/java/io/github/js0ny/ilp_coursework/data/RegionDto.java index 181899a..dd29144 100644 --- a/src/main/java/io/github/js0ny/ilp_coursework/data/RegionDto.java +++ b/src/main/java/io/github/js0ny/ilp_coursework/data/RegionDto.java @@ -6,17 +6,21 @@ import java.util.Objects; /** * Represents the data transfer object for a region definition *
- * This record encapsulates the data for calculating if a coordinate is inside the region + * This record encapsulates the data for calculating if a coordinate is inside + * the region *
- * A built-in method isClosedTo is defined to check this DTO is valid or not in the mean of closing polygon
+ * A built-in method {@code isClosedTo} is defined to check this DTO is valid or
+ * not in the mean of closing polygon
*
* @param name The human-readable name for the region
* @param vertices list of coordinates that forms a polygon as a region.
*
- * In order to define a valid region, the last element of the list should be the same as the first, or
+ * In order to define a valid region, the last element of the
+ * list should be the same as the first, or
* known as closed
* @see RegionCheckRequestDto
- * @see io.github.js0ny.ilp_coursework.service.GpsCalculationService#checkIsInRegion(LngLatDto, RegionDto)
+ * @see io.github.js0ny.ilp_coursework.service.GpsCalculationService#checkIsInRegion(LngLatDto,
+ * RegionDto)
*/
public record RegionDto(String name, List
- * Note that = 0.00015 will be counted as not close to and will return vertices forms a closed polygon
+ * Method to check if the region has a valid polygon by checking if the
+ * {@code vertices} forms a closed polygon
*
- * @return {@code true} if the vertices are able to form a polygon and form a closed polygon
+ * @return {@code true} if the {@code vertices} are able to form a polygon and
+ * form a closed polygon
*/
public boolean isClosed() {
if (vertices == null || vertices.size() < MINIMUM_VERTICES) {
diff --git a/src/main/java/io/github/js0ny/ilp_coursework/service/GpsCalculationService.java b/src/main/java/io/github/js0ny/ilp_coursework/service/GpsCalculationService.java
index a27243a..be193a2 100644
--- a/src/main/java/io/github/js0ny/ilp_coursework/service/GpsCalculationService.java
+++ b/src/main/java/io/github/js0ny/ilp_coursework/service/GpsCalculationService.java
@@ -29,29 +29,38 @@ public class GpsCalculationService {
private static final double CLOSE_THRESHOLD = 0.00015;
/**
- * Calculate the Euclidean distance between position1 and position2, which are coordinates
+ * Calculate the Euclidean distance between {@code position1} and
+ * {@code position2}, which are coordinates
* defined as {@link LngLatDto}
*
* @param position1 The coordinate of the first position
+ *
* @param position2 The coordinate of the second position
- * @return The Euclidean distance between position1 and position2
- * @see io.github.js0ny.ilp_coursework.controller.ApiController#getDistance(DistanceRequestDto)
+ * @return The Euclidean distance between {@code position1} and
+ * {@code position2}
+ * @see
+ * io.github.js0ny.ilp_coursework.controller.ApiController#getDistance(DistanceRequestDto)
*/
public double calculateDistance(LngLatDto position1, LngLatDto position2) {
double lngDistance = position2.lng() - position1.lng();
double latDistance = position2.lat() - position1.lat();
- // Euclidean: \sqrt{a^2 + b^2}
+ // Euclidean: \sqrt{a^2 + b^2}
return Math.sqrt(lngDistance * lngDistance + latDistance * latDistance);
}
/**
- * Check if position1 and position2 are close to each other, the threshold is < 0.00015
+ * Check if {@code position1} and
+ * {@code position2} are close to each other, the threshold is < 0.00015
+ *
* false
+ * Note that = 0.00015 will be counted as not close to and will return {@code
+ * false}
*
* @param position1 The coordinate of the first position
+ *
* @param position2 The coordinate of the second position
- * @return True if position1 and position2 are close to each other
+ * @return {@code true} if {@code position1} and
+ * {@code position2} are close to each other
* @see #CLOSE_THRESHOLD
* @see io.github.js0ny.ilp_coursework.controller.ApiController#getIsCloseTo(DistanceRequestDto)
*/
@@ -61,12 +70,14 @@ public class GpsCalculationService {
}
/**
- * Returns the next position moved from start in the direction with angle, with step size
+ * Returns the next position moved from {@code start} in the direction with
+ * {@code angle}, with step size
* 0.00015
*
* @param start The coordinate of the original start point.
+ *
* @param angle The direction to be moved in angle.
- * @return The next position moved from start
+ * @return The next position moved from {@code start}
* @see #STEP
* @see io.github.js0ny.ilp_coursework.controller.ApiController#getNextPosition(MovementRequestDto)
*/
@@ -78,13 +89,14 @@ public class GpsCalculationService {
}
/**
- * Used to check if the given position
- * is inside the region, on edge and vertex is considered as inside.
+ * Used to check if the given {@code position}
+ * is inside the {@code region}, on edge and vertex is considered as inside.
*
* @param position The coordinate of the position.
- * @param region A {@link RegionDto} that contains name and a list of LngLatDto
- * @return true if position is inside the region.
- * @throws IllegalArgumentException If region is not closed
+ * @param region A {@link RegionDto} that contains name and a list of
+ * {@code LngLatDto}
+ * @return {@code true} if {@code position} is inside the {@code region}.
+ * @throws IllegalArgumentException If {@code region} is not closed
* @see io.github.js0ny.ilp_coursework.controller.ApiController#getIsInRegion(RegionCheckRequestDto)
* @see RegionDto#isClosed()
*/
@@ -95,16 +107,15 @@ public class GpsCalculationService {
return rayCasting(position, region.vertices());
}
-
/**
- * Helper function to checkIsInRegion, use of ray-casting algorithm
+ * Helper function to {@code checkIsInRegion}, use of ray-casting algorithm
* to check if inside the polygon
*
* @param point The point to check
- * @param polygon The region that forms a polygon to check if point
+ * @param polygon The region that forms a polygon to check if {@code point}
* sits inside.
- * @return If the point sits inside the polygon then
- * return True
+ * @return If the {@code point} sits inside the {@code polygon} then
+ * return {@code true}
* @see #isPointOnEdge(LngLatDto, LngLatDto, LngLatDto)
* @see #checkIsInRegion(LngLatDto, RegionDto)
*/
@@ -138,7 +149,6 @@ public class GpsCalculationService {
double xIntersection = a.lng() + ((point.lat() - a.lat()) * (b.lng() - a.lng())) / (b.lat() - a.lat());
-
if (xIntersection > point.lng()) {
++intersections;
}
@@ -150,13 +160,15 @@ public class GpsCalculationService {
}
/**
- * Helper function from rayCasting that used to simply calculation
- * Used to check if point p is on the edge formed by a and b
+ * Helper function from {@code rayCasting} that used to simply calculation
+ * Used to check if point {@code p} is on the edge formed by
+ * {@code a} and {@code b}
*
* @param p point to be checked on the edge
+ *
* @param a point that forms the edge
* @param b point that forms the edge
- * @return boolean, if p is on ab then true
+ * @return {@code true} if {@code p} is on {@code ab}
* @see #rayCasting(LngLatDto, List)
*/
private boolean isPointOnEdge(LngLatDto p, LngLatDto a, LngLatDto b) {
diff --git a/src/test/java/io/github/js0ny/ilp_coursework/service/GpsCalculationServiceTest.java b/src/test/java/io/github/js0ny/ilp_coursework/service/GpsCalculationServiceTest.java
index 4f8a52d..3f8bc81 100644
--- a/src/test/java/io/github/js0ny/ilp_coursework/service/GpsCalculationServiceTest.java
+++ b/src/test/java/io/github/js0ny/ilp_coursework/service/GpsCalculationServiceTest.java
@@ -13,11 +13,10 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.within;
-
public class GpsCalculationServiceTest {
private static final double STEP = 0.00015;
- // private static final double CLOSE_THRESHOLD = STEP;
+ // private static final double CLOSE_THRESHOLD = STEP;
private static final double PRECISION = 1e-9;
private GpsCalculationService service;
@@ -180,7 +179,8 @@ public class GpsCalculationServiceTest {
void nextPosition_shouldMoveWest_forAngle180() {
var start = new LngLatDto(0.0, 0.0);
double angle = 180;
- // For 180 degrees, cos(180)=-1, sin(180)=0. Move happens entirely on negative lng axis.
+ // For 180 degrees, cos(180)=-1, sin(180)=0. Move happens entirely on negative
+ // lng axis.
var expected = new LngLatDto(-STEP, 0.0);
var actual = service.nextPosition(start, angle);
@@ -194,7 +194,8 @@ public class GpsCalculationServiceTest {
void nextPosition_shouldMoveSouth_forAngle270() {
var start = new LngLatDto(0.0, 0.0);
double angle = 270;
- // For 270 degrees, cos(270)=0, sin(270)=-1. Move happens entirely on negative lat axis.
+ // For 270 degrees, cos(270)=0, sin(270)=-1. Move happens entirely on negative
+ // lat axis.
var expected = new LngLatDto(0.0, -STEP);
var actual = service.nextPosition(start, angle);
@@ -257,13 +258,17 @@ public class GpsCalculationServiceTest {
@DisplayName("Test for checkIsInRegion(LngLatDto, RegionDto) -> boolean")
class CheckIsInRegionTests {
- public static final RegionDto RECTANGLE_REGION = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(2.0, 0.0), new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, 0.0)));
+ public static final RegionDto RECTANGLE_REGION = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0),
+ new LngLatDto(2.0, 0.0), new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, 0.0)));
@Test
@DisplayName("General Case: Given Example for Testing")
void isInRegion_shouldReturnFalse_givenPolygonCentral() {
var position = new LngLatDto(1.234, 1.222);
- var region = new RegionDto("central", List.of(new LngLatDto(-3.192473, 55.946233), new LngLatDto(-3.192473, 55.942617), new LngLatDto(-3.184319, 55.942617), new LngLatDto(-3.184319, 55.946233), new LngLatDto(-3.192473, 55.946233)));
+ var region = new RegionDto("central",
+ List.of(new LngLatDto(-3.192473, 55.946233), new LngLatDto(-3.192473, 55.942617),
+ new LngLatDto(-3.184319, 55.942617), new LngLatDto(-3.184319, 55.946233),
+ new LngLatDto(-3.192473, 55.946233)));
boolean expected = false;
boolean actual = service.checkIsInRegion(position, region);
assertThat(actual).isEqualTo(expected);
@@ -291,7 +296,10 @@ public class GpsCalculationServiceTest {
@DisplayName("General Case: Simple Hexagon")
void isInRegion_shouldReturnTrue_forSimpleHexagon() {
var position = new LngLatDto(2.0, 2.0);
- var region = new RegionDto("hexagon", List.of(new LngLatDto(1.0, 0.0), new LngLatDto(4.0, 0.0), new LngLatDto(5.0, 2.0), new LngLatDto(4.0, 4.0), new LngLatDto(1.0, 4.0), new LngLatDto(0.0, 2.0), new LngLatDto(1.0, 0.0)));
+ var region = new RegionDto("hexagon",
+ List.of(new LngLatDto(1.0, 0.0), new LngLatDto(4.0, 0.0), new LngLatDto(5.0, 2.0),
+ new LngLatDto(4.0, 4.0), new LngLatDto(1.0, 4.0), new LngLatDto(0.0, 2.0),
+ new LngLatDto(1.0, 0.0)));
boolean expected = true;
boolean actual = service.checkIsInRegion(position, region);
assertThat(actual).isEqualTo(expected);
@@ -301,7 +309,8 @@ public class GpsCalculationServiceTest {
@DisplayName("Edge Case: Small Triangle")
void isInRegion_shouldReturnTrue_forSmallTriangle() {
var position = new LngLatDto(0.00001, 0.00001);
- var region = new RegionDto("triangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0), new LngLatDto(0.00005, 0.0001), new LngLatDto(0.0, 0.0)));
+ var region = new RegionDto("triangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0),
+ new LngLatDto(0.00005, 0.0001), new LngLatDto(0.0, 0.0)));
boolean expected = true;
boolean actual = service.checkIsInRegion(position, region);
assertThat(actual).isEqualTo(expected);
@@ -356,7 +365,8 @@ public class GpsCalculationServiceTest {
@DisplayName("Edge Case: Region not forming polygon")
void isInRegion_shouldThrowExceptions_whenRegionNotFormingPolygon() {
var position = new LngLatDto(2.0, 2.0);
- var region = new RegionDto("line", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0), new LngLatDto(0.0, 0.0)));
+ var region = new RegionDto("line",
+ List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0), new LngLatDto(0.0, 0.0)));
assertThatThrownBy(() -> {
service.checkIsInRegion(position, region);
}).isInstanceOf(IllegalArgumentException.class).hasMessage("Region is not closed.");
@@ -366,10 +376,11 @@ public class GpsCalculationServiceTest {
@DisplayName("Edge Case: Region is not closed")
void isInRegion_shouldThrowExceptions_whenRegionNotClose() {
var position = new LngLatDto(2.0, 2.0);
- var region = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(2.0, 0.0), new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, -1.0)));
+ var region = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(2.0, 0.0),
+ new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, -1.0)));
assertThatThrownBy(() -> {
service.checkIsInRegion(position, region);
}).isInstanceOf(IllegalArgumentException.class).hasMessage("Region is not closed.");
}
}
-}
\ No newline at end of file
+}