After reloading chart many times, drawing goes insane


#1

I have no idea what’s going on here and after spending a couple of hours attempting to debug this I’m almost certainly convinced this is a bug with Shinobi Charts. I’m calling -reloadData frequently, due to the fact that SCharts can’t deal with the number of column I’m attemping to show, so I reload the data when the user has stopped dragging to display the currently visible area. The problem isn’t with the columms, but it’s with the area series. The data for this series is immutable, so I’m not changing it every reload. This work fine, I set the default range before the reload, call reload, then draw everything again. Nothing bad happens. Normally it looks like this:

However, after around 40 refreshes, the chart starts to slowly slip into a really strange drawing behavior. The peaks begin to flatten out, ranges start behaving incorrectly, and graphical glitches start to happen. At around 60 refreshes this is what the chart displays:

It only gets worse from there, to the point where no data is even visible, even though the correct range has most definitely been set. I can rule out the following:

  • It is not a data issue. The data for the area chart is immutable and through multiple verifications is returning exactly the same data every single refresh.
  • It is not a range-setting issue. I have veified each and every range each time this starts to slip into weird behavior, and the ranges are exactly as expected.

The strange part is that if I drag the chart around for a couple of seconds without letting it reload, it quickly reverts back to the correct apperance, but only until the next reload, at which point it gets worse.

So there’s little doubt in my mind this is a Shinobi bug, although I’d love to be proven wrong. This is a serious issue, and even if this is a bug I would not have time to wait for a bugfix. If you all have any idea what could be wrong, could you please share a workaround for this as soon as possible? Thank you.


#2

Hi Jwilling,

I tried replicating your issue by doing the following:

  1. I created a plain chart with two number axes.

  2. I generated 1000 points of data on app start up.

  3. I set the default range of the X axis from 0-100

  4. When pan finished, I set the default range, reloaded my data to just contain the visible data & called a chart redraw.

  5. I panned all over the place 60+ times.

Unfortunately I couldn’t see the behaviour you described. Would you be able to a cut down version of your project to info@shinobicontrols.com that demonstrates the issue, with a reference to this forum post? That way, someone will be able to take a look first hand the issue you are having.

Thanks,

Jan


#3

I attempted to replicate this in a smaller project and I could not do so, but this is pretty tied in and very hard to separate, so there must be something I’m doing in the actual project that is causing this that I can’t find. Through extended logging I finally realized that every time I reload the chart the y axis maxRange  _doubles _each time! This doesn’t seem like it’s a public property and I have no way to access it since it’s a protected instance variable (although technically I could), but what affects this max range property? Knowing what is causing the doubling could help me track down something that I might be doing wrong if it’s my fault.


#4

Hi Jwilling,

Thanks for putting that sample project together, I’ve had a look and I do think something not quite right is going on. We will be investigating this issue very shortly and should hopefully have an answer for you soon.

To help you find a workaround, could I ask a little bit more about your use case?

How close are your points on the X-axis? Are they 1 appart like in the demo project you mentioned here? In this original post, you mention the number of redraws being the trigger for this undesirable effect. Do you think this is still the case? Or is it the distance that the datapoints are away from eachother?

For a workaround, my general thinking is that we space your datapoints further away from eachother so that you get the rendering effect you are after (as you mention in your other forum post I linked above) and we format/change the axis labels so that the labels match the original data.

For example, we multiply your X-axis values by 100, so that your datapoints are 100 appart on your X-axis. We then edit your axis labels so that they show their value, but divided by 100. (There are a few ways we can modify our axis labels - we can use the sChart:alterTickMark:beforeAddingToAxis: delegate method, or set a custom number formatter to our axis.)

Any thoughts?

Thanks,
Jan


#5

Hey Jan, thanks for responding.

I put that clustering thing in a separate issue since I’m certain they are different . I was hoping it wouldn’t come down to me manually adjusting my data, but if that’s the only workaround at the moment then it’ll have to do. I will attempt to implement that workaround shortly and will report my results.

The one I’m actually more concerned about is the one I have in this issue, which is the one where redraws start messing up the apperance. Since I don’t have access to y’alls code other than decompiling it, I would love some answers from you all about what is happening here. As I mentioned in my latest post before your reply, the max range (which is included in -description when logging the axis) is doubling each time I refresh. I have inferred from the documentation that the max range is supposed to be the union of the data and the default range. So, somehow when I set the default range, the way you all calculate this union is going wonky.

Now whether it’s a fault of mine when I time this range setting I do not know, but any insight into how this max range is calculated would be very helpful in debugging this issue. I am 100% sure that a wrong max range value is the issue here.


#6

Progressed a bit further here. At the time the chart is refreshed my _dataRange _appears to actually have its minimum in the negative range, which is crazy since my data has no negative values. So the fault isn’t with the max range, but it’s actually with the data range calculation since the max is the union of data and default.

This is some logging from my data range, once per refresh:

{ -0.500000, 0.500000 }

{ -0.750000, 702.099976 }

{ -176.462494, 702.099976 }

{ -396.103111, 702.099976 }

{ -670.653883, 702.099976 }

… and so on. How can I fix this?

Edit: To hold me off for the rest of the day until I hear back from y’all I’ve overridden the private method, -setDataRangeInternal: and capped the lower bound of the range. This isn’t a solution as I’ll need negative numbers in the next feature I’m adding, but it’s a start I guess. I still want to find the source of this negative data range.


#7

Well I unfortunately never heard back from you all on this, so after some nasty debugging I finally figured it out. I was setting the line series’ baseline to a number beneath the axis, and due to an error in some calculations I was making it was continuously decreasing. That was my error.

However, even though that was an error on my part, Shinobi should not be destroying the drawing of the chart like it did, even if there is a massive data range.

So the following are conclusively bugs in Shinobi that are really quite serious:

  • Large (and increasing) data ranges mess up the drawing above the baseline.
  • Points that are scattered very closely together have awful drawing artifacts due to a fault in the way they are either culled or drawn by Shinobi.

#8

Hi Jwilling,

It’s great you found the issue in your code and I assure you that we are looking into the drawing of extreme ranges.

Thanks,
Jan


#9

I would also like to thank you for sending in those projects. They will be helpful in our investigation.

Jan