Найти точки между кривой, которая рисуется заданными точками - PullRequest
0 голосов
/ 29 августа 2018

У меня есть задача нарисовать кривой путь через заданные точки. Я сделал с помощью CGMutablepath, чтобы закончить эту работу. Но в какой-то момент времени мне нужно найти точку «у», основанную на предоставлении точки «х», чтобы показать значение. Я приложил образец изображения ниже. enter image description here

Точки, которые я показал черными точками. Мне нужно найти точку «у», если я дам «х», который где-то лежит на пути. Если кто-нибудь знает решение, пожалуйста, помогите мне.

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Я решил эту проблему с помощью кубической функции. Я ссылался на это видео

//
//  CubicFunction.swift
//
//  Created by Karthik Venkatesh on 30/08/18.
//  Copyright © 2018 karthik. All rights reserved.
//

import Foundation
import Accelerate

extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0 ..< Swift.min($0 + size, count)])
        }
    }
}

class CubicFunction {

    var matrix_a = [[CGFloat]]()
    var matrix_b = [CGFloat]()

    var coefficients = [CGFloat]()

    init(withPoints points: [CGPoint]) {
        self.constructMatrixA(forXValues: points.map{ $0.x })
        let matrixAItemsPerRow = matrix_a.first?.count ?? 0
        self.constructMatrixB(forXValues: points.map{ $0.y })
        var matrix_a_1d = [CGFloat]()
        for row in matrix_a { matrix_a_1d.append(contentsOf: row) }
        let inversed = self.invert(matrix: matrix_a_1d.map{ Double($0) }).map{ CGFloat($0) }
        let inversed_matrix = inversed.chunked(into: matrixAItemsPerRow)
        self.coefficients.append(contentsOf: self.multiply(matrixA: inversed_matrix, matrixB: matrix_b))
   }

   private func constructMatrixA(forXValues values: [CGFloat]) {
        for value in values {
            var row = [CGFloat]()
            for i in stride(from: values.count - 1, to: 0, by: -1) {
                row.append(pow(value,CGFloat(i)))
            }
            row.append(1)
            matrix_a.append(row)
        }
    }

    private func constructMatrixB(forXValues values: [CGFloat]) {
        self.matrix_b.append(contentsOf: values)
    }

    private func invert(matrix : [Double]) -> [Double] {
        var inMatrix = matrix
        var N = __CLPK_integer(sqrt(Double(matrix.count)))
        var pivots = [__CLPK_integer](repeating: 0, count: Int(N))
        var workspace = [Double](repeating: 0.0, count: Int(N))
        var error : __CLPK_integer = 0

        withUnsafeMutablePointer(to: &N) {
            dgetrf_($0, $0, &inMatrix, $0, &pivots, &error)
            dgetri_($0, &inMatrix, $0, &pivots, &workspace, $0, &error)
        }
        return inMatrix
    }

    private func multiply(matrixA: [[CGFloat]], matrixB: [CGFloat]) -> [CGFloat] {
        if matrixA[0].count != matrixB.count { return [] }
        var result: [CGFloat] = [CGFloat]()
        for i in 0..<matrixA.count {
            let row = matrixA[i]
            var value: CGFloat = 0
            for j in 0..<row.count {
                value = value + (row[j] * matrixB[j])
            }
            result.append(value)
        }
        return result
    }

    func y(forX x: CGFloat) -> CGFloat? {
        var y: CGFloat? = nil
        for index in 0..<self.coefficients.count {
            y = (y ?? 0) + (self.coefficients[index] * pow(x, CGFloat(self.coefficients.count - 1 - index)))
        }
        return y
    }
}
0 голосов
/ 29 августа 2018

Скорее всего, у вас есть кусочно-параметрический интерполант, то есть в форме

x(t) = Pi(t),
y(t) = Qi(t)

, где Pi, Qi - это полиномы, коэффициенты которых известны.

Если вы укажете x, вы должны решить уравнение x = Pi(t) для i и t. Чтобы найти i, вам нужно знать диапазоны Pi (не слишком сложно для полинома). Затем, когда у вас есть i, вы должны решить полиномиальное уравнение. Это хорошо для кубических кривых, проблематично для более высоких степеней.

В зависимости от данных может быть несколько решений для i и t.

Затем, когда вы знаете t, вычислите y(t).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...