Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LineChartView with a line that goes backwards #3919

Closed
davidebalistreri opened this issue Mar 27, 2019 · 6 comments
Closed

LineChartView with a line that goes backwards #3919

davidebalistreri opened this issue Mar 27, 2019 · 6 comments

Comments

@davidebalistreri
Copy link

davidebalistreri commented Mar 27, 2019

What did you do?

I need to draw the FVC graph (flow-volume) for a macOS app.

The graph should represent the loop-curve which measures the amount (volume) and speed (flow) of the air that was exhaled and inhaled by a patient during a breathing test.

Example:
image

I managed to draw the exhalation phase correctly and effortlessly (in the example it starts from 0 and it goes forward and upward, reaching the Peak expiratory flow at 12 liters per seconds, then slowly decreases until it almost reaches the 6 liters maximum volume).

What did you expect to happen?

After the exhalation phase, the graph should draw a line that goes backwards and below the x-axis, for the inhalation phase (in the example it starts from almost 6 liters of volume, goes backwards, reaches the -7 liters per seconds flow, then reconnects at 0).

What happened instead?

During the inhalation phase the values go backwards. Sometimes one value is drawn properly, sometimes not, either way when a second value is passed the graph ceases to work, and it removes all drawn lines (I think it crashes).

I tried to simulate this behavior in the ChartsDemo-macOS app, by creating a simple LineChartView with these values:

x: 0, y: 0
x: 2, y: 2
x: 4, y: 4
x: 2, y: 6
x: 0, y: 8

Schermata 2019-03-27 alle 18 05 16

The fourth value (x: 2, y: 6) isn't drawn at all.

The fifth value (x: 0, y: 8) makes the app crash:

Schermata 2019-03-27 alle 17 48 26

Fatal error: Can't form Range with upperBound < lowerBound

Charts Environment

Charts version/Branch/Commit Number: 3.2.2 (branch: master, commit: 5d0b99a)
Xcode version: 10.1, 10.2
Swift version: 4.2
Platform(s) running Charts: macOS
macOS version running Xcode: 10.14.3 (18D109), 10.14.4 (18E226)

Demo Project

Demo project with the values described above:
ChartsDemo-macOS-linebug.zip

@lucasmpaim
Copy link

Hi,

I get this error too, the error that is occurring is because your X values is not sorted on your dataset,
this is a restriction of library in both plataforms.

Something like this:

entries.sort(by: { $0.x < $1.x })

will fix the error

@davidebalistreri
Copy link
Author

Hi @lucasmpaim, and thank you for your feedback!

Unfortunately I shouldn't sort the values, otherwise I'll get a wrong graph:

Schermata 2019-04-08 alle 12 57 36

Anyway I managed to achieve my goal by manually setting the proper "min" and "max" values in the BarLineScatterCandleBubbleRenderer.XBounds class:

Schermata 2019-04-08 alle 12 56 06

This is the resulting graph, representing the input values just as expected:

Schermata 2019-04-08 alle 12 56 58

I don't quite understand how the XBounds class calculates its "min" and "max" values, but if we enhance that we can support datasets that go backwards.

Let me know if I can help!

@liuxuan30
Copy link
Member

sees we can close now

@davidebalistreri
Copy link
Author

The bug is still there, but thank you anyway.

@TerletskyIgor
Copy link

TerletskyIgor commented Nov 4, 2019

I had the same problem.
How I solved this problem:

  • I needed to keep the order of my points.
  • I had two arrays of points.
  • I created a dictionary. In which the first array was keys, the second array was values.

Then I sorted the dictionary by keys. It solved this problem.

//your value
let l0 = [Double]()
let l1 = [Double]()

var temp = [Double: Double]()

 for i in 0..<l0.count {
    let key = l0[i]
    let value = l1[i]
    temp[key] = value
}
temp.sorted {$0.key < $1.key}

Screenshot 2019-11-04 at 23 31 09

After that, there was a problem that the function graph was filled in and inside.
To fix this, I added:

let line1 = LineChartDataSet(entries: lineChartEntry1, label: nil)
line1.drawCirclesEnabled = true // Default value
line1.colors = [UIColor (red: CGFloat (0/255), green: CGFloat (0/255), blue: CGFloat (0/255), alpha: 0)]

When you set the color to transparent, you will get your function graph that won`t be filled inside.
In my case there was a lot of point and all drawCircles seem like a solid line.
Screenshot 2019-11-04 at 23 33 52

I know that this is not the best solution =)

@YulinLiu1998
Copy link

I had the same problem.
How I solved this problem:

  • I needed to keep the order of my points.
  • I had two arrays of points.
  • I created a dictionary. In which the first array was keys, the second array was values.

Then I sorted the dictionary by keys. It solved this problem.

//your value
let l0 = [Double]()
let l1 = [Double]()

var temp = [Double: Double]()

 for i in 0..<l0.count {
    let key = l0[i]
    let value = l1[i]
    temp[key] = value
}
temp.sorted {$0.key < $1.key}
Screenshot 2019-11-04 at 23 31 09

After that, there was a problem that the function graph was filled in and inside.
To fix this, I added:

let line1 = LineChartDataSet(entries: lineChartEntry1, label: nil)
line1.drawCirclesEnabled = true // Default value
line1.colors = [UIColor (red: CGFloat (0/255), green: CGFloat (0/255), blue: CGFloat (0/255), alpha: 0)]

When you set the color to transparent, you will get your function graph that won`t be filled inside.
In my case there was a lot of point and all drawCircles seem like a solid line.
Screenshot 2019-11-04 at 23 33 52

I know that this is not the best solution =)

Sorry,I don't understand what you mean. Can you tell me more in detail?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants