如何在使用OpenGL ES的iOS SDK中绘制黑色边缘?

时间:2018-06-20 09:26:25

标签: ios objective-c swift opengl-es

请参阅下面的图像,如何在不使用遮罩的情况下在黑色边缘内部进行绘制[例如,如果要在笔帽内部进行绘制,则完全需要使用画笔工具填充笔帽]。

我们已经使用洪水填充算法实现了存储桶工具。

请参阅[IMAGE 4]这种类型的绘图是错误的,因此我们只需要在黑色边缘内绘制,请参阅[IMAGE 2]和[IMAGE 3]。

我们需要在iOS SDK中实现它,

我已经尝试了这两种方法-

  1. 我已经记录了特定区域的坐标,它滞后太多,并且内存泄漏在那里。这不是一个好方法

  2. 我必须在背景中使用存储桶工具(洪水填充算法)填充特定区域,然后尝试匹配触摸点的颜色。它也不能提供理想的输出。

[图像1]

enter image description here

[图像2]

enter image description here

[图像3]

enter image description here

[图像4]

enter image description here

1 个答案:

答案 0 :(得分:1)

有几种可能的方法。例如,可以使用基于纯矢量的方法。但是,转换单个图形可能会非常耗时。

一种更为实用的方法如下:

方法

您可以定义一个Bézier路径列表(UIBezierPath),每个路径描述一个可以独立绘制的区域。

贝塞尔曲线路径有两个作用:

  • 确定中风的开始区域
  • 将用户绘图限制在该区域

如何在黑线内完美绘制

如果使给定图形的背景透明,则可以在黑色线条图形下方进行剪裁来创建用户的图形操作。这意味着贝塞尔曲线不一定是完美的,而必须足够精确。

层/剪切

步骤如下:

  • 最初显示给定的图纸
  • 确定用户开始绘制贝塞尔曲线的路径
  • 剪切到确定的贝塞尔曲线路径
  • 通过裁剪绘制用户笔划
  • 在给定的透明线条图上绘制

快速演示

这是一个简短的演示,展示了当用户开始使用所描述的绘制顺序在剪切的贝塞尔曲线路径中绘制图形时的外观(另请参见下面的代码段):

quick demo

代码段

贝塞尔曲线示例

bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 55.94, y: 60.19))
bezierPath.addCurve(to: CGPoint(x: 50.32, y: 94.09), controlPoint1: CGPoint(x: 56.92, y: 59.69), controlPoint2: CGPoint(x: 55.25, y: 73.99))
bezierPath.addCurve(to: CGPoint(x: 48.81, y: 115.93), controlPoint1: CGPoint(x: 46.9, y: 107.97), controlPoint2: CGPoint(x: 49.09, y: 115.33))
bezierPath.addCurve(to: CGPoint(x: 74.36, y: 146.45), controlPoint1: CGPoint(x: 50.56, y: 127.4), controlPoint2: CGPoint(x: 60.85, y: 141.06))
bezierPath.addCurve(to: CGPoint(x: 119.11, y: 126.29), controlPoint1: CGPoint(x: 93.52, y: 141.34), controlPoint2: CGPoint(x: 107.61, y: 134.31))
bezierPath.addCurve(to: CGPoint(x: 223.27, y: 93.88), controlPoint1: CGPoint(x: 150.33, y: 112.49), controlPoint2: CGPoint(x: 183.59, y: 100.44))
bezierPath.addCurve(to: CGPoint(x: 300.41, y: 69.01), controlPoint1: CGPoint(x: 250.68, y: 87.71), controlPoint2: CGPoint(x: 276.22, y: 79.2))
bezierPath.addCurve(to: CGPoint(x: 297.23, y: 59.69), controlPoint1: CGPoint(x: 301.38, y: 65.82), controlPoint2: CGPoint(x: 300.22, y: 62.01))
bezierPath.addCurve(to: CGPoint(x: 212.85, y: 38.3), controlPoint1: CGPoint(x: 290.2, y: 62.67), controlPoint2: CGPoint(x: 256.59, y: 52.37))
bezierPath.addCurve(to: CGPoint(x: 137.05, y: 37.2), controlPoint1: CGPoint(x: 191.43, y: 31.36), controlPoint2: CGPoint(x: 158.26, y: 29.92))
bezierPath.addCurve(to: CGPoint(x: 100.74, y: 48.08), controlPoint1: CGPoint(x: 126.18, y: 40.93), controlPoint2: CGPoint(x: 111.78, y: 44.75))
bezierPath.addCurve(to: CGPoint(x: 55.94, y: 60.19), controlPoint1: CGPoint(x: 86.15, y: 52.48), controlPoint2: CGPoint(x: 70.56, y: 56.69))
bezierPath.close()

剪切到路径

self.currentBezierPath.addClip()

确定触摸是否在封闭的贝塞尔曲线路径内开始

假设self是一种自定义视图,则可以这样写:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    ...
    let point = touch.location(in: self)
    ...
    let inside = bezierPath.contains(point)
    ...

绘制透明图纸

第一个必须使图形的背景透明。然后,可以以支持透明性的格式(例如.png。

context.saveGState()
context.scaleBy(x: 1, y: -1)
context.translateBy(x: 0, y: -oOV7Impng.size.height)
context.draw(oOV7Impng.cgImage!, in: CGRect(x: 0, y: 0, width: oOV7Impng.size.width, height: oOV7Impng.size.height))
context.restoreGState()

如果应用程序中有很多图纸,则可以考虑以编程方式使图像的背景透明(例如,使白色像素透明)。取决于用例。