Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios SCNShape不';t为NSBezierPath绘制形状_Ios_Swift_Macos_Scenekit - Fatal编程技术网

Ios SCNShape不';t为NSBezierPath绘制形状

Ios SCNShape不';t为NSBezierPath绘制形状,ios,swift,macos,scenekit,Ios,Swift,Macos,Scenekit,我经历过,对于一些NSBezierPathsSCNShape似乎无法绘制形状 仅使用行(to:)创建路径 为了验证创建SCNShape的一般过程是否正确,我还绘制了一个蓝色的形状,它只因具有不同的点而有所不同。蓝色的形状会被画出来,绿色的形状不会 您可以找到包含完整示例的游乐场。在本例中,您应该能够在助手编辑器中看到绿色和蓝色形状。但只有蓝色的形状会被画出来 你知道为什么没有显示绿色形状吗?短篇故事:你的路径的点比它需要的多,导致你遇到意想不到的、难以发现的几何问题 请注意以下内容中的此位: 拉

我经历过,对于一些
NSBezierPath
s
SCNShape
似乎无法绘制形状

仅使用
行(to:)
创建路径

为了验证创建
SCNShape
的一般过程是否正确,我还绘制了一个蓝色的形状,它只因具有不同的点而有所不同。蓝色的形状会被画出来,绿色的形状不会

您可以找到包含完整示例的游乐场。在本例中,您应该能够在助手编辑器中看到绿色和蓝色形状。但只有蓝色的形状会被画出来


你知道为什么没有显示绿色形状吗?

短篇故事:你的路径的点比它需要的多,导致你遇到意想不到的、难以发现的几何问题

请注意以下内容中的此位:

拉伸自交路径的结果未定义

事实证明,在前8点左右的某个地方,您的“曲线”以错误的方式转弯,使闭合路径的线(路径中的第一个点
0,0
,和最后一个点
32.366829,29.713470
)与路径的其余部分相交。这里尝试通过排除操场渲染中除前几个点和最后一个点以外的所有点(请参见左下角的小锯齿)使其可见:

至少在某些SceneKit版本/渲染器上,当它试图从自相交路径生成网格时,它只是放弃,什么也不做

然而,你真的不需要那么多的点来让你的路径看起来很好。如果使用1倍、1/5倍和1/10倍的点数,则为:

如果从整体上排除了足够多的点,并且/或者在开始时跳过了使曲线在应该弯曲的地方弯曲的少数点,则SceneKit会将形状渲染得很好:


诊断问题的一些提示:

在处理大量这样的坐标数据时,我喜欢使用
ExpressibleByArrayLiteral
,这样我就可以轻松地构建大量点/向量等的数组:

extension CGPoint: ExpressibleByArrayLiteral {
    public init(arrayLiteral elements: CGFloat...) {
        precondition(elements.count == 2)
        self.init(x: elements.first!, y: elements.last!)
    }
}

var points: [CGPoint] = [
    [0.000000, 0.000000],
    [0.011681, 0.029526],
    // ...
]
这让我得到了一个数组(而且更不用说反复输入像
NSPointMake
之类的东西了),这样我就可以对数据进行切片和切分,找出它的错误所在。(例如,我早期的一个理论是可能存在负坐标,因此我做了一些
map
min()
来找到最负的X和Y值,然后再做一些
map
来制作一个数组,其中所有点都以常量偏移。)

现在,为了使用点数组创建路径,我在
NSBezierPath
上做了一个扩展:

extension NSBezierPath {
    convenience init(linesBetween points: [CGPoint], stride: Int = 1)  {
        precondition(points.count > 1)
        self.init()
        move(to: points.first! )
        for i in Swift.stride(from: 1, to: points.count, by: stride) {
            line(to: points[i])
        }
    }
}
有了这个,我可以很容易地从整个点阵列创建路径,而且

  • 跳过原始数组部分的路径(使用
    stride
    参数)

    (这对于更快地生成操场预览也很方便。)

  • 使用原始数组的某些块或片的路径

    let zigzag = NSBezierPath(linesBetween: Array(points.prefix(to:10)) + [points.last!])
    let lopOffBothEnds = NSBezierPath(linesBetween: Array(points[1 ..< points.count < 1]))
    

    通过在路径中添加更多点,可以获得(稍微)更好的渲染效果,但更好的方法是使用曲线而不是直线创建路径。为了获得额外的积分,请尝试扩展上面的
    NSBezierPath(linesBetween:)
    初始值设定项,以添加曲线,方法是将每个
    n
    th点作为路径的一部分,同时使用两个中间点作为控制手柄。(这不是通用的自动跟踪算法,但对于这样的情况可能已经足够好了。)

    与Rikster的答案相比,这是不可能的,但有另一种方法可以防止此类问题。这是一种商业化的方式,可能也有类似的免费软件应用,但这是我习惯使用的一种,它做得很好

    我说的“这”是什么

    通过名为PaintCode的应用程序将图形转换为代码。这将让你看到你的道路,并确保他们没有任何冲突,里克斯特指出是你的问题

    在这里查看:


    答案中列出了其他选项:

    Wow。哇!!!这是一流的文档。我谨代表所有习惯于用钢笔、鼠标或平板电脑绘图的设计型、触觉型插图画家,感谢你们!路径的问题是,它是由我的应用程序的用户创建的,所以我事先不知道路径将包含多少个点和哪个点。谢谢你的回答!!:)为了收集这个例子的数据,我们要求用户在空中画一个圆圈。显然,结果不是一个完美的循环。理想情况下,我们会将其识别为一个圆,然后更改数据以绘制一个完美的圆。但这是另一个问题……是的,你绝对不能指望能够将用户草图输入到
    SCNShape
    。正如你所注意到的,将“圆”识别为实际的圆是一个完全独立的问题。。。虽然有几十年的研究成果可以利用,但如果可以将Illustrator或其他矢量程序中的形状复制并粘贴到SceneKit的场景编辑器中,效果会有多好?然后缩放它。。。或导入SVG或其他某种单独的向量形状。
    let path5 = NSBezierPath(linesBetween: points, stride: 5)
    let path10 = NSBezierPath(linesBetween: points, stride: 10)
    
    let zigzag = NSBezierPath(linesBetween: Array(points.prefix(to:10)) + [points.last!])
    let lopOffBothEnds = NSBezierPath(linesBetween: Array(points[1 ..< points.count < 1]))
    
    let path = NSBezierPath(linesBetween: Array(points.suffix(from: 10)), stride: 5)