ShapeJS Developer Tutorials

Wrap

We often want to make circular things out of flat ones. Otherwise, we might as well stick to traditional printing. ShapeJS provides a built in way to create a cylinder from planar data sources, with a transformation called RingWrap. And what if we could make our own volume patterns? In this tutorial, we will cover the PeriodicWrap and RingWrap transformation.

1. Periodic Wrap

This function essentially lets us create our own volume pattern, although we can constrain it to one or two dimensions if desired. If you don't remember much about them, go ahead and review the Volume Pattern tutorial.

function main(args) {
  var r0 = 1*MM;
  var r1 = 50*MM;
  var bx = 10*MM;
  var s  = 300*MM;

  var bars = new Cylinder(new Vector3d(0, bx, 0), new Vector3d(0, -bx, 0), r0);

  var trans = new CompositeTransform();
  trans.add(new PeriodicWrap(new Vector3d(r0*5,0,0)));
  trans.add(new Translation(new Vector3d(r1,0,0)));
  bars.setTransform(trans);

  return new Scene(bars, new Bounds(-s, s, -s,s,-s,s));
}

When we can create volume patterns of our own this way, it becomes easy to create hollowed out shapes without giving shoppers anything overly familiar. In this case, we only used a one dimensional PeriodicWrap, but you can make it two dimensional:

function main(args) {
  var r0 = 1*MM;
  var r1 = 50*MM;
  var bx = 10*MM;
  var s  = 300*MM;

  var bars = new Cylinder(new Vector3d(0, bx, 0), new Vector3d(0, -bx, 0), r0);

  var trans = new CompositeTransform();
  trans.add(new PeriodicWrap(new Vector3d(r0*5,0,0),new Vector3d(0,r0*5,0)));
  trans.add(new Translation(new Vector3d(r1,0,0)));
  bars.setTransform(trans);

  return new Scene(bars, new Bounds(-s, s, -s,s,-s,s));
}

Or three dimensional:

function main(args) {
  var r0 = 1*MM;
  var r1 = 50*MM;
  var bx = 10*MM;
  var s  = 300*MM;

  var bars = new Cylinder(new Vector3d(0, bx, 0), new Vector3d(0, -bx, 0), r0);

  var trans = new CompositeTransform();
  trans.add(new PeriodicWrap(new Vector3d(r0*5,0,0),new Vector3d(0,r0*5,0)));
  trans.add(new Translation(new Vector3d(r1,0,0)));
  bars.setTransform(trans);

  return new Scene(bars, new Bounds(-s, s, -s,s,-s,s));
}

It is as simple as adding on another vector. That vector defines, essentially, a reflection plane pointed at the origin. but unlike the reflections we learned about earlier, Periodic Wrap will make the data source go out until it hits the bounds in those directions.

2. Ring Wrap

RingWrap allows us to take a data source from the XY plane and wrap it into a cylinder around the Y axis. This transformation can be used for rings, as you might have guessed from the name, but also for vases, bracelets, and even coffee cups if you are feeling nostalgic. But let's work on something simple. Let's look at how to use RingWrap in order to make a simple bracelet that a shopper can resize at will.

PeriodicWrap and RingWrap work very well for creating a consistent look in resizable objects. This will allows us to create a consistent pattern despite how the shopper may decide to resize the bracelet.

function main(args) {
  var comp_rad = 1*MM;
  var brace_rad = 60*MM;
  var height= 6*MM;
  var s  = 65*MM;
  var bx = 7*MM;

  var bars = new Cylinder(new Vector3d(0, height, 0), new Vector3d(0, -height, 0), comp_rad);

  var trans = new CompositeTransform();
  trans.add(new PeriodicWrap(new Vector3d(comp_rad*5,0,0)));
  trans.add(new Translation(new Vector3d(brace_rad,0,0)));
  trans.add(new RingWrap(brace_rad));
  bars.setTransform(trans);

  var top = new Torus(brace_rad, comp_rad);
  var ct = new CompositeTransform();
  ct.add(new Translation(new Vector3d(0,0,bx)));
  ct.add(new Rotation(1,0,0, Math.PI/2));
  top.setTransform(ct);

  var bottom = new Torus(brace_rad, comp_rad);
  var ct2 = new CompositeTransform();
  ct2.add(new Translation(new Vector3d(0,0,-bx)));
  ct2.add(new Rotation(1,0,0, Math.PI/2));
  bottom.setTransform(ct2);

  var shape = new Union();
  shape.add(bars);
  shape.add(top);
  shape.add(bottom);

  return new Scene(shape, new Bounds(-s, s, -s,s,-s,s));
}

When we can create volume patterns of our own this way, it becomes easy to create hollowed out shapes without giving shoppers anything overly familiar. In this case, we only used a one dimensional PeriodicWrap, but you can make it two dimensional: