Skip to content

Commit

Permalink
Fix #486 : Can't set None for coord limit.
Browse files Browse the repository at this point in the history
  • Loading branch information
alshan committed Feb 17, 2024
1 parent 08b9f5e commit 9ec69ce
Show file tree
Hide file tree
Showing 15 changed files with 162 additions and 75 deletions.
1 change: 1 addition & 0 deletions future_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
- Bar width is too large when x-domain is defined via x-scale limits [[#1013](https://github.com/JetBrains/lets-plot/issues/1013)].
- How to hide only main tooltip? [[LPK-#232](https://github.com/JetBrains/lets-plot-kotlin/issues/232)].
- Make middle strip in `geomCrossbar()` optional [[LPK-#233](https://github.com/JetBrains/lets-plot-kotlin/issues/233)].
- Can't set None for coord limit [[#486](https://github.com/JetBrains/lets-plot/issues/486)].
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import org.jetbrains.letsPlot.commons.geometry.DoubleVector
import org.jetbrains.letsPlot.commons.interval.DoubleSpan

internal class CartesianCoordProvider(
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean = false
) : CoordProviderBase(xLim, yLim, flipped) {
override fun with(
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean
): CoordProvider {
return CartesianCoordProvider(xLim, yLim, flipped)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ interface CoordProvider {
val isPolar: Boolean

fun with(
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean
): CoordProvider

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ import org.jetbrains.letsPlot.commons.interval.DoubleSpan
import org.jetbrains.letsPlot.core.plot.base.coord.CoordinatesMapper

internal abstract class CoordProviderBase(
protected val xLim: DoubleSpan?,
protected val yLim: DoubleSpan?,
protected val xLim: Pair<Double?, Double?>,
protected val yLim: Pair<Double?, Double?>,
override val flipped: Boolean,
protected val projection: Projection = identity(),
) : CoordProvider {

init {
require(xLim == null || xLim.length > 0.0) { "Coord x-limits range should be > 0.0" }
require(yLim == null || yLim.length > 0.0) { "Coord y-limits range should be > 0.0" }
require(
xLim.first == null || xLim.second == null ||
xLim.second!! > xLim.first!!
) { "Invalid coord x-limits: $xLim " }
require(
yLim.first == null || yLim.second == null ||
yLim.second!! > yLim.first!!
) { "Invalid coord y-limits: $yLim" }
}

override val isLinear: Boolean = !projection.nonlinear
Expand All @@ -30,13 +36,24 @@ internal abstract class CoordProviderBase(
/**
* Reshape and flip the domain if necessary.
*/
override fun adjustDomain(domain: DoubleRectangle): DoubleRectangle {
final override fun adjustDomain(domain: DoubleRectangle): DoubleRectangle {
val xSpan = DoubleSpan(
xLim.first ?: domain.left,
xLim.second ?: domain.right
)

val ySpan = DoubleSpan(
yLim.first ?: domain.top,
yLim.second ?: domain.bottom
)

return adjustXYDomains(xSpan, ySpan)
}

protected open fun adjustXYDomains(xRange: DoubleSpan, yRange: DoubleSpan): DoubleRectangle {
val domain = DoubleRectangle(xRange, yRange)
val validDomain = domain.let {
val withLims = DoubleRectangle(
xLim ?: domain.xRange(),
yLim ?: domain.yRange(),
)
projection.validDomain().intersect(withLims)
projection.validDomain().intersect(it)
}

return if (validDomain != null && validDomain.height > 0.0 && validDomain.width > 0.0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ package org.jetbrains.letsPlot.core.plot.builder.coord

import org.jetbrains.letsPlot.commons.intern.spatial.projections.Projection
import org.jetbrains.letsPlot.commons.intern.spatial.projections.mercator
import org.jetbrains.letsPlot.commons.interval.DoubleSpan

private val NO_LIM: Pair<Double?, Double?> = Pair(null, null)

object CoordProviders {
@Suppress("NAME_SHADOWING")
fun cartesian(
xLim: DoubleSpan? = null,
yLim: DoubleSpan? = null,
xLim: Pair<Double?, Double?> = NO_LIM,
yLim: Pair<Double?, Double?> = NO_LIM,
flipped: Boolean = false
): CoordProvider {
return CartesianCoordProvider(xLim, yLim, flipped)
Expand All @@ -22,17 +23,17 @@ object CoordProviders {
@Suppress("NAME_SHADOWING")
fun fixed(
ratio: Double,
xLim: DoubleSpan? = null,
yLim: DoubleSpan? = null,
xLim: Pair<Double?, Double?> = NO_LIM,
yLim: Pair<Double?, Double?> = NO_LIM,
flipped: Boolean = false
): CoordProvider {
return FixedRatioCoordProvider(ratio, xLim, yLim, flipped)
}

@Suppress("NAME_SHADOWING")
fun map(
xLim: DoubleSpan? = null,
yLim: DoubleSpan? = null,
xLim: Pair<Double?, Double?> = NO_LIM,
yLim: Pair<Double?, Double?> = NO_LIM,
flipped: Boolean = false,
projection: Projection = mercator()
): CoordProvider {
Expand All @@ -45,8 +46,8 @@ object CoordProviders {
}

fun polar(
xLim: DoubleSpan? = null,
yLim: DoubleSpan? = null,
xLim: Pair<Double?, Double?> = NO_LIM,
yLim: Pair<Double?, Double?> = NO_LIM,
flipped: Boolean,
start: Double,
clockwise: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import org.jetbrains.letsPlot.commons.interval.DoubleSpan
*/
internal open class FixedRatioCoordProvider(
private val ratio: Double,
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean
) : CoordProviderBase(xLim, yLim, flipped) {
override fun with(
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean
): CoordProvider {
return FixedRatioCoordProvider(ratio, xLim, yLim, flipped)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import org.jetbrains.letsPlot.commons.interval.DoubleSpan
import org.jetbrains.letsPlot.commons.unsupported.UNSUPPORTED

internal class MarginalLayerCoordProvider : CoordProviderBase(
xLim = null,
yLim = null,
xLim = Pair(null, null),
yLim = Pair(null, null),
flipped = false
) {

override fun with(xLim: DoubleSpan?, yLim: DoubleSpan?, flipped: Boolean): CoordProvider {
override fun with(xLim: Pair<Double?, Double?>, yLim: Pair<Double?, Double?>, flipped: Boolean): CoordProvider {
UNSUPPORTED("MarginalLayerCoordProvider.with()")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import kotlin.math.sin
private const val R_EXPAND = 1.15

internal class PolarCoordProvider(
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean,
val start: Double,
val clockwise: Boolean,
Expand All @@ -33,15 +33,44 @@ internal class PolarCoordProvider(
override val isLinear: Boolean = false
override val isPolar: Boolean = true

override fun with(xLim: DoubleSpan?, yLim: DoubleSpan?, flipped: Boolean): CoordProvider {
override fun with(xLim: Pair<Double?, Double?>, yLim: Pair<Double?, Double?>, flipped: Boolean): CoordProvider {
return PolarCoordProvider(xLim, yLim, flipped, start, clockwise)
}

fun withHScaleContinuous(b: Boolean): PolarCoordProvider {
return PolarCoordProvider(xLim, yLim, flipped, start, clockwise, isHScaleContinuous = b)
}

override fun adjustDomain(domain: DoubleRectangle): DoubleRectangle {
// override fun adjustDomain(domain: DoubleRectangle): DoubleRectangle {
// val realDomain = domain.flipIf(flipped)
//
// // Domain of a data without any adjustments (i.e. no expand).
// // For theta, leave the lower end as it is to avoid a hole in the centre and to maintain the correct start angle.
// // Extend the upper end of the radius by 0.15 to allow space for labels and axis line.
//
// val adjustedXRange = realDomain.xRange().let {
// // For discrete scale add extra segment by increasing domain by 1
// // so that the last point won't overlap with the first one
// // in contrast to the continuous scale where the last point
// // has the same coordinate as the first one
// // i.e. ['a', 'b', 'c'] instead of [360/0, 180]
// val upperExpand = if (isHScaleContinuous) 0.0 else 1.0
// DoubleSpan.withLowerEnd(it.lowerEnd, it.length + upperExpand)
// }
//
// val adjustedYRange = (yLim ?: realDomain.yRange()).let {
// DoubleSpan.withLowerEnd(it.lowerEnd, it.length * R_EXPAND)
// }
//
// return DoubleRectangle(
// xLim ?: adjustedXRange, //theta
// adjustedYRange // r
// )
// }

override fun adjustXYDomains(xRange: DoubleSpan, yRange: DoubleSpan): DoubleRectangle {
val domain = DoubleRectangle(xRange, yRange)

val realDomain = domain.flipIf(flipped)

// Domain of a data without any adjustments (i.e. no expand).
Expand All @@ -58,12 +87,16 @@ internal class PolarCoordProvider(
DoubleSpan.withLowerEnd(it.lowerEnd, it.length + upperExpand)
}

val adjustedYRange = (yLim ?: realDomain.yRange()).let {
// val adjustedYRange = (yLim ?: realDomain.yRange()).let {
// DoubleSpan.withLowerEnd(it.lowerEnd, it.length * R_EXPAND)
// }
val adjustedYRange = realDomain.yRange().let {
DoubleSpan.withLowerEnd(it.lowerEnd, it.length * R_EXPAND)
}

return DoubleRectangle(
xLim ?: adjustedXRange, //theta
// xLim ?: adjustedXRange, //theta
adjustedXRange, //theta
adjustedYRange // r
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import org.jetbrains.letsPlot.core.plot.base.coord.projectDomain

internal class ProjectionCoordProvider(
projection: Projection,
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean
) : CoordProviderBase(xLim, yLim, flipped, projection) {

override fun with(
xLim: DoubleSpan?,
yLim: DoubleSpan?,
xLim: Pair<Double?, Double?>,
yLim: Pair<Double?, Double?>,
flipped: Boolean
): CoordProvider {
return ProjectionCoordProvider(projection, xLim, yLim, flipped)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import kotlin.test.assertEquals
class BreaksDataTest {
@Test
fun simple() {
val polarCoordProvider = PolarCoordProvider(xLim = null, yLim = null, flipped = false, start = 0.0, clockwise = true)
val polarCoordProvider = PolarCoordProvider(
xLim = Pair(null, null),
yLim = Pair(null, null),
flipped = false, start = 0.0, clockwise = true)
val dataDomain = DoubleRectangle.XYWH(-5.0, 10.0, 5.0, 8.0)
val adjustedDomain = polarCoordProvider.adjustDomain(dataDomain)
val gridDomain = polarCoordProvider.gridDomain(adjustedDomain)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ internal class CoordCartesianTest : CoordTestBase() {
}

companion object {
private val PROVIDER = CoordProviders.cartesian(null, null)
private val PROVIDER = CoordProviders.cartesian()
}
}
Loading

0 comments on commit 9ec69ce

Please sign in to comment.