3

I have to make a SCNCylinder to look like a dynamic pie chart, I am able to make it look like static pie chart by adding texture or applying color to SCNCylinder with below code. However, my pie chart values changes randomly and want to add material with color values occupying percentage portion of the cylinder.

    var planet : SCNGeometry
    planet = SCNCylinder(radius: 0.2, height: 0.05)
    let material = SCNMaterial()
    material.diffuse.contents = UIImage(named: "texture.jpg")
    //OR to apply single color
    material.diffuse.contents = UIColor.red
    planet.materials = [material]
    let planetNode = SCNNode(geometry: planet)
Venkatesh
  • 3,558
  • 8
  • 32
  • 38

1 Answers1

6

You can’t recolor arbitrary parts of SCNCylinder with discrete materials. SceneKit defines only one way to decompose a cylinder into separate portions with separate materials (from the docs):

A cylinder contains three SCNGeometryElement objects: one each for its base and top, and one that wraps around its sides. SceneKit can render each element using a different material. For details, see the materials property in SCNGeometry.

That means you can set your planet.materials to an array of three materials, but SceneKit can only use them to color the top, bottom, and sides separately.


So what recourse do you have if you want to create a pie-chart style appearance? OTOH, I can think of two or three directions to investigate:

Do it with images

You mention you’ve already tried something like this — create a static image that looks like a pie chart and assign it to the (top material?) of the cylinder.

There’s nothing preventing you from extending this technique to non-static pie charts. You’ll just need to create your images dynamically (with CoreGraphics, UIGraphicsImageRenderer, etc).

To get your pie chart looking right in 3D you’ll need to create 3 images — a regular pie chart for the top of the cylinder, a reversed version of the same pie chart for the bottom, and a rectangular image with top-to-bottom blocks of color in the same relative proportions as the pie slices that wraps around the sides. It’ll probably take some experimentation to figure out how to format those three images so they line up right.

Do it with custom geometry

If you want a “fully 3D” pie chart (like the ones you see in Pages, Numbers, and Keynote), where each slice is a separate 3D object that can be pulled away from the pie made taller/shorter than other slices, etc, then SCNCylinder is not for you. It only knows how to draw complete cylinders.

There aren’t any built-in SceneKit classes for creating wedge shapes, but if you can work out the math to construct a mesh yourself, you can use SCNGeometrySource and SCNGeometryElement to construct that mesh in SceneKit.

Do it with SCNShape

Custom geometry might be overkill for this task, though. The kind of shape you’re looking for is one of the simpler kinds of 3D geometry — a 2D shape (a sector of a circle) extruded in a third dimension to create a 3D solid (a wedge of a pie, slice of a cake, or whatever other delicious metaphor you prefer).

In SceneKit, there’s an app for that. (Er, a class.) SCNShape takes a 2D UIBezierPath and extrudes it to create a 3D object. You can even apply nice little rounded edges to it. And UIBezierPath lets you create paths using circle arcs.

So, to build a pie chart:

  1. Create several UIBezierPath objects, one for each slice of pie, using the init(arcCenter:radius:startAngle:endAngle:clockwise:) initializer. Use the same center point for all of them (zero is probably fine).

  2. From each Bézier path, create an SCNShape with your preferred extrusion depth. If you want each slice of your pie to have a different flavor color, assign a different material to each shape.

  3. Assemble the slices into a pie by creating an SCNNode to hold each, and placing those nodes at the same position. (The 2D origin of the arc is respected in the 3D coordinate system, so if you set the same node position for different arcs created with the same center they’ll have the same center in 3D.) If you want to be able to move the whole pie together after that, create another SCNNode and make all of the slices its children.

Dangit, now I’m hungry...

rickster
  • 124,678
  • 26
  • 272
  • 326