【问题标题】:SCNShape not drawing with UIBezierPath under certain circumstances在某些情况下,SCNShape 不使用 UIBezierPath 绘制
【发布时间】:2018-07-15 15:27:27
【问题描述】:

我相信这可能是一个 iOS 错误,我已通过错误报告向 Apple 报告了它。如果有一些我可以使用的解决方法或解释原因,我会在这里发布。

我想在 SceneKit 中绘制 UIBezierPath 的笔触。我正在使用 CGPath copyStrokingWithWidth 函数,然后使用给定的路径创建一个 SCNShape

这适用于具有 2 点的线条,但在具有 3 点的线条上,SCNShape 不显示任何内容。我已经确定只有lineWidth 大于 0.1 时才会出现这种情况。将lineWidth 设置为 0.1,它可以完美显示。

let strokeBezierPath = UIBezierPath()
strokeBezierPath.lineWidth = 1
strokeBezierPath.move(to: CGPoint.zero)
strokeBezierPath.addLine(to: CGPoint(x: 10, y: 0))
strokeBezierPath.addLine(to: CGPoint(x: 10, y: 10))
let cgPath = strokeBezierPath.cgPath.copy(
    strokingWithWidth: strokeBezierPath.lineWidth,
    lineCap: strokeBezierPath.lineCapStyle,
    lineJoin: strokeBezierPath.lineJoinStyle,
    miterLimit: strokeBezierPath.miterLimit)

let bezierPath = UIBezierPath(cgPath: cgPath)
let shape = SCNShape(path: bezierPath, extrusionDepth: 1)
shape.firstMaterial?.diffuse.contents = UIColor.blue
let node = SCNNode(geometry: shape)
node.position.z = -40

sceneView.scene.rootNode.addChildNode(node)

这适用于:

  • 仅前 2 点
  • 0.1 的线宽
  • 人工绘制的覆盖同一区域的贝塞尔路径

将线宽的 UIBezierPath 打印为 0.1(显示):

<UIBezierPath: 0x1d00b12e0; <MoveTo {0, 0.050000000000000003}>,
 <LineTo {10, 0.050000000000000003}>,
 <LineTo {9.9499999999999993, 10}>,
 <LineTo {10.050000000000001, 10}>,
 <LineTo {10.050000000000001, 0}>,
 <LineTo {0, -0.050000000000000003}>,
 <LineTo {0, 0.050000000000000003}>,
 <Close>

线宽为0.2(不显示):

<UIBezierPath: 0x1d00b7160; <MoveTo {0, 0.10000000000000001}>,
 <LineTo {10, 0.10000000000000001}>,
 <LineTo {9.9000000000000004, 0}>,
 <LineTo {9.9000000000000004, 10}>,
 <LineTo {10.1, 10}>,
 <LineTo {10.1, 0}>,
 <LineTo {10, -0.10000000000000001}>,
 <LineTo {0, -0.10000000000000001}>,
 <LineTo {0, 0.10000000000000001}>,
 <Close>

【问题讨论】:

    标签: ios core-graphics scenekit uibezierpath arkit


    【解决方案1】:
       let strokeBezierPath = UIBezierPath()
              strokeBezierPath.lineWidth = 1   
              strokeBezierPath.move(to: CGPoint.zero)
              strokeBezierPath.addLine(to: CGPoint(x: 10, y: 0))
              strokeBezierPath.addLine(to: CGPoint(x: 10, y: 10))
    

    你还没有关闭路径。您将无法挤出两条尚未闭合的线段......所以什么都不会出现。使用以下命令关闭路径。这将在场景视图中显示您的几何体。

        strokeBezierPath.close()
    

    编辑:Scenekit 单位以米为单位。所以要在你面前处理一个较小的物体。将单位和线宽更改为以下。这会将物体放在前面 1 米处……而且要小得多,这样你就可以更好地看到发生了什么。

    let strokeBezierPath = UIBezierPath()
        strokeBezierPath.lineWidth = 0.01
        strokeBezierPath.move(to: CGPoint.zero)
        strokeBezierPath.addLine(to: CGPoint(x: 0.1, y: 0))
        strokeBezierPath.addLine(to: CGPoint(x: 0.1, y: 0.1))
        strokeBezierPath.addLine(to: CGPoint(x: 0.0, y: 0.1))
        strokeBezierPath.addLine(to: CGPoint(x: 0, y: 0))
        strokeBezierPath.close()
        let cgPath = strokeBezierPath.cgPath.copy(
            strokingWithWidth: strokeBezierPath.lineWidth,
            lineCap: strokeBezierPath.lineCapStyle,
            lineJoin: strokeBezierPath.lineJoinStyle,
            miterLimit: strokeBezierPath.miterLimit)
    
        let bezierPath = UIBezierPath(cgPath: cgPath)
        let shape = SCNShape(path: bezierPath, extrusionDepth: 0.01)
        shape.firstMaterial?.diffuse.contents = UIColor.blue
        let node = SCNNode(geometry: shape)
        node.position.z = -1
    
        sceneView.scene.rootNode.addChildNode(node)
    

    【讨论】:

    • 如果我在一个开放的形状上调用close(),例如我的 2 行形状,它会创建一个“闭合”形状的贝塞尔路径,在这种情况下创建一个三角形贝塞尔路径。
    • 你只画了两条线。所以关闭路径将创建一个三角形贝塞尔路径。在第二个示例中,我又添加了两条线来绘制方形贝塞尔路径。
    • 对。我现在的目标是画一个开放的形状,所以 2 或 3 条线,它们不会回到起点。
    • 好的。但是贝塞尔路径总是必须在场景包中关闭......以便创建一个要挤出的表面。
    • 将 lineWidth 从 0.01、0.05、0.1、0.5 等更改为 1 ... 这将让您了解在 scenekit 中绘制形状时线宽如何影响表面几何形状。需要根据几何体的大小按比例设置lineWidth,否则,宽度本身可能大于点之间的距离。
    猜你喜欢
    • 2018-04-02
    • 2016-01-27
    • 1970-01-01
    • 2015-05-02
    • 2013-05-21
    • 2017-06-21
    • 2018-11-28
    • 2011-09-04
    • 1970-01-01
    相关资源
    最近更新 更多