diff --git a/README.md b/README.md index 44a5e334..4737ce7d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,18 @@ # YCharts +This is a fork the YCharts library using Advanced Cubic Bezier algorithm for prettier line charts. +The algorithm is explained in detail at [https://medium.com/mobile-app-development-publication/making-graph-plotting-function-in-jetpack-compose-95c80ee6fc7f](https://medium.com/mobile-app-development-publication/making-graph-plotting-function-in-jetpack-compose-95c80ee6fc7f) +
+
+ +
+
+ Advanced Cubic Bezier +
+
+ +
+
+ Basic Cubic Bezier YCharts is a Jetpack-compose based charts library which enables developers to easily integrate various types of charts/graphs into their existing ui to visually represent statistical data. YCharts supports both cartesian(XY-charts) and polar charts(Radial charts), which include: diff --git a/YChartsLib/build.gradle.kts b/YChartsLib/build.gradle.kts index b99e40b6..37f47887 100644 --- a/YChartsLib/build.gradle.kts +++ b/YChartsLib/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } android { - compileSdk = 33 + compileSdk = 35 namespace = "co.yml.charts.components" defaultConfig { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/YChartsLib/src/main/java/co/yml/charts/ui/linechart/LineChart.kt b/YChartsLib/src/main/java/co/yml/charts/ui/linechart/LineChart.kt index b7230d10..f704c1be 100644 --- a/YChartsLib/src/main/java/co/yml/charts/ui/linechart/LineChart.kt +++ b/YChartsLib/src/main/java/co/yml/charts/ui/linechart/LineChart.kt @@ -59,6 +59,7 @@ import co.yml.charts.ui.linechart.model.LineType import co.yml.charts.ui.linechart.model.SelectionHighlightPoint import co.yml.charts.ui.linechart.model.SelectionHighlightPopUp import kotlinx.coroutines.launch +import kotlin.math.sqrt /** * @@ -450,25 +451,57 @@ fun DrawScope.drawShadowUnderLineAndIntersectionPoint( } } +private fun getInBetweenSlope(m1: Float, m2: Float) : Float { + return if (m1 == m2) m1 else (m1 + m2) / ( 1 - m1 * m2 + sqrt(((m1*m1) + 1) * ((m2*m2) + 1)) ) +} +private fun getSlope(p1: Offset, p2: Offset): Float { + return (p2.y-p1.y) / (p2.x-p1.x) +} /** * * getCubicPoints method provides left and right average value for a given point to get a smooth curve. + * Using the Advanced Cubic Bezier method as given in https://medium.com/mobile-app-development-publication/making-graph-plotting-function-in-jetpack-compose-95c80ee6fc7f * @param pointsData : List of the points on the Line graph. */ fun getCubicPoints(pointsData: List): Pair, MutableList> { val cubicPoints1 = mutableListOf() val cubicPoints2 = mutableListOf() + val slopes = FloatArray(pointsData.size) + for (i in 1 until pointsData.size) { + val currSlope = if (i == 1) getSlope(pointsData[1], pointsData[0]) else slopes [i] + + val nextSlope: Float + if (i < pointsData.size-1) { + nextSlope = getSlope(pointsData[i + 1], pointsData[i]) + slopes[i+1] = nextSlope + } + else { + nextSlope = currSlope + } + + val prevSlope = if (i >1 ) slopes[i-1] else currSlope + + val cp1x = ((pointsData[i-1].x * 2f) + pointsData[i].x)/3f + val cp1slope = getInBetweenSlope(prevSlope, currSlope) + val cp1c = pointsData[i-1].y - (cp1slope * pointsData[i-1].x) + val cp1y = (cp1slope * cp1x) + cp1c + + val cp2x = (pointsData[i-1].x + (pointsData[i].x * 2f))/3f + val cp2slope = getInBetweenSlope(currSlope, nextSlope) + val cp2c = pointsData[i].y - (cp2slope * pointsData[i].x) + val cp2y = (cp2slope * cp2x ) + cp2c + cubicPoints1.add( Offset( - (pointsData[i].x + pointsData[i - 1].x) / 2, pointsData[i - 1].y + cp1x, cp1y ) ) cubicPoints2.add( Offset( - (pointsData[i].x + pointsData[i - 1].x) / 2, pointsData[i].y + cp2x, cp2y ) ) } diff --git a/build.gradle.kts b/build.gradle.kts index b1b684b9..efa4ed35 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ buildscript { dependencies { classpath(versionCatalogLibs.android.gradle.plugin) classpath(versionCatalogLibs.kotlin.gradle.plugin) - classpath("org.jetbrains.kotlin:kotlin-android-extensions:1.8.20") + classpath("org.jetbrains.kotlin:kotlin-android-extensions:1.9.23") } tasks { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 731b9783..e4ba9897 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,47 +2,47 @@ # Define the dependency versions #Project #kotlin -kotlinVersion = "1.8.20" +kotlinVersion = "1.9.21" kotlinxSerializationJson = "1.5.0" #gradle androidGradlePlugin = "8.0.2" #Modules #androidx -androidxComposeBom = "2023.05.01" -androidxActivityCompose = "1.7.0" -androidxAppCompat = "1.6.1" -androidxComposeCompiler = "1.4.6" -androidxCore = "1.9.0" -androidxLifecycle = "2.6.1" -androidxNavigation = "2.5.3" -androidxEspresso = "3.5.1" -androidxTestRules = "1.5.0" -androidxTestRunner = "1.5.2" -androidxTestMonitor = "1.6.1" -androidxTestCore = "1.5.0" -androidxTestExt = "1.1.5" +androidxComposeBom = "2024.12.01" +androidxActivityCompose = "1.9.3" +androidxAppCompat = "1.7.0" +androidxComposeCompiler = "1.5.7" +androidxCore = "1.15.0" +androidxLifecycle = "2.8.7" +androidxNavigation = "2.8.5" +androidxEspresso = "3.6.1" +androidxTestRules = "1.6.1" +androidxTestRunner = "1.6.2" +androidxTestMonitor = "1.7.2" +androidxTestCore = "1.6.1" +androidxTestExt = "1.2.1" androidxCrypto = "1.1.0-alpha04" androidxDatastore = "1.0.0" #compose -compose_ui = "1.4.3" -compose_ui_testing = "1.4.3" +compose_ui = "1.7.6" +compose_ui_testing = "1.7.6" compose_constraint_layout = "1.1.0-alpha05" #ktx -core_ktx = "1.9.0" +core_ktx = "1.15.0" #coroutine -coroutine = "1.7.1" +coroutine = "1.8.1" turbine = "1.0.0" #android test junit4 = "4.13.2" -android_junit = "1.1.5" +android_junit = "1.2.1" espresso = "3.5.0" jupiter_junit = "5.9.2" #Mock -anotation = "1.6.0" +anotation = "1.9.1" mockk_android = "1.13.4" -test_runner = "1.5.2" +test_runner = "1.6.2" #sonar sonar = "4.0.0.2929" #dokka