iPhone iOS Программно генерировать звезду, солнечные лучи или многоугольник UIBezierPath

Я ищу способ программно создавать звезды, солнечные лучи и другие "колючие" эффекты с использованием UIBezierPath.

Starburst image

<code>UIBezierPath *sunbeamsPath = [UIBezierPath bezierPath];
[sunbeamsPath moveToPoint: CGPointMake(x, y)];
</code>

Существуют ли алгоритмы, которые могут программно генерировать точки для солнечных лучей, подобных фигурам, без перекрытия путей?

Меня также интересуют солнечные лучи неправильной формы, подобные приведенным ниже:

irregular sunburst

Я предположил бы, что такой алгоритм будет принимать определенное количество лучей, а затем примерно делить круг на несколько сегментов и генерировать точки для такого сегмента по часовой стрелке. Существует ли алгоритм, подобный тому, который я описываю, уже существует, или мне придется написать его самому?

Спасибо!

Ответы на вопрос(3)

но мне было любопытно, что касается первой части этого вопроса, и, исходя из поста jrturton, я создал пользовательский UIView, который генерирует UIBezierPath из центра представления. Даже анимация вращается за бонусные баллы. Вот результат:

enter image description 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];

}

И вы можете скачать пример проекта здесь:

https://github.com/meekapps/Sunburst

но у меня есть несколько советов - создайте свой путь Безье так, чтобы (0,0) был центром солнечного луча, а затем определите, сколько точек вам нужно для рисования одного "луча". вашего солнечного взрыва идет вверх, возвращаясь к (0,0)

Затем для любого количества лучей выполните цикл: примените преобразование вращения (2 pi / число лучей) к точкам солнечных лучей (CGPointApplyTransform) и добавьте их в путь.

Как только вы закончите, вы можете перевести и масштабировать путь для рисования.

Я недавно использовал похожий процесс для рисования звездных полигонов, и это было очень просто. Кредит дляРоб Нейпир книга для идеи.

Swift version for this


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()
    }

}

ВАШ ОТВЕТ НА ВОПРОС