Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev branch #66

Merged
merged 15 commits into from
Dec 18, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
base <=> base-portable refactoring
  • Loading branch information
IKupriyanov-HORIS committed Dec 18, 2019
commit 2084319a8864dde8cc84f22b12082dd11eeccb55
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ package jetbrains.datalore.base.algorithms

import jetbrains.datalore.base.gcommon.collect.ClosedRange
import jetbrains.datalore.base.geometry.DoubleVector
import jetbrains.datalore.base.projectionGeometry.MultiPolygon
import jetbrains.datalore.base.projectionGeometry.Polygon
import jetbrains.datalore.base.projectionGeometry.Ring
import jetbrains.datalore.base.projectionGeometry.Vec
import kotlin.math.abs

fun <T> splitRings(points: List<T>): List<List<T>> {
Expand Down Expand Up @@ -58,33 +54,6 @@ fun calculateArea(ring: List<DoubleVector>): Double {
return calculateArea(ring, DoubleVector::x, DoubleVector::y)
}

private fun <T> isClockwise(ring: List<Vec<T>>): Boolean {
return isClockwise(ring, Vec<T>::x, Vec<T>::y)
}

fun <T> createMultiPolygon(points: List<Vec<T>>): MultiPolygon<T> {
if (points.isEmpty()) {
return MultiPolygon(emptyList())
}

val polygons = ArrayList<Polygon<T>>()
var rings = ArrayList<Ring<T>>()

for (ring in splitRings(points)) {
if (rings.isNotEmpty() && isClockwise(ring)) {
polygons.add(Polygon(rings))
rings = ArrayList()
}
rings.add(Ring(ring))
}

if (rings.isNotEmpty()) {
polygons.add(Polygon(rings))
}

return MultiPolygon(polygons)
}

fun <T> isClockwise(ring: List<T>, x: (T) -> Double, y: (T) -> Double): Boolean {
check(ring.isNotEmpty()) { "Ring shouldn't be empty to calculate clockwise" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,12 @@

package jetbrains.datalore.base.geometry

import jetbrains.datalore.base.projectionGeometry.Rect
import jetbrains.datalore.base.projectionGeometry.Vec
import jetbrains.datalore.base.projectionGeometry.newSpanRectangle
import kotlin.math.max
import kotlin.math.min

object DoubleRectangles {
private val DOUBLE_VECTOR_GET_X = { p: DoubleVector -> p.x }
private val DOUBLE_VECTOR_GET_Y = { p: DoubleVector -> p.y }
private val VEC_GET_X = { p: Vec<*> -> p.x }
private val VEC_GET_Y = { p: Vec<*> -> p.y }

fun boundingBox(points: Iterable<DoubleVector>): DoubleRectangle {
return calculateBoundingBox(points, DOUBLE_VECTOR_GET_X, DOUBLE_VECTOR_GET_Y)
Expand All @@ -27,17 +22,7 @@ object DoubleRectangles {
}
}

fun <TypeT> boundingBox(points: Iterable<Vec<TypeT>>): Rect<TypeT> {
return calculateBoundingBox(points, VEC_GET_X, VEC_GET_Y)
{ minX, minY, maxX, maxY ->
newSpanRectangle(
Vec(minX, minY),
Vec(maxX, maxY)
)
}
}

private fun <PointT, BoxT> calculateBoundingBox(
fun <PointT, BoxT> calculateBoundingBox(
points: Iterable<PointT>,
getX: (PointT) -> Double,
getY: (PointT) -> Double,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/

package jetbrains.datalore.base.geospatial

const val EARTH_RADIUS = 6378137.0
const val MIN_LONGITUDE = -180.0
const val MAX_LONGITUDE = 180.0
const val FULL_LONGITUDE = MAX_LONGITUDE - MIN_LONGITUDE
const val MIN_LATITUDE = -90.0
const val MAX_LATITUDE = 90.0
const val FULL_LATITUDE = MAX_LATITUDE - MIN_LATITUDE
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/

package jetbrains.datalore.base.spatial
package jetbrains.datalore.base.geospatial

import jetbrains.datalore.base.gcommon.collect.ClosedRange
import jetbrains.datalore.base.math.toDegrees
Expand All @@ -12,7 +12,6 @@ import jetbrains.datalore.base.math.toRadians
import kotlin.math.*

object MercatorUtils {
private const val EARTH_RADIUS = 6378137.0
private const val MAX_LONGITUDE = 180.0
private const val MAX_LATITUDE = 85.0511287798
val VALID_LONGITUDE_RANGE = ClosedRange.closed(-MAX_LONGITUDE, MAX_LONGITUDE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ package jetbrains.datalore.base.math

import jetbrains.datalore.base.geometry.DoubleVector
import jetbrains.datalore.base.geometry.Vector
import kotlin.math.PI
import kotlin.math.ceil
import kotlin.math.round
import kotlin.math.sqrt
import kotlin.math.*

fun toRadians(degrees: Double): Double = degrees * PI / 180.0
fun toDegrees(radians: Double): Double = radians * 180.0 / PI
Expand Down Expand Up @@ -41,3 +38,6 @@ fun distance(vector: Vector, doubleVector: DoubleVector): Double {
}


fun Int.ipow(e: Int): Double {
return this.toDouble().pow(e)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,14 @@
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/

package jetbrains.datalore.base.spatial
package jetbrains.datalore.base.geospatial

import jetbrains.datalore.base.projectionGeometry.Rect
import jetbrains.datalore.base.typedGeometry.Rect
import kotlin.math.max
import kotlin.math.min

class LonLat

internal const val MIN_LONGITUDE = -180.0
internal const val MAX_LONGITUDE = 180.0
const val FULL_LONGITUDE = MAX_LONGITUDE - MIN_LONGITUDE
private const val MIN_LATITUDE = -90.0
private const val MAX_LATITUDE = 90.0
private const val FULL_LATITUDE = MAX_LATITUDE - MIN_LATITUDE
val EARTH_RECT = Rect<LonLat>(MIN_LONGITUDE, MIN_LATITUDE, FULL_LONGITUDE, FULL_LATITUDE)

fun limitLon(lon: Double) = max(MIN_LONGITUDE, min(lon, MAX_LONGITUDE))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/

package jetbrains.datalore.base.spatial
package jetbrains.datalore.base.geospatial

import jetbrains.datalore.base.gcommon.base.Preconditions.checkArgument
import jetbrains.datalore.base.gcommon.collect.ClosedRange
import jetbrains.datalore.base.geometry.DoubleRectangle
import jetbrains.datalore.base.projectionGeometry.*
import jetbrains.datalore.base.spatial.LongitudeRange.Companion.splitRange
import jetbrains.datalore.base.geospatial.LongitudeRange.Companion.splitRange
import jetbrains.datalore.base.typedGeometry.*
import kotlin.math.max
import kotlin.math.min

class GeoBoundingBoxCalculator<TypeT>(
private val myMapRect: Rect<TypeT>,
private val myLoopX: Boolean,
private val myLoopY: Boolean) {
private val myLoopY: Boolean
) {

fun calculateBoundingBox(xyCoords: List<Double>): Rect<TypeT> {
checkArgument(xyCoords.size % 2 == 0, "Longitude-Latitude list is not even-numbered.")
Expand All @@ -31,43 +32,45 @@ class GeoBoundingBoxCalculator<TypeT>(
}

fun calculateBoundingBox(
minXCoords: List<Double>,
minYCoords: List<Double>,
maxXCoords: List<Double>,
maxYCoords: List<Double>
minXCoords: List<Double>,
minYCoords: List<Double>,
maxXCoords: List<Double>,
maxYCoords: List<Double>
): Rect<TypeT> {
val count = minXCoords.size
checkArgument(minYCoords.size == count && maxXCoords.size == count && maxYCoords.size == count,
"Counts of 'minLongitudes', 'minLatitudes', 'maxLongitudes', 'maxLatitudes' lists are not equal.")
checkArgument(
minYCoords.size == count && maxXCoords.size == count && maxYCoords.size == count,
"Counts of 'minLongitudes', 'minLatitudes', 'maxLongitudes', 'maxLatitudes' lists are not equal."
)

return calculateBoundingBox(
itemGetter(minXCoords),
itemGetter(maxXCoords),
itemGetter(minYCoords),
itemGetter(maxYCoords),
count
itemGetter(minXCoords),
itemGetter(maxXCoords),
itemGetter(minYCoords),
itemGetter(maxYCoords),
count
)
}

fun calculateBoundingBoxFromGeoRectangles(rectangles: List<GeoRectangle>): Rect<TypeT> {
val geoRectGetter = itemGetter(rectangles)
return calculateBoundingBox(
{ x: Int -> MIN_LONGITUDE_GETTER(geoRectGetter(x)) },
{ x: Int -> MAX_LONGITUDE_GETTER(geoRectGetter(x)) },
{ x: Int -> MIN_LATITUDE_GETTER(geoRectGetter(x)) },
{ x: Int -> MAX_LATITUDE_GETTER(geoRectGetter(x)) },
rectangles.size
{ x: Int -> MIN_LONGITUDE_GETTER(geoRectGetter(x)) },
{ x: Int -> MAX_LONGITUDE_GETTER(geoRectGetter(x)) },
{ x: Int -> MIN_LATITUDE_GETTER(geoRectGetter(x)) },
{ x: Int -> MAX_LATITUDE_GETTER(geoRectGetter(x)) },
rectangles.size
)
}

fun calculateBoundingBoxFromRectangles(rectangles: List<Rect<TypeT>>): Rect<TypeT> {
val rectGetter = itemGetter(rectangles)
return calculateBoundingBox(
{ x: Int -> LEFT_RECT_GETTER(rectGetter(x)) },
{ x: Int -> RIGHT_RECT_GETTER(rectGetter(x)) },
{ x: Int -> TOP_RECT_GETTER(rectGetter(x)) },
{ x: Int -> BOTTOM_RECT_GETTER(rectGetter(x)) },
rectangles.size
{ x: Int -> LEFT_RECT_GETTER(rectGetter(x)) },
{ x: Int -> RIGHT_RECT_GETTER(rectGetter(x)) },
{ x: Int -> TOP_RECT_GETTER(rectGetter(x)) },
{ x: Int -> BOTTOM_RECT_GETTER(rectGetter(x)) },
rectangles.size
)
}

Expand All @@ -76,9 +79,9 @@ class GeoBoundingBoxCalculator<TypeT>(
}

private fun calculateBoundingBox(
minX: (Int) -> Double, maxX: (Int) -> Double,
minY: (Int) -> Double, maxY: (Int) -> Double,
size: Int
minX: (Int) -> Double, maxX: (Int) -> Double,
minY: (Int) -> Double, maxY: (Int) -> Double,
size: Int
): Rect<TypeT> {
val xRange = calculateBoundingRange(CoordinateHelperImpl(minX, maxX, size), myMapRect.xRange(), myLoopX)
val yRange = calculateBoundingRange(CoordinateHelperImpl(minY, maxY, size), myMapRect.yRange(), myLoopY)
Expand All @@ -90,7 +93,11 @@ class GeoBoundingBoxCalculator<TypeT>(
)
}

private fun calculateBoundingRange(helper: CoordinateHelper, mapRange: ClosedRange<Double>, loop: Boolean): ClosedRange<Double> {
private fun calculateBoundingRange(
helper: CoordinateHelper,
mapRange: ClosedRange<Double>,
loop: Boolean
): ClosedRange<Double> {
return if (loop) calculateLoopLimitRange(helper, mapRange) else calculateLimitRange(helper)
}

Expand Down Expand Up @@ -172,7 +179,10 @@ class GeoBoundingBoxCalculator<TypeT>(
return { index -> values[2 * index + 1] }
}

internal fun calculateLoopLimitRange(helper: CoordinateHelper, mapRange: ClosedRange<Double>): ClosedRange<Double> {
internal fun calculateLoopLimitRange(
helper: CoordinateHelper,
mapRange: ClosedRange<Double>
): ClosedRange<Double> {
if (helper.size() == 0) {
throw RuntimeException("No coordinates for bounding box calculation.")
}
Expand All @@ -187,8 +197,8 @@ class GeoBoundingBoxCalculator<TypeT>(
range
} else {
ClosedRange.closed(
range.lowerEndpoint() - length(mapRange),
range.upperEndpoint() - length(mapRange)
range.lowerEndpoint() - length(mapRange),
range.upperEndpoint() - length(mapRange)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/

package jetbrains.datalore.base.spatial
package jetbrains.datalore.base.geospatial

import jetbrains.datalore.base.gcommon.collect.ClosedRange
import jetbrains.datalore.base.projectionGeometry.Rect
import jetbrains.datalore.base.projectionGeometry.Vec
import jetbrains.datalore.base.projectionGeometry.newSpanRectangle
import jetbrains.datalore.base.typedGeometry.Rect
import jetbrains.datalore.base.typedGeometry.Vec
import jetbrains.datalore.base.typedGeometry.newSpanRectangle

class GeoRectangle(minLongitude: Double, minLatitude: Double, maxLongitude: Double, maxLatitude: Double) {
private val myLongitudeRange: LongitudeRange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/

package jetbrains.datalore.base.spatial
package jetbrains.datalore.base.geospatial

import jetbrains.datalore.base.projectionGeometry.*
import jetbrains.datalore.base.typedGeometry.*


object GeoUtils {

val BBOX_CALCULATOR = GeoBoundingBoxCalculator(EARTH_RECT, true, false)
val BBOX_CALCULATOR = GeoBoundingBoxCalculator(EARTH_RECT, myLoopX = true, myLoopY = false)


fun convertToGeoRectangle(rect: Rect<LonLat>): GeoRectangle {
Expand All @@ -25,11 +25,13 @@ object GeoUtils {
right = EARTH_RECT.right
}

return GeoRectangle(left, limitLat(rect.top), right, limitLat(rect.bottom))
return GeoRectangle(left,
limitLat(rect.top), right,
limitLat(rect.bottom)
)
}



fun tileXYToTileID(tileX: Int, tileY: Int, zoom: Int): String {
var tileID = ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/

package jetbrains.datalore.base.spatial
package jetbrains.datalore.base.geospatial

import jetbrains.datalore.base.gcommon.collect.ClosedRange

Expand Down Expand Up @@ -45,7 +45,9 @@ internal class LongitudeRange(lower: Double, upper: Double) {

fun splitByAntiMeridian(): List<ClosedRange<Double>> {
val result = ArrayList<ClosedRange<Double>>()
splitRange(myLower, myUpper, MIN_LONGITUDE, MAX_LONGITUDE, result)
splitRange(myLower, myUpper,
MIN_LONGITUDE,
MAX_LONGITUDE, result)
return result
}

Expand All @@ -61,7 +63,13 @@ internal class LongitudeRange(lower: Double, upper: Double) {
}

companion object {
fun splitRange(lower: Double, upper: Double, min: Double, max: Double, result: MutableCollection<ClosedRange<Double>>) {
fun splitRange(
lower: Double,
upper: Double,
min: Double,
max: Double,
result: MutableCollection<ClosedRange<Double>>
) {
if (upper < lower) {
result.add(ClosedRange.closed(lower, max))
result.add(ClosedRange.closed(min, upper))
Expand All @@ -70,7 +78,10 @@ internal class LongitudeRange(lower: Double, upper: Double) {
}
}

private fun disjointRangesEncloseRange(ranges: List<ClosedRange<Double>>, internalRange: ClosedRange<Double>): Boolean {
private fun disjointRangesEncloseRange(
ranges: List<ClosedRange<Double>>,
internalRange: ClosedRange<Double>
): Boolean {
for (range in ranges) {
if (range.encloses(internalRange)) {
return true
Expand Down
Loading