24/7 Customer Service (800) 927-7671

Learn ShapeJS: Symmetry and Reflections Part 1

by • May 4, 2016 • No Comments

For this week we can begin
into the powerful world of symmetry and reflections. ShapeJS allows for arbitrary alterations of objects and as we can see in this post this has excellent power and a few sharp edges to avoid. Guest writing this week is Vladimir Bulatov, he’s the math whiz behind the curtains of ShapeJS.

PeriodicWrap is a ShapeJS alteration which
is most
useful for creating repeated shapes and patterns. But
if utilized
incorrectly it can turn it into unexpected outcomes. The purpose of this guide is to provide basic info and examples with correct use of PeriodicWrap, highlight future problems and suggest possible solutions.

PeriodicWrap generates a fill of the three dimensional space (tiling) with copies of a single tile – the important domain. PeriodicWrap is described by linearly independent basis vectors and an origin. All parameters have type Vector3d. Basis vectors define the shape and orientation of the important domain and the origin defines the place of the important domain in space. There are 3 variants of PeriodicWrap one-, two- and three-periodic. This week we can examine the one periodic edition, and in a later post we can cover the additional rigorous editions.

One-periodic wrap

We begin
with the easyst variant – one-periodic. It is described by one basis vector and origin. The origin has default value (0,0,0) which
means the PeriodicWrap is located at the origin of the coordinate axes.

var a = 5*MM; var pw = new PeriodicWrap(new Vector3d(a,0,0)); 

This produces a one dimensional PeriodicWrap with basis vector (a,0,0).

The one-periodic tiling can be imagined as cutting a space into set of identical slices. The important domain (yellow) is a single slice. Slices are orthogonal to the basis vector (in this case (a,0,0). The thickness of the slice equals the length of the basis vector (5mm in this case) and the left side of the slice passes through the origin of the PeriodicWrap (in this case default value (0,0,0)). Let’s place a easy shape within of the important domain.

 var sphere = new Sphere(a/2,a/2,0, a/3); // sphere radius a/3 centered at (a/2,a/2, 0) 

And apply PeriodicWrap to the shape.

 sphere.setTransform(pw); // tiled sphere 

Here is the diagram of the outcome:

Shapes are replicated in both directions indefinitely. Below is the screenshot of the ShapeJS rendering:

Let’s place a various shape in a various spot

 var redSphere = new Sphere(0,a/3,0,a/2); // sphere radius a/2 centered at (0,a/3,0) 

PeriodicWrap works by filling the whole space by identical copies of single tile – the important domain.The interior of the important domain is replicated. Parts of the shape outside of important domain are cropped. It means, which
the half of sphere sitting outside of important domain abruptly disappears.

The rendering looks actually worse, the cropping induces severe rendering artifacts

There is a easy solution to the problem. We can shift the origin of the tiling to manufacture a shape enclosed by the important domain

 pw.setOrigin(new Vector3d(-a/2,0,0)); 

And here is the tiling

The rendering now looks correct as well

But it is not always possible to elect a great location for the tilings origin. In example at a lower place we have a union of two shapes.

The union does not fit within of important domain. So the shape always can be partially cropped:

The solution to the problem is to turn it into a shape within of the important domain in a way which
can compensate for unavoidable cropping: the opposite sides of important domain have to pair seamlessly to every other. In this case we can place copy of another red sphere translated by the tiling basis vector (a,0,0)

Here are the drawing and rendering of the outcomeing tiling:

Complete ShapeJS script of the example with two shapes:

 function main(args) { var w = 30*MM; // scene dimensions var a = 5*MM; // period of wrap var s1 = new Sphere(a/2, a/2, 0, a/3); // shape 1 var s2 = new Sphere(0, 0.7*a, 0, a/2); // shape 2 var s2t = new Sphere(a, 0.7*a, 0, a/2); // translated shape 2 var pw = new PeriodicWrap(new Vector3d(a,0,0)); var shape = new Union(s1, s2); shape.add(s2t); shape.setTransform(pw); return new Scene(shape,new Bounds(-w,w,-w,w,-w,w)); } 

After a PeriodicWrap alter is applied to a shape within of the important domain we normally receive an unbounded shape. That shape intersects the scene bounds and as outcome has an open interior, which
outcomes in manifold problems in the produced mesh as is shown at a lower place with red.

In order to receive a finite shape of specific dimensions, we may intersect unbounded shape with a few shape of specific dimensions, for example a box:

 shape = new Intersection(shape, new Box(55*MM, 20*MM, 20*MM)); 

PeriodWraps are a powerful method for creating most
copies of your geometry. It is in addition
a much additional efficient way to turn it into lots of shapes instead of copying the datasources. In our upcoming posting on symmetry and reflections we can explore the two and three periodic wrappings. These allow you to turn it into a few informative
patterns, much like
to what you can find in nature. As a taste here are a few two and three periodic wrappings:

Latest posts

by admin • March 5, 2017