// TODO: Consider a more sophisticated gradient function, as it recommends in the paper. // But for now, I can't imagine subpixel accuracy is going to make a whole lot of difference. private static vFloat GradientAtPoint(this IField2d <float> field, vFloat point) { int pX = (int)point[0]; int pY = (int)point[1]; float x, y; if (pX % 2 == 1 || pX == field.Width - 1) { x = field[pY, pX - 1] - field[pY, pX]; } else { x = field[pY, pX] - field[pY, pX + 1]; } if (pY % 2 == 1 || pY == field.Height - 1) { y = field[pY - 1, pX] - field[pY, pX]; } else { y = field[pY, pX] - field[pY + 1, pX]; } return(new vFloat(x, y)); }
private List <vFloat> BuildSplinesRecursively(TreeNode <Point2d> node, vFloat parentPoint) { vFloat herePoint = new vFloat( node.value.x + (float)this.random.NextDouble(), // X position in world coordinates node.value.y + (float)this.random.NextDouble(), // Y position in world coordinates this.altitudes[node.value.y, node.value.x], // altitude in whatever units were used by the "altitudes" input node.Size() / CAPACITY_DIVISOR); // river size, meaning the count of pixels above this, divided to avoid affecting the spline if (node.children.Count == 0 || (node.children.Count > 1 && node.Depth() <= minSizeForFork)) { // Idiotic case, tree has only one element and a spline is ridiculous. if (node.parent == null) { throw new ArgumentException("A tree with only one node cannot be made into a spline tree."); } List <vFloat> lst = new List <vFloat>(); lst.Add(2 * herePoint - parentPoint); lst.Add(herePoint); return(lst); } else if (node.children.Count == 1) { // We know there's only one because we just checked; we just use this syntax to get that one out of the children. foreach (var child in node.children) { List <vFloat> lst = BuildSplinesRecursively(child, herePoint); lst.Add(herePoint); return(lst); } throw new InvalidOperationException("A non-empty list behaved as if it was empty. Has a race condition been introduced?"); } else { List <List <vFloat> > lsts = new List <List <vFloat> >(); int minIdx = 0; foreach (var n in node.children) { if (n.Size() < minSizeForFork) { continue; } lsts.Add(BuildSplinesRecursively(n, herePoint)); lsts[lsts.Count - 1].Add(herePoint); if (lsts[lsts.Count - 1].Count < lsts[minIdx].Count) { minIdx = lsts.Count - 1; } } if (parentPoint == null) { parentPoint = GetParentPoint(lsts[minIdx]); } for (int idx = 0; idx < lsts.Count; idx++) { if (idx != minIdx) { lsts[idx].Add(parentPoint); lsts[idx].Add(2 * lsts[idx][lsts[idx].Count - 2] - parentPoint); this.splines.Add(new CenCatRomSpline(lsts[idx].ToArray(), this.alpha)); } } return(lsts[minIdx]); } }