Red Coder
Red Coder

Reputation: 145

Floating Range with additional number in Kotlin

I make Wind direction enum and I want to make a range that catches all values between 2 numbers OR third one:

number between (0.0 and 45.0) OR (360.0)

enum class WindDirections(val description: String,val shortName : String, val range: ClosedFloatingPointRange<Double>,val image: Int) {

// North
NORTH("N North", "N" ,(0.0..45.0), R.drawable.wind_north_red50),
NORTH_EAST("NE North-East", "NE" ,45.1..90.0, R.drawable.wind_north_east_red),
(... East, South, West etc)
NOT_FOUND ("", "-",-1.1..-1.0,0); // error one, now 360* is inside that

(...)

With these functions, I want to get enum class - WindDirections with the right value, based on given angle windDirection: Double. For example:

I want to get North for a range of 0..45 and also 360

fun getWindDirectionByDouble(windDirection: Double): WindDirections {
        return when (windDirection) {
            in NORTH.range -> NORTH //   number between (0.0 and 45.0) OR (360.0 need to accomplish that one, now it isn't)
            in NORTH_EAST.range -> NORTH_EAST //   45 and 90
            (... East, South, West etc)
            else -> NOT_FOUND // when angle is not between 0 and 359.9 (for now 360 is here)

Thank you in advance

EDIT:

The way to accomplish that is to make when catching my special case for 360 in function getWindDirectionByDouble() like that in bellow, but I ask, is it possible to add 360 in the range of NORTH somehow. "(0.0..45.0) and (360.0)"

fun getWindDirectionByDouble(windDirection: Double): WindDirections {
    return when (windDirection) {
        360.0 -> NORTH // Like that one, i will return right WindDirections.NORTH
        in NORTH.range -> NORTH //   number between (0.0 and 45.0) OR (360.0 need to accomplish that one, now it isn't)
        in NORTH_EAST.range -> NORTH_EAST //   45 and 90
        (... East, South, West etc)
        else -> NOT_FOUND

Upvotes: 0

Views: 680

Answers (1)

Tenfour04
Tenfour04

Reputation: 93581

There is a flaw in using a Double ClosedRange for this since it treats the start and end inclusively. You worked around that by using 45.1 for example, but then there are numbers like 45.05 that won't be in any of the ranges.

You could make your own type of range that treats the end as exclusive. And you could also design it to handle angles outside 0-360 by calculating the positive remainder (modulo).

data class AngleRange(val start: Double, val endExclusive: Double) {
    operator fun contains(value: Double) = 
        ((value % 360.0 + 360.0) % 360.0).let { it >= start && it < endExclusive }
}

Then you can fully cover the possible ranges using AngleRange(0.0, 45.0), AngleRange(45.0, 90.0), etc.

Upvotes: 2

Related Questions