kzen.dev
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
Cristián Romo
Cristián Romo
Вопрос

Эквидистантные точки кривых Безье

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

9 2008-08-13T23:31:32+00:00 3
Программирование
graphics
interpolation
bezier
curve
J. Peterson
J. Peterson
12-го мая 2009 в 10:23
2009-05-12T22:23:58+00:00
Дополнительно
Источник
Редактировать
#8414411

Это называется параметризацией "длины дуги". Я написал об этом статью несколько лет назад:

http://www.saccade.com/writing/graphics/RE-PARAM.PDF

Идея заключается в том, чтобы предварительно вычислить кривую "параметризации" и оценить кривую через нее.

9
0
Решение / Ответ
 nlucaroni
nlucaroni
14-го августа 2008 в 12:47
2008-08-14T00:47:05+00:00
Дополнительно
Источник
Редактировать
#8414410

расстояние между P_0 и P_3 (в кубической форме), да, но я думаю, вы это знали, является прямым.

Расстояние на кривой - это просто длина дуги:

рис. 1

где:

рис 2

(см. остальное)

Вероятно, t_0 = 0, t_1 = 1.0, и dz(t) = 0 (2d плоскость).

 nlucaroni
nlucaroni
Редактировал ответ 14-го августа 2008 в 12:50
4
0
 enc_life
enc_life
15-го января 2016 в 4:40
2016-01-15T04:40:56+00:00
Дополнительно
Источник
Редактировать
#8414412

Я знаю, что это старый вопрос, но недавно я столкнулся с этой проблемой и создал расширение UIBezierPath, чтобы решить для координаты X, заданной координатой Y и наоборот. Написано на swift.

https://github.com/rkotzy/RKBezierMath

extension UIBezierPath {

func solveBezerAtY(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, y: CGFloat) -> [CGPoint] {

    // bezier control points
    let C0 = start.y - y
    let C1 = point1.y - y
    let C2 = point2.y - y
    let C3 = end.y - y

    // The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
    let A = C3 - 3.0*C2 + 3.0*C1 - C0
    let B = 3.0*C2 - 6.0*C1 + 3.0*C0
    let C = 3.0*C1 - 3.0*C0
    let D = C0

    let roots = solveCubic(A, b: B, c: C, d: D)

    var result = [CGPoint]()

    for root in roots {
        if (root >= 0 && root <= 1) {
            result.append(bezierOutputAtT(start, point1: point1, point2: point2, end: end, t: root))
        }
    }

    return result
}

func solveBezerAtX(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, x: CGFloat) -> [CGPoint] {

    // bezier control points
    let C0 = start.x - x
    let C1 = point1.x - x
    let C2 = point2.x - x
    let C3 = end.x - x

    // The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
    let A = C3 - 3.0*C2 + 3.0*C1 - C0
    let B = 3.0*C2 - 6.0*C1 + 3.0*C0
    let C = 3.0*C1 - 3.0*C0
    let D = C0

    let roots = solveCubic(A, b: B, c: C, d: D)

    var result = [CGPoint]()

    for root in roots {
        if (root >= 0 && root <= 1) {
            result.append(bezierOutputAtT(start, point1: point1, point2: point2, end: end, t: root))
        }
    }

    return result

}

func solveCubic(a: CGFloat?, var b: CGFloat, var c: CGFloat, var d: CGFloat) -> [CGFloat] {

    if (a == nil) {
        return solveQuadratic(b, b: c, c: d)
    }

    b /= a!
    c /= a!
    d /= a!

    let p = (3 * c - b * b) / 3
    let q = (2 * b * b * b - 9 * b * c + 27 * d) / 27

    if (p == 0) {
        return [pow(-q, 1 / 3)]

    } else if (q == 0) {
        return [sqrt(-p), -sqrt(-p)]

    } else {

        let discriminant = pow(q / 2, 2) + pow(p / 3, 3)

        if (discriminant == 0) {
            return [pow(q / 2, 1 / 3) - b / 3]

        } else if (discriminant > 0) {
            let x = crt(-(q / 2) + sqrt(discriminant))
            let z = crt((q / 2) + sqrt(discriminant))
            return [x - z - b / 3]
        } else {

            let r = sqrt(pow(-(p/3), 3))
            let phi = acos(-(q / (2 * sqrt(pow(-(p / 3), 3)))))

            let s = 2 * pow(r, 1/3)

            return [
                s * cos(phi / 3) - b / 3,
                s * cos((phi + CGFloat(2) * CGFloat(M_PI)) / 3) - b / 3,
                s * cos((phi + CGFloat(4) * CGFloat(M_PI)) / 3) - b / 3
            ]

        }

    }
}

func solveQuadratic(a: CGFloat, b: CGFloat, c: CGFloat) -> [CGFloat] {

    let discriminant = b * b - 4 * a * c;

    if (discriminant < 0) {
        return []

    } else {
        return [
            (-b + sqrt(discriminant)) / (2 * a),
            (-b - sqrt(discriminant)) / (2 * a)
        ]
    }

}

private func crt(v: CGFloat) -> CGFloat {
    if (v<0) {
        return -pow(-v, 1/3)
    }
    return pow(v, 1/3)
}

private func bezierOutputAtT(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, t: CGFloat) -> CGPoint {

    // bezier control points
    let C0 = start
    let C1 = point1
    let C2 = point2
    let C3 = end

    // The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
    let A = CGPointMake(C3.x - 3.0*C2.x + 3.0*C1.x - C0.x, C3.y - 3.0*C2.y + 3.0*C1.y - C0.y)
    let B = CGPointMake(3.0*C2.x - 6.0*C1.x + 3.0*C0.x, 3.0*C2.y - 6.0*C1.y + 3.0*C0.y)
    let C = CGPointMake(3.0*C1.x - 3.0*C0.x, 3.0*C1.y - 3.0*C0.y)
    let D = C0

    return CGPointMake(((A.x*t+B.x)*t+C.x)*t+D.x, ((A.y*t+B.y)*t+C.y)*t+D.y)
}

// TODO: - future implementation
private func tangentAngleAtT(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, t: CGFloat) -> CGFloat {

    // bezier control points
    let C0 = start
    let C1 = point1
    let C2 = point2
    let C3 = end

    // The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
    let A = CGPointMake(C3.x - 3.0*C2.x + 3.0*C1.x - C0.x, C3.y - 3.0*C2.y + 3.0*C1.y - C0.y)
    let B = CGPointMake(3.0*C2.x - 6.0*C1.x + 3.0*C0.x, 3.0*C2.y - 6.0*C1.y + 3.0*C0.y)
    let C = CGPointMake(3.0*C1.x - 3.0*C0.x, 3.0*C1.y - 3.0*C0.y)

    return atan2(3.0*A.y*t*t + 2.0*B.y*t + C.y, 3.0*A.x*t*t + 2.0*B.x*t + C.x)
}

}
 Mykola
Mykola
Редактировал ответ 15-го января 2016 в 6:23
2
0
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Ilya Smirnov
Зарегистрирован 2 дня назад
2
Денис Васьков
Зарегистрирован 4 дня назад
3
Dima Patrushev
Зарегистрирован 6 дней назад
4
sirojidddin otaboyev
Зарегистрирован 2 недели назад
5
Елена Гайдамамакинат
Зарегистрирован 2 недели назад
ID
KO
RU
© kzen.dev 2023
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией