chore: formatting and use modern javadoc style
This commit is contained in:
parent
79db47459a
commit
c2a39936ec
3 changed files with 69 additions and 40 deletions
|
|
@ -6,17 +6,21 @@ import java.util.Objects;
|
|||
/**
|
||||
* Represents the data transfer object for a region definition
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* A built-in method <code>isClosedTo</code> 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.
|
||||
* <p>
|
||||
* 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<LngLatDto> vertices) {
|
||||
/**
|
||||
|
|
@ -27,9 +31,11 @@ public record RegionDto(String name, List<LngLatDto> vertices) {
|
|||
private static final int MINIMUM_VERTICES = 4;
|
||||
|
||||
/**
|
||||
* Method to check if the region has a valid polygon by checking if the <code>vertices</code> 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 <code>vertices</code> 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) {
|
||||
|
|
|
|||
|
|
@ -29,13 +29,17 @@ public class GpsCalculationService {
|
|||
private static final double CLOSE_THRESHOLD = 0.00015;
|
||||
|
||||
/**
|
||||
* Calculate the Euclidean distance between <code>position1</code> and <code>position2</code>, 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 <code>position1</code> and <code>position2</code>
|
||||
* @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();
|
||||
|
|
@ -45,13 +49,18 @@ public class GpsCalculationService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if <code>position1</code> and <code>position2</code> 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
|
||||
*
|
||||
* <p>
|
||||
* Note that = 0.00015 will be counted as not close to and will return <code>false</code>
|
||||
* 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 <code>position1</code> and <code>position2</code> 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 <code>start</code> in the direction with <code>angle</code>, 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 <code>start</code>
|
||||
* @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 <code>position</code>
|
||||
* is inside the <code>region</code>, 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 <code>LngLatDto</code>
|
||||
* @return true if <code>position</code> is inside the <code>region</code>.
|
||||
* @throws IllegalArgumentException If <code>region</code> 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 <code>checkIsInRegion</code>, 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 <code>point</code>
|
||||
* @param polygon The region that forms a polygon to check if {@code point}
|
||||
* sits inside.
|
||||
* @return If the <code>point</code> sits inside the <code>polygon</code> 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 <code>rayCasting</code> that used to simply calculation <br>
|
||||
* Used to check if point <code>p</code> is on the edge formed by <code>a</code> and <code>b</code>
|
||||
* Helper function from {@code rayCasting} that used to simply calculation <br>
|
||||
* 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 <code>p</code> is on <code>ab</code> 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) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ 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;
|
||||
|
|
@ -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,7 +376,8 @@ 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.");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue