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

HorizontalBarCharView incorrect results for bounding box query #1382

Closed
dbquarrel opened this issue Aug 31, 2016 · 1 comment
Closed

HorizontalBarCharView incorrect results for bounding box query #1382

dbquarrel opened this issue Aug 31, 2016 · 1 comment

Comments

@dbquarrel
Copy link

Current implementation works fine if you have one data set and a few columns. Breaks on multiple data sets and maybe on stacks. Generates garbage values.

I ripped code from the chart renderer and used it for a replacement. Seems to generate good results. I'm not a Swift programmer and won't be because I think it sucks.

Anyway this is maybe not up to date as Cocoapods is not vending me the latest changes but I checked in the repo and seems like the same simplistic method is using to return some boxes based on the most basic use of the charts.

I had to rip this from the drawing side because that was filled with constants and tweaks and methods used to calculate the boxes. This means you have to do this in three places and will have to update in three places if you change the methods. What you need is one method to return your bounding boxes and then use that to generate the drawing code and the hit detection and for users to pass back and get a box if they get a touch passed through to them. If you want to run a popover you need to have a box from a source, and in context it's one of these bars. So this method needs to work right if you're going to run popovers after it.

Again, not a Swift programmer and this is a hack just distilled down from the drawing code. But it works better than what's in there.

    public override func getBarBounds(e: BarChartDataEntry) -> CGRect
    {
        guard let
            set = _data?.getDataSetForEntry(e) as? IBarChartDataSet
            else { return CGRectNull }

        let dataSetOffset = (barData!.dataSetCount - 1)
        let groupSpace = barData!.groupSpace
        let groupSpaceHalf = groupSpace / 2.0
        let barSpace = set.barSpace
        let barSpaceHalf = barSpace / 2.0
        let barWidth: CGFloat = 0.5
        var barRect = CGRect()
        var y: Double
        let trans =  getTransformer(set.axisDependency)
        let isInverted = false
        //let index = 0;
        let index = Int(_data!.indexOfDataSet(set))
            // calculate the x-position, depending on datasetcount
        let x = CGFloat(e.xIndex) +
            (CGFloat(e.xIndex) *
                CGFloat(dataSetOffset))
            + CGFloat(index)
            + groupSpace * CGFloat(e.xIndex) + groupSpaceHalf
        let values = e.values

        if (!(set.isStacked) || values == nil) {
            y = e.value
            let bottom = x - barWidth + barSpaceHalf
            let top = x + barWidth - barSpaceHalf
            var right = isInverted ? (y <= 0.0 ? CGFloat(y) : 0) : (y >= 0.0 ? CGFloat(y) : 0)
            var left = isInverted ? (y >= 0.0 ? CGFloat(y) : 0) : (y <= 0.0 ? CGFloat(y) : 0)
            barRect.origin.x = left
            barRect.size.width = right - left
            barRect.origin.y = top
            barRect.size.height = bottom - top
        } else {
            let dataSetIndex = Int(_data!.indexOfDataSet(set))

            let vals = values!
            var posY = 0.0
            var negY = -e.negativeSum
            var yStart = 0.0

            // fill the stack
            let k = dataSetIndex;

            let value = vals[k]

            if (value >= 0.0) {
                y = posY
                yStart = posY + value
                posY = yStart
            } else {
                y = negY
                yStart = negY + abs(value)
                negY += abs(value)
            }

            let bottom = x - barWidth + barSpaceHalf
            let top = x + barWidth - barSpaceHalf
            var right: CGFloat, left: CGFloat
            if (isInverted) {
                left = y >= yStart ? CGFloat(y) : CGFloat(yStart)
                right = y <= yStart ? CGFloat(y) : CGFloat(yStart)
            } else {
                right = y >= yStart ? CGFloat(y) : CGFloat(yStart)
                left = y <= yStart ? CGFloat(y) : CGFloat(yStart)
            }
            barRect.origin.x = left
            barRect.size.width = right - left
            barRect.origin.y = top
            barRect.size.height = bottom - top
        }
        trans.rectValueToPixel(&barRect)
        return barRect
    }

Results after fixing:

chart view example

@liuxuan30
Copy link
Member

liuxuan30 commented Sep 1, 2016

This is on version 3 or 2? It's just too long and I agree we could have a func to return barRect, but I am missing what's the real problem with your title.. any screenshot before fixing?

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