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

Cubic Area Lines with String Data #111

Closed
dhruveonmars opened this issue Apr 1, 2016 · 17 comments
Closed

Cubic Area Lines with String Data #111

dhruveonmars opened this issue Apr 1, 2016 · 17 comments

Comments

@dhruveonmars
Copy link

|s it possible to get cubic lines with string data rather than integers?
I've got data such as;
var lineTest: [(title: String, val: Double)]! = []
where title could be something like "31/3" and double could be 27.7

The Area lines work, but I am just wondering if it is possible to make them cubic lines or cubic areas?
Also, Since it is in a scroll view, is it possible for it to cut off at the first and last values, rather than drop down to 0.

untitled 2

@dhruveonmars dhruveonmars changed the title Cubic Lines with String Data Cubic Area Lines with String Data Apr 2, 2016
@ivnsch
Copy link
Owner

ivnsch commented Apr 2, 2016

Hi,
you can use anything as long as you can convert it to a double which represents the axis internal value (scalar). In the case of the strings you would of course have to parse them to numbers in order to set the internal value. You can create an axis subclass, if you want, that accepts the value as a string and does the conversion internally.

You can use cubic lines, you just would have to switch the layer. For cubic areas there's no layer yet. You can implement one if you want.

Not sure I understood the scroll issue, cut off how? You mean make that the axis values are between chart points min / max? If yes you can use ChartAxisValuesGenerator which uses chart points to generates axis values. You can also define the axis values manually.

@dhruveonmars
Copy link
Author

Ah, for some reason, it wasn't working in my application when I had 0.3 set in my pod file, but when I changed it to:

pod 'SwiftCharts', :git => 'https://github.com/i-schuetz/SwiftCharts.git'

to make the axis width change, the cubic line also started working when I added it to the line layer;

let lineLayer = ChartPointsLineLayer(xAxis: xAxis3, yAxis: yAxis3, innerFrame: innerFrame3, lineModels: [lineModel], pathGenerator: CubicLinePathGenerator(tension1: 0.3, tension2: 0.3))

How would I go about implementing a cubic area layer? I currently have this for the area;

let chartPointsLayer1 = ChartPointsAreaLayer(xAxis: xAxis3, yAxis: yAxis3, innerFrame: innerFrame3, chartPoints: lineChartPoints, areaColor: csRed.colorWithAlphaComponent(0.8), animDuration: 1.5, animDelay: 0, addContainerPoints: true)

Also, for the cut off, what I mean, is that the area layer, after the last value (see last '29.9' figure in the line graph), it goes down to 0 at an angle rather than shooting straight down to 0.

This image is what the line graph now looks like with the cubic line;
untitled 2a

Thanks for the getting back to me and the help!

@ivnsch
Copy link
Owner

ivnsch commented Apr 2, 2016

The areas layer would be similar to ChartPointsAreaLayer (which is the areas layer you're using now), which generates the chart points screen locations and passes them to ChartAreasView to create the path. You could maybe reuse CubicLinePathGenerator, which generates the path for the cubic lines. Ideally you would not need a new layer/view but adjust the current one to accept a generic path generator, similar to the line layer.

Btw: The current cubic path generator is not very good, the curves look weird, but you can use a different algorithm/library to generate the path and pass it to the line layer. In this issue #47 near the end you find an example. It should not be very difficult to fix the algorithm in this library (by e.g. copying the one of the library referenced in the issue) but I haven't had time. In this issue #57 somebody also mentioned https://github.com/andrelind/swift-catmullrom which is written in Swift but I haven't tested this one.

About cutting, it should work if you set the last x axis value to the exact coordinate of the last chart point (29.9 in this case).

@dhruveonmars
Copy link
Author

I tried adding pathGenerator to the AreaLayer, but it simply tells me that there is an extra argument 'pathGenerator' in call;

let chartPointsLayer1 = ChartPointsAreaLayer(xAxis: xAxis3, yAxis: yAxis3, innerFrame: innerFrame3, chartPoints: lineChartPoints, pathGenerator: CubicLinePathGenerator(tension1: 0.3, tension2: 0.3), areaColor: csRed, animDuration: 1.5, animDelay: 0, addContainerPoints: true)

Not sure if I'm over simplifying what you are suggesting.

For the cutting, do you mean, add an extra point so that the value of x is the same as x of 29 and y=0
or something else, as the last item in the data is currently:
("2/4", 29.899999618530273)

@ivnsch
Copy link
Owner

ivnsch commented Apr 4, 2016

Yes, you are simplifying it :) the functionality to draw cubic areas as I said doesn't exist and you would have to implement it, either modifying the existing layer or creating a new one. This is an important missing feature and glad to assist you implementing it such that we can merge it in the library after it. It should not be very difficult as there's already functionality to draw an area, and to draw cubic lines, so it's just about combining this.

About cutting the area, you have to ensure that the last axis value matches exactly with the corresponding max coordinate of the chart points. You can simply make that your x axis ends exactly at 29.899999618530273 (by passing this number as the value of the last axis value). If you are not showing axis labels, as it appears from your images you're already done.

If you are showing axis labels you probably don't want to show this number. Something similar to this:

564
src: https://plot.ly/~Dreamshot/564.png

The max x value of chart points here may be, say, 2008, so in swiftcharts the x axis values you would have to pass would be [1900, 1920, 1940, 1960, 1980, 2000, 2008]. In order to not display 2008 (in your case 29.899999618530273) you have to set its hidden flag to true when generating the axis values.

@dhruveonmars
Copy link
Author

Okay, thanks for the help. I really appreciate it.

Also, I was wondering, is it possible to reverse the animations so that the animation started on the end and finished at the start, particularly with the line graph?

@ivnsch
Copy link
Owner

ivnsch commented Apr 4, 2016

To reverse the animation I think if you pass the chart points to the respective layer(s) in reversed order it should work. This may not work for the area layer due to the way the path is completed. Try it out and if something doesn't work we look further.

@dhruveonmars
Copy link
Author

Wouldn't passing the data in a reverse order also cause the chart to be drawn in reverse, so from my pictures, 29.9 would end up being at the start rather than at the end

@ivnsch
Copy link
Owner

ivnsch commented Apr 4, 2016

The chart uses the internal values of the points to determine the screen location so it doesn't matter where they are in the array. This only affects the animation.

@dhruveonmars
Copy link
Author

So, if my original array is;

[("19/03", 10.699999809265137), ("20/03", 25.0), ("21/03", 17.700000762939453), ("22/03", 16.700000762939453), ("23/03", 13.5), ("24/03", 16.700000762939453), ("25/03", 14.699999809265137), ("26/03", 16.700000762939453), ("27/03", 12.699999809265137), ("28/03", 16.700000762939453), ("29/03", 16.700000762939453), ("30/03", 0.0), ("31/03", 20.700000762939453), ("01/04", 27.0), ("02/04", 29.899999618530273), ("03/04", 21.899999618530273), ("04/04", 23.899999618530273)]

I could reverse it, using

lineData = lineData.reverse()

but that does plot it out in the reverse order;
untitled 2aa

@ivnsch
Copy link
Owner

ivnsch commented Apr 4, 2016

Hmm I just did a quick test with the original areas example, calling reverse() in all the chart points passed to layers and it works. Except the issue I mentioned with the areas. Are you sure you are reverting only the points passed to the layers? If it still doesn't work please post a self contained example I can run and I'll look later into it.

@dhruveonmars
Copy link
Author

Ah, my mistake. I was reversing the original array that is used to create the charts rather than reversing the lineChartPoints. Thanks for clearing that up :)

@ivnsch
Copy link
Owner

ivnsch commented Apr 4, 2016

I think you may be reversing the points used to generate the axis values. Please ensure that you reverse only the chart points you pass to the content layers (the line/bars layer in your case).

@dhruveonmars
Copy link
Author

Yup, I realised as soon as I read what I posted. The line chart works now. Thanks for the help!
I shall have to leave out the area layer for now due to time constraints and other things that need to be done, but thanks for all the help

I really appreciate it :)

@ivnsch
Copy link
Owner

ivnsch commented Apr 4, 2016

Ok, no problem!

@andrewrynhard
Copy link

I have changed the following in ChartAreasView as a test:

//        self.show(path: self.generateAreaPath(points: points))
        self.show(path: CubicLinePathGenerator(tension1: 0.3, tension2: 0.3).generatePath(points: points, lineWidth: 0.0))

and got the following. Not sure why the area is not under the curve. I would like to add this feature and make a PR.

screen shot 2016-06-12 at 12 29 33 pm

@ivnsch
Copy link
Owner

ivnsch commented Jun 13, 2016

The line path generator generates the path only for the line. To fill the area you need to add the points at the bottom of the chart to the path, similar to how it's done in generateAreaPath.

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

3 participants