internal PAxis(PAxis src, double [] tw) { Base = src.Base; Dir = PGeom.ApplyTwist(tw, src.Dir); Matrix = PGeom.ApplyTwist(tw, src.Matrix); int ntw = src.Twists.Length; Twists = new double[ntw][]; for (int i = 0; i < ntw; i++) { Twists[i] = PGeom.ApplyTwist(tw, src.Twists[i]); } }
internal int BaseSticker(int st, int ax) { int rax = Math.Abs(ax) - 1; PAxis p = Axes[rax]; int lv = ax > 0 ? 0 : p.Layers.Length - 1; int[] L = p.Layers[lv]; for (int i = 0; i < L.Length; i++) { if (L[i] == st) { return(i); } } throw new Exception("Can't find sticker in Layer"); }
void MakeMacroStep(long code, double[,] matr, bool qrev) { int ax, tw, an, ms; UnpackCode(code, out ax, out tw, out an, out ms); PAxis A = Str.Axes[ax]; int ax1 = AxisMap[ax]; if (ax1 == 0) { AxisMap[ax] = ax1 = Str.FindAxis(A.Dir, matr); } if (ax1 < 0) { ms = A.Base.ReverseMask(ms); ax1 = -ax1; } ax1--; PAxis A1 = Str.Axes[ax1]; if (TwistMap[ax] == null) { TwistMap[ax] = new int[A1.Twists.Length]; } int tw1 = TwistMap[ax][tw]; if (tw1 == 0) { bool qrev1; tw1 = A1.FindTwist(A.Twists[tw], matr, out qrev1); tw1 = qrev1 ? -1 - tw1 : 1 + tw1; TwistMap[ax][tw] = tw1; } if (tw1 < 0) { qrev = !qrev; tw1 = -tw1; } tw1--; if (qrev) { an = -an; } TwistNormMask(ax1, tw1, an, ms); }
private void ExpandAxes() { int q = BaseAxes.Length; PAxis[] CAxes = new PAxis[MaxNAxes]; for (int i = 0; i < q; i++) { PBaseAxis ax = BaseAxes[i]; ax.Id = i; ax.ExpandPrimaryTwists(); CAxes[i] = new PAxis(ax); // matrix=id } for (int p = 0; p < q; p++) { double[] R = CAxes[p].Dir; foreach (double [] G in Group) { double[] v = PGeom.ApplyTwist(G, R); int j; bool qr; for (j = 0; j < q; j++) { if (PGeom.AxisEqual(v, CAxes[j].Dir, out qr)) { break; } } if (j == q) { if (q == MaxNAxes) { throw new Exception("Too many axes"); } CAxes[q] = new PAxis(CAxes[p], G); q++; } } } Axes = new PAxis[q]; for (int i = 0; i < q; i++) { Axes[i] = CAxes[i]; Axes[i].Id = i; } }
internal void SetTwist(int axis, int mask, Func <int, bool> F) // for animation { PAxis A = Str.Axes[axis]; mask = A.Base.Remask(mask); // insert or clear zero layer if necessary int k = 0; while (mask != 0) { if ((mask & 1) != 0) { foreach (int s in A.Layers[k]) { F(s); } } mask >>= 1; k++; } }
private unsafe void DoTwist(int axis, int twist, int angle, int mask) { Buffer.BlockCopy(Field, 0, Fld2, 0, NStk * sizeof(short)); PAxis A = Str.Axes[axis]; angle = A.Base.Twists[twist].NormAngle(angle); // symmetric class of remainders if (angle == 0) { return; } int a = Math.Abs(angle); int k = 0; while (mask != 0) { if ((mask & 1) != 0) { int[] stks = A.Layers[k]; int[] map = angle < 0 ? A.Base.Twists[twist].InvMap[k] : A.Base.Twists[twist].Map[k]; int lm = map.Length; if (a == 1) { for (int i = 0; i < lm; i++) { Field[stks[map[i]]] = Fld2[stks[i]]; } } else { for (int i = 0; i < lm; i++) { int x = i; for (int j = 0; j < a; j++) { x = map[x]; } Field[stks[x]] = Fld2[stks[i]]; } } } mask >>= 1; k++; } }
internal int CheckTwist(int ax, int[] stkseq, int lstkseq, short[] fld, out int tw) { for (int i = 0; i < NStickers; i++) { fld[i] &= 0x7fff; } int rax = Math.Abs(ax) - 1; tw = 0; PAxis p = Axes[rax]; int lv = ax > 0 ? 0 : p.Base.NLayers - 1; int[] L = p.Layers[lv], LB = p.Base.Layers[lv]; int ntw = p.Twists.Length; int[] tws = new int[ntw * 2]; int ntws = 0; for (int i = 0; i < ntw; i++) { int[] LT = p.Base.Twists[i].Map[lv]; bool q = true, q1 = true; for (int a = 0; a < lstkseq - 1; a++) { int h = stkseq[a], h1 = stkseq[a + 1]; if (h < 0 || h1 < 0) { continue; } if (LT[h] != h1) { q = false; } if (LT[h1] != h) { q1 = false; } if (!q && !q1) { break; } } if (q) { tws[ntws++] = i + 1; } if (q1) { tws[ntws++] = -i - 1; } } if (ntws == 0) { throw new Exception("No twists for stkseq"); } if (ntws == 1) { tw = ax < 0 ? -tws[0] : tws[0]; return(2); // finita } if (lstkseq != 0) { int a = stkseq[lstkseq - 1]; if (a >= 0) { int nnext = 0; int _b = 0; for (int b = 0; b < ntws; b++) { int t = tws[b]; int b1 = t > 0 ? p.Base.Twists[t - 1].Map[lv][a] : p.Base.Twists[-t - 1].InvMap[lv][a]; b1 = L[b1]; if ((fld[b1] & 0x8000) == 0) { nnext++; fld[b1] |= unchecked ((short)0x8000); _b = b1; } } if (nnext > 1) { return(0); // continue; } fld[_b] &= 0x7fff; } } int nq = 0; for (int a = 0; a < LB.Length; a++) { int _b = -1; bool qc = false; for (int b = 0; b < ntws; b++) { int t = tws[b]; int b1 = t > 0 ? p.Base.Twists[t - 1].Map[lv][a] : p.Base.Twists[-t - 1].InvMap[lv][a]; if (_b < 0) { _b = b1; } else if (_b != b1) { qc = true; break; } } if (qc) { fld[L[a]] |= unchecked ((short)0x8000); nq++; } } if (nq != 0) { return(1); } tw = ax < 0 ? -tws[0] : tws[0]; return(2); }
private void CutFaces() { double RMax = 0; foreach (PBaseFace F in BaseFaces) { RMax = Math.Max(RMax, PGeom.VLength(F.Pole)); } int minrank = int.MaxValue; foreach (PBaseFace F in BaseFaces) { CutNode face = CutNode.GenCube(Dim, RMax * Dim); double[] hpln = CutNetwork.GetPlane(F.Pole, 1); face.Split(1, hpln, false); face = face.ZeroNode; int opgen = 1; foreach (PFace FF in Faces) { if (F.Id != FF.Id) { hpln = CutNetwork.GetPlane(FF.Pole, 1); face.Split(++opgen, hpln, true); if (face.Status != CutNode.STAT_PLUS) { throw new Exception("Empty face: Id=" + F.Id); } } } int nff = face.Children.Length; double[][] ffpol = new double[nff][]; for (int i = 0; i < nff; i++) { ffpol[i] = face.Children[i].Pole; } F.FPoles = ffpol; LMesh m = new LMesh(Dim, true); face.FillLMesh(++opgen, m); m.CloseCtr(); F.FaceMesh = new PMesh(m); F.FaceMesh.FCtr = F.Pole; double[] verts = m.pts; int nverts = m.npts; CutNetwork CN = new CutNetwork(face, Dim, opgen); double[][] fctrs = null; if (QSimplified) { fctrs = CN.GetCtrs(); } F.AxisLayers = new int[Axes.Length]; for (int u = 0; u < Axes.Length; u++) { PAxis Ax = Axes[u]; double[] D = Ax.Dir; double lD = PGeom.Dist2(D, new double[Dim]); double smin = double.MaxValue, smax = double.MinValue; for (int i = 0; i < nverts; i++) { double v = 0; for (int j = 0; j < Dim; j++) { v += D[j] * verts[i * Dim + j]; } if (v < smin) { smin = v; } if (v > smax) { smax = v; } } smin /= lD; smax /= lD; bool cs = false, cc = false; int k = Ax.Base.NLayers - 1; for (int i = 0; i < Ax.Base.Cut.Length; i++) { double p = Ax.Base.Cut[i]; if (p >= smax - 0.0001) { continue; } if (!cs) { k = i; cs = true; } if (p <= smin + 0.0001) { break; } hpln = CutNetwork.GetPlane(Ax.Dir, p); CN.Split(hpln, false); cc = true; } if (cc) { k = -1; } F.AxisLayers[u] = k; } F.SetStickers(m, CN, Axes, fctrs); minrank = Math.Min(minrank, F.MinRank()); } foreach (PBaseFace F in BaseFaces) { F.SubRank(minrank); } }
internal void SetStickers(LMesh M, CutNetwork CN, PAxis[] Axes, double[][] fctrs) { int dim = Pole.Length; NCutAxes = 0; int nax = Axes.Length; for (int i = 0; i < nax; i++) { if (AxisLayers[i] < 0) { NCutAxes++; } } CutAxes = new int[NCutAxes]; int d = 0; int rnk = 0; for (int u = 0; u < nax; u++) { if (AxisLayers[u] < 0) { CutAxes[d++] = u; } else { rnk += Axes[u].Base.GetRank(AxisLayers[u]); } } NStickers = CN.Nodes.Length; StickerMask = new byte[NStickers, NCutAxes]; StickerMesh = new PMesh[NStickers]; int nstk = 0; for (int i = 0; i < NStickers; i++) { PMesh xx = CN.GetPMesh(i); if (fctrs != null) { bool qg = false; foreach (double[] p in fctrs) { if (PGeom.VertEqual(p, xx.Ctr)) { qg = true; break; } } if (!qg) { continue; } } xx.FCtr = Pole; double[] ctr = xx.GetMCtr(); int rnk1 = rnk; for (int j = 0; j < NCutAxes; j++) { PAxis ax = Axes[CutAxes[j]]; double[] h = ax.Dir; double lh = PGeom.DotProd(h, h); double s = 0; for (int k = 0; k < dim; k++) { s += ctr[k] * h[k]; } s /= lh; int lv = ax.Base.NLayers - 1; for (int g = 0; g < lv; g++) { if (s > ax.Base.Cut[g]) { lv = g; break; } } rnk1 += ax.Base.GetRank(lv); StickerMask[nstk, j] = (byte)lv; } xx.Rank = rnk1; StickerMesh[nstk++] = xx; } if (nstk != NStickers) { PMesh[] stkm = new PMesh[nstk]; byte[,] stkmsk = new byte[nstk, NCutAxes]; for (int i = 0; i < nstk; i++) { stkm[i] = StickerMesh[i]; for (int j = 0; j < NCutAxes; j++) { stkmsk[i, j] = StickerMask[i, j]; } } StickerMask = stkmsk; StickerMesh = stkm; NStickers = nstk; } }