Проблема визуального рендеринга MPAndroidChart с определенными данными

Я пытаюсь нарисовать многоугольник с помощью MPAndroidChart в AndroidStudio в Котлине для разработки Android. Я столкнулся с проблемой визуального рендеринга.

Я рисую 2 разных полигона на 2 разных графиках. Первый работает отлично, но второй создает проблему визуального рендеринга и приводит к сбою моего приложения, когда я пытаюсь увеличить масштаб или сделать что-либо на своей диаграмме.

Координата для второго полигона должна быть следующей:

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)
)

Результатом является следующая картинка ниже со вторым полигоном, для которого у меня есть только одна линия, и он вылетает всякий раз, когда я его касаюсь.

Если я просто прокомментирую координату Pair(100.0, -3.0), У меня нет этой проблемы, но, конечно, я хочу нарисовать свой полный полигон. Ниже показан полигон без координаты, вызвавшей ошибку:

Наконец, если координата Pair(100.0, -3.0) находится где-то выше или равна последней по оси X, это работает. Например, если я поставлю Pair(103.0, -3.0),, это сработает.

Кто-нибудь может помочь мне с этой проблемой?

Я пробовал много вещей, но я действительно не понимаю проблемы

О коде сказать особо нечего, потому что проблема связана с координатами, но вот моя функция для рисования моего многоугольника:

    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()
}

Если приложение дает сбой, включите в свой вопрос полную трассировку стека из Logcat. Вы также должны включить достаточно кода, чтобы кто-то другой мог воспроизвести вашу проблему — очень мало кто может сделать с объемом информации, которую вы здесь включили.

Tyler V 01.05.2023 00:10

@TylerV Мне нечего сказать о моем коде, потому что проблема связана с координатами, но я отредактировал свой пост, добавив свою функцию, которая рисует многоугольник, и у меня нет ничего в виде сообщения о сбое, приложение просто закрывается

col625 01.05.2023 01:32

В случае сбоя всегда появляется сообщение о сбое, посмотрите на вкладку Logcat в Android Studio (нижняя часть экрана). Я посмотрю, смогу ли я воспроизвести это из того, что вы разместили

Tyler V 01.05.2023 02:24
1
3
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что линейная диаграмма предполагает, что предоставленные точки будут отсортированы по координате x (возрастанию). Если их нет, может возникнуть ряд ошибок. Некоторая предыстория этого требования есть в этом выпуске Github и в документации.

Имейте в виду, что эта библиотека официально не поддерживает рисование данных LineChart из списка записей, не отсортированных по x-позиции записей в порядке возрастания. Добавление записей несортированным образом может привести к правильному рисованию, но также может привести к непредвиденному поведению.

Даже в случае "работы", когда вы отбрасывали точку (100,-3), если вы увеличили масштаб диаграммы и прокрутили ее, заливка будет отображаться неправильно. В этом случае, когда вы пытаетесь панорамировать или масштабировать, включая точку (100,-3), возникает следующая ошибка:

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)

Одним из решений является разделение ребер многоугольника на несколько отдельных линий, одна из которых проходит «поверх» многоугольника, а другая образует основание. Оба они должны быть неубывающими по 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))

Результат:

Примечания

  • Вам, вероятно, потребуется исправить легенду, так как теперь она показывает две записи, так как есть две строки
  • Если ваш многоугольник не расположен симметрично относительно линии y = 0, вам нужно будет изменить способ заполнения. Он заполняется только от линии до уровня y = 0, поэтому, если полигон находится выше y = 0, вам нужно установить заливку для «нижней» линии на Color.WHITE вместо альфа-канала 255. Это описано ️ 🔁 здесь
  • Применение этого подхода в более общем плане потребует знания некоторых вещей о ваших многоугольниках (например, всегда ли они выпуклые?). Если вам не так важна заливка, вы можете просто нарисовать каждый сегмент линии как отдельный LineDataSet, что будет работать с полигоном любой сложности.
  • Если вы хотите рисовать сложные многоугольники с заливкой, MPAndroidChart, вероятно, не лучший выбор. Возможно, вы захотите просто нарисовать его на холсте вручную.

Большое спасибо ! Это объясняет проблему и почему она связана с моими данными. Я попробую некоторые из предложенных вами решений, но, с моей точки зрения, вопрос можно считать закрытым.

col625 01.05.2023 16:17

Другие вопросы по теме