public static void Rect(int x0, int y0, int x1, int y1, bool isFilled, PlotFunction plot) { if (x0 > x1) { Swap <int>(ref x0, ref x1); } if (y0 > y1) { Swap <int>(ref y0, ref y1); } if (isFilled) { for (int y = y0; y <= y1; ++y) { for (int x = x0; x <= x1; plot(x, y), ++x) { ; } } } else { for (int y = y0; y <= y1; ++y) { plot(x0, y); plot(x1, y); } for (int x = x0; x <= x1; ++x) { plot(x, y0); plot(x, y1); } } }
//ref: http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm public static void Line(int x0, int y0, int x1, int y1, PlotFunction plot) { bool steep = Mathf.Abs(y1 - y0) > Mathf.Abs(x1 - x0); if (steep) { Swap <int>(ref x0, ref y0); Swap <int>(ref x1, ref y1); } if (x0 > x1) { Swap <int>(ref x0, ref x1); Swap <int>(ref y0, ref y1); } int dX = (x1 - x0), dY = Mathf.Abs(y1 - y0), err = (dX / 2), ystep = (y0 < y1 ? 1 : -1), y = y0; for (int x = x0; x <= x1; ++x) { if (!(steep ? plot(y, x) : plot(x, y))) { return; } err = err - dY; if (err < 0) { y += ystep; err += dX; } } }
/// <summary> /// Plot the line from (x0, y0) to (x1, y1) by using the Bresenham algorithm. /// See http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm for details. /// </summary> /// <param name="x0">The start x</param> /// <param name="y0">The start y</param> /// <param name="x1">The end x</param> /// <param name="y1">The end y</param> /// <param name="plot">The plotting function (if this returns false, the algorithm stops early)</param> public static void Bresenham(float x0, float y0, float x1, float y1, PlotFunction plot) { Bresenham( MathUtils.FloorToInt(x0), MathUtils.FloorToInt(y0), MathUtils.FloorToInt(x1), MathUtils.FloorToInt(y1), plot); }
protected static void AddPlotFunctionLists( List <List <double> > dataList, List <double> abscissae, PlotFunction function ) { List <double> fieldValues = GetPlotFunctionValueList(abscissae, function); dataList.Add(fieldValues); }
// Detect whether x1 > x0 or y1 > y0 and reverse the input coordinates, if needed, before drawing public static void Plot(Point pt1, Point pt2, PlotFunction plotFunction) { if (Math.Abs(pt2.Y - pt1.Y) < Math.Abs(pt2.X - pt1.X)) { PlotLowSlope(pt1, pt2, plotFunction); } else { PlotHighSlope(pt1, pt2, plotFunction); } }
public void UpdateFuncInfo(PlotFunction func) { if (func == null) { InfoText = ""; } else { InfoText = $" | {func.GetType().ToString()}: A: {func.A:0.####} C: {func.C:0.####} K: {func.K:0.####} D: {func.D:0.####} Start: {func.Start:0.####} End: {func.End:0.####}"; } }
public static List <Vector2i> GetPointsOnSegment(Vector2i start, Vector2i end) { bool flag; Class236 class2 = new Class236 { list_0 = new List <Vector2i>() }; PlotFunction function = new PlotFunction(class2.method_0); int x = start.X; int y = start.Y; int num3 = end.X; int num4 = end.Y; if (flag = Math.Abs((int)(num4 - y)) > Math.Abs((int)(num3 - x))) { smethod_0 <int>(ref x, ref y); smethod_0 <int>(ref num3, ref num4); } if (x > num3) { smethod_0 <int>(ref x, ref num3); smethod_0 <int>(ref y, ref num4); } int num5 = num3 - x; int num6 = Math.Abs((int)(num4 - y)); int num7 = num5 / 2; int num8 = (y < num4) ? 1 : -1; int num9 = y; for (int i = x; i <= num3; i++) { if (!(flag ? function(num9, i) : function(i, num9))) { return(class2.list_0); } num7 -= num6; if (num7 < 0) { num9 += num8; num7 += num5; } } Vector2i vectori = class2.list_0[0]; vectori = class2.list_0[class2.list_0.Count - 1]; int introduced14 = vectori.Distance(start); if (introduced14 > vectori.Distance(start)) { class2.list_0.Reverse(); } return(class2.list_0); }
protected static List <double> GetPlotFunctionValueList( List <double> abscissae, PlotFunction function ) { List <double> functionValues = new List <double>(); foreach (double value in abscissae) { functionValues.Add(function(value)); } return(functionValues); }
/// <summary> /// Plot the line from (x0, y0) to (x1, y10 /// </summary> /// <param name="x0">The start x</param> /// <param name="y0">The start y</param> /// <param name="x1">The end x</param> /// <param name="y1">The end y</param> /// <param name="plot">The plotting function (if this returns false, the algorithm stops early)</param> public static void Line(int x0, int y0, int x1, int y1, PlotFunction plot) { bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); if (steep) { Swap(ref x0, ref y0); Swap(ref x1, ref y1); } if (x0 > x1) { Swap(ref x0, ref x1); Swap(ref y0, ref y1); } int dX = (x1 - x0), dY = Math.Abs(y1 - y0), err = (dX / 2), ystep = (y0 < y1 ? 1 : -1), y = y0; for (int x = x0; x <= x1; ++x) { if (!(steep ? plot(y, x) : plot(x, y))) return; err = err - dY; if (err < 0) { y += ystep; err += dX; } } }
public double GetNeightbourAveragePixelColor(Bitmap image, System.Drawing.Point current, int lineScanRadius, double R) { if (current.X < 0 || current.Y < 0) { return(-1); } if (current.X >= image.Width || current.Y >= image.Height) { return(-1); } double average = 0; System.Drawing.Point p_start, p_end; p_start = new System.Drawing.Point((int)(current.X + Math.Sqrt(lineScanRadius * lineScanRadius / (1 + 1 / R * R))), (int)(current.Y + (-1 / R) * Math.Sqrt(lineScanRadius * lineScanRadius / (1 + 1 / (R * R))))); p_end = new System.Drawing.Point((int)(current.X - Math.Sqrt(lineScanRadius * lineScanRadius / (1 + 1 / R * R))), (int)(current.Y - (-1 / R) * Math.Sqrt(lineScanRadius * lineScanRadius / (1 + 1 / (R * R))))); PlotFunction plot = AddPerpPoint; current_perp_points = new List <System.Drawing.Point>(); Line((int)p_start.X, (int)p_start.Y, (int)p_end.X, (int)p_end.Y, plot); Color c; int count = 0; foreach (System.Drawing.Point current_point in current_perp_points) { if (current_point.X < 0 || current_point.Y < 0) { continue; } if (current_point.X >= image.Width || current_point.Y >= image.Height) { continue; } c = image.GetPixel(current_point.X, current_point.Y); average += Math.Abs(c.R - 255); count++; } return(average); }
protected static void AddSurfacePlotFunctionLists( List <List <double> > dataList, List <double> abscissaeX, List <double> abscissaeY, SurfacePlotFunction function ) { foreach (double valueX in abscissaeX) { PlotFunction functionY = valueY => function(valueX, valueY); List <double> fieldValues = GetPlotFunctionValueList(abscissaeY, functionY); fieldValues.Insert(0, valueX); dataList.Add(fieldValues); } dataList.Insert(0, abscissaeY); dataList[0].Insert(0, double.NaN); }
private List <List <double> > CreateEnergiesFromQQDataFileContinuousDataList() { List <List <double> > dataList = new List <List <double> >(); List <double> temperatureValues = GetLinearAbscissaList(0, 800, 800); dataList.Add(temperatureValues); QQDataProvider provider = CreateQQDataProvider(); foreach (BottomiumState state in BottomiumStates) { DecayWidthAverager averager = provider.CreateDecayWidthAverager(state); PlotFunction energyFunction = temperature => averager.GetEnergy(temperature); AddPlotFunctionLists(dataList, temperatureValues, energyFunction); } return(dataList); }
private List <List <double> > CreatePointChargeFieldRadialDistanceDataList( EMFComponent component ) { List <List <double> > dataList = new List <List <double> >(); List <double> radialDistanceValues = GetLogarithmicAbscissaList(0.1, 100, Samples); dataList.Add(radialDistanceValues); foreach (EMFCalculationMethod method in Enum.GetValues(typeof(EMFCalculationMethod))) { PointChargeElectromagneticField emf = PointChargeElectromagneticField.Create( method, ParticleRapidity); PlotFunction fieldValue = radius => EMFNormalization * emf.CalculateElectromagneticField(component, FixedTime, radius, QGPConductivity_MeV); AddPlotFunctionLists(dataList, radialDistanceValues, fieldValue); } return(dataList); }
public static void InfiniteLine(float x0, float y0, float x1, float y1, float diagonal, PlotFunction plot) { float dx = x1 - x0; float dy = y1 - y0; float mx = (x1 + x0) / 2; float my = (y1 + y0) / 2; float l = (float)Math.Sqrt(dx * dx + dy * dy); dx /= l; dy /= l; x0 = mx + dx * diagonal; y0 = my + dy * diagonal; x1 = mx - dx * diagonal; y1 = my - dy * diagonal; Line((int)(x0 + 0.5f), (int)(y0 + 0.5f), (int)(x1 + 0.5f), (int)(y1 + 0.5f), plot); }
/// <summary> /// Plot the line from the specified start to the specified end location by using the Bresenham algorithm. /// See http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm for details. /// </summary> /// <param name="start">The start location.</param> /// <param name="end">The end location.</param> /// <param name="plot">The plotting function (if this returns false, the algorithm stops early)</param> public static void Bresenham(Vector2I start, Vector2I end, PlotFunction plot) { Bresenham(start.X, start.Y, end.X, end.Y, plot); }
public void AddFunction(PlotFunction function) { Functions.Add(function); mCanvas.Children.Add(function.PlotPath); mCanvas.InvalidateVisual(); }
public void Deselect() { selected?.SetSelected(false); selected = null; window.UpdateFuncInfo(selected); }
//ref: https://github.com/Skiles/aseprite/blob/a5056e15512b219d7dbbb902feb89362e614891e/src/raster/algo.cpp //NOTE: this is not working for cases where x1 x2 y1 or y2 are negative or x1 > x2 or y1 > y2 public static void Ellipse(int x1, int y1, int x2, int y2, bool isFilled, PlotFunction plot) { int mx, my, rx, ry; int err; int xx, yy; int xa, ya; int x, y; int mx2, my2; mx = (x1 + x2) / 2; mx2 = (x1 + x2 + 1) / 2; my = (y1 + y2) / 2; my2 = (y1 + y2 + 1) / 2; rx = Mathf.Abs(x1 - x2); ry = Mathf.Abs(y1 - y2); if (isFilled) { int xmin = Mathf.Min(x1, x2); int xmax = Mathf.Max(x1, x2); int ymin = Mathf.Min(y1, y2); int ymax = Mathf.Max(y1, y2); if (rx == 1) { for (int c = ymin; c <= ymax; ++c) { plot(x2, c); } rx--; } if (rx == 0) { for (int c = ymin; c <= ymax; ++c) { plot(x1, c); } return; } if (ry == 1) { for (int c = xmin; c <= xmax; ++c) { plot(c, y2); } ry--; } if (ry == 0) { for (int c = xmin; c <= xmax; ++c) { plot(c, y1); } return; } } else { if (rx == 1) { Line(x2, y1, x2, y2, plot); rx--; } if (rx == 0) { Line(x1, y1, x1, y2, plot); return; } if (ry == 1) { Line(x1, y2, x2, y2, plot); ry--; } if (ry == 0) { Line(x1, y1, x2, y1, plot); return; } } rx /= 2; ry /= 2; /* Draw the 4 poles. */ plot(mx, my2 + ry); plot(mx, my - ry); if (isFilled) { for (int c = mx - rx; c <= mx2 + rx; ++c) { plot(c, my); } } else { plot(mx2 + rx, my); plot(mx - rx, my); } /* For even diameter axis, double the poles. */ if (mx != mx2) { plot(mx2, my2 + ry); plot(mx2, my - ry); } if (my != my2) { if (isFilled) { for (int c = mx - rx; c <= mx2 + rx; ++c) { plot(c, my2); } } else { plot(mx2 + rx, my2); plot(mx - rx, my2); } } xx = rx * rx; yy = ry * ry; /* Do the 'x direction' part of the arc. */ x = 0; y = ry; xa = 0; ya = xx * 2 * ry; err = xx / 4 - xx * ry; for (; ;) { err += xa + yy; if (err >= 0) { ya -= xx * 2; err -= ya; y--; } xa += yy * 2; x++; if (xa >= ya) { break; } if (isFilled) { for (int c = mx - x; c <= mx2 + x; ++c) { plot(c, my - y); } for (int c = mx - x; c <= mx2 + x; ++c) { plot(c, my2 + y); } } else { plot(mx2 + x, my - y); plot(mx - x, my - y); plot(mx2 + x, my2 + y); plot(mx - x, my2 + y); } } /* Fill in missing pixels for very thin ellipses. (This is caused because * we always take 1-pixel steps above, and thus might jump past the actual * ellipse line.) */ if (y == 0) { while (x < rx) { if (isFilled) { for (int c = mx - x; c <= mx2 + x; ++c) { plot(c, my - 1); } for (int c = mx - x; c <= mx2 + x; ++c) { plot(c, my2 + 1); } } else { plot(mx2 + x, my - 1); plot(mx2 + x, my2 + 1); plot(mx - x, my - 1); plot(mx - x, my2 + 1); } x++; } } /* Do the 'y direction' part of the arc. */ x = rx; y = 0; xa = yy * 2 * rx; ya = 0; err = yy / 4 - yy * rx; for (; ;) { err += ya + xx; if (err >= 0) { xa -= yy * 2; err -= xa; x--; } ya += xx * 2; y++; if (ya > xa) { break; } if (isFilled) { for (int c = mx - x; c <= mx2 + x; ++c) { plot(c, my - y); } for (int c = mx - x; c <= mx2 + x; ++c) { plot(c, my2 + y); } } else { plot(mx2 + x, my - y); plot(mx - x, my - y); plot(mx2 + x, my2 + y); plot(mx - x, my2 + y); } } /* See comment above. */ if (x == 0) { while (y < ry) { if (isFilled) { for (int c = mx - 1; c <= mx2 + 1; ++c) { plot(c, my - y); } for (int c = mx - 1; c <= mx2 + 1; ++c) { plot(c, my2 + y); } } else { plot(mx - 1, my - y); plot(mx2 + 1, my - y); plot(mx - 1, my2 + y); plot(mx2 + 1, my2 + y); } y++; } } }
/// <summary> /// Plot the line from (x0, y0) to (x1, y1) /// </summary> /// <param name="x0">The start x</param> /// <param name="y0">The start y</param> /// <param name="x1">The end x</param> /// <param name="y1">The end y</param> /// <param name="plot">The plotting function (if this returns false, the algorithm stops early)</param> private static void Line(int x0, int y0, int x1, int y1, PlotFunction plot) { int w = x1 - x0; int h = y1 - y0; int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0; if (w < 0) { dx1 = -1; } else if (w > 0) { dx1 = 1; } if (h < 0) { dy1 = -1; } else if (h > 0) { dy1 = 1; } if (w < 0) { dx2 = -1; } else if (w > 0) { dx2 = 1; } int longest = Mathf.Abs(w); int shortest = Mathf.Abs(h); if (!(longest > shortest)) { longest = Mathf.Abs(h); shortest = Mathf.Abs(w); if (h < 0) { dy2 = -1; } else if (h > 0) { dy2 = 1; } dx2 = 0; } int numerator = longest >> 1; for (int i = 0; i <= longest; i++) { if (plot(x0, y0) == false) { return; } numerator += shortest; if (!(numerator < longest)) { numerator -= longest; x0 += dx1; y0 += dy1; } else { x0 += dx2; y0 += dy2; } } }
public void DeleteSelected() { mCanvas.Children.Remove(selected.PlotPath); Functions.Remove(selected); selected = null; }
public static void DrawLine(float x0, float y0, float x1, float y1, bool aliasEndPoint, PlotFunction plot) { bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); if (steep) { // swap(x0, y0); float temp = x0; x0 = y0; y0 = temp; // swap(x1, y1); temp = x1; x1 = y1; y1 = temp; } if (x0 > x1) { // swap(x0, x1); float temp = x0; x0 = x1; x1 = temp; // swap(y0, y1); temp = y0; y0 = y1; y1 = temp; } float dx = x1 - x0; float dy = y1 - y0; float gradient = (dx == 0.0f) ? 1.0f : dy / dx; // handle first endpoint int xend = Round(x0); int yend = (int)(y0 + gradient * (xend - x0)); float xgap = RFractionOf(x0 + 0.5f); int xpxl1 = xend; // this will be used in the main loop int ypxl1 = IntegerOf(yend); if (steep) { plot(ypxl1, xpxl1, RFractionOf(yend) * xgap); plot(ypxl1 + 1, xpxl1, FractionOf(yend) * xgap); } else { plot(xpxl1, ypxl1, RFractionOf(yend) * xgap); plot(xpxl1, ypxl1 + 1, FractionOf(yend) * xgap); } float intery = yend + gradient; // first y-intersection for the main loop // handle second endpoint xend = Round(x1); yend = (int)(y1 + gradient * (xend - x1)); xgap = FractionOf(x1 + 0.5f); int xpxl2 = xend; //this will be used in the main loop int ypxl2 = IntegerOf(yend); if (steep) { plot(ypxl2, xpxl2, RFractionOf(yend) * xgap); if (aliasEndPoint) { plot(ypxl2 + 1, xpxl2, FractionOf(yend) * xgap); } } else { plot(xpxl2, ypxl2, RFractionOf(yend) * xgap); if (aliasEndPoint) { plot(xpxl2, ypxl2 + 1, FractionOf(yend) * xgap); } } // main loop if (steep) { for (int x = xpxl1 + 1; x < xpxl2; ++x) { plot(IntegerOf(intery), x, RFractionOf(intery)); plot(IntegerOf(intery) + 1, x, FractionOf(intery)); intery = intery + gradient; } } else { for (int x = xpxl1 + 1; x < xpxl2; ++x) { plot(x, IntegerOf(intery), RFractionOf(intery)); plot(x, IntegerOf(intery) + 1, FractionOf(intery)); intery = intery + gradient; } } }
public TrajectorySet CalculateDiscontinuityPoints(TrajectorySet ts, int lineScanThreshold, int lineScanRadius, int radialThreshold, Boolean geometrical) { //foreach hough line foreach (HoughLine line in ts.lines) { int r = line.Radius; double t = line.Theta; // check if line is in lower part of the image if (r < 0) { t += 180; r = -r; } // convert degrees to radians t = (t / 180) * Math.PI; // get image centers (all coordinate are measured relative // to center) int w2 = ts.image.Width / 2; int h2 = ts.image.Height / 2; double x0 = 0, x1 = 0, y0 = 0, y1 = 0; if (line.Theta != 0) { // none vertical line x0 = -w2; // most left point x1 = w2; // most right point // calculate corresponding y values y0 = (-Math.Cos(t) * x0 + r) / Math.Sin(t); y1 = (-Math.Cos(t) * x1 + r) / Math.Sin(t); } else { // vertical line x0 = line.Radius; x1 = line.Radius; y0 = h2; y1 = -h2; } int X0, Y0, X1, Y1; X0 = (int)x0 + w2; Y0 = h2 - (int)y0; X1 = (int)x1 + w2; Y1 = h2 - (int)y1; PlotFunction plot = AddPlotPoint; Line((int)X0, (int)Y0, (int)X1, (int)Y1, plot); double R = -((double)Y1 - (double)Y0) / ((double)X1 - (double)X0); ts.bresenhamsLines.Add(current_line_points); List <System.Drawing.Point> black_points = new List <System.Drawing.Point>(); int end_segments = 10; Boolean start_segment = false; BlackSegment current_segment = new BlackSegment(); int segment_tollerance = 10; foreach (System.Drawing.Point current in current_line_points) { //get pixel neighbours average colour double average; if (geometrical) { average = GetNeightbourAveragePixelColor(ts.elaborated_image, current, lineScanRadius); } else { average = GetNeightbourAveragePixelColor(ts.elaborated_image, current, lineScanRadius, R); } if (average > lineScanThreshold) { if (!start_segment) { current_segment.start = current; start_segment = true; } black_points.Add(current); } else { if (start_segment) { segment_tollerance--; if (segment_tollerance <= 0) { current_segment.end = current; start_segment = false; ts.black_segments.Add(current_segment); current_segment = new BlackSegment(); segment_tollerance = 10; } } } } current_line_points = new List <System.Drawing.Point>(); ts.black_points = new List <System.Drawing.Point>(black_points); //foreach segment check the size and get the central pixel foreach (BlackSegment current in ts.black_segments) { if (geometrical) { /* Algoritmo basato su punto medio dei segmenti * restituisce alcuni falsi positivi a causa dell'imprecisione introdotta dal calcolo della media dei punti * inoltre non restituisce i punti esatti intermedi della discontinuità.*/ int len = SunoLogic.distanceBetween2Points(current.start, current.end); int mid_len = len / 2; Boolean start = false; foreach (System.Drawing.Point current_point in ts.black_points) { if (current_point.X == current.start.X && current_point.Y == current.start.Y) { start = true; } if (start) { mid_len--; if (mid_len <= 0) { ts.trajectory_points.Add(current_point); start = false; break; } } } } else { List <System.Drawing.Point> start_neightbour = new List <System.Drawing.Point>(); List <System.Drawing.Point> end_neightbour = new List <System.Drawing.Point>(); foreach (IntPoint current_corner in ts.corners) { System.Drawing.Point current_corner_point = new System.Drawing.Point(current_corner.X, current_corner.Y); //check start points int distance_from_start = SunoLogic.distanceBetween2Points(current_corner_point, current.start); if (distance_from_start - radialThreshold <= 0) { start_neightbour.Add(current_corner_point); } int distance_from_end = SunoLogic.distanceBetween2Points(current_corner_point, current.end); if (distance_from_end - radialThreshold <= 0) { end_neightbour.Add(current_corner_point); } } int ts_x = 0, ts_y = 0, te_x = 0, te_y = 0; int count = 0; foreach (System.Drawing.Point current_pount in start_neightbour) { //media tra le coordinate X dello start //media tra le coordinate Y dello start ts_x += current_pount.X; ts_y += current_pount.Y; count++; } if (count == 0) { ts_x = current.start.X; ts_y = current.start.Y; } else { ts_x /= count; ts_y /= count; } count = 0; foreach (System.Drawing.Point current_pount in end_neightbour) { //media tra le coordinate X dell'end //media tra le coordinate Y dell'end te_x += current_pount.X; te_y += current_pount.Y; count++; } if (count == 0) { te_x = current.end.X; te_y = current.end.Y; } else { te_x /= count; te_y /= count; } //calculate segment lenght System.Drawing.Point mid = SunoLogic.midPoint(new System.Drawing.Point(ts_x, ts_y), new System.Drawing.Point(te_x, te_y)); //add point ts.trajectory_points.Add(mid); } } } return(ts); }
/// <summary> /// Invokes a speicifed plot function for each pixel that passes through on the speicfied line /// </summary> /// <param name="plotFunction">The fuction to call to plot the lines</param> /// <param name="startPoint">The start point for the line</param> /// <param name="endPoint">The end point of the line</param> /// <param name="size">The size of the line to plot</param> /// <param name="ignoreFirstPlot">Whether to ignore the first plot of the sequence and not call the plot function on it</param> protected void InvokePlotsOnLine(PlotFunction plotFunction, Point startPoint, Point endPoint, int size, bool ignoreFirstPlot = false) { int x0 = startPoint.X; int y0 = startPoint.Y; int x1 = endPoint.X; int y1 = endPoint.Y; bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); if (steep) { int t = x0; x0 = y0; y0 = t; t = x1; x1 = y1; y1 = t; } if (x0 > x1) { int t = x0; x0 = x1; x1 = t; t = y0; y0 = y1; y1 = t; } int deltax = x1 - x0; int deltay = Math.Abs(y1 - y0); int error = deltax / 2; int ystep; int y = y0; if (y0 < y1) { ystep = 1; } else { ystep = -1; } // The point that represents each pixel to plot Point p = new Point(); // Iterate through and plot the line for (int x = x0; x <= x1; x++) { if (steep) { p.X = y; p.Y = x; } else { p.X = x; p.Y = y; } if (!(ignoreFirstPlot && p == startPoint)) { plotFunction(p, size, (p == startPoint || p == endPoint) ? 0 : 2); } error = error - deltay; if (error < 0) { y = y + ystep; error = error + deltax; } } }