Okay so I want to rotate CGPoint(A) 50 degrees around CGPoint(B) is there a good way to do that?
CGPoint(A) = CGPoint(x: 50, y: 100)
CGPoint(B) = CGPoint(x: 50, y: 0)
Here's what I want to do:
This is really a maths question. In Swift, you want something like:
func rotatePoint(target: CGPoint, aroundOrigin origin: CGPoint, byDegrees: CGFloat) -> CGPoint {
let dx = target.x - origin.x
let dy = target.y - origin.y
let radius = sqrt(dx * dx + dy * dy)
let azimuth = atan2(dy, dx) // in radians
let newAzimuth = azimuth + byDegrees * CGFloat(M_PI / 180.0) // convert it to radians
let x = origin.x + radius * cos(newAzimuth)
let y = origin.y + radius * sin(newAzimuth)
return CGPoint(x: x, y: y)
}
There are lots of ways to simplify this, and it's a perfect case for an extension to CGPoint, but I've left it verbose for clarity.
public extension CGFloat {
///Returns radians if given degrees
var radians: CGFloat{return self * .pi / 180}
}
public extension CGPoint {
///Rotates point by given degrees
func rotate(origin: CGPoint? = CGPoint(x: 0.5, y: 0.5), _ byDegrees: CGFloat) -> CGPoint {
guard let origin = origin else {return self}
let rotationSin = sin(byDegrees.radians)
let rotationCos = cos(byDegrees.radians)
let x = (self.x * rotationCos - self.y * rotationSin) + origin.x
let y = (self.x * rotationSin + self.y * rotationCos) + origin.y
return CGPoint(x: x, y: y)
}
}
Usage
var myPoint = CGPoint(x: 40, y: 50).rotate(45)
var myPoint = CGPoint(x: 40, y: 50).rotate(origin: CGPoint(x: 0, y: 0), 45)
Related
I'm trying to draw an arrow on a MKPolyline, which is working well by overriding the draw method, however the result is a blurred line. Any clues on why this might be?
It also does not show the arrows when zoomed out (zoomScale < 0.05), and also increases the line width as you zoom out,
Code below:
class ArrowPolylineRenderer: MKPolylineRenderer {
override func applyStrokeProperties(to context: CGContext, atZoomScale zoomScale: MKZoomScale) {
super.applyStrokeProperties(to: context, atZoomScale: zoomScale)
UIGraphicsPushContext(context)
if let ctx = UIGraphicsGetCurrentContext() {
ctx.setLineWidth(self.lineWidth)
}
}
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
if self.polyline.pointCount < 2 { return }
let mapPoints = self.polyline.points()
let startPoint = mapPoints[0]
let endPoint = mapPoints[1]
let p = CGMutablePath()
if zoomScale >= 0.05 {
let midPoint = self.point(for: MKMapPoint(x: (startPoint.x + endPoint.x)/2, y: (startPoint.y + endPoint.y)/2))
let originX = endPoint.x - startPoint.x
let originY = endPoint.y - startPoint.y
let bearingR = atan2f(Float(originY), Float(originX))
let p1 = CGPoint(x: midPoint.x - 60 / (zoomScale + 0.5), y: midPoint.y + 80 / (zoomScale + 0.5))
let p2 = CGPoint(x: midPoint.x + 60 / (zoomScale + 0.5), y: midPoint.y)
let p3 = CGPoint(x: midPoint.x - 60 / (zoomScale + 0.5), y: midPoint.y - 80 / (zoomScale + 0.5))
let points = [p1, p2, p3]
let t1 = CGAffineTransform(translationX: midPoint.x, y: midPoint.y)
let t2 = t1.rotated(by: CGFloat(bearingR))
let t3 = t2.translatedBy(x: -midPoint.x, y: -midPoint.y)
p.addLines(between: points, transform: t3)
}
p.addLines(between: [self.point(for: startPoint), self.point(for: endPoint)])
p.closeSubpath()
context.setStrokeColor(UIColor.yellow.cgColor)
context.setLineWidth(5/zoomScale)
context.addPath(p)
context.strokePath()
}
}
I used this tutorial to create a hexagon shape:
https://www.hackingwithswift.com/quick-start/swiftui/how-to-draw-polygons-and-stars
My goal is to try to round the corners of my hexagon shape. I know I have to use the path.addCurve somehow, but I cannot figure out where I need to do that. I am only getting weird results. Has anyone got an idea?
struct Polygon: Shape {
let corners: Int
let smoothness: CGFloat
func path(in rect: CGRect) -> Path {
guard corners >= 2 else { return Path() }
let center = CGPoint(x: rect.width / 2, y: rect.height / 2)
var currentAngle = -CGFloat.pi / 2
let angleAdjustment = .pi * 2 / CGFloat(corners * 2)
let innerX = center.x * smoothness
let innerY = center.y * smoothness
var path = Path()
path.move(to: CGPoint(x: center.x * cos(currentAngle), y: center.y * sin(currentAngle)))
var bottomEdge: CGFloat = 0
for corner in 0 ..< corners * 2 {
let sinAngle = sin(currentAngle)
let cosAngle = cos(currentAngle)
let bottom: CGFloat
if corner.isMultiple(of: 2) {
bottom = center.y * sinAngle
path.addLine(to: CGPoint(x: center.x * cosAngle, y: bottom))
} else {
bottom = innerY * sinAngle
path.addLine(to: CGPoint(x: innerX * cosAngle, y: bottom))
}
if bottom > bottomEdge {
bottomEdge = bottom
}
currentAngle += angleAdjustment
}
let unusedSpace = (rect.height / 2 - bottomEdge) / 2
let transform = CGAffineTransform(translationX: center.x, y: center.y + unusedSpace)
return path.applying(transform)
}
}
struct Hexagon: View {
#Environment(\.colorScheme) var colorScheme
var body: some View {
Polygon(corners: 3, smoothness: 1)
.fill(.clear)
.frame(width: 76, height: 76)
}
}
Haven't found a fix but this library does what I want:
https://github.com/heestand-xyz/PolyKit
I create this circle view like this:
override func draw(_ rect: CGRect) {
super.draw(rect)
if let context = UIGraphicsGetCurrentContext()
{
let width = fmin(self.frame.size.width, self.frame.size.height)
let offset_x = abs(width - self.frame.size.width)/2
let offset_y = abs(width - self.frame.size.height)/2
let padding = CGFloat(0.5)
let radius_size = (width/2) - (padding*2)
let circle_width = radius_size/4
context.setStrokeColor(UIColor.black.cgColor)
// Draw a circle
for i in 0 ..< 4
{
let offset = CGFloat(i) * circle_width
context.strokeEllipse(in:
CGRect(
x: padding + offset + offset_x,
y: padding + offset + offset_y,
width: (radius_size - offset)*2,
height: (radius_size - offset)*2))
}
context.strokePath()
}
}
How can I create a line to the circle center, if I have an array, of angles for the most top circle? And how can I do the same, for the middle circle?
For example, I have an array, with the given angles in degrees: [87.0, 112.0, 150.0]
Here's a function drawLine that draws a line from a center point at an angle with a specific radius. To change which circle the line reaches, just change the radius:
override func draw(_ rect: CGRect) {
super.draw(rect)
if let context = UIGraphicsGetCurrentContext()
{
let width = fmin(self.frame.size.width, self.frame.size.height)
let offset_x = abs(width - self.frame.size.width)/2
let offset_y = abs(width - self.frame.size.height)/2
let padding = CGFloat(0.5)
let radius_size = (width/2) - (padding*2)
let circle_width = radius_size/4
context.setStrokeColor(UIColor.black.cgColor)
// Draw a circle
for i in 0 ..< 4
{
let offset = CGFloat(i) * circle_width
context.strokeEllipse(in:
CGRect(
x: padding + offset + offset_x,
y: padding + offset + offset_y,
width: (radius_size - offset)*2,
height: (radius_size - offset)*2))
}
let angles: [CGFloat] = [87.0, 112.0, 150]
let angles2: [CGFloat] = [210.0, 250.0, 330.0]
let center = CGPoint(x: width/2 + offset_x, y: width/2 + offset_y)
for angle in angles {
drawLine(context: context, center: center, radius: radius_size, angle: angle)
}
for angle in angles2 {
drawLine(context: context, center: center, radius: radius_size * 3 / 4, angle: angle)
}
context.strokePath()
}
}
func drawLine(context: CGContext, center: CGPoint, radius: CGFloat, angle: CGFloat) {
context.move(to: center)
context.addLine(to: CGPoint(x: center.x + radius * cos(angle * .pi / 180), y: center.y - radius * sin(angle * .pi / 180)))
}
The small circle can move left and right by any amount
and I have to calculate the red dot’s coordinates wherever
its location is, if they intersect. I only calculate this under that condition. I must find the intersection and be sure that it is the intersection on the red dot, and not the intersection below it, so always the one with the higher Y value.
I have solved for all the distances of the triangles and blue dots.
How do I compute the red point?
If you want to look at my current code to help debug it, try this.
My Playground To Test:
//: Playground - noun: a place where people can play
import UIKit
infix operator **
let pretendWidth: CGFloat = 374
let pretendHeight: CGFloat = 7
// Testing scenario is pretendWidth..<(pretendWidth + (pretendHeight / 2))
let spacer: CGFloat = 0.5
extension CGFloat {
public static func **(base: CGFloat, exp: CGFloat) -> CGFloat {
return CGFloat(pow(Double(base), Double(exp)))
}
}
class BottomBarGradientNode: UIView {
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.saveGState()
context.clip(to: bounds)
// Gradient Creation
let locations: [CGFloat] = [0, 1]
let components: [CGFloat] = [0.2706, 0.6863, 0.8902, 1, 0, 0.8745, 0.7294, 1]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient: CGGradient = CGGradient(colorSpace: colorSpace, colorComponents: components, locations: locations, count: 2)!
let startPoint = CGPoint(x: bounds.maxX, y: bounds.maxY)
let endPoint = CGPoint(x: bounds.minX, y: bounds.minY)
let halfHeight = bounds.height / 2
let path = UIBezierPath()
let startPointForPath = CGPoint(x: bounds.width - halfHeight, y: 0)
path.move(to: startPointForPath)
let firstCenterPoint = CGPoint(x: bounds.width - halfHeight, y: halfHeight)
let secondCenterPoint = CGPoint(x: pretendWidth - bounds.height, y: 0)
Computation: if bounds.width > (pretendWidth + halfHeight) {
path.addArc(withCenter: secondCenterPoint, radius: bounds.height, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: true)
} else if bounds.width > pretendWidth {
//
// ------------------------------------------------------------------------------------------------------------------------------------
// Though this looks like a complicated geometry problem, this is really best done as an ugly algebra problem.
// We want the coordinates of the red dot: (x,y)
// We know the red dot is on the big circle and since that circle is not moving I'm going to call it's center (0,0) thus:
// x^2 + y^2 = 49
// We also know that the red dot is on the little circle, it has a moving center but we know that the y value for that
// center is always -3.5. so we'll let the x-value of that center be t:
// (x-t)^2 + (y-3.5)^2 = (3.5)^2
// which expands to:
// x^2 - 2xt + t^2 + y^2 -7y + (3.5)^2 = (3.5)^2
// which when we plug in our other equation simplifies to:
// y = (1/7)(-2tx + 49 + t^2)
// plugging that back into the first equation gives:
// x^2 + ((1/7)(-2tx + 49 + t^2))^2 = 49
// which is terrible to look out but turns out to be a quadratic equation in x, so from this point you'd just simplify
// and plug it into the quadratic formula. Pick the value of x that is smaller in magnitude (be careful about negatives
// here). Then plug that x back into the first equation to solve for y.
// ------------------------------------------------------------------------------------------------------------------------------------
//
let boundsHeightSquared = bounds.height ** 2
let distanceFromOtherCenter = firstCenterPoint.x - secondCenterPoint.x
// x^2 + ((1/7)(-2tx + 49 + t^2))^2 = 49 <<<< translates to VVVVVV
//
// ((4/49)t^2 + 1)(x^2) + (-4t - (4t^3/49))(x) + (2t^2 + (t^4)/49) = 0
// ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
// value1(a) value2(b) value3(c)
let value1 = ((4 * (distanceFromOtherCenter ** 2)) / boundsHeightSquared) + 1
let value2 = (-4 * distanceFromOtherCenter) - ((4 * (distanceFromOtherCenter ** 3)) / boundsHeightSquared)
let value3 = (2 * (distanceFromOtherCenter ** 2)) + ((distanceFromOtherCenter ** 4) / boundsHeightSquared)
let (first, second) = getQuadraticValues(a: value1, b: value2, c: value3)
// guarentee positive values
var areBothGreaterThanZero: Bool = false
var chosenX: CGFloat!
if first < 0 { chosenX = second }
else if second < 0 { chosenX = first }
else { chosenX = first < second ? first : second; areBothGreaterThanZero = true }
// y = (1/7)(-2tx + 49 + t^2)
var chosenY = (1 / bounds.height) * ((-2 * distanceFromOtherCenter * chosenX) + boundsHeightSquared - (distanceFromOtherCenter ** 2))
// last check on weird values
if chosenY < 0 && areBothGreaterThanZero {
chosenX = first < second ? first : second
chosenY = (1 / bounds.height) * ((-2 * distanceFromOtherCenter * chosenX) + boundsHeightSquared - (distanceFromOtherCenter ** 2))
}
// Computatation failed. Show full segment.
if chosenY < 0 {
print("Computation Failed")
path.addArc(withCenter: secondCenterPoint, radius: bounds.height, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: true)
break Computation
}
// true point
let intersectingPoint = CGPoint(x: chosenX + secondCenterPoint.x, y: chosenY)
// c^2 = a^2 + b^2 - 2abCOS(C)
// (a^2 + b^2 - c^2) / 2ab = COS(C)
let topPoint = CGPoint(x: firstCenterPoint.x, y: 0)
// compute c (distance)
let firstDistanceBetweenPoints = getDistanceBetweenTwoPoints(firstPoint: intersectingPoint, secondPoint: topPoint)
// where a and b are halfHeight
let firstCosC = getCosC(a: halfHeight, b: halfHeight, c: firstDistanceBetweenPoints)
let firstAngle = acos(firstCosC)
path.addArc(withCenter: firstCenterPoint, radius: halfHeight, startAngle: CGFloat.pi * 1.5, endAngle: CGFloat.pi * 1.5 + firstAngle, clockwise: true)
// c^2 = a^2 + b^2 - 2abCOS(C)
// (a^2 + b^2 - c^2) / 2ab = COS(C)
let lastPoint = CGPoint(x: pretendWidth, y: 0)
// compute c (distance)
let secondDistanceBetweenPoints = getDistanceBetweenTwoPoints(firstPoint: lastPoint, secondPoint: intersectingPoint)
// where a and b are bounds.height
let secondCosC = getCosC(a: bounds.height, b: bounds.height, c: secondDistanceBetweenPoints)
let secondAngle = acos(secondCosC)
path.addArc(withCenter: secondCenterPoint, radius: bounds.height, startAngle: secondAngle, endAngle: CGFloat.pi / 2, clockwise: true)
} else {
path.addArc(withCenter: firstCenterPoint, radius: halfHeight, startAngle: CGFloat.pi * 1.5, endAngle: CGFloat.pi / 2, clockwise: true)
}
path.addLine(to: CGPoint(x: bounds.height, y: bounds.height))
let finalCenterPoint = CGPoint(x: bounds.height, y: 0)
path.addArc(withCenter: finalCenterPoint, radius: bounds.height, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi, clockwise: true)
path.addLine(to: startPointForPath)
path.close()
path.addClip()
context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: .drawsAfterEndLocation)
context.restoreGState()
}
}
func getDistanceBetweenTwoPoints(firstPoint: CGPoint, secondPoint: CGPoint) -> CGFloat {
let diffX = (firstPoint.x - secondPoint.x) ** 2
let diffY = (firstPoint.y - secondPoint.y) ** 2
return sqrt(diffX + diffY)
}
func getSlopeBetweenTwoPoints(firstPoint: CGPoint, secondPoint: CGPoint) -> CGFloat {
let diffY = firstPoint.y - secondPoint.y
let diffX = firstPoint.x - secondPoint.x
return diffY / diffX
}
func getHypotenuse(firstDistance: CGFloat, secondDistance: CGFloat) -> CGFloat {
return sqrt((firstDistance ** 2) + (secondDistance ** 2))
}
func getQuadraticValues(a: CGFloat, b: CGFloat, c: CGFloat) -> (CGFloat, CGFloat) {
let first = (-b + sqrt((b ** 2) - (4 * a * c))) / (2 * a)
let second = (-b - sqrt((b ** 2) - (4 * a * c))) / (2 * a)
return (first, second)
}
func getCosC(a: CGFloat, b: CGFloat, c: CGFloat) -> CGFloat {
// (a^2 + b^2 - c^2) / 2ab = COS(C)
return ((a ** 2) + (b ** 2) - (c ** 2)) / (2 * a * b)
}
// Testing scenario is pretendWidth..<(pretendWidth + (height / 2))
let bounds = CGRect(x: 0, y: 0, width: pretendWidth + spacer, height: pretendHeight)
let bar = BottomBarGradientNode(frame: bounds)
Find both points of intersection then pick the appropriate one. Or formulate solution in terms of y coordinate then pick higher solution there to compute x coordinate for that.
The equation of a circle 1 is (x2+y2)+a1x+b1y+c1=0. Write both circles in this form, then subtract one equation from the other. The quadratic terms will cancel out, and the remaining equation describes the radical axis of the circles. ax+by+c=0 where a=a1−a2 and so on. Solve for x=−(by+c)/a. Plug this term into one of the original equations for the circle, and you have a quadratic equation in y.
Now a quadratic equation in y is of the form py2+qy+r=0 and has solutions −q±sqrt(q2−4pr)/2p. Look at the sign of p, then pick that same sign in front of the square root to get the solution with larger y value. Plug that back into the equation of the radical axis to compute the x coordinate.
If there is no intersection, q2−4pr < 0 and your solutions would become complex. If a=0 your radical axis is horizontal so you can't parametrize it by y value, and picking a solution by y value doesn't make any sense.
I'm looking for a way to programmatically create stars, sunburst, and other "spiky" effects using UIBezierPath.
UIBezierPath *sunbeamsPath = [UIBezierPath bezierPath];
[sunbeamsPath moveToPoint: CGPointMake(x, y)];
Are there any algorithms that can generate points for sunburst like shapes programmatically, without paths overlapping?
I'm also interested in an irregular shape sunburst like the one below:
I would imagine that such algorithm would take a certain number of rays, then roughly divide the circle in a number of segments and generate points for such segment in a clockwise direction. Does an algorithm like the one I'm describing already exists or will I have to write one by myself?
Thank you!
I know this old, but I was curious about the first part of this question myself, and going off jrturton's post, I created a custom UIView that generates a UIBezierPath from center of the view. Even animated it spinning for bonus points. Here is the result:
The code I used is here:
- (void)drawRect:(CGRect)rect {
CGFloat radius = rect.size.width/2.0f;
[self.fillColor setFill];
[self.strokeColor setStroke];
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
CGPoint centerPoint = CGPointMake(rect.origin.x + radius, rect.origin.y + radius);
CGPoint thisPoint = CGPointMake(centerPoint.x + radius, centerPoint.y);
[bezierPath moveToPoint:centerPoint];
CGFloat thisAngle = 0.0f;
CGFloat sliceDegrees = 360.0f / self.beams / 2.0f;
for (int i = 0; i < self.beams; i++) {
CGFloat x = radius * cosf(DEGREES_TO_RADIANS(thisAngle + sliceDegrees)) + centerPoint.x;
CGFloat y = radius * sinf(DEGREES_TO_RADIANS(thisAngle + sliceDegrees)) + centerPoint.y;
thisPoint = CGPointMake(x, y);
[bezierPath addLineToPoint:thisPoint];
thisAngle += sliceDegrees;
CGFloat x2 = radius * cosf(DEGREES_TO_RADIANS(thisAngle + sliceDegrees)) + centerPoint.x;
CGFloat y2 = radius * sinf(DEGREES_TO_RADIANS(thisAngle + sliceDegrees)) + centerPoint.y;
thisPoint = CGPointMake(x2, y2);
[bezierPath addLineToPoint:thisPoint];
[bezierPath addLineToPoint:centerPoint];
thisAngle += sliceDegrees;
}
[bezierPath closePath];
bezierPath.lineWidth = 1;
[bezierPath fill];
[bezierPath stroke];
}
And you can download a sample project here:
https://github.com/meekapps/Sunburst
I'm not aware of an algorithm to create these but I do have some advice - create your bezier path such that (0,0) is the centre of the sunburst, then define however many points you need to draw one "beam" of your sunburst going upwards, returning to (0,0)
Then, for as many beams as you want, perform a loop: apply a rotation transform (2 pi / number of beams) to your sunbeam points (CGPointApplyTransform), and add them to the path.
Once you are finished, you can translate and scale the path for drawing.
I used a similar process to draw star polygons recently and it was very simple. Credit to Rob Napier's book for the idea.
Swift version for this
import UIKit
extension Int {
var degreesToRadians: Double { return Double(self) * .pi / 180 }
var radiansToDegrees: Double { return Double(self) * 180 / .pi }
}
extension FloatingPoint {
var degreesToRadians: Self { return self * .pi / 180 }
var radiansToDegrees: Self { return self * 180 / .pi }
}
class SunBurstView: UIView {
override func draw(_ rect: CGRect) {
let radius: CGFloat = rect.size.width / 2.0
UIColor.red.setFill()
UIColor.blue.setStroke()
let bezierPath = UIBezierPath()
let centerPoint = CGPoint(x: rect.origin.x + radius, y: rect.origin.y + radius)
var thisPoint = CGPoint(x: centerPoint.x + radius, y: centerPoint.y)
bezierPath.move(to: centerPoint)
var thisAngle: CGFloat = 0.0
let sliceDegrees: CGFloat = 360.0 / self.beams / 2.0
for _ in 0..<self.beams {
let x = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x, y: y)
bezierPath.addLine(to: thisPoint)
thisAngle += sliceDegrees
let x2 = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y2 = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x2, y: y2)
bezierPath.addLine(to: thisPoint)
bezierPath.addLine(to: centerPoint)
thisAngle += sliceDegrees
}
bezierPath.close()
bezierPath.lineWidth = 1
bezierPath.fill()
bezierPath.stroke()
}
}
I noticed that the Swift version didn't compile for me or take up enough of the screen, so here's Reinier's answer in Swift 4 adjusted for a rectangular view.
extension Int {
var degreesToRadians: Double { return Double(self) * .pi / 180 }
var radiansToDegrees: Double { return Double(self) * 180 / .pi }
}
extension FloatingPoint {
var degreesToRadians: Self { return self * .pi / 180 }
var radiansToDegrees: Self { return self * 180 / .pi }
}
class SunBurstView: UIView {
var beams: CGFloat = 20
override func draw(_ rect: CGRect) {
self.clipsToBounds = false
self.layer.masksToBounds = false
let radius: CGFloat = rect.size.width * 1.5
UIColor.orange.withAlphaComponent(0.3).setFill()
UIColor.clear.setStroke()
let bezierPath = UIBezierPath()
let centerPoint = CGPoint(x: rect.origin.x + (radius / 3), y: rect.origin.y + (radius / 1.5))
var thisPoint = CGPoint(x: centerPoint.x + radius, y: centerPoint.y)
bezierPath.move(to: centerPoint)
var thisAngle: CGFloat = 0.0
let sliceDegrees: CGFloat = 360.0 / self.beams / 2.0
for _ in 0...Int(beams) {
let x = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x, y: y)
bezierPath.addLine(to: thisPoint)
thisAngle += sliceDegrees
let x2 = radius * CGFloat(cosf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.x
let y2 = radius * CGFloat(sinf(Float((thisAngle + sliceDegrees).degreesToRadians))) + centerPoint.y
thisPoint = CGPoint(x: x2, y: y2)
bezierPath.addLine(to: thisPoint)
bezierPath.addLine(to: centerPoint)
thisAngle += sliceDegrees
}
bezierPath.close()
bezierPath.lineWidth = 1
bezierPath.fill()
bezierPath.stroke()
}
}