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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selection on bubble chart #654

Closed
chuynadamas opened this issue Jan 6, 2016 · 18 comments
Closed

Selection on bubble chart #654

chuynadamas opened this issue Jan 6, 2016 · 18 comments
Labels

Comments

@chuynadamas
Copy link
Contributor

Hi All ios-charts users 馃槂.

First, congrats on all the work @PhilJay and @danielgindi put into these libraries. High quality products, both.

Then, I found the little bug in the bubble chart, the specific case is when you have more than one bubble which belongs at the same set and both has the same x position e.g. check the image below.

screen shot 2016-01-06 at 12 13 20 pm

In the example, we have tree bubbles in the same x-position, I mean 121.2K. Now when I try to select one of them it seems that the API always select the same and I guess is the one in the middle.

So I suppose that the API only search at the first element of every set wich is near to the tap, but in my case, I need to search to the elements of the set. Do you have any idea how I can do this? or where I can start reading the code just to add the fix?

@liuxuan30
Copy link
Member

I think this can be done by overriding getHighlightByTouchPoint or getHighlight in your custom chart highlighter.
simply calculate the closest data entry on y axis if they have same xIndex

@liuxuan30
Copy link
Member

sorry I should not close it right now -
for your second question, I am not sure if you override anything, or its ios-charts defect to handle such scenarios. If latter, you are welcome to file a PR:)

BTW, is this a scatter chart or bubble chart?

@liuxuan30 liuxuan30 reopened this Jan 7, 2016
@liuxuan30
Copy link
Member

UPDATE - I just tried ChartsDemo with bubble/scatter chart, I can choose any bubble on same xIndex without problems. The difference is that you only has one data set?
@danielgindi Not sure if we should support single data set, but entries inside can have same xIndex.

@chuynadamas
Copy link
Contributor Author

Hi @liuxuan30 please let me explain better my problem.

The problem, in fact, is when you have one data set with more than one value in the same xIndex e.g. in the BubbleChartViewController.m in the ChartDemo project, if you have change the method

- (void)setDataCount:(int)count range:(double)range like following:

- (void)setDataCount:(int)count range:(double)range{
    NSMutableArray *xVals = [[NSMutableArray alloc] init];

    //I'm sending all the values to the same index
    double xIndex = 1;

    for (int i = 0; i < count; i++)
    {
        [xVals addObject:[@(i) stringValue]];
    }

    NSMutableArray *yVals1 = [[NSMutableArray alloc] init];

    for (int i = 0; i < count; i++)
    {
        double val = (double) (arc4random_uniform(range));
        double size = (double) (arc4random_uniform(range));

        //In this part we are sending all the bubbles to the same xIndex.
        [yVals1 addObject:[[BubbleChartDataEntry alloc] initWithXIndex:xIndex value:val size:size]];
    }

    BubbleChartDataSet *set1 = [[BubbleChartDataSet alloc] initWithYVals:yVals1 label:@"DS 1"];
    [set1 setColor:ChartColorTemplates.colorful[0] alpha:0.50f];
    [set1 setDrawValuesEnabled:YES];

    NSMutableArray *dataSets = [[NSMutableArray alloc] init];
    [dataSets addObject:set1];
    BubbleChartData *data = [[BubbleChartData alloc] initWithXVals:xVals dataSets:dataSets];
    [data setValueFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:7.f]];
    [data setHighlightCircleWidth: 1.5];
    [data setValueTextColor:UIColor.whiteColor];

    _chartView.data = data;
}

You will see something like this: (Maybe in a different color and with different entries 馃槤)

screen shot 2016-01-07 at 3 59 56 pm

You must be able to select just one of the bubbles and not the rest of them. 鈽癸笍

I'll check the both methods that you told me. getHighlightByTouchPoint or getHighlight but if you guys please give some guidance about the way that you find the select entry that would be extremely helpful.

Thanks in advance. 馃

P.D. The android library have the same problem.

@pmairoldi
Copy link
Collaborator

I have seen this issue. It is because the highlight method tries to guess the closest point based on the touch location but is wrong since it doesn't take the y position into consideration I think.

I'd have to look into it but this is indeed a bug. I'd look at the highlight code for the bubble chart view. It might use a generic chart highlighter which might need to be changed.

@pmairoldi pmairoldi added the bug label Jan 7, 2016
@chuynadamas
Copy link
Contributor Author

Thanks @petester42 for the quick response. I did a quick research, we have the method:

internal func getHighlight(x x: Double, y: Double) -> ChartHighlight

    /// Returns a Highlight object corresponding to the given x- and y- touch positions in pixels.
    /// - parameter x:
    /// - parameter y:
    /// - returns:
    internal func getHighlight(x x: Double, y: Double) -> ChartHighlight?
    {
        let xIndex = getXIndex(x)
        if (xIndex == -Int.max)
        {
            return nil
        }

        let dataSetIndex = getDataSetIndex(xIndex: xIndex, x: x, y: y)
        if (dataSetIndex == -Int.max)
        {
            return nil
        }

        return ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex)
    }

According this they take in count the x and y just to select the dataSet but not the elements inside the dataSet and this working fine, but the bubble needs a method more like the one in the bar, spefically in the stacked bar. I mean

internal func getStackedHighlight(old old: ChartHighlight?, set: BarChartDataSet, xIndex: Int, dataSetIndex: Int, yValue: Double) -> ChartHighlight?

    /// This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected.
    /// - parameter old: the old highlight object before looking for stacked values
    /// - parameter set:
    /// - parameter xIndex:
    /// - parameter dataSetIndex:
    /// - parameter yValue:
    /// - returns:
    internal func getStackedHighlight(old old: ChartHighlight?, set: BarChartDataSet, xIndex: Int, dataSetIndex: Int, yValue: Double) -> ChartHighlight?
    {
        let entry = set.entryForXIndex(xIndex) as? BarChartDataEntry

        if entry?.values === nil
        {
            return old
        }

        if let ranges = getRanges(entry: entry!)
        {
            let stackIndex = getClosestStackIndex(ranges: ranges, value: yValue)
            let h = ChartHighlight(xIndex: xIndex, dataSetIndex: dataSetIndex, stackIndex: stackIndex, range: ranges[stackIndex])
            return h
        }
        return nil
    }

Do you recommend to create a new BubbleChartHihlighter.swift file to implement a method like getClosestStackIndex above all the values with the same index?

@liuxuan30
Copy link
Member

@lidgardo Yes I understand the problem, and overriding getHighlightByTouchPoint or getHighlight can solve your problem in a short time - if you are hurry;

I am just not sure if it's valid/good that single data set can have entries inside with same xIndex for bubble charts. If we support this, we will support both multiple data sets + single data set scenarios that have same xIndex.
If we think of the axis space, y = f(x), now for a single x, there are two y values.
stacked bar chart is an exception, and we see the complexity it has :)

@chuynadamas
Copy link
Contributor Author

Hi @liuxuan30 , @petester42 I've already fixed the issue, I've to modify a little bit the following classes:

ChartHighlight
ChartHighligher
ChartDataSet
ChartViewBase
BubbleChartRenderer

I have to fix some code because the way that I'm adding the data sets force me to use the x-Axis axis with a continuing scale and not with discrete value as you already have, now I'm able to select multiple bubbles in the same x-Index.

Just like this:

screen shot 2016-01-14 at 5 15 30 pm

_Selecting the second value_

screen shot 2016-01-14 at 5 15 53 pm

_Selecting a value for different set and same x-Index_
screen shot 2016-01-14 at 5 16 54 pm

I'll add mi changes ina PR just to see if you guys want to implement mi code on the API I'd be reaaly happy to be a contributor.

@pmairoldi
Copy link
Collaborator

Great 馃帀. I'll review it when you send it in.

@chuynadamas
Copy link
Contributor Author

Hi guys, I just test your latest version and I saw your improvements on the selection but I guess this still having troubles, I just modify the class BubbleChartViewController on your code in order to get the special case like following:

- (void)setDataCount:(int)count range:(double)range{
.
.
.
 for (int i = 0; i < count; i++)
    {
        double val = (double) (arc4random_uniform(range));
        double size = (double) (arc4random_uniform(range));
        [yVals1 addObject:[[BubbleChartDataEntry alloc] initWithXIndex:i%3 value:val size:size]];

        val = (double) (arc4random_uniform(range));
        size = (double) (arc4random_uniform(range));
        [yVals2 addObject:[[BubbleChartDataEntry alloc] initWithXIndex:i%3 value:val size:size]];

        val = (double) (arc4random_uniform(range));
        size = (double) (arc4random_uniform(range));
        [yVals3 addObject:[[BubbleChartDataEntry alloc] initWithXIndex:i%3 value:val size:size]];
    }
.
.
.
}

Then I got the following result:

ezgif-2366490129

As you can see I'm not able to select all the bubbles on the axis 馃槥

I'll try to fix this issue following the changes that you did on the 8f82f60

Thanks in advance! 馃惣

@danielgindi
Copy link
Collaborator

The issue does not exist on master. Are you 100% sure you compiled the latest code and not just latest release?

See example: (Dataset 1 has two entries for each xIndex)

Low Res Recording

@chuynadamas
Copy link
Contributor Author

Yes, I'm 100% sure that is latest code and I guess that the problem is the following function, entriesForXIndex on the ChartDataSet file when you do a binary search on the _yVals. The problem here is that you are asssuming that the _yVals are ordered and if this is not the case, the code doensn't work.

Also on the drawHighlighted method on the BubbleChartRenderer you have this condition, could you please explain me what is the intention of this:

if (high.xIndex < minx || high.xIndex >= maxx)
{
    continue
}

I did a new branch changing the binary search for a simple for, and commented the condition above, with that, the API works like a charm, please check it.

@chuynadamas
Copy link
Contributor Author

I'm not able to create succesfully the pull request 馃槗 but you can check on my fork. 馃檪 the changes that I mentioned before.

@danielgindi
Copy link
Collaborator

That condition is for not looping over highlight values which are not in the viewport.

@shreeshabhat
Copy link

The touch problem still exists in bubble graph of charts framework.For same X value multiple Y values are present the single bubble is only selected for all the bubbles for that X value.Can you please update the code that needs to be changed in the swift files,since i am using this framework in my iOS project.

@Andy1984
Copy link

How do I reopen the issue? The problem still exists in 3.3.0

@Andy1984
Copy link

Okay. I finally solved the problem. I did not understand sort properly. It should sort x first, then y. I did not see any sorting code in the example. What still confuses me is that in the scatter example, highlights will first responds to the closest x, but in my code, it will respond to the closest distance.

@patrickSebastian97
Copy link

@Andy1984 hey bro, i've seen you on the candle stick chart thread as well. when u mean sort, were u referring to a line of code like this : self.candleChartValues.sorted(by: { $0.x < $1.x })? or is it a different method or synthax?

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

No branches or pull requests

7 participants