package Current.basic; /** This class keeps track of slightly finer information * then the HexPosition class. Essentially it keeps track of the change in the * normal in the standard foliation of the unfolding, where the leaves always * go through a vertex. */ public class HolonomyPosition { public int[] p=new int[3]; boolean even; int last; /** Initialize to the origin */ public HolonomyPosition(int first_letter){ p[0]=p[1]=p[2]=0; last=first_letter; even=false; } /** Copy constructor */ public HolonomyPosition(HolonomyPosition hp){ p[0]=hp.p[0]; p[1]=hp.p[1]; p[2]=hp.p[2]; last=hp.last; even=hp.even; } public final boolean equals(HolonomyPosition hp){ return (p[0]==hp.p[0])&&(p[1]==hp.p[1])&&(p[2]==hp.p[2]); } /** return true iff the points represent the same point on the hexagonal * grid */ public final boolean hexEquals(HolonomyPosition hp){ return (p[1]-p[0]==hp.p[1]-hp.p[0])&&(p[2]-p[0]==hp.p[2]-hp.p[0]); } /** Overwrite this holonomy position with data from hp */ public final void set(HolonomyPosition hp){ p[0]=hp.p[0]; p[1]=hp.p[1]; p[2]=hp.p[2]; last=hp.last; even=hp.even; } /** Returns the total associated rotation. * ang is meant to be the angles of a triangle. */ public final double dot(double ang[]){ return p[0]*ang[0]+p[1]*ang[1]+p[2]*ang[2]; } /** Returns the total associated rotation if i is added to the word. * @param ang the angles of a triangle in McB coordinates. */ public final double futureDot(int i, double ang[]){ double ret=p[0]*ang[0]+p[1]*ang[1]+p[2]*ang[2]; if (even()) { if (i==(last+1)%3) ret+=ang[(6-(last+i))%3]; else ret-=ang[(6-(last+i))%3]; } else { if (i==(last+1)%3) ret-=ang[(6-(last+i))%3]; else ret+=ang[(6-(last+i))%3]; } return ret; } /** Return true if the vertex represented is even. *
The vertices of the hexagonal grid can be colored black and * white, so no two adjacent vertices are the same color. * Even vertices are those that are the same color as the origin. */ public final boolean even(){ return even; } public final int direction(){ if (even) return (3+2*last)%6; return 2*last; } /** Move the vertex along the edge marked by i (i=0,1,2)*/ public final void shift(int i){ if (even()) { if (i==(last+1)%3) p[(6-(last+i))%3]++; else p[(6-(last+i))%3]--; } else { if (i==(last+1)%3) p[(6-(last+i))%3]--; else p[(6-(last+i))%3]++; } last=i; even=!even; } /** Compute the path distance to the origin*/ public final int dist(){ int ret=0; if (p[0]>=0) ret+=p[0]; else ret-=p[0]; if (p[1]>=0) ret+=p[1]; else ret-=p[1]; if (p[2]>=0) ret+=p[2]; else ret-=p[2]; return ret; } public final int futureDist(int i){ int ret=0; if (p[0]>=0) ret+=p[0]; else ret-=p[0]; if (p[1]>=0) ret+=p[1]; else ret-=p[1]; if (p[2]>=0) ret+=p[2]; else ret-=p[2]; if (even()) { if (i==(last+1)%3) if (p[(6-(last+i))%3]>=0) ret++; else ret--; else if (p[(6-(last+i))%3]<=0) ret++; else ret--; } else { if (i==(last+1)%3) if (p[(6-(last+i))%3]<=0) ret++; else ret--; else if (p[(6-(last+i))%3]>=0) ret++; else ret--; } return ret; } /** Compute the path distance to the origin*/ public final double scaledDist(Complex z){ double ret=0; if (p[0]>=0) ret+=z.x*p[0]; else ret-=z.x*p[0]; if (p[1]>=0) ret+=z.y*p[1]; else ret-=z.y*p[1]; if (p[2]>=0) ret+=(2-z.x-z.y)*p[2]; else ret-=(2-z.x-z.y)*p[2]; return ret*3/2; } public final double futureScaledDist(Complex z, int i){ double ret=0; if (p[0]>=0) ret+=z.x*p[0]; else ret-=z.x*p[0]; if (p[1]>=0) ret+=z.y*p[1]; else ret-=z.y*p[1]; if (p[2]>=0) ret+=(2-z.x-z.y)*p[2]; else ret-=(2-z.x-z.y)*p[2]; int sign; if (even()) { if (i==(last+1)%3) if (p[(6-(last+i))%3]>=0) sign=1; else sign=-1; else if (p[(6-(last+i))%3]<=0) sign=1; else sign=-1; } else { if (i==(last+1)%3) if (p[(6-(last+i))%3]<=0) sign=1; else sign=-1; else if (p[(6-(last+i))%3]>=0) sign=1; else sign=-1; } switch ((6-(last+i))%3) { case 0: ret+=sign*z.x; break; case 1: ret+=sign*z.y; break; case 2: ret+=sign*(2-z.x-z.y); break; } return ret*3/2; } public String toString(){ return "("+p[0]+", "+p[1]+", "+p[2]+")"; } }