我的任务是通过给定点绘制一条曲线路径。我使用CGMutablepath完成了这项工作。但是有些时候,我需要根据给出“ x”点的价值来找到“ y”点。我在下面附上了示例图片。
我显示为黑点的点。如果我给出的“ x”位于路径中某处,则需要找到一个“ y”点。如果有人知道解决方案,请帮助我。
答案 0 :(得分:0)
您很可能具有分段参数插值,即形式为
x(t) = Pi(t),
y(t) = Qi(t)
其中Pi
,Qi
是系数已知的多项式。
如果指定x
,则必须求解x = Pi(t)
和i
的方程t
。要找到i
,您需要知道Pi
的范围(对于多项式来说并不难)。然后,当您拥有i
时,必须求解一个多项式方程。对于三次曲线来说很好,对于更高的度数来说是有问题的。
根据数据,i
和t
可能有几种解决方案。
然后,当您知道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
}
}