I am trying to draw a polygon using MPAndroidChart in AndroidStudio in Kotlin for an Android developpment. I am facing a visual rendering problem.
I am drawing 2 different polygons on 2 different charts. The first one is working perfectly but the second one is creating a visual rendering problem and making my application to crash when I try to zoom or do anything in my chart.
The coordinate for the second polygon should be the following:
polygonTopView = Polygon(
Pair(92.0, 3.0),
Pair(100.0, 3.0),
Pair(102.5, 1.5),
Pair(102.5, -1.5),
Pair(100.0, -3.0),
Pair(92.0, -3.0),
Pair(92.0, 3.0)
)
The result is the following picture below with the second polygon, for which I have only one line and it crashes whenever I touch it
If I just comment the coordinate Pair(100.0, -3.0),
I don't have this problem but of course I want to draw my full polygon. Below is the polygon without the coordinate that generates the error:
Finally if the coordinate Pair(100.0, -3.0)
is somewhere above or equal to the last one on the X-axis it works. For example if I put Pair(103.0, -3.0),
it will works.
Does anyone can help me with this problem ?
I tried many things but I really don't get the problem
There is not much to say about the code because the problem is relative to the coordinates, but here is my function to draw my polygon:
private fun drawPolygon(view: View, polygonSideView: Polygon, polygonTopView: Polygon){
chartSideView = view.findViewById(R.id.chartSideView)
chartSideView.setTouchEnabled(true)
chartSideView.setPinchZoom(true)
val entriesSideView = mutableListOf<Entry>()
for (point in polygonSideView.vertices) {
entriesSideView.add(Entry(point.first.toFloat(), point.second.toFloat()))
}
val dataSetSideView = LineDataSet(entriesSideView, "CG limit Side view")
dataSetSideView.color = ColorTemplate.COLORFUL_COLORS[0]
dataSetSideView.lineWidth = 1f // set the line width to 2 pixels
dataSetSideView.fillColor = ColorTemplate.COLORFUL_COLORS[0]
dataSetSideView.setDrawFilled(true)
val lineDataSetsSideView = mutableListOf<ILineDataSet>()
lineDataSetsSideView.add(dataSetSideView)
val lineDataSideView = LineData(lineDataSetsSideView)
chartSideView.data = lineDataSideView
chartSideView.description.isEnabled = false
chartSideView.legend.isEnabled = true
chartSideView.axisRight.isEnabled = false
chartSideView.axisLeft.axisMinimum = 1500f
chartSideView.axisLeft.axisMaximum = 2600f
//chartSideView.xAxis.labelRotationAngle = -45f
chartSideView.xAxis.granularity = 1f
chartSideView.xAxis.isGranularityEnabled = true
chartSideView.xAxis.axisMinimum = 91f
chartSideView.xAxis.axisMaximum = 103f
chartSideView.invalidate()
// end of sideview
// chartview 2
//chartTopView = view?.findViewById(R.id.chartTopView) ?: throw IllegalStateException("View is null")
chartTopView = view.findViewById(R.id.chartTopView)
chartTopView.setTouchEnabled(true)
chartTopView.setPinchZoom(true)
val entriesTopView = mutableListOf<Entry>()
for (point in polygonTopView.vertices) {
entriesTopView.add(Entry(point.first.toFloat(), point.second.toFloat()))
}
//entriesTopView.add(Entry(polygonTopView.vertices[0].first.toFloat(), polygonTopView.vertices[0].second.toFloat()))
val dataSetTopView = LineDataSet(entriesTopView, "CG limit Top view")
dataSetTopView.color = ColorTemplate.COLORFUL_COLORS[0]
dataSetTopView.lineWidth = 2f // set the line width to 2 pixels
dataSetTopView.fillColor = ColorTemplate.COLORFUL_COLORS[0]
dataSetTopView.setDrawFilled(true)
val lineDataSetsTopView = mutableListOf<ILineDataSet>()
lineDataSetsTopView.add(dataSetTopView)
val lineDataTopView = LineData(lineDataSetsTopView)
chartTopView.data = lineDataTopView
chartTopView.description.isEnabled = false
chartTopView.legend.isEnabled = true
chartTopView.axisRight.isEnabled = false
chartTopView.axisLeft.axisMinimum = -4f
chartTopView.axisLeft.axisMaximum = 4f
//chartTopView.xAxis.labelRotationAngle = -45f
chartTopView.xAxis.granularity = 1f
chartTopView.xAxis.isGranularityEnabled = true
chartTopView.xAxis.axisMinimum = 91f
chartTopView.xAxis.axisMaximum = 103f
chartTopView.invalidate()
}
The issue is that the line chart expects the provided points to be sorted by x-coordinate (increasing). When they are not, there are a number of errors that can occur. There is some background about this requirement in this Github issue and in the docs.
Please be aware that this library does not officially support drawing LineChart data from an Entry list not sorted by the x-position of the entries in ascending manner. Adding entries in an unsorted way may result in correct drawing, but may also lead to unexpected behaviour.
Even in the case that was "working" where you dropped the (100,-3) point, if you zoomed in on the chart and panned around the fill would show up wrong. In this case, when you try to pan or zoom including the (100,-3) point it throws the error below:
Process: com.example.chartdemo, PID: 31183
java.lang.NegativeArraySizeException: -6
at com.github.mikephil.charting.utils.Transformer.generateTransformedValuesLine(Transformer.java:178)
at com.github.mikephil.charting.renderer.LineChartRenderer.drawValues(LineChartRenderer.java:549)
at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:278)
at android.view.View.draw(View.java:22644)
One solution is to split the polygon edges into multiple separate lines, one which goes "over the top" of the polygon and one which forms the base. Both of these should be non-decreasing in X.
val polyUpper = listOf(
Pair(92.0, -3.0),
Pair(92.0, 3.0),
Pair(100.0, 3.0),
Pair(102.5, 1.5),
Pair(102.5, -1.5)
)
val polyLower = listOf(
Pair(92.0, -3.0),
Pair(100.0, -3.0),
Pair(102.5, -1.5)
)
val entriesUpper = polyUpper.map { Entry(it.first.toFloat(), it.second.toFloat()) }
val entriesLower = polyLower.map { Entry(it.first.toFloat(), it.second.toFloat()) }
val dataSetUpper = LineDataSet(entriesUpper, "CG limit Side view")
dataSetUpper.color = ColorTemplate.COLORFUL_COLORS[0]
dataSetUpper.lineWidth = 1f // set the line width to 2 pixels
dataSetUpper.fillColor = ColorTemplate.COLORFUL_COLORS[0]
dataSetUpper.setDrawFilled(true)
val dataSetLower = LineDataSet(entriesLower, "")
dataSetLower.color = ColorTemplate.COLORFUL_COLORS[0]
dataSetLower.lineWidth = 1f // set the line width to 2 pixels
dataSetLower.fillColor = ColorTemplate.COLORFUL_COLORS[0]
dataSetLower.setDrawFilled(true)
val lineDataSideView = LineData(listOf(dataSetUpper, dataSetLower))
Notes
Color.WHITE
instead with an alpha of 255. This is described hereLineDataSet
, which would work with any complexity of polygon.