public static SpiroSegment[] setup_path(SpiroControlPoint[] src, int n) { int i, ilast, n_seg; double dx, dy; SpiroSegment[] r; #if CHECK_INPUT_FINITENESS // Verify that input values are within realistic limits for (i = 0; i < n; i++) { if (IsFinite(src[i].X) == 0 || IsFinite(src[i].Y) == 0) { return null; } } #endif n_seg = src[0].Type == SpiroPointType.OpenContour ? n - 1 : n; r = new SpiroSegment[n_seg + 1]; for (int j = 0; j < n_seg + 1; j++) r[j].ks = new double[4]; if (r == null) return null; for (i = 0; i < n_seg; i++) { r[i].X = src[i].X; r[i].Y = src[i].Y; r[i].Type = src[i].Type; r[i].ks[0] = 0.0; r[i].ks[1] = 0.0; r[i].ks[2] = 0.0; r[i].ks[3] = 0.0; } r[n_seg].X = src[n_seg % n].X; r[n_seg].Y = src[n_seg % n].Y; r[n_seg].Type = src[n_seg % n].Type; for (i = 0; i < n_seg; i++) { dx = r[i + 1].X - r[i].X; dy = r[i + 1].Y - r[i].Y; #if !CHECK_INPUT_FINITENESS r[i].seg_ch = hypot(dx, dy); #else if (IsFinite(dx) == 0 || IsFinite(dy) == 0 || IsFinite((r[i].seg_ch = hypot(dx, dy))) == 0) { return null; } #endif r[i].seg_th = Math.Atan2(dy, dx); } ilast = n_seg - 1; for (i = 0; i < n_seg; i++) { if (r[i].Type == SpiroPointType.OpenContour || r[i].Type == SpiroPointType.EndOpenContour || r[i].Type == SpiroPointType.Corner) r[i].bend_th = 0.0; else r[i].bend_th = mod_2pi(r[i].seg_th - r[ilast].seg_th); ilast = i; } return r; }
public static SpiroSegment[] run_spiro(SpiroControlPoint[] src, int n) { int converged, nseg; SpiroSegment[] s; if (src == null || n <= 0) return null; s = setup_path(src, n); if (s != null) { nseg = src[0].Type == SpiroPointType.OpenContour ? n - 1 : n; converged = 1; // this value is for when nseg == 1; else actual value determined below if (nseg > 1) converged = solve_spiro(s, nseg); if (converged != 0) return s; } return null; }