Схема звезда и треугольник: Схема соединения звезда треугольник — В помощь Электрику

Геометрия звезд

Геометрия звезд

MartianCraft

  • Услуги
  • Команда
  • Карьера
  • Блог

 

Звезда — широко известный символ, используемый для рейтингов. Если вы создаете пользовательский интерфейс для рейтинга в приложении, скорее всего, вы где-то будете использовать звездочку. Есть много разных способов получить звезду на экране в вашем приложении, но лучший способ — нарисовать ее с нуля в коде. Это не только дает вам полную гибкость с точки зрения размера и разрешения экрана, а также возможность создавать удивительные эффекты с помощью основной анимации, но также позволяет вам полный ботаник в геометрии . Вы можете указать на подобные статьи в следующий раз, когда кто-то осмелится спросить, почему вы изучаете все это в школе, потому что «вы никогда не будете использовать это в реальной жизни».

Круги

Начните с классической пятиконечной звезды.

Звезда помещается внутри круга. Острие звезды идет прямо вверх. В полном круге 2 𝛑 радиана, поэтому каждая другая точка попадает в круг на 2 𝛑 / 5 радиан раунда от предыдущего:

Чтобы вычислить координаты каждой точки по краю круга, я могу использовать Метод UIBezierPath addArc . Меня не интересуют сами дуги, но currentPoint пути, когда вы добавляете каждую дугу, будут представлять интерес. Это расширение на UIBezierPath дает мне то, что мне нужно:

расширение UIBezierPath {
    статический пусть двенадцатиоклок: CGFloat = .pi * 1,5
    класс func pointsOnCircle(
        центр: CGPoint,
        радиус: CGFloat,
        очки: инт,
        startAngle: CGFloat = двенадцатиоклок) -> [CGPoint] {
        пусть pointOffsetAngle = ((.pi * 2.0) / CGFloat (точки))
        вар начальный угол = начальный угол
        вар конечный угол = начальный угол
        пусть путь = UIBezierPath()
        path.move (к: .
zero) var CirclePoints = [CGPoint]() за _ в 1...баллах { path.addArc (withCenter: центр, радиус: радиус, startAngle: startAngle, endAngle: endAngle, по часовой стрелке: true) CirclePoints.append (путь.currentPoint) начальный угол = конечный угол endAngle += pointOffsetAngle } вернуть кругОчки } }

Как только я наберу очки, я могу нарисовать звезду, соединив точки на круге, как показано здесь, начиная с 1 и заканчивая 5, а затем возвращаясь к 1:

Рисование такой звезды не дает нужного результата. Это нормально, если все, что я хочу сделать, это заполнить путь, но если я хочу иметь пустые или частично заполненные звезды (например, для представления среднего рейтинга в 3,6 звезды), тогда этот путь не будет работать. В середине весь этот беспорядок, который я не хочу видеть. Как я могу рассчитать, где будут эти внутренние точки? Пришло время разобраться с тригонометрией.

Треугольники

Тригонометрия — это прямоугольные треугольники, и на первый взгляд на диаграмме их нет. Но это только потому, что я не нарисовал на нем достаточно лишних линий. Я могу сделать пятиугольник большего размера, соединив все внешние точки звезды, и я могу провести линию из центра круга, которая проходит через внутреннюю точку. Это дает мне что-то вроде этого:

Оранжевая область представляет собой прямоугольный треугольник! Тем не менее, я недостаточно знаю об этом. Для описания прямоугольного треугольника мне нужно хотя бы два числа из:

  • Длины сторон
  • Неправильные углы

В настоящее время я могу вычислить только длину одной стороны — стороны, которая проходит на полпути вдоль края этого большого пятиугольника. Я могу сделать это, используя это расширение на

CGPoint для расчета средних точек и расстояний. Дистанционный метод использует теорему Пифагора, так что вы чертовски правы, он используется в реальной жизни! :

расширение CGPoint {
    расстояние функции (до: CGPoint) -> CGFloat {
        пусть deltaX = Double (to. x - self.x)
        пусть deltaY = Double (to.y - self.y)
        пусть расстояние = sqrt((deltaX * deltaX) + (deltaY * deltaY))
        вернуть CGFloat(расстояние)
    }
    func midPoint(to: CGPoint) -> CGPoint {
        пусть deltaX = to.x - self.x
        пусть deltaY = to.y - self.y
        return self.applying(CGAffineTransform(translationX: deltaX * 0,5, y: deltaY * 0,5))
    }
}
 

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

Пентагоны

В центре пятиконечной звезды находится пятиугольник. Это не совпадение. В центре шестиконечной звезды вы найдете шестиугольник и так далее. Вот геометрический факт, который вы, возможно, забыли со школы (я точно забыл): внутренние углы правильного многоугольника, например пятиугольника, можно найти по следующей формуле: ((n — 2) * 𝛑) / n , где n — количество сторон. Вот внутренние углы пятиугольника:

Таким образом, каждый из отмеченных углов равен 3𝛑 / 5 . Почему меня это волнует? Присмотритесь к внутренней точке, где виден пятиугольник:

.

Рассмотрим окружность над внутренней точкой. Синяя часть круга соответствует внутреннему углу пятиугольника. Внизу справа это 𝛑 — это значение, потому что именно столько радиан содержится в половине круга. Эти значения отражаются в верхней половине круга, поэтому желтая часть круга совпадает с внутренним углом пятиугольника. Верхний правый желтый участок — это интересующий меня угол — край треугольника проходит через него, и, поскольку край заканчивается в средней точке линии между двумя внешними точками, я знаю, что край пересекает этот желтый угол пополам — так что теперь у меня есть один из внутренних углов моего треугольника! Этой информации мне достаточно, чтобы рассчитать все, что мне нужно знать.

Термины, используемые при описании прямоугольного треугольника:

  • Гипотенуза — ребро треугольника, противоположное прямому углу
  • 𝜃 (тета) — интересующий вас непрямой угол
  • Противоположный
    — край треугольника напротив 𝜃
  • Смежный — ребро треугольника рядом с 𝜃

Как было сказано ранее, мне нужны любые две из этих частей информации. У меня есть 𝜃, который составляет половину внутреннего угла пятиугольника, или (3𝛑 / 5) / 2 (упрощено до 0,3𝛑 , если хотите), и у меня есть длина стороны напротив . Меня интересует длина стороны , прилегающей к стороне .

На этой диаграмме показаны различные части треугольника:

Есть три формулы тригонометрии, которые вам, возможно, приходилось учить в школе. Тот, который включает противоположные и смежные стороны, таков:

Желто-коричневый 𝜃 = напротив / рядом

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

рядом = напротив / Желто-коричневый 𝜃

Это дает мне расстояние от внутренней точки до средней точки двух внешних точек. На самом деле мне важно расстояние от центра круга до внутренней точки, но его легко рассчитать с помощью моего расширения CGPoint .

Теперь у меня есть радиус другого, меньшего круга, у которого есть все внутренние точки по окружности. Это означает, что я могу снова использовать свой метод pointsOnCircle , передав новый радиус и другой начальный угол (на полпути между первыми двумя внешними точками). Вот внутренний круг:

Объединение двух массивов точек в один путь дает мне идеальную звезду без грязных внутренних линий. ★★★★★ для геометрии!

Код

Это расширение дает новый инициализатор для

UIBezierPath , который возвращает звезду с заданным количеством точек внутри заданного прямоугольника. Это зависит от других расширений ранее в статье:

расширение UIBezierPath {
    удобство инициализации (starIn rect: CGRect, points: Int = 5) {
        предварительное условие (точки >= 3, «Неверное количество баллов»)
        // Константы, описывающие звезду
        пусть центр = CGPoint (x: rect.midX, y: rect.midY)
        пусть радиус = rect. size.width * 0,5
        пусть externalPoints = UIBezierPath.pointsOnCircle (центр: центр, радиус: радиус, точки: точки)
        // Этот расчет вычисляет расстояние от линии между первыми двумя внешними
        // точки и первая внутренняя точка
        // Внутренний угол правильного многоугольника в центре звезды
        пусть внутренний угол: CGFloat = (CGFloat (точки - 2) * .pi) / CGFloat (точки)
        // Середина линии между двумя внешними точками
        пусть midPoint = externalPoints[0].midPoint(to: externalPoints[1])
        // Длина этой строки
        пусть opp = externalPoints[0].distance(to: midPoint)
        пусть тета = внутренний угол * 0,5
        пусть DistanceIn = opp / tan (тета)
        // Это даст нам радиус внутреннего круга
        пусть внутреннийРадиус: CGFloat
        точки переключения {
        случай 3, 4: innerRadius = center.distance(to: midPoint) * 0,5
        по умолчанию: innerRadius = center.distance(to: midPoint) - DistanceIn
        }
        // Теперь мы можем повторить трюк с дугами окружностей, чтобы получить точки на внутренней окружности.
Начальный угол необходимо отрегулировать, так как он будет не в верхней части круга, а на полпути между двумя внешними точками. пусть innerPointOffset = (.pi * 2,0 / CGFloat (точки)) * 0,5 пусть innerPoints = UIBezierPath.pointsOnCircle (центр: центр, радиус: innerRadius, точки: точки, startAngle: UIBezierPath.twelveOClock + innerPointOffset) // Наконец, используем два набора точек для создания пути самостоятельная инициализация() self.move (к: externalPoints [0]) для (внешнего, внутреннего) в zip (outerPoints, innerPoints) { self.addLine (к: внешнему) self.addLine (к: внутренний) } self.close () // Центрируем звезду по вертикали в переданном прямоугольнике пусть starBounds = self.bounds пусть heightAdjustment = (rect.height - starBounds.height) * 0,5 self.apply(CGAffineTransform(translationX: 0, y: heightAdjustment)) } }

Одним из способов использования этого кода было бы нарисовать изображение звезды — вот способ нарисовать частично закрашенную звезду:

расширение UIImage {
    class func star (размер: CGSize, цвет: UIColor, точки: Int = 5, заполнено: CGFloat = 1. 0) -> UIImage {
        let renderer = UIGraphicsImageRenderer (размер: размер)
        пусть изображение = renderer.image { rendererContext в
            пусть границы = rendererContext.format.bounds
            пусть starPath = UIBezierPath (starIn: bounds.insetBy (dx: 2, dy: 2), точки: точки)
            звездный путь.lineWidth = 4
            цвет.setStroke()
            starPath.stroke()
            starPath.addClip()
            var fillRect = границы
            fillRect.size.width *= заполнено
            цвет.setFill()
            UIRectFill(fillRect)
        }
        вернуть изображение
    }
}
UIImage.star (из: CGSize (ширина: 200, высота: 200), цвет: .orange, точки: 5, заполнено: 0,6)
 

Дает вам:

Звездообразный путь более гибкий и обеспечивает лучшую производительность при использовании вместе с CAShapeLayer . Эта реализация оставлена ​​в качестве упражнения для читателя.

Заключение

Наличие геометрических форм в виде путей Безье дает вам полную гибкость для дизайна пользовательского интерфейса и упрощает изменение размера, стиля и цвета.

В коде можно создать почти любую геометрическую форму, но для этого вам, возможно, придется стряхнуть пыль со школьной геометрии. И, возможно, вам даже будет весело!

MartianCraft — американское агентство по разработке программного обеспечения для мобильных устройств. На протяжении почти двух десятилетий мы разрабатываем отмеченные наградами мобильные приложения мирового класса для всех видов бизнеса. Мы хотели бы создать индивидуальное программное решение, отвечающее вашим конкретным потребностям. Давайте свяжемся.

Предыдущий артикул

по Алекс Репти 6 марта 2017 г.


Следующая статья

по Бен Брукс 3 апреля 2017 г.

Классификационная система в нацистских концентрационных лагерях

Подробнее об этом изображении

  • Цитировать