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

Fixes #4099: Line renderer did not render lines if their coordinates fell outside of the viewport. #4100

Merged
merged 7 commits into from
Oct 9, 2019
23 changes: 13 additions & 10 deletions Source/Charts/Renderers/LineChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -353,17 +353,20 @@ open class LineChartRenderer: LineRadarRenderer
_lineSegments[i] = _lineSegments[i].applying(valueToPixelMatrix)
}

if (!viewPortHandler.isInBoundsRight(_lineSegments[0].x))
{
break
}
// Determine the start and end coordinates of the line, and make sure they differ.
guard
let firstCoordinate = _lineSegments.first,
let lastCoordinate = _lineSegments.last,
firstCoordinate != lastCoordinate else { continue }

// make sure the lines don't do shitty things outside bounds
if !viewPortHandler.isInBoundsLeft(_lineSegments[1].x)
|| (!viewPortHandler.isInBoundsTop(_lineSegments[0].y) && !viewPortHandler.isInBoundsBottom(_lineSegments[1].y))
{
continue
}
// If both points lie left of viewport, skip stroking.
if !viewPortHandler.isInBoundsLeft(firstCoordinate.x) && !viewPortHandler.isInBoundsLeft(lastCoordinate.x) { continue }

// If both points lie right of the viewport, break out early.
if !viewPortHandler.isInBoundsRight(firstCoordinate.x) && !viewPortHandler.isInBoundsRight(lastCoordinate.x) { break }
liuxuan30 marked this conversation as resolved.
Show resolved Hide resolved

// Only stroke the line if it intersects with the viewport.
guard viewPortHandler.isIntersectingLine(from: firstCoordinate, to: lastCoordinate) else { continue }

// get the color that is set for this line-segment
context.setStrokeColor(dataSet.color(atIndex: j).cgColor)
Expand Down
42 changes: 42 additions & 0 deletions Source/Charts/Utils/ViewPortHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,17 @@ open class ViewPortHandler: NSObject
return isInBoundsTop(y) && isInBoundsBottom(y)
}

/**
A method to check whether coordinate lies within the viewport.

- Parameters:
- point: a coordinate.
*/
@objc open func isInBounds(point: CGPoint) -> Bool
{
return isInBounds(x: point.x, y: point.y)
}

@objc open func isInBounds(x: CGFloat, y: CGFloat) -> Bool
{
return isInBoundsX(x) && isInBoundsY(y)
Expand Down Expand Up @@ -443,6 +454,37 @@ open class ViewPortHandler: NSObject
return (_contentRect.origin.y + _contentRect.size.height) >= normalizedY
}

/**
A method to check whether a line between two coordinates intersects with the view port.

- Parameters:
- startPoint: the start coordinate of the line.
- endPoint: the end coordinate of the line.
*/
@objc open func isIntersectingLine(from startPoint: CGPoint, to endPoint: CGPoint) -> Bool
{
// If the start or endpoint fall within the viewport, bail out early.
if isInBounds(point: startPoint) || isInBounds(point: endPoint) { return true }

// Calculate the slope of the line.
let slope = (endPoint.y - startPoint.y) / (endPoint.x - startPoint.x)

// Check for colission with the left edge of the view port.
if isInBoundsY((slope * (contentRect.minX - startPoint.x)) + startPoint.y) { return true }
liuxuan30 marked this conversation as resolved.
Show resolved Hide resolved

// Check for colission with the right edge of the view port.
if isInBoundsY((slope * (contentRect.maxX - startPoint.x)) + startPoint.y) { return true }

// Check for colission with the top edge of the view port.
if isInBoundsX(((contentRect.minY - startPoint.y) / slope) + startPoint.x) { return true }

// Check for colission with the bottom edge of the viewport.
if isInBoundsX(((contentRect.maxY - startPoint.y) / slope) + startPoint.x) { return true }

// This line does not intersect the view port.
return false
}

/// The current x-scale factor
@objc open var scaleX: CGFloat
{
Expand Down