static internal CutNode GenCube(int dim, double V) { int m = 1; for (int i = 0; i < dim; i++) { m *= 3; } CutNode[] u = new CutNode[m]; for (int a = 0; a < m; a++) { int d = 0; for (int b = a; b > 0; b /= 3) { if (b % 3 == 2) { d++; } } if (d == 0) { double[] pt = new double[dim]; int b = a; for (int i = 0; i < dim; i++) { pt[i] = (b % 3 - 0.5) * 2 * V; b /= 3; } u[a] = new PointNode() { Pos = pt, Dim = 0 }; } else { CutNode[] ch = new CutNode[2 * d]; int k = 0; for (int b = 1; b < m; b *= 3) { if ((a / b) % 3 == 2) { ch[k++] = u[a - 2 * b]; ch[k++] = u[a - b]; } } u[a] = new CutNode() { Dim = d, Children = ch }; } } return(u[m - 1]); }
internal virtual CutNode Copy(int opgen) { if (opgen == OpGen) { return(Pair); } OpGen = opgen; CutNode res = new CutNode(); res.Dim = Dim; res.Children = new CutNode[Children.Length]; for (int i = 0; i < Children.Length; i++) { res.Children[i] = Children[i].Copy(opgen); } Pair = res; return(res); }
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 CutNetwork(CutNode x, int dim, int opgen) { Nodes = new CutNode[] { x }; Dim = dim; OpGen = opgen; }
internal virtual void Split(int opgen, double[] hpln, bool qpos) { if (opgen == OpGen) { return; } OpGen = opgen; ZeroNode = Pair = null; int nplus = 0, nminus = 0; foreach (CutNode D in Children) { D.Split(opgen, hpln, qpos); if (D.IsDivided) { nminus++; } switch (D.Status) { case STAT_MINUS: nminus++; break; case STAT_PLUS: nplus++; break; case STAT_ZERO: ZeroNode = D; break; } } if (nplus == 0) { Status = nminus != 0 ? STAT_MINUS : STAT_ZERO; // PrintLevel(); return; } if (nminus == 0) { Status = STAT_PLUS; // PrintLevel(); return; } CutNode[] chp = new CutNode[nplus + 1]; CutNode[] chm = new CutNode[nminus + 1]; if (ZeroNode == null) { if (Dim == 1) { if (nplus != 1 || nminus != 1) { throw new Exception("Wrong length of edge"); } PointNode p0 = (PointNode)Children[0]; PointNode p1 = (PointNode)Children[1]; double p = p1.Val / (p1.Val - p0.Val); int n = p0.Pos.Length; double[] cc = new double[n]; for (int i = 0; i < n; i++) { cc[i] = p0.Pos[i] * p + p1.Pos[i] * (1 - p); } PointNode z = new PointNode(); z.Pos = cc; z.Val = 0; ZeroNode = z; } else { ArrayList arr = new ArrayList(); foreach (CutNode D in Children) { if (D.Status == STAT_PLUS && D.HaveZero) { arr.Add(D.ZeroNode); } } if (Dim == 2 && arr.Count != 2) { throw new Exception("Wrong number of segment ends"); } ZeroNode = new CutNode(); ZeroNode.Children = (CutNode[])arr.ToArray(typeof(CutNode)); } ZeroNode.Dim = Dim - 1; ZeroNode.Status = STAT_ZERO; ZeroNode.BrdDim = BrdDim; ZeroNode.Pole = IntPole(Pole, hpln); ZeroNode.OpGen = opgen; // if(Dim>1) ZeroNode.PrintLevel(); } chp[0] = chm[0] = ZeroNode; int np = 1, nm = 1; foreach (CutNode D in Children) { if (D.IsDivided) { chm[nm++] = D.Pair; } if (D.Status == STAT_PLUS) { chp[np++] = D; } else if (D.Status == STAT_MINUS) { chm[nm++] = D; } } if (np != nplus + 1 || nm != nminus + 1) { throw new Exception("Wrong length of children"); } Pair = new CutNode(); Pair.Dim = Dim; Pair.Children = chm; Pair.Status = STAT_MINUS; Pair.ZeroNode = ZeroNode; Pair.BrdDim = BrdDim; Pair.OpGen = opgen; Children = chp; Status = STAT_PLUS; // PrintLevel(); }