Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ package io.trewartha.positional.core.measurement
*/
public data class Distance(val magnitude: Double, val unit: Unit) {

/**
* `true` if the distance is finite, `false` if it is negative or positive infinity
*/
val isFinite: Boolean get() = magnitude.isFinite()
init {
require(magnitude.isFinite()) { "Distance magnitude must be finite, but was $magnitude" }
}

/**
* `true` if the distance is negative, `false` if it is positive or zero
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public data class MgrsCoordinates(
) : Coordinates {

private val worldWindMgrsCoordinates = try {
require(easting.isFinite && !easting.isNegative) { "Invalid easting: $easting" }
require(northing.isFinite && !northing.isNegative) { "Invalid northing: $northing" }
require(!easting.isNegative) { "Easting must not be negative but was $easting" }
require(!northing.isNegative) { "Northing must not be negative but was $northing" }
val easting = easting.inRoundedAndPaddedMeters()
val northing = northing.inRoundedAndPaddedMeters()
MGRSCoord.fromString("$gridZoneDesignator $gridSquareID $easting $northing")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public data class UtmCoordinates(
Hemisphere.NORTH -> earth.worldwind.geom.coords.Hemisphere.N
Hemisphere.SOUTH -> earth.worldwind.geom.coords.Hemisphere.S
}
require(easting.isFinite && !easting.isNegative) { "Invalid easting: $easting" }
require(northing.isFinite && !northing.isNegative) { "Invalid northing: $northing" }
require(!easting.isNegative) { "Easting must not be negative but was $easting" }
require(!northing.isNegative) { "Northing must not be negative but was $northing" }
val easting = easting.inMeters().magnitude
val northing = northing.inMeters().magnitude
UTMCoord.fromUTM(zone, hemisphere, easting, northing)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,71 @@
package io.trewartha.positional.core.measurement

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.booleans.shouldBeFalse
import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.doubles.plusOrMinus
import io.kotest.matchers.shouldBe
import io.kotest.property.Arb
import io.kotest.property.arbitrary.double
import io.kotest.property.arbitrary.enum
import io.kotest.property.arbitrary.filter
import io.kotest.property.arbitrary.negativeDouble
import io.kotest.property.arbitrary.numericDouble
import io.kotest.property.arbitrary.of
import io.kotest.property.arbitrary.positiveDouble
import io.kotest.property.checkAll
import kotlin.math.abs

class DistanceTest : DescribeSpec({

describe("creating a Distance") {
context("with a finite magnitude") {
it("succeeds") {
checkAll(Arb.numericDouble(), Arb.enum<Distance.Unit>()) { magnitude, unit ->
Distance(magnitude, unit)
}
}
}

context("with a NaN magnitude") {
it("throws IllegalArgumentException") {
checkAll(Arb.enum<Distance.Unit>()) { unit ->
shouldThrow<IllegalArgumentException> { Distance(Double.NaN, unit) }
}
}
}

context("with an infinite magnitude") {
it("throws IllegalArgumentException") {
checkAll(
Arb.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
Arb.enum<Distance.Unit>()
) { magnitude, unit ->
shouldThrow<IllegalArgumentException> { Distance(magnitude, unit) }
}
}
}
}

describe("creating a distance in feet") {
it("creates a distance with the correct magnitude and unit") {
checkAll(Arb.double()) { number ->
checkAll(Arb.numericDouble()) { number ->
number.feet.shouldBe(Distance(number, Distance.Unit.FEET))
}
}
}

describe("creating a distance in meters") {
it("creates a distance with the correct magnitude and unit") {
checkAll(Arb.double()) { number ->
checkAll(Arb.numericDouble()) { number ->
number.meters.shouldBe(Distance(number, Distance.Unit.METERS))
}
}
}

describe("checking whether the distance is negative") {
describe("whether the distance is negative") {
context("when the magnitude is negative") {
it("returns true") {
checkAll(
Arb.negativeDouble().filter { !it.isNaN() },
Arb.numericDouble().filter { it < 0 },
Arb.enum<Distance.Unit>()
) { magnitude, unit ->
Distance(magnitude, unit).isNegative.shouldBeTrue()
Expand All @@ -57,28 +84,20 @@ class DistanceTest : DescribeSpec({
context("when the magnitude is positive") {
it("returns false") {
checkAll(
Arb.positiveDouble().filter { !it.isNaN() },
Arb.numericDouble().filter { it > 0 },
Arb.enum<Distance.Unit>()
) { magnitude, unit ->
Distance(magnitude, unit).isNegative.shouldBeFalse()
}
}
}

context("when the magnitude is NaN") {
it("returns false") {
checkAll(Arb.enum<Distance.Unit>()) { unit ->
Distance(Double.NaN, unit).isNegative.shouldBeFalse()
}
}
}
}

describe("checking whether the distance is positive") {
describe("whether the distance is positive") {
context("when the magnitude is negative") {
it("returns false") {
checkAll(
Arb.negativeDouble().filter { !it.isNaN() },
Arb.numericDouble().filter { it < 0 },
Arb.enum<Distance.Unit>()
) { magnitude, unit ->
Distance(magnitude, unit).isPositive.shouldBeFalse()
Expand All @@ -97,59 +116,19 @@ class DistanceTest : DescribeSpec({
context("when the magnitude is positive") {
it("returns true") {
checkAll(
Arb.positiveDouble().filter { !it.isNaN() },
Arb.numericDouble().filter { it > 0 },
Arb.enum<Distance.Unit>()
) { magnitude, unit ->
Distance(magnitude, unit).isPositive.shouldBeTrue()
}
}
}

context("when the magnitude is NaN") {
it("returns false") {
checkAll(Arb.enum<Distance.Unit>()) { unit ->
Distance(Double.NaN, unit).isPositive.shouldBeFalse()
}
}
}
}

describe("checking whether the distance is finite") {
context("when the magnitude is NaN") {
it("returns false") {
checkAll(Arb.enum<Distance.Unit>()) { unit ->
Distance(Double.NaN, unit).isFinite.shouldBeFalse()
}
}
}

context("when the magnitude is infinite") {
it("returns false") {
checkAll(
Arb.of(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
Arb.enum<Distance.Unit>()
) { magnitude, unit ->
Distance(magnitude, unit).isFinite.shouldBeFalse()
}
}
}

context("when the magnitude is finite") {
it("returns true") {
checkAll(
Arb.numericDouble(),
Arb.enum<Distance.Unit>()
) { magnitude, unit ->
Distance(magnitude, unit).isFinite.shouldBeTrue()
}
}
}
}

describe("converting to feet") {
context("when the distance is already in feet") {
it("returns the original distance") {
checkAll(Arb.double()) { magnitude ->
checkAll(Arb.numericDouble()) { magnitude ->
magnitude.feet.inFeet().shouldBe(magnitude.feet)
}
}
Expand Down Expand Up @@ -191,7 +170,7 @@ class DistanceTest : DescribeSpec({

context("when the distance is already in meters") {
it("returns the original distance") {
checkAll(Arb.double()) { magnitude ->
checkAll(Arb.numericDouble()) { magnitude ->
magnitude.meters.inMeters().shouldBe(magnitude.meters)
}
}
Expand Down