ios - 理解 UIBezierPath 曲线机制、controlPoint 和曲线点

标签 ios swift graphics uibezierpath

我正在尝试使用 UIBezierPath 绘制一个简单的抛物线形状。我有一个 maxPoint 和一个 boundingRect,我基于抛物线的宽度和拉伸(stretch)。
这是我绘制抛物线的函数(我在容器 View 中绘制抛物线,rect 将是 container.bounds):

func addParabolaWithMax(maxPoint: CGPoint, inRect boundingRect: CGRect) {
    let path = UIBezierPath()

    let p1 = CGPointMake(1, CGRectGetMaxY(boundingRect)-1)
    let p3 = CGPointMake(CGRectGetMaxX(boundingRect)-1, CGRectGetMaxY(boundingRect)-1)

    path.moveToPoint(p1)
    path.addQuadCurveToPoint(p3, controlPoint: maxPoint)

    // Drawing code
    ...
}

我的问题是,我希望我在函数中发送的 maxPoint 是抛物线本身的实际极值点。因此,例如,如果我发送 (CGRectGetMidX(container.bounds), 0),最大点应该位于最顶部的中心。但是在这个特定点上使用这个函数,结果是这样的:

enter image description here

那么这里的路径到底是做什么的呢?或者换句话说,我怎样才能从 controlPoint 到达我需要的实际最大点?我已经尝试根据 boundingRect 的高度从 y 值中添加和减去不同的值,但我找不到正确的组合,因为在不同的点具有不同的 y 值,它的行为不同。好像加了个乘法器,怎么解决?

最佳答案

对于许多应用程序,adam.wulf 的解决方案很好,但它实际上并没有创建抛物线。要创建抛物线,我们需要计算给定二次曲线中点的控制点。贝塞尔路径只是数学;我们可以很容易地计算出来。我们只需要反转 Bézier 函数并求解 t=0.5。

0.5(中点)处的贝塞尔解决方案在 Draw a quadratic Bézier curve through three given points 处很好地导出.

2*Pc - P0/2 - P2/2

其中Pc是我们要经过的点,P0P2是终点。

(在其他点计算贝塞尔曲线不是很直观。t=0.25 处的值不是“路径的四分之一”。但幸运的是,就我们的目的而言,t=0.5 与我们的直觉非常吻合二次方程的“中点”。)

鉴于我们的解决方案,我们可以编写我们的代码。请原谅对 Swift 3 的翻译;我的 Xcode 7.3 副本对 iOS Playground 不是很满意,但应该很容易转换到 2.2。

func addParabolaWithMax(maxPoint: CGPoint, inRect boundingRect: CGRect) -> UIBezierPath {

    func halfPoint1D(p0: CGFloat, p2: CGFloat, control: CGFloat) -> CGFloat {
        return 2 * control - p0 / 2 - p2 / 2
    }

    let path = UIBezierPath()

    let p0 = CGPoint(x: 0, y: boundingRect.maxY)
    let p2 = CGPoint(x: boundingRect.maxX, y: boundingRect.maxY)

    let p1 = CGPoint(x: halfPoint1D(p0: p0.x, p2: p2.x, control: maxPoint.x),
                     y: halfPoint1D(p0: p0.y, p2: p2.y, control: maxPoint.y))

    path.move(to: p0)
    path.addQuadCurve(to: p2, controlPoint: p1)
    return path
}

halfPoint1D 函数是我们解决方案的一维实现。对于我们的二维 CGPoint,我们只需调用它两次。

如果我只能推荐一种理解贝塞尔曲线的资源,那很可能是 "Constructing Bézier curves"来自维基百科的部分。研究显示曲线如何产生的小动画,我发现非常有启发性。 “特定案例”部分也很有用。为了深入探讨这个主题(我建议所有开发人员都熟悉这个主题),我喜欢 A Primer on Bézier Curves .可以略读一下,只阅读您目前感兴趣的部分。但是对这组函数的基本理解将大大有助于消除 Core Graphics 中绘图的魔力,并使 UIBezierPath 成为一个工具而不是一个黑盒子。

关于ios - 理解 UIBezierPath 曲线机制、controlPoint 和曲线点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38723031/

相关文章:

ios - 华氏度/摄氏度符号 ASCII NSString

iphone - IOS CATransform3DMakeRotation 需要矢量方面的帮助

ios - 自定义搜索结果 TableView

ios - 我如何计算 Swift 2 中坐标的反射

delphi - 设置 Paintbox 的字体大小会导致调用 OnPaint

java - 绘制的字符串(使用drawString)闪烁

ios - 如何使用 Core Graphics/Quartz 2D 在 iOS 中制作圆锥形渐变?

ios - 如何计算表格 View 中的值并显示在单独的标签中

iOS : Swift - How to add pinpoint to map on touch and get detailed address of that location?

c++ - 在 OpenGL 中渲染火焰