Skip to content

Commit 9a8c74e

Browse files
committed
BarEntry with high precision
1 parent b389ef4 commit 9a8c74e

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package info.appdev.charting.data
2+
3+
import android.graphics.drawable.Drawable
4+
import info.appdev.charting.highlight.RangeDouble
5+
import kotlin.math.abs
6+
7+
/**
8+
* High-precision bar entry that stores x and y as Double, extending [BarEntryFloat]
9+
* so it works seamlessly in the existing bar chart rendering pipeline.
10+
* Use [xDouble] and [yDouble] for full-precision access.
11+
* For stacked bars use [yValsDouble] and [rangesDouble].
12+
*/
13+
open class BarEntryDouble : BarEntryFloat {
14+
15+
var xDouble: Double = 0.0
16+
var yDouble: Double = 0.0
17+
18+
override var x: Float
19+
get() = xDouble.toFloat()
20+
set(value) { xDouble = value.toDouble() }
21+
22+
/**
23+
* Returns the double-precision stacked values, or null for simple bars.
24+
*/
25+
var yValsDouble: DoubleArray? = null
26+
private set
27+
28+
/**
29+
* Double-precision ranges for stacked bars.
30+
*/
31+
var rangesDouble: Array<RangeDouble> = arrayOf()
32+
private set
33+
34+
var negativeDoubleSum: Double = 0.0
35+
private set
36+
37+
var positiveDoubleSum: Double = 0.0
38+
private set
39+
40+
// ── Simple bar constructors ──────────────────────────────────────────────
41+
42+
constructor(x: Double, y: Double) : super(x.toFloat(), y.toFloat()) {
43+
xDouble = x; yDouble = y
44+
}
45+
46+
constructor(x: Double, y: Double, data: Any?) : super(x.toFloat(), y.toFloat(), data) {
47+
xDouble = x; yDouble = y
48+
}
49+
50+
constructor(x: Double, y: Double, icon: Drawable?) : super(x.toFloat(), y.toFloat(), icon) {
51+
xDouble = x; yDouble = y
52+
}
53+
54+
constructor(x: Double, y: Double, icon: Drawable?, data: Any?) : super(x.toFloat(), y.toFloat(), icon, data) {
55+
xDouble = x; yDouble = y
56+
}
57+
58+
// ── Stacked bar constructors ─────────────────────────────────────────────
59+
60+
constructor(x: Double, vals: DoubleArray?) : super(x.toFloat(), calcDoubleSum(vals).toFloat()) {
61+
xDouble = x
62+
yDouble = calcDoubleSum(vals)
63+
yValsDouble = vals
64+
calcDoublePosNegSum()
65+
calcDoubleRanges()
66+
}
67+
68+
constructor(x: Double, vals: DoubleArray?, data: Any?) : super(x.toFloat(), calcDoubleSum(vals).toFloat(), data) {
69+
xDouble = x
70+
yDouble = calcDoubleSum(vals)
71+
yValsDouble = vals
72+
calcDoublePosNegSum()
73+
calcDoubleRanges()
74+
}
75+
76+
constructor(x: Double, vals: DoubleArray?, icon: Drawable?) : super(x.toFloat(), calcDoubleSum(vals).toFloat(), icon) {
77+
xDouble = x
78+
yDouble = calcDoubleSum(vals)
79+
yValsDouble = vals
80+
calcDoublePosNegSum()
81+
calcDoubleRanges()
82+
}
83+
84+
// ── y override (always reflects yDouble) ────────────────────────────────
85+
86+
override var y: Float
87+
get() = yDouble.toFloat()
88+
set(value) { yDouble = value.toDouble() }
89+
90+
// ── Stack helpers ────────────────────────────────────────────────────────
91+
92+
val isStackedDouble: Boolean get() = yValsDouble != null
93+
94+
fun setValsDouble(vals: DoubleArray?) {
95+
yDouble = calcDoubleSum(vals)
96+
yValsDouble = vals
97+
calcDoublePosNegSum()
98+
calcDoubleRanges()
99+
}
100+
101+
fun getSumBelowDouble(stackIndex: Int): Double {
102+
val vals = yValsDouble ?: return 0.0
103+
var remainder = 0.0
104+
var index = vals.size - 1
105+
while (index > stackIndex && index >= 0) {
106+
remainder += vals[index]
107+
index--
108+
}
109+
return remainder
110+
}
111+
112+
private fun calcDoublePosNegSum() {
113+
val vals = yValsDouble
114+
if (vals == null) { negativeDoubleSum = 0.0; positiveDoubleSum = 0.0; return }
115+
var sumNeg = 0.0; var sumPos = 0.0
116+
for (v in vals) { if (v <= 0.0) sumNeg += abs(v) else sumPos += v }
117+
negativeDoubleSum = sumNeg; positiveDoubleSum = sumPos
118+
}
119+
120+
private fun calcDoubleRanges() {
121+
val values = yValsDouble
122+
if (values == null || values.isEmpty()) return
123+
124+
rangesDouble = Array(values.size) { RangeDouble(0.0, 0.0) }
125+
var negRemain = -negativeDoubleSum
126+
var posRemain = 0.0
127+
128+
for (i in values.indices) {
129+
val value = values[i]
130+
if (value < 0) {
131+
rangesDouble[i] = RangeDouble(negRemain, negRemain - value)
132+
negRemain -= value
133+
} else {
134+
rangesDouble[i] = RangeDouble(posRemain, posRemain + value)
135+
posRemain += value
136+
}
137+
}
138+
}
139+
140+
override fun toString(): String = "BarEntryDouble xDouble=$xDouble yDouble=$yDouble yValsDouble=${yValsDouble?.contentToString()}"
141+
142+
companion object {
143+
private fun calcDoubleSum(vals: DoubleArray?): Double = vals?.sum() ?: 0.0
144+
}
145+
}
146+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package info.appdev.charting.highlight
2+
3+
/**
4+
* Double-precision equivalent of [Range] for use with [info.appdev.charting.data.BarEntryDouble]
5+
* stacked entries. e.g. stack values are -10.0, 5.0, 20.0 -> ranges are (-10 to 0, 0 to 5, 5 to 25).
6+
*/
7+
class RangeDouble(var from: Double, var to: Double) {
8+
fun contains(value: Double): Boolean = value > from && value <= to
9+
fun isLarger(value: Double): Boolean = value > to
10+
fun isSmaller(value: Double): Boolean = value < from
11+
}
12+

0 commit comments

Comments
 (0)