在给定点绘制的曲线之间找到点

时间:2018-08-29 07:22:34

标签: ios math graph charts

我的任务是通过给定点绘制一条曲线路径。我使用CGMutablepath完成了这项工作。但是有些时候,我需要根据给出“ x”点的价值来找到“ y”点。我在下面附上了示例图片。 enter image description here

我显示为黑点的点。如果我给出的“ x”位于路径中某处,则需要找到一个“ y”点。如果有人知道解决方案,请帮助我。

2 个答案:

答案 0 :(得分:0)

您很可能具有分段参数插值,即形式为

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

其中PiQi是系数已知的多项式。

如果指定x,则必须求解x = Pi(t)i的方程t。要找到i,您需要知道Pi的范围(对于多项式来说并不难)。然后,当您拥有i时,必须求解一个多项式方程。对于三次曲线来说很好,对于更高的度数来说是有问题的。

根据数据,it可能有几种解决方案。

然后,当您知道t时,计算y(t)

答案 1 :(得分:0)

我通过使用三次函数解决了这个问题。我提到了这个video

//
//  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
    }
}