Draw circle with polyline
geo circle swift algorithm Estimated reading time: 2 minutesDisplaying maps on iOS often is not enough. We would like to show some kind of tips, identifiers or other objects.
If u deal with not only displayable information but also provides functionality for rich editing or creating/managing something - drawing different shapes can be an essential part of this process.
Previously, I already cover few subjects related to the map, and in this article, I would like to show how we can draw a circle on the map using polyline only.
Previous posts related to tasks with map:
The problem
In the current project, we are using maps extensively, but the SDK that we use has some limited out-of-the-box functionality, and drawing the circle is not one of them. What can be done - is just drawing a filled circle, line or polygon. :[
The purpose of such function can be simple hightlight of some circular zone (for example selected spot):

Left side: unselected blue circle and selected white and on right - blue circle selected, white unselected
The solution
The solution to the problem can be a circle drawn with some kind of simplicity.
The good question here - is “how the circle can be drawn on the screen, in the simplest way possible?”. The answer is in the next picture.

This image is from the page Simple Circle Algorithms
Also, the equation of the circle can helps us a lot:

Unfortunately, I’m not a math guy… so I just looked for some existing algorithms for drawing circles and found a few already well-explained.
All I need to do - is just use them in the code - generate the points and draw a polyline using a set of these points.
The possible solution could be next:
public static func circlePolylinePointsWithCenterAt(
point: CLLocationCoordinate2D,
radiusInMeters: Double,
pointsCount: Int = 72
) -> [CLLocationCoordinate2D] {
let earthsRadius = point.earthRadius()
let radiusLatitude = (radiusInMeters / earthsRadius).radiansToDegrees
let radiusLongitude = radiusLatitude / cos(point.latitude.degreesToRadians)
var circlePoints: [CLLocationCoordinate2D] = []
for i in 0... pointsCount {
let theta = Double.pi * (Double(i) / Double(pointsCount/2))
let longitudePoint = point.longitude + (radiusLongitude * cos(theta))
let latitudePoint = point.latitude + (radiusLatitude * sin(theta))
circlePoints.append(.init(latitude: latitudePoint, longitude: longitudePoint))
}
return circle points
}
where the Earch radius (as described in prev post):
extension CLLocationCoordinate2D {
public func earthRadius() -> CLLocationDistance {
let earthRadiusInMetersAtSeaLevel = 6378137.0
let earthRadiusInMetersAtPole = 6356752.314
let r1 = earthRadiusInMetersAtSeaLevel
let r2 = earthRadiusInMetersAtPole
let beta = latitude.degreesToRadians
let earthRadiuseAtGivenLatitude = (
( pow(pow(r1, 2) * cos(beta), 2) + pow(pow(r2, 2) * sin(beta), 2) ) /
( pow(r1 * cos(beta), 2) + pow(r2 * sin(beta), 2) )
)
.squareRoot()
return earthRadiuseAtGivenLatitude
}
}
Then, we can just draw a polyline using the array of the CLLocationCoordinate2D
.
The result:

changing the
pointsCount
can leads to the change of the quality and performance, so try it out and select the trade-off most suitable for u.
Resources
Share on: