private void TrackLineNonRecursive(Edge inEdge, double value, int x, int y) { int s = x, t = y; ValuesInCell vc = new ValuesInCell( values[x, y], values[x + 1, y], values[x + 1, y + 1], values[x, y + 1]); IrregularCell rect = new IrregularCell( grid[x, y], grid[x + 1, y], grid[x + 1, y + 1], grid[x, y + 1]); Point point = GetPointXY(inEdge, value, vc, rect); segments.StartLine(point, currentRatio, value); MakeEdgePassed(inEdge, x, y); double x2, y2; do { inEdge = TrackLine(inEdge, value, ref s, ref t, out x2, out y2); } while (s != -1); }
private Edge GetOutForOpposite(Edge inEdge, CellBitmask cellVal, double value, ValuesInCell cellValues, IrregularCell rect) { Edge outEdge; SubCell subCell = GetSubCell(inEdge, value, cellValues); int iters = 1000; // max number of iterations do { ValuesInCell subValues = cellValues.GetSubCell(subCell); IrregularCell subRect = rect.GetSubRect(subCell); outEdge = GetOutEdge(inEdge, subValues, subRect, value); bool isAppropriate = subCell.IsAppropriate(outEdge); if (isAppropriate) { ValuesInCell sValues = subValues.GetSubCell(subCell); Point point = GetPointXY(outEdge, value, subValues, subRect); segments.AddPoint(point); return(outEdge); } else { subCell = GetAdjacentEdge(subCell, outEdge); } byte e = (byte)outEdge; inEdge = (Edge)((e > 2) ? (e >> 2) : (e << 2)); iters--; } while (iters >= 0); throw new IsolineGenerationException(Properties.Resources.IsolinesDataIsUndetailized); }
private Point GetPointXY(Edge edge, double value, ValuesInCell vc, IrregularCell rect) { double lt = vc.LeftTop; double lb = vc.LeftBottom; double rb = vc.RightBottom; double rt = vc.RightTop; switch (edge) { case Edge.Left: return(GetPoint(value, lb, lt, rect.LeftBottom, rect.LeftTop)); case Edge.Top: return(GetPoint(value, lt, rt, rect.LeftTop, rect.RightTop)); case Edge.Right: return(GetPoint(value, rb, rt, rect.RightBottom, rect.RightTop)); case Edge.Bottom: return(GetPoint(value, lb, rb, rect.LeftBottom, rect.RightBottom)); default: throw new InvalidOperationException(); } }
private Edge TrackLine(Edge inEdge, double value, ref int x, ref int y, out double newX, out double newY) { // Getting output edge ValuesInCell vc = new ValuesInCell( values[x, y], values[x + 1, y], values[x + 1, y + 1], values[x, y + 1]); IrregularCell rect = new IrregularCell( grid[x, y], grid[x + 1, y], grid[x + 1, y + 1], grid[x, y + 1]); Edge outEdge = GetOutEdge(inEdge, vc, rect, value); // Drawing new segment Point point = GetPointXY(outEdge, value, vc, rect); newX = point.X; newY = point.Y; segments.AddPoint(point); // Whether out-edge already was passed? if (IsPassed(outEdge, x, y, edges)) // line is closed { MakeEdgePassed(outEdge, x, y); // boundaries should be marked as passed too x = y = -1; return(Edge.Bottom); } // Make this edge passed MakeEdgePassed(outEdge, x, y); // Getting next cell's indices switch (outEdge) { case Edge.Left: x--; return(Edge.Right); case Edge.Top: y++; return(Edge.Bottom); case Edge.Right: x++; return(Edge.Left); case Edge.Bottom: y--; return(Edge.Top); default: throw new InvalidOperationException(); } }
private Edge GetOutEdge(Edge inEdge, ValuesInCell cv, IrregularCell rect, double value) { // value smaller than all values in corners or // value greater than all values in corners if (!cv.ValueBelongTo(value)) { throw new IsolineGenerationException(Properties.Resources.IsolinesValueIsOutOfCell); } CellBitmask cellVal = cv.GetCellValue(value); var dict = dictChooser[(int)inEdge]; if (dict.ContainsKey((int)cellVal)) { return(dict[(int)cellVal]); } else if (cellVal.IsDiagonal()) { return(GetOutForOpposite(inEdge, cellVal, value, cv, rect)); } const double near_zero = 0.0001; const double near_one = 1 - near_zero; double lt = cv.LeftTop; double rt = cv.RightTop; double rb = cv.RightBottom; double lb = cv.LeftBottom; switch (inEdge) { case Edge.Left: if (value == lt) { value = near_one * lt + near_zero * rt; } else if (value == rt) { value = near_one * rt + near_zero * lt; } else { throw new IsolineGenerationException(Properties.Resources.IsolinesUnsupportedCase); } break; case Edge.Top: if (value == rt) { value = near_one * rt + near_zero * lt; } else if (value == lt) { value = near_one * lt + near_zero * rt; } else { throw new IsolineGenerationException(Properties.Resources.IsolinesUnsupportedCase); } break; case Edge.Right: if (value == rb) { value = near_one * rb + near_zero * rt; } else if (value == rt) { value = near_one * rt + near_zero * rb; } else { throw new IsolineGenerationException(Properties.Resources.IsolinesUnsupportedCase); } break; case Edge.Bottom: if (value == rb) { value = near_one * rb + near_zero * lb; } else if (value == lb) { value = near_one * lb + near_zero * rb; } else { throw new IsolineGenerationException(Properties.Resources.IsolinesUnsupportedCase); } break; } return(GetOutEdge(inEdge, cv, rect, value)); }