Как получить каждый CGPoint на UIBezierPath в Swift
Я хочу выяснить все cgpoints, которые идут по пути UIBezierPath, для этого у меня есть 3 пункта, по которым я создаю путь UIBezier. Я попробовал приведенный ниже код, но он не дает точных результатов. Пожалуйста, проверьте прикрепленное изображение Может ли какой-либо орган помочь мне в этом.
Заранее спасибо:)
func getPathElementsPointsAndTypes() -> ([CGPoint],[CGPathElementType]) {
var arrayPoints : [CGPoint]! = [CGPoint]()
var arrayTypes : [CGPathElementType]! = [CGPathElementType]()
self.forEach { element in
switch (element.type) {
case CGPathElementType.moveToPoint:
arrayPoints.append(element.points[0])
arrayTypes.append(element.type)
case .addLineToPoint:
arrayPoints.append(element.points[0])
arrayTypes.append(element.type)
case .addQuadCurveToPoint:
arrayPoints.append(element.points[0])
arrayPoints.append(element.points[1])
arrayTypes.append(element.type)
arrayTypes.append(element.type)
case .addCurveToPoint:
arrayPoints.append(element.points[0])
arrayPoints.append(element.points[1])
arrayPoints.append(element.points[2])
arrayTypes.append(element.type)
arrayTypes.append(element.type)
arrayTypes.append(element.type)
default: break
}
}
return (arrayPoints,arrayTypes)
}
0 ответов
Давайте сделаем шаг назад. Зачем вам все эти очки? Чтобы увидеть, касается ли кто-то контура пути? Если да, используйтеCGPathCreateCopyByStrokingPath
чтобы создать новый контур, который заполняется там, где был обведен оригинал, а затем используйте метод containsPoint для нового контура. Легко.
Если вы действительно хотите "все" точки, вы должны принять, что математически существует бесконечное количество точек на линиях и кривых, поэтому вы не можете получить их все. В iOS, где точки представляют собой пары CGFloat, их все еще слишком много, чтобы иметь практически "все" точки. Однако вы можете получить столько точек, сколько захотите, на любой части кривой, поэтому, если вы скажете "100 точек на пути" или "1000 точек на пути" (или почти любое целое число, которое вам нравится), вы решите вашу проблему. тогда это все еще решаемая проблема.
Итерации по каждому элементу пути - хорошее начало.
Для каждой линии вам нужно сгенерировать "все" точки на линии, это довольно простая геометрия: вычислить вектор от начальной точки до конца. Итерируйте от 0,0 до 1,0 с любым шагом. Умножьте вектор на эту дробь, добавьте его в начальную точку, и это будет ваша точка.
Для каждой кривой вам понадобится более сложное уравнение, вот некоторый псевдокод:
function computeCurve(points[], t):
if(points.length==1):
recordPoint(points[0])
else:
newpoints=array(points.size-1)
for(i=0; i<newpoints.length; i++):
newpoints[i] = (1-t) * points[i] + t * points[i+1]
computeCurve(newpoints, t)
Чтобы получить действительно хороший обзор того, как кривые Безье "действительно работают", посмотрите https://pomax.github.io/bezierinfo/ (у него есть псевдокод, включая в основном ту часть, которую я описал выше, но ничего, что вы можете выполнить напрямую в Swift).
Для кода, который уже делает это на iOS, посмотрите:
https://github.com/CodingMeSwiftly/UIBezierPath-Superpowers
Для macOS я сделал довольно незначительную вилку для поддержки немного другого набора примитивов в macOS:
https://github.com/stripes/UIBezierPath-Superpowers
Они предоставят вам новый метод для UIBezierPath (или NSBezierPath) mx_point(в фракции: CGFloat), который позволит вам присвоить ему значение от 0 до 1 и получить интересующую вас точку. У него также есть метод, чтобы дать вам общую длину пути, поэтому, если вам не нужны "100 точек на пути", а "точки на пути не более чем на 3 пикселя друг от друга", вы можете как бы использовать это, чтобы получить некоторые оценки того, как быстро шагать эта часть. Это только предположение, потому что некоторые части дуги будут "двигаться" быстрее, чем другие. Поэтому вам нужно будет сгенерировать каждую точку, и если они слишком далеко друг от друга для вашего использования, сделайте шаг назад.
Удачи!