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 static SubCell GetSubCell(Edge inEdge, double value, ValuesInCell vc) { double lb = vc.LeftBottom; double rb = vc.RightBottom; double rt = vc.RightTop; double lt = vc.LeftTop; SubCell res = SubCell.LeftBottom; switch (inEdge) { case Edge.Left: res = (Math.Abs(value - lb) < Math.Abs(value - lt)) ? SubCell.LeftBottom : SubCell.LeftTop; break; case Edge.Top: res = (Math.Abs(value - lt) < Math.Abs(value - rt)) ? SubCell.LeftTop : SubCell.RightTop; break; case Edge.Right: res = (Math.Abs(value - rb) < Math.Abs(value - rt)) ? SubCell.RightBottom : SubCell.RightTop; break; case Edge.Bottom: default: res = (Math.Abs(value - lb) < Math.Abs(value - rb)) ? SubCell.LeftBottom : SubCell.RightBottom; break; } ValuesInCell subValues = vc.GetSubCell(res); bool valueInside = subValues.ValueBelongTo(value); if (!valueInside) { throw new IsolineGenerationException(Strings.Exceptions.IsolinesDataIsUndetailized); } return(res); }
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); if (outEdge == Edge.None) { return(Edge.None); } 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(Strings.Exceptions.IsolinesDataIsUndetailized); }
private void TrackLineNonRecursive(Edge inEdge, double value, int x, int y) { int s = x, t = y; ValuesInCell vc = (missingValue.IsNaN()) ? (new ValuesInCell(values[x, y], values[x + 1, y], values[x + 1, y + 1], values[x, y + 1])) : (new ValuesInCell(values[x, y], values[x + 1, y], values[x + 1, y + 1], values[x, y + 1], missingValue)); 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, (value - minMax.Min) / (minMax.Max - minMax.Min), value); MakeEdgePassed(inEdge, x, y); //processed[x, y] = true; double x2, y2; do { inEdge = TrackLine(inEdge, value, ref s, ref t, out x2, out y2); } while (inEdge != Edge.None); }
private Edge TrackLine(Edge inEdge, double value, ref int x, ref int y, out double newX, out double newY) { // Getting output edge ValuesInCell vc = (missingValue.IsNaN()) ? (new ValuesInCell(values[x, y], values[x + 1, y], values[x + 1, y + 1], values[x, y + 1])) : (new ValuesInCell(values[x, y], values[x + 1, y], values[x + 1, y + 1], values[x, y + 1], missingValue)); 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); if (outEdge == Edge.None) { newX = newY = -1; // Impossible cell indices return(Edge.None); } // Drawing new segment Point point = GetPointXY(outEdge, value, vc, rect); newX = point.X; newY = point.Y; segments.AddPoint(point); processed[x, y] = true; // 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 return(Edge.None); } // 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(Strings.Exceptions.IsolinesValueIsOutOfCell); } CellBitmask cellVal = cv.GetCellValue(value); var dict = dictChooser[(int)inEdge]; if (dict.ContainsKey((int)cellVal)) { Edge result = dict[(int)cellVal]; switch (result) { case Edge.Left: if (cv.LeftTop.IsNaN() || cv.LeftBottom.IsNaN()) { result = Edge.None; } break; case Edge.Right: if (cv.RightTop.IsNaN() || cv.RightBottom.IsNaN()) { result = Edge.None; } break; case Edge.Top: if (cv.RightTop.IsNaN() || cv.LeftTop.IsNaN()) { result = Edge.None; } break; case Edge.Bottom: if (cv.LeftBottom.IsNaN() || cv.RightBottom.IsNaN()) { result = Edge.None; } break; } return(result); } 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 * lb; } else if (value == lb) { value = near_one * lb + near_zero * lt; } else { return(Edge.None); } // Now this is possible because of missing value //throw new IsolineGenerationException(Strings.Exceptions.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 { return(Edge.None); } // Now this is possibe because of missing value //throw new IsolineGenerationException(Strings.Exceptions.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 { return(Edge.None); } // Now this is possibe because of missing value //throw new IsolineGenerationException(Strings.Exceptions.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 { return(Edge.None); } // Now this is possibe because of missing value //throw new IsolineGenerationException(Strings.Exceptions.IsolinesUnsupportedCase); break; } // Recursion? //return GetOutEdge(inEdge, cv, rect, value); return(Edge.None); }