Note: The tutorials next week will meet in the PORTAL (Second floor, same end of the building as BMS). We will have a demo of the facilities there, including the 3D printing and scanning area.
Assignments. The continuation of Assignment 4 is described in the previous post. It’s due this Friday Dec. 6. Assignment 5 — creation of a Christmas calendar image — is also described there. It’s due on Dec. 13. December 9: See this update.
03.12.13: Mr. Gunn continued the guided tour of the planar symmetry groups by considering symmetry groups of the plane with 2 independent translations: the wallpaper groups. In contrast to the frieze groups, they can have rotational symmetries of order greater than 2.
Wallpaper group application. You can run a jReality wallpaper group application from your eclipse project by navigating in the Package Explorer to “Referenced Libraries->discretegroupCGG.jar->discreteGroup.wallpaper.WallpaperPluggedIn.class” and then using right-mouse click to choose “Run as … Java application”. (Here is a Java webstart of the same application. But be careful — if you run it under Java 7, which is sometimes difficult to avoid with webstarts, make sure the left hand panel is hidden or it runs v e r y slowly.) This application allows you to experiment with all 17 wallpaper groups — see the “Wallpaper” menu and the left inspection panel. Here’s a picture generated the group 244 with the automatic painting option (choose “Wallpaper->run” option):
Wallpaper group resource: The following chart contains a list of all 17 wallpaper groups including the standard fundamental domains and the generators used in the discretegroup WallpaperGroup class.
More group theory. To obtain a good answer for Assignment 4 it’s useful to understand a bit more about the internal structure of the frieze groups. It turns out the the translation subgroup plans an important role. To understand this, we need to introduce some notation.
Definition: A subgroup $H$ of a group $G$ is normal if $gHg^{-1} = H \forall g \in G$. We write $H \trianglelefteq G$.
Theorem: The translation subgroup $T$ of a euclidean group $G$ is a normal subgroup.
Proof: A general isometry $g$ can be written as $g(\mathbf{X}) = A.\mathbf{x} + T$ where $A \in O(n)$ is an orthogonal transformation and $T \in \mathbb{R}^n$ is the vector of the translation. Then $g^{-1} = A^{-1}.\mathbf{x} + A^{-1}.T$ and writing out the composition $gSg^{-1}$ where $S$ is the translation $\mathbf{x} \rightarrow \mathbf{x} + S$ yields the result $gSg^{-1}(\mathbf{x})= \mathbf{x} + A^{-1}.S$, which is clearly a translation. \qed
Cosets. A subgroup $H \trianglelefteq G$ determines an equivalence relation on the group $G$ as follows: Define $\mathbf{x} \sim \mathbf{y} \iff x^{-1}y \in H$. We leave it to the reader to verify that this is an equivalence relation. Hence, it partitions $G$ into equivalence classes of elements. Each equivalence class is called a left coset of $G$ with respect to $H$. A similar definition involving $xy^{-1}$ yields the right cosets. The coset containing $id$ is clearly $H$ itself. [Exercise: when $H$ is normal, the left cosets and the right cosets coincide.] The coset containing $\mathbf{x} \in G$ is written $[\mathbf{x}]$. [Exercise: Every element of $[\mathbf{x}]$ can be uniquely written as $\mathbf{x}\mathbf{h}_x$ for some $h_x \in H$.] Let us choose a set of representative ${\mathbf{a}_i}$ for the cosets. Then $\mathbf{x} \in [\mathbf{a}_i]$ can be written as $\mathbf{x} = \mathbf{a}_i \mathbf{h}_x$ for some $\mathbf{h}_x \in H$.
The quotient group. The cosets of a normal subgroup have an induced group structure. Indeed, let $[\mathbf{x}]$ and $[\mathbf{y}]$ be two cosets. Then define a product on cosets by $[x][y] = [xy]$. Using our canonical representatives we can write the RHS as $[(\mathbf{a}_i \mathbf{h}_x) (\mathbf{a}_j \mathbf{h}_y)]$. Now since right and left cosets are the same, there exists $\mathbf{h}^{‘}_x \in H$ such that $\mathbf{h}_x \mathbf{a}_j = \mathbf{a}_j \mathbf{h}^{‘}_x$. Then moving parentheses $[\mathbf{a}_i (\mathbf{h}_x \mathbf{a}_j) \mathbf{h}_y] = [\mathbf{a}_i \mathbf{a}_j \mathbf{h}^{‘}_x \mathbf{h}_y] = [ \mathbf{a}_i \mathbf{a}_j]$ so the result is clearly independent of the choice of $\mathbf{x}$ and $\mathbf{y}$.
We write $G/H$ and call it the quotient group of $G$ by $H$.
Connection to Assignment 4. At the conclusion of thursday’s lecture, Mr. Gunn showed how these ideas could be applied to Assignment 4 to generate the desired list of elements of the freize groups. Here’s what the resulting code for updateCopies() looks like:
Matrix[] cosets = null;
Matrix generatingTranslation = null;
int numCosets = 0;
switch(whichGroup) {
case 0:
numCosets = 1;
cosets = new Matrix[1];
cosets[0] = new Matrix();
generatingTranslation = MatrixBuilder.euclidean().translate(1, 0, 0).getMatrix();
break;
case 1:
numCosets = 2;
cosets = new Matrix[numCosets];
cosets[0] = new Matrix(); // identity
cosets[1] = MatrixBuilder.euclidean().reflect(new double[]{1,0,0,0}).getMatrix();
generatingTranslation = MatrixBuilder.euclidean().translate(2, 0, 0).getMatrix();
break;
// implement this group (* infinity infinity ) here as above in case 0
// there are two vertical mirrors a distance 1 apart.
case 3:
generatingTranslation = MatrixBuilder.euclidean().reflect(new double[]{0,1,0,0}).translate(1,0,0).getMatrix();
numCosets = 1;
cosets = new Matrix[1];
cosets[0] = new Matrix();
break;
case 6:
// implement this group (* 2 2 infinity) here as above in case 0
// there are two vertical mirrors a distance 1 apart and a horizontal mirror in the line y = 0.
generatingTranslation = MatrixBuilder.euclidean().translate(2,0,0).getMatrix();
numCosets = 4;
cosets = new Matrix[4];
cosets[0] = new Matrix();
cosets[1] = MatrixBuilder.euclidean().reflect(new double[]{1,0,0,0}).getMatrix();
cosets[2] = MatrixBuilder.euclidean().reflect(new double[]{0,1,0,0}).getMatrix();
cosets[3] = MatrixBuilder.euclidean().rotateZ(Math.PI).getMatrix();
break;
.... // other cases not included here
}
int outerLoopCount = count/numCosets, counter = 0;
// run through the powers of the generating translation ...
for (int j = 0; j <= outerLoopCount; ++j) {
Matrix powerOfTranslation = Matrix.power(generatingTranslation, (j - outerLoopCount/2));
// and multiply it on the right by each of the coset representatives
for (int k = 0; k<numCosets; ++k) { // skip over non-existing scene graph components at end if (counter >= count) continue;
SceneGraphComponent child = translationListSGC.getChildComponent(counter++);
Matrix tmp = new Matrix(cosets[k].getArray().clone());
tmp.multiplyOnLeft(powerOfTranslation);
tmp.assignTo(child);
}
}
}
Pingback: Course Log | Mathematical Visualization