SCNShape在某些情况下不使用UIBezierPath进行绘制

时间:2018-02-05 17:31:53

标签: ios core-graphics scenekit uibezierpath arkit

我相信这可能是一个iOS错误,我已经通过Bug Report向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>

1 个答案:

答案 0 :(得分:0)

   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))

您还没有关闭路径。您将无法挤出两个尚未关闭的线段...因此不会显示任何内容。使用以下命令关闭路径。这将在sceneView中显示您的几何体。

    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)