76990

SCNShape not drawing with UIBezierPath under certain circumstances

Question:

I believe this may be an iOS bug, and I've reported it to Apple via Bug Report. I'll post it here in case there's some workaround I can use, or explanation of the cause.

I'm wanting to draw the stroke of a UIBezierPath within SceneKit. I'm using the CGPath copyStrokingWithWidth function, and then creating a SCNShape using the given path.

This works fine for lines with 2 points, but on lines with 3 points, the SCNShape doesn't display anything. I've determined that this is only the case when the lineWidth is more than 0.1. With lineWidth set to 0.1, it displays perfectly.

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)

This works fine with:

<ul><li>Just the first 2 points</li> <li>Line width of 0.1</li> <li>A manually-drawn bezier path covering the same area</li> </ul>

Printing the UIBezierPath for line width as 0.1 (does display):

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

With line width as 0.2 (doesn't display):

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

Answer1:

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

You haven’t closed the path. You won’t be able to extrude two line segments that have not been closed... so nothing will appear. Close the path off with the following. This will bring up your geometry in the sceneView.

strokeBezierPath.close()

Edit: Scenekit units are in metres. So to work with a smaller object in front of you. Change your units, and linewidth to the following. This will put the object 1 metre in front... and much smaller so you can see whats going on better.

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)

Recommend

  • Reading raw json data of a table into df table?
  • No such file or directory Command PhaseScriptExecution failed with a nonzero exit code
  • Unable to merge branch in in-house TFS GIT from Visual Studio 2013
  • How to pass DataTable data to a Bootstrap modal
  • Form not displaying in credential provider
  • Change width proportions of two blocks with a slider
  • MongoDB sorting date string (mm/dd/yyyy)
  • OpenMP and nested parallelism
  • How to add a Class Diagram to an ASP.NET Core project in VS 2017?
  • How to get VCAP_SERVICES environment variables WITHOUT binding to an application?
  • If babel converts let and const to var, what's the difference?
  • Elastic Beanstalk not loading assets for Ruby on Rails
  • Google plus signin “immediate_failed” error
  • Mounting a gcePersistentDisk kubernetes volume is very slow
  • Xcode STL C++ Debug compile error
  • Why is my string value accumulating empty spaces when inserting into SQL database?
  • Conditionally modify global variable
  • .net core : incomplete JSON response
  • How to give column names after count and joins?
  • How to create a Flutter plugin that works in another Flutter project?
  • .NET COM assembly interacting with Excel via BackgroundWorker
  • Login View controller before SWRevealViewController
  • Is there a modern ( e.g. CLR ) replacement for bison / yacc?
  • WPF binding to property of all items in a collection
  • How to change the default browser in visual studio code latest released?
  • How to set title name of the pdf. While viewing the Document(New Tab)
  • Reference after posting data from web worker
  • get all files in git diff in intellij
  • Refresh JSF component after custom javascript Ajax call
  • How can i use JQuery fadeTo() in IE 7?
  • Can I read another applications memory?
  • How to restrict use of third party camera app from your app