/* ********************************************************************************* */ public static void Create_Control_Point( PointX Prev, PointX CornerPnt, PointX Next, PointX CtrlPnt) { PointX before = new PointX(Prev), after = new PointX(Next); before.Subtract(CornerPnt); before.Normalize(); after.Subtract(CornerPnt); after.Normalize(); before.Add(after); // this now divides the angle between the two lines before.Normalize(); // this gives us normalized output // CtrlPnt.CopyFrom(before); double x0, y0, sin, cos; double d = (after.x * before.y) - (after.y * before.x); // winding order: d=(x-x1)*(y2-y1)-(y-y1)*(x2-x1) if (d > 0) { sin = Sin90; // 90 degrees cos = Cos90; } else { sin = Sin270; // 270 degrees cos = Cos270; } x0 = (before.x * cos) - (before.y * sin); // precalculated all to constants y0 = (before.y * cos) + (before.x * sin); CtrlPnt.Assign(x0, y0); // result is one point, 1 unit long, 'tangent' to the corner. /* position = sign((Bx - Ax) * (Y - Ay) - (By - Ay) * (X - Ax))// alternative: cross product */ }
/* ********************************************************************************* */ public static void Cubic_Spline_Chunk( PointX p0, PointX p1, PointX p2, PointX p3, double FractAlong, PointX result) { // B(t) = (1-t)^3*P0 + 3*(1-t)^2*t*P1 + 3*(1-t)*t^2*P2 + t^3*P3 double MinusFract = 1.0 - FractAlong; double Wgt0 = Math.pow(MinusFract, 3); // * P0; double Wgt1 = 3 * FractAlong * Math.pow(MinusFract, 2); // * P1; double Wgt2 = 3 * MinusFract * Math.pow(FractAlong, 2); // * P2; double Wgt3 = Math.pow(FractAlong, 3); // * P3; double XLoc = (p0.x * Wgt0) + (p1.x * Wgt1) + (p2.x * Wgt2) + (p3.x * Wgt3); double YLoc = (p0.y * Wgt0) + (p1.y * Wgt1) + (p2.y * Wgt2) + (p3.y * Wgt3); result.Assign(XLoc, YLoc); }
/* ********************************************************************************* */ public static void Test(Graphics2D gr) { double Factor = 150; PointX p0 = new PointX(1 * Factor, 1 * Factor), ctr = new PointX(2 * Factor, 2 * Factor), p1 = new PointX(3 * Factor, 0.5 * Factor); int len = 256; PointX[] results = new PointX[len]; for (int cnt = 0; cnt < len; cnt++) { results[cnt] = new PointX(); } Cheap_Spline(gr, p0, ctr, p1, results); PointX[] raw = new PointX[10]; p0.Assign(0, 0); PointX prevpnt = p0, pnt = p0; for (int cnt = 0; cnt < raw.length; cnt++) { prevpnt = pnt; pnt = new PointX( 60 + cnt * 80, 200 + (cnt % 2) * 80 + (Globals.RandomGenerator.nextDouble() * 100)); raw[cnt] = pnt; gr.setColor(Globals.ToColorWheel(Globals.RandomGenerator.nextDouble())); gr.drawLine((int) prevpnt.x, (int) prevpnt.y, (int) pnt.x, (int) pnt.y); } int NumSubLines = 8; results = new PointX[NumSubLines * (raw.length - 1) + 1]; for (int pcnt = 0; pcnt < results.length; pcnt++) { results[pcnt] = new PointX(); } Cubic_Spline(gr, raw, NumSubLines, results); if (true) { pnt = results[0]; len = results.length; gr.setColor(Color.red); for (int cnt = 1; cnt < len; cnt++) { prevpnt = pnt; pnt = results[cnt]; // gr.setColor(Globals.ToColorWheel(Globals.RandomGenerator.nextDouble())); gr.drawLine((int) prevpnt.x, (int) prevpnt.y, (int) pnt.x, (int) pnt.y); } } }