Skip to content

Commit

Permalink
Fixed ChartsOrg#4099: Line renderer did not render lines if they coor…
Browse files Browse the repository at this point in the history
…dinates fell outside of the viewport, even though they might intersect the viewport.
  • Loading branch information
4np committed Aug 8, 2019
1 parent 8a98ee2 commit af3c727
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 10 deletions.
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 }

// 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
36 changes: 36 additions & 0 deletions Source/Charts/Utils/ViewPortHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ open class ViewPortHandler: NSObject
return isInBoundsTop(y) && isInBoundsBottom(y)
}

@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 +448,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 left edge of the view port.
if isInBoundsY((slope * (contentRect.minX - startPoint.x)) + startPoint.y) { return true }

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

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

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

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

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

0 comments on commit af3c727

Please sign in to comment.