Create hexagon design using UIBezierPath in swift ios - ios

I want to achieve a hexagon shape using UIBezierPath like in the image below. But I don´t know how to create this kind of hexagon shape.
I´ve tried following code:
func roundedPolygonPath(rect: CGRect, lineWidth: CGFloat, sides: NSInteger, cornerRadius: CGFloat, rotationOffset: CGFloat = 0)
-> UIBezierPath {
let path = UIBezierPath()
let theta: CGFloat = CGFloat(2.0 * M_PI) / CGFloat(sides) // How much to turn at every corner
let offset: CGFloat = cornerRadius * tan(theta / 2.0) // Offset from which to start rounding corners
let width = min(rect.size.width, rect.size.height) // Width of the square
let center = CGPoint(x: rect.origin.x + width / 2.0, y: rect.origin.y + width / 2.0)
// Radius of the circle that encircles the polygon
// Notice that the radius is adjusted for the corners, that way the largest outer
// dimension of the resulting shape is always exactly the width - linewidth
let radius = (width - lineWidth + cornerRadius - (cos(theta) * cornerRadius)) / 2.0
// Start drawing at a point, which by default is at the right hand edge
// but can be offset
var angle = CGFloat(rotationOffset)
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
path.move(to: CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta)))
for _ in 0 ..< sides {
angle += theta
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
let tip = CGPoint(x: center.x + radius * cos(angle), y: center.y + radius * sin(angle))
let start = CGPoint(x: corner.x + cornerRadius * cos(angle - theta), y: corner.y + cornerRadius * sin(angle - theta))
let end = CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta))
path.addLine(to: start)
path.addQuadCurve(to: end, controlPoint: tip)
}
path.close()
// Move the path to the correct origins
let bounds = path.bounds
let transform = CGAffineTransform(translationX: -bounds.origin.x + rect.origin.x + lineWidth / 2.0,
y: -bounds.origin.y + rect.origin.y + lineWidth / 2.0)
path.apply(transform)
return path
}
Current code output:

for this kind of shape i took two center points and make rectangle hexagon from that
func customPolygonPath(rect: CGRect, lineWidth: CGFloat, sides: NSInteger, cornerRadius: CGFloat, rotationOffset: CGFloat = 0)
-> UIBezierPath {
let path = UIBezierPath()
let theta: CGFloat = CGFloat(2.0 * M_PI) / CGFloat(sides) // How much to turn at every corner
let offset: CGFloat = cornerRadius * tan(theta / 2.0) // Offset from which to start rounding corners
let width = min(rect.size.width, rect.size.height) // Width of the square
let height = max(rect.size.width, rect.size.height)
let upperCenter = CGPoint(x: rect.origin.x + width / 2.0, y: rect.origin.y + width / 2.0)
let bottomCenter = CGPoint(x: upperCenter.x, y: height - upperCenter.y)
let center = CGPoint(x: rect.origin.x + width / 2.0, y: rect.origin.y + height / 2.0)
// Radius of the circle that encircles the polygon
// Notice that the radius is adjusted for the corners, that way the largest outer
// dimension of the resulting shape is always exactly the width - linewidth
let radius = (width - lineWidth + cornerRadius - (cos(theta) * cornerRadius)) / 2.0
// Start drawing at a point, which by default is at the right hand edge
// but can be offset
var angle = CGFloat(rotationOffset)
let bottomCorner = CGPoint(x: bottomCenter.x + (radius - cornerRadius) * cos(angle), y: bottomCenter.y + (radius - cornerRadius) * sin(angle))
path.move(to: CGPoint(x: bottomCorner.x + cornerRadius * cos(angle + theta), y: bottomCorner.y + cornerRadius * sin(angle + theta)))
// print("corner:::\(corner)")
// print("point:::\(CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta)))")
for i in 0 ..< sides {
angle += theta
if i == 0 || i == 4 || i == 5 {
//bottomCenter
let corner = CGPoint(x: bottomCenter.x + (radius - cornerRadius) * cos(angle), y: bottomCenter.y + (radius - cornerRadius) * sin(angle))
let tip = CGPoint(x: bottomCenter.x + radius * cos(angle), y: bottomCenter.y + radius * sin(angle))
let start = CGPoint(x: corner.x + (cornerRadius * cos(angle - theta)), y: corner.y + (cornerRadius * sin(angle - theta)))
let end = CGPoint(x: corner.x + (cornerRadius * cos(angle + theta)), y: corner.y + (cornerRadius * sin(angle + theta)))
path.addLine(to: start)
path.addQuadCurve(to: end, controlPoint: tip)
}else {
//upperCenter
let corner = CGPoint(x: upperCenter.x + (radius - cornerRadius) * cos(angle), y: upperCenter.y + (radius - cornerRadius) * sin(angle))
let tip = CGPoint(x: upperCenter.x + radius * cos(angle), y: upperCenter.y + radius * sin(angle))
let start = CGPoint(x: corner.x + cornerRadius * cos(angle - theta), y: corner.y + cornerRadius * sin(angle - theta))
let end = CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta))
path.addLine(to: start)
path.addQuadCurve(to: end, controlPoint: tip)
}
}
path.close()
// Move the path to the correct origins
let bounds = path.bounds
let transform = CGAffineTransform(translationX: 0,
y: 0)
path.apply(transform)
return path
}

Related

How to draw another layer of hexagon UIBezier Path and animate accordingly

I'm looking for a way to add another layer of hexagon bezier path like the ones below.
I have been able to create Hexagon using bezier path and animate accordingly but I am trying to add another grey colour layer of bezier path. I tried adding multiple bezier paths but it doesn't work.
This is the output I achieved.
Here is my LoaderView class
class LoaderView: UIView {
private let lineWidth : CGFloat = 5
internal var backgroundMask = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
setUpLayers()
createAnimation()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpLayers()
createAnimation()
}
func setUpLayers()
{
backgroundMask.lineWidth = lineWidth
backgroundMask.fillColor = nil
backgroundMask.strokeColor = UIColor.blue.cgColor
layer.mask = backgroundMask
layer.addSublayer(backgroundMask)
}
func createAnimation()
{
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.duration = 1
animation.repeatCount = .infinity
backgroundMask.add(animation, forKey: "MyAnimation")
}
override func draw(_ rect: CGRect) {
let sides = 6
let rect = self.bounds
let path = UIBezierPath()
let cornerRadius : CGFloat = 10
let rotationOffset = CGFloat(.pi / 2.0)
let theta: CGFloat = CGFloat(2.0 * .pi) / CGFloat(sides) // How much to turn at every corner
let width = min(rect.size.width, rect.size.height) // Width of the square
let center = CGPoint(x: rect.origin.x + width / 2.0, y: rect.origin.y + width / 2.0)
// Radius of the circle that encircles the polygon
// Notice that the radius is adjusted for the corners, that way the largest outer
// dimension of the resulting shape is always exactly the width - linewidth
let radius = (width - lineWidth + cornerRadius - (cos(theta) * cornerRadius)) / 2.0
// Start drawing at a point, which by default is at the right hand edge
// but can be offset
var angle = CGFloat(rotationOffset)
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
path.move(to: CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta)))
for _ in 0..<sides {
angle += theta
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
let tip = CGPoint(x: center.x + radius * cos(angle), y: center.y + radius * sin(angle))
let start = CGPoint(x: corner.x + cornerRadius * cos(angle - theta), y: corner.y + cornerRadius * sin(angle - theta))
let end = CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta))
path.addLine(to: start)
path.addQuadCurve(to: end, controlPoint: tip)
}
path.close()
backgroundMask.path = path.cgPath
}}
To add the gray hexagon under the blue animating path, you can add another CAShapeLayer:
var grayLayer = CAShapeLayer()
Set it up in a similar way to backgroundMask:
grayLayer.lineWidth = lineWidth
grayLayer.fillColor = nil
grayLayer.strokeColor = UIColor.gray.cgColor
Set its path to be the same path as backgroundMask:
backgroundMask.path = path.cgPath
grayLayer.path = path.cgPath
Finally, add the gray layer before you add backgroundMask. This makes it go at the bottom:
layer.addSublayer(grayLayer)
layer.addSublayer(backgroundMask)
Also note that your path drawing code doesn't need to go in draw. It could just go in init.
Here's what one frame of the animation looks like:

How to bend text like line segment into circle with core graphics?

The question was asked for BezierPath but now I not necessary to be with bezier it can be with core graphics also.
I am trying to draw curved text (shape it could be started as straight line to circle) and I saw CoreText allow us to draw text on UIBezierPath path. So I tried to draw a straight line and curved it into circle by given bend factor value. It should straight line if value is zero and if its positive bend line to down side else bend the line to up side [text will draw along this path.]
Did a way to bend straight line with given 'bend factor' into circle with UIBezierPath like this ?
i'have tried with way actually I am not convinced... Draw curve with 2 control points, if bend factor is 0 draw straight line else curve line while curve != half circle then updating path with half circle to complete path into a circle if bend factor is positive and doing reverse if bend factor is negative value it looks like straight line converts into circle but this not a good method to do this..For better understanding please take a look here
For example:
let r = textFXmodel.radius // This is bend factor
if r != 0.0 { // If bend factor is equals to zero draw straight line
let positiveR = abs(r)
let fullSize = self.bounds.size
var curvedLinePath = UIBezierPath()
let insetRect = self.bounds.insetBy(dx: 10, dy: 10)
let maximumValue = Float(insetRect.size.width / 2)
let minimumValue = -Float(insetRect.size.width / 2)
if r >= 0.0 { // If bend factor 'r' is positive value
if r <= CGFloat(maximumValue / 2) { // If bend factor 'r' less then half of circle ⌢
// Draw curved line and bend it from control points
let controlPoint1 = CGPoint(x: fullSize.width / 2 - (r + r * 0.2), y: fullSize.height / 2 - (r * 1.5))
let controlPoint2 = CGPoint(x: fullSize.width / 2 + (r + r * 0.2), y: fullSize.height / 2 - (r * 1.5))
let curveStartPoint = CGPoint(x: r, y: fullSize.height / 2)
let curveEndPoint = CGPoint(x: fullSize.width - r, y: fullSize.height / 2)
curvedLinePath.move(to: curveStartPoint)
curvedLinePath.addCurve(to: curveEndPoint, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
} else { // bend factor 'r' is greater or equal to half circle so remove curved line and draw half circle path
let scaledRadius: CGFloat = r - 60
let centerPoint = CGPoint(x: fullSize.width / 2, y: fullSize.height / 2)
let startAngel = CGFloat.pi - (scaledRadius * 0.023)
let endAngle = (CGFloat.pi * 2) + (scaledRadius * 0.023)
curvedLinePath.removeAllPoints()
curvedLinePath = UIBezierPath(arcCenter: centerPoint, radius: (fullSize.width / 4), startAngle: startAngel, endAngle: endAngle, clockwise: true)
}
} else {
if r >= CGFloat(minimumValue / 2) {
let controlPoint1 = CGPoint(x: fullSize.width / 2 - (positiveR + positiveR * 0.2), y: fullSize.height / 2 + (positiveR * 1.5))
let controlPoint2 = CGPoint(x: fullSize.width / 2 + (positiveR + positiveR * 0.2), y: fullSize.height / 2 + (positiveR * 1.5))
let curveStartPoint = CGPoint(x: positiveR, y: fullSize.height / 2)
let curveEndPoint = CGPoint(x: fullSize.width - positiveR, y: fullSize.height / 2)
curvedLinePath.move(to: curveStartPoint)
curvedLinePath.addCurve(to: curveEndPoint, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
} else {
let scaledRadius: CGFloat = positiveR - 60
let centerPoint = CGPoint(x: fullSize.width / 2, y: fullSize.height / 2)
let startAngel = CGFloat.pi + (scaledRadius * 0.023)
let endAngle = (CGFloat.pi * 2) - (scaledRadius * 0.023)
curvedLinePath.removeAllPoints()
curvedLinePath = UIBezierPath(arcCenter: centerPoint, radius: (fullSize.width / 4), startAngle: startAngel, endAngle: endAngle, clockwise: false)
}
}
// and here goes drawing code...
My code works like this it looks like line break at half of way (:
If you have a way to draw text like this without Bezierpath or CoreText please share it with me. I've googled a lot and I read all answers about this topic and no one helped me even this answer, and this
UPDATE:-
In this version line segment will bend in same center but this also not real circle it looks like drop shape
private func updatePath(withRadius radius: CGFloat) -> UIBezierPath {
var curveStartPoint: CGPoint = .zero
var curveEndPoint: CGPoint = .zero
var controlPoint1: CGPoint = .zero
var controlPoint2: CGPoint = .zero
if radius > 0.0 {
controlPoint1 = CGPoint(x: size.width / 2 - (radius + radius * 0.2), y: size.height / 2 - radius)
controlPoint2 = CGPoint(x: size.width / 2 + (radius + radius * 0.2), y: size.height / 2 - radius)
curveStartPoint = CGPoint(x: radius, y: size.height / 2 + (radius * 0.5))
curveEndPoint = CGPoint(x: size.width - radius, y: size.height / 2 + (radius * 0.5))
} else {
let positateR: CGFloat = abs(radius)
controlPoint1 = CGPoint(x: size.width / 2 - (positateR + positateR * 0.2), y: size.height / 2 + positateR)
controlPoint2 = CGPoint(x: size.width / 2 + (positateR + positateR * 0.2), y: size.height / 2 + positateR)
curveStartPoint = CGPoint(x: positateR, y: size.height / 2 + (radius * 0.5))
curveEndPoint = CGPoint(x: size.width - positateR, y: size.height / 2 + (radius * 0.5))
}
let drawingPath = UIBezierPath()
drawingPath.move(to: curveStartPoint)
drawingPath.addCurve(to: curveEndPoint, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
return drawingPath
}

How to draw slices in semicircle shape layers in objective-c

I have drawn the semicircle shape by using following code
- (void)drawRect:(CGRect)rect
{
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
[bezierPath addArcWithCenter:CGPointMake(self.frame.size.width, self.frame.size.height/2) radius:150 startAngle:0 endAngle:2 * M_PI clockwise:YES];
CAShapeLayer *progressLayer = [[CAShapeLayer alloc] init];
[progressLayer setPath:bezierPath.CGPath];
[progressLayer setStrokeColor:[UIColor colorWithWhite:1. alpha:.2].CGColor];
[progressLayer setFillColor:[UIColor colorWithRed:67.0/255.0 green:144.0/255.0 blue:246.0/255.0 alpha:1.0].CGColor];
[progressLayer setLineWidth:.7 * self.bounds.size.width];
[[self layer] addSublayer:progressLayer];
// [self drawWheel];
}
I want to draw a slices like pie in a semicircle using objective-c that should match exactly like image as shown below
Can anyone suggest me any solution please
Add this code in your drawRect(_:)
let radius = min(bounds.size.width, bounds.size.height) / 2;
let center = CGPoint.init(x: bounds.size.width / 2, y: bounds.size.height / 2)
let sliceCount = 6;
let slicePath = UIBezierPath.init()
slicePath.lineWidth = 1;
slicePath.move(to: center)
var angle: CGFloat = 0 - (CGFloat.pi / 2);
var interval: CGFloat = (CGFloat.pi) / CGFloat(sliceCount)
for i in 0 ... sliceCount {
let x = center.x + (radius * cos(angle))
let y = center.y + (radius * sin(angle))
slicePath.addLine(to: CGPoint.init(x: x, y: y))
slicePath.move(to: center)
angle -= interval;
}
UIColor.white.setStroke()
slicePath.stroke()
Here is the result.
Updated
Another code that's very similar to your goal
override func draw(_ rect: CGRect) {
let radius = min(bounds.size.width, bounds.size.height) / 2;
let center = CGPoint.init(x: bounds.size.width, y: bounds.size.height / 2)
let sliceCount = 6;
let semiCirclePath = UIBezierPath.init()
semiCirclePath.move(to: center)
semiCirclePath.addArc(withCenter: center, radius: radius, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi + (CGFloat.pi / 2) , clockwise: true)
semiCirclePath.close()
UIColor.blue.setFill()
semiCirclePath.fill()
let slicePath = UIBezierPath.init()
slicePath.lineWidth = 1;
slicePath.move(to: center)
var angle: CGFloat = 0 - (CGFloat.pi / 2);
var interval: CGFloat = (CGFloat.pi) / CGFloat(sliceCount)
for i in 0 ... sliceCount {
let x = center.x + (radius * cos(angle))
let y = center.y + (radius * sin(angle))
slicePath.addLine(to: CGPoint.init(x: x, y: y))
slicePath.move(to: center)
angle -= interval;
}
UIColor.white.setStroke()
slicePath.stroke()
semiCirclePath.removeAllPoints()
semiCirclePath.move(to: center)
semiCirclePath.addArc(withCenter: center, radius: 30, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi + (CGFloat.pi / 2) , clockwise: true)
UIColor.lightGray.setFill()
semiCirclePath.fill()
}
Here what it looks like,
Updated second time
For the one that's completely looked like
override func draw(_ rect: CGRect) {
let radius = min(bounds.size.width, bounds.size.height) / 2;
let center = CGPoint.init(x: bounds.size.width, y: bounds.size.height / 2)
let selectedSliceIndex = 2;
let sliceCount = 6;
let slicePath = UIBezierPath.init()
let selectedSlicePath = UIBezierPath.init()
slicePath.lineWidth = 1;
slicePath.move(to: center)
var angle: CGFloat = 0 - (CGFloat.pi / 2);
let interval: CGFloat = (CGFloat.pi) / CGFloat(sliceCount)
for i in 0 ... sliceCount {
let x = center.x + (radius * cos(angle))
let y = center.y + (radius * sin(angle))
slicePath.addLine(to: CGPoint.init(x: x, y: y))
slicePath.move(to: center)
if i == selectedSliceIndex {
selectedSlicePath.move(to: center)
selectedSlicePath.addArc(withCenter: center, radius: radius, startAngle: angle - interval, endAngle: angle, clockwise: true)
selectedSlicePath.close()
}
angle -= interval;
}
// outer blue circle
let semiCirclePath = UIBezierPath.init()
semiCirclePath.move(to: center)
semiCirclePath.addArc(withCenter: center, radius: radius, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi + (CGFloat.pi / 2) , clockwise: true)
semiCirclePath.close()
UIColor.blue.setFill()
semiCirclePath.fill()
// lines
UIColor.white.setStroke()
slicePath.stroke()
// selected slice
UIColor.lightGray.setFill()
selectedSlicePath.fill()
UIColor.clear.setFill()
// inner gray circle
semiCirclePath.removeAllPoints()
semiCirclePath.move(to: center)
semiCirclePath.addArc(withCenter: center, radius: 30, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi + (CGFloat.pi / 2) , clockwise: true)
UIColor.lightGray.setFill()
semiCirclePath.fill()
}
You might need to adjust some values to look beautiful.
I Moved the view's frame inside ViewController FYI.

How to draw CATransform3D for this layer?

I'm using CATransform3D and CAShapeLayer to create a layer like below
Here is my code.
let path = CGMutablePath()
let startPoint = CGPoint(x: center.x - width / 2, y: center.y - height / 2)
path.move(to: startPoint)
path.addLine(to: CGPoint(x: startPoint.x + width, y: startPoint.y))
path.addLine(to: CGPoint(x: startPoint.x + width, y: startPoint.y + height))
path.addLine(to: CGPoint(x: startPoint.x, y: startPoint.y + height))
path.closeSubpath()
let backgroundLayer = CAShapeLayer()
backgroundLayer.path = path
backgroundLayer.fillColor = UIColor.clear.cgColor
backgroundLayer.strokeColor = boarderColor.cgColor
var transform = CATransform3DIdentity
transform.m34 = -1 / 500
let angle = 45.toRadians
backgroundLayer.transform = CATransform3DRotate(transform, angle, 1, 0, 0)
The output is like below.
What is the reason for the difference of shape?
The backgroundLayer needs a frame and a position. If these are added, the result is as follows:
Source
Here a slightly modified version of your code that gives the result shown in the screenshot.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let boarderColor = UIColor.red
let height: CGFloat = 400
let width: CGFloat = 250
let center = CGPoint(x: width / 2.0, y: height / 2)
let path = CGMutablePath()
let startPoint = CGPoint(x: center.x - width / 2, y: center.y - height / 2)
path.move(to: startPoint)
path.addLine(to: CGPoint(x: startPoint.x + width, y: startPoint.y))
path.addLine(to: CGPoint(x: startPoint.x + width, y: startPoint.y + height))
path.addLine(to: CGPoint(x: startPoint.x, y: startPoint.y + height))
path.closeSubpath()
let backgroundLayer = CAShapeLayer()
backgroundLayer.path = path
backgroundLayer.fillColor = UIColor.clear.cgColor
backgroundLayer.strokeColor = boarderColor.cgColor
//these two lines are missing
backgroundLayer.frame = CGRect(x: 0, y: 0, width: width, height: height)
backgroundLayer.position = CGPoint(x: self.view.bounds.width / 2.0, y: self.view.bounds.height / 2)
var transform = CATransform3DIdentity
transform.m34 = -1 / 500
let angle = CGFloat(45 * Double.pi / 180.0)
backgroundLayer.transform = CATransform3DRotate(transform, angle, 1, 0, 0)
self.view.layer.addSublayer(backgroundLayer)
}
}

Swift 3: Hexagon do not show center of the imageView

My hexagon do not show in center of the imageView, how to fix this? Here is my code.
func roundedPolygonPath(rect: CGRect, lineWidth: CGFloat, sides: NSInteger, cornerRadius: CGFloat, rotationOffset: CGFloat = 0)
-> UIBezierPath {
let path = UIBezierPath()
let theta: CGFloat = CGFloat(2.0 * M_PI) / CGFloat(sides) // How much to turn at every corner
// let offset: CGFloat = cornerRadius * tan(theta / 2.0) // Offset from which to start rounding corners
let width = min(rect.size.width, rect.size.height) // Width of the square
let center = CGPoint(x: rect.origin.x + width + 10 / 2.0, y: rect.origin.y + width / 2.0)
// Radius of the circle that encircles the polygon
// Notice that the radius is adjusted for the corners, that way the largest outer
// dimension of the resulting shape is always exactly the width - linewidth
let radius = (width - lineWidth + cornerRadius - (cos(theta) * cornerRadius)) / 2.0
// Start drawing at a point, which by default is at the right hand edge
// but can be offset
var angle = CGFloat(rotationOffset)
let corner = CGPoint(center.x + (radius - cornerRadius) * cos(angle), center.y + (radius - cornerRadius) * sin(angle))
path.move(to: CGPoint(corner.x + cornerRadius * cos(angle + theta), corner.y + cornerRadius * sin(angle + theta)))
for _ in 0 ..< sides {
angle += theta
let corner = CGPoint(center.x + (radius - cornerRadius) * cos(angle), center.y + (radius - cornerRadius) * sin(angle))
let tip = CGPoint(center.x + radius * cos(angle), center.y + radius * sin(angle))
let start = CGPoint(corner.x + cornerRadius * cos(angle - theta), corner.y + cornerRadius * sin(angle - theta))
let end = CGPoint(corner.x + cornerRadius * cos(angle + theta), corner.y + cornerRadius * sin(angle + theta))
path.addLine(to: start)
path.addQuadCurve(to: end, controlPoint: tip)
}
path.close()
// Move the path to the correct origins
let bounds = path.bounds
let transform = CGAffineTransform(translationX: -bounds.origin.x + rect.origin.x + lineWidth / 2.0,
y: -bounds.origin.y + rect.origin.y + lineWidth / 2.0)
path.apply(transform)
return path
}
Both of this elements has x and y equals 0. Try to use width properties to calculate transform.

Resources