/// <summary> /// Draw Line with clipping. /// </summary> /// <param name="g"></param> /// <param name="pen"></param> /// <param name="p1"></param> /// <param name="p2"></param> private static void DrawLine(Graphics g, Pen pen, Vector2 p1, Vector2 p2) { g.DrawLine(pen, p1.X, p1.Y, p2.X, p2.Y); }
public static void DrawCurve(this Graphics g, Curve curve, float x, float y, float width, float height, Color curveColor, float thickness) { float lastPosition = curve.Keys[curve.Keys.Count - 1].Position; // get curve max value float top = float.MaxValue, bottom = float.MinValue; foreach (var v in curve.Keys) { if (v.Value == 0) { if (v.Value > bottom) bottom = v.Value; if (v.Value < top) top = v.Value; } else if (v.Value > 0) { if (v.Value > bottom) bottom = v.Value; } else { if (v.Value < top) top = v.Value; } } // fixed float curveHeight = bottom + -top; if (lastPosition == 0) lastPosition = width; if (curveHeight == 0) curveHeight = height; Vector2 scale = new Vector2(width / lastPosition, height / curveHeight); double dt0 = x; double dt1 = dt0 + width / scale.X; double step = scale.X / smoothnessTable[(int)curveSmoothness]; Pen pen0 = new Pen(curveColor, thickness); if (curve.Keys.Count > 0) { double kt0 = curve.Keys[0].Position; double kt1 = curve.Keys[curve.Keys.Count - 1].Position; double t0 = dt0; double t1 = Math.Min(dt1, kt0); // draw fact section t0 = Math.Max(dt0, kt0); t1 = Math.Min(dt1, kt1); if (t0 < t1) { Vector2[] p = new Vector2[2] { new Vector2(), new Vector2() }; // Search key and next key that includes t0 position. int keyIndex = 0; CurveKey key = null, nextKey = null; for (; keyIndex < curve.Keys.Count; ++keyIndex) { key = nextKey; nextKey = curve.Keys[keyIndex]; if (nextKey.Position > t0) break; } int pIdx = 0; p[pIdx] = new Vector2((float)t0 / scale.X, curve.Evaluate((float)t0) * scale.Y + y); for (double t = t0; t < t1; ) { double nextT = t1 + step; if (nextKey != null) nextT = Math.Min(t1, nextKey.Position); // Draw current key and next key section. if (key.Continuity == CurveContinuity.Smooth) { while (t < nextT) { // If this line crosses next key position, draw line from // current position to next key position. t = (t < nextT && t + step > nextT) ? nextT : t + step; pIdx = (pIdx + 1) & 1; p[pIdx] = new Vector2((float)t / scale.X, curve.Evaluate((float)t) / scale.Y + y); DrawLine(g, pen0, p[0], p[1]); } } else { // Step case, // Draw, horizontal line. pIdx = (pIdx + 1) & 1; p[pIdx] = new Vector2(nextKey.Position / scale.X, key.Value / scale.Y + y); DrawLine(g, pen0, p[0], p[1]); // Draw vertical line. pIdx = (pIdx + 1) & 1; p[pIdx] = new Vector2(nextKey.Position / scale.X, nextKey.Value / scale.Y + y); DrawLine(g, pen0, p[0], p[1]); t = nextT; } // Advance to next key. key = nextKey; nextKey = (++keyIndex < curve.Keys.Count) ? curve.Keys[keyIndex] : null; } } } }