コード例 #1
0
        public static void compute_pderivs(ref SpiroSegment s, double[][] ends, double[][][] derivs, int jinc)
        {
            double recip_d = 2e6;
            double delta   = 1.0 / recip_d;

            double[]   try_ks = new double[4];
            double[][] try_ends = { new double[4], new double[4] };
            int        i, j, k;

            compute_ends(s.ks, ends, s.seg_ch);
            for (i = 0; i < jinc; i++)
            {
                for (j = 0; j < 4; j++)
                {
                    try_ks[j] = s.ks[j];
                }

                try_ks[i] += delta;
                compute_ends(try_ks, try_ends, s.seg_ch);

                for (k = 0; k < 2; k++)
                {
                    for (j = 0; j < 4; j++)
                    {
                        derivs[j][k][i] = recip_d * (try_ends[k][j] - ends[k][j]);
                    }
                }
            }
        }
コード例 #2
0
        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);
        }
コード例 #3
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        public static void spiro_to_bpath(SpiroSegment[] s, int n, IBezierContext bc)
        {
            int i, nsegs;
            double x0, y0, x1, y1;

            if (s == null || n <= 0 || bc == null)
                return;

            nsegs = s[n - 1].Type == SpiroPointType.EndOpenContour ? n - 1 : n;

            for (i = 0; i < nsegs; i++)
            {
                x0 = s[i].X; x1 = s[i + 1].X;
                y0 = s[i].Y; y1 = s[i + 1].Y;

                if (i == 0)
                    bc.MoveTo(x0, y0, s[0].Type == SpiroPointType.OpenContour ? true : false);

                bc.MarkKnot(i, get_knot_th(s, i), s[i].X, s[i].Y, s[i].Type);
                spiro_seg_to_bpath(s[i].ks, x0, y0, x1, y1, bc, 0);
            }

            if (nsegs == n - 1)
                bc.MarkKnot(n - 1, get_knot_th(s, n - 1), s[n - 1].X, s[n - 1].Y, s[n - 1].Type);
        }
コード例 #4
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        public static int solve_spiro(SpiroSegment[] s, int nseg)
        {
            int i, converged, nmat, n_alloc;
            BandMatrix[] m;
            double[] v;
            int[] perm;
            double norm;

            nmat = count_vec(s, nseg);
            n_alloc = nmat;

            if (nmat == 0)
                return 1; // just means no convergence problems
            if (s[0].Type != SpiroPointType.OpenContour && s[0].Type != SpiroPointType.Corner)
                n_alloc *= 3;
            if (n_alloc < 5)
                n_alloc = 5;

            m = new BandMatrix[n_alloc];
            for (int n = 0; n < n_alloc; n++)
            {
                m[n].a = new double[11];
                m[n].al = new double[5];
            }

            v = new double[n_alloc];
            perm = new int[n_alloc];

            i = converged = 0; // not solved (yet)
            if (m != null && v != null && perm != null)
            {
                while (i++ < 60)
                {
                    norm = spiro_iter(s, m, perm, v, nseg, nmat);
                    if (check_finiteness(s, nseg) == false)
                        break;

                    if (norm < 1e-12)
                    {
                        converged = 1;
                        break;
                    }
                }
            }

            return converged;
        }
コード例 #5
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        public static double spiro_iter(SpiroSegment[] s, BandMatrix[] m, int[] perm, double[] v, int n, int nmat)
        {
            bool cyclic;
            int i, j, jthl, jthr, jk0l, jk0r, jk1l, jk1r, jk2l, jk2r, jinc, jj, k, n_invert;
            SpiroPointType ty0, ty1;
            double dk, norm, th;
            double[][] ends = { new double[4], new double[4] };
            double[][][] derivs =
            {
                new double[2][] { new double[4], new double[4] },
                new double[2][] { new double[4], new double[4] },
                new double[2][] { new double[4], new double[4] },
                new double[2][] { new double[4], new double[4] },
            };

            cyclic = s[0].Type != SpiroPointType.OpenContour && s[0].Type != SpiroPointType.Corner;

            for (i = 0; i < nmat; i++)
            {
                v[i] = 0.0;

                for (j = 0; j < 11; j++)
                    m[i].a[j] = 0.0;

                for (j = 0; j < 5; j++)
                    m[i].al[j] = 0.0;
            }

            j = 0;

            if (s[0].Type == SpiroPointType.G4)
                jj = nmat - 2;
            else if (s[0].Type == SpiroPointType.G2)
                jj = nmat - 1;
            else
                jj = 0;

            for (i = 0; i < n; i++)
            {
                ty0 = s[i].Type;
                ty1 = s[i + 1].Type;
                jinc = compute_jinc(ty0, ty1);
                th = s[i].bend_th;
                jthl = jk0l = jk1l = jk2l = -1;
                jthr = jk0r = jk1r = jk2r = -1;

                compute_pderivs(ref s[i], ends, derivs, jinc);

                // constraints crossing left
                if (ty0 == SpiroPointType.G4 || ty0 == SpiroPointType.G2 || ty0 == SpiroPointType.Left || ty0 == SpiroPointType.Right)
                {
                    jthl = jj++;
                    jj %= nmat;
                    jk0l = jj++;

                    if (ty0 == SpiroPointType.G4)
                    {
                        jj %= nmat;
                        jk1l = jj++;
                        jk2l = jj++;
                    }
                }

                // constraints on left
                if ((ty0 == SpiroPointType.Left || ty0 == SpiroPointType.Corner || ty0 == SpiroPointType.OpenContour || ty0 == SpiroPointType.G2) && jinc == 4)
                {
                    if (ty0 != SpiroPointType.G2)
                        jk1l = jj++;

                    jk2l = jj++;
                }

                // constraints on right
                if ((ty1 == SpiroPointType.Right || ty1 == SpiroPointType.Corner || ty1 == SpiroPointType.EndOpenContour || ty1 == SpiroPointType.G2) && jinc == 4)
                {
                    if (ty1 != SpiroPointType.G2)
                        jk1r = jj++;

                    jk2r = jj++;
                }

                // constraints crossing right
                if (ty1 == SpiroPointType.G4 || ty1 == SpiroPointType.G2 || ty1 == SpiroPointType.Left || ty1 == SpiroPointType.Right)
                {
                    jthr = jj;
                    jk0r = (jj + 1) % nmat;

                    if (ty1 == SpiroPointType.G4)
                    {
                        jk1r = (jj + 2) % nmat;
                        jk2r = (jj + 3) % nmat;
                    }
                }

                add_mat_line(m, v, derivs[0][0], th - ends[0][0], 1, j, jthl, jinc, nmat);
                add_mat_line(m, v, derivs[1][0], ends[0][1], -1, j, jk0l, jinc, nmat);
                add_mat_line(m, v, derivs[2][0], ends[0][2], -1, j, jk1l, jinc, nmat);
                add_mat_line(m, v, derivs[3][0], ends[0][3], -1, j, jk2l, jinc, nmat);
                add_mat_line(m, v, derivs[0][1], -ends[1][0], 1, j, jthr, jinc, nmat);
                add_mat_line(m, v, derivs[1][1], -ends[1][1], 1, j, jk0r, jinc, nmat);
                add_mat_line(m, v, derivs[2][1], -ends[1][2], 1, j, jk1r, jinc, nmat);
                add_mat_line(m, v, derivs[3][1], -ends[1][3], 1, j, jk2r, jinc, nmat);

                if (jthl >= 0)
                    v[jthl] = mod_2pi(v[jthl]);

                if (jthr >= 0)
                    v[jthr] = mod_2pi(v[jthr]);

                j += jinc;
            }

            if (cyclic)
            {
                BandMatrix.Copy(m, 0, m, nmat, nmat);
                BandMatrix.Copy(m, 0, m, 2 * nmat, nmat);
                Array.Copy(v, 0, v, nmat, nmat);
                Array.Copy(v, 0, v, 2 * nmat, nmat);
                n_invert = 3 * nmat;
                j = nmat;
            }
            else
            {
                n_invert = nmat;
                j = 0;
            }

            bandec11(m, perm, n_invert);
            banbks11(m, perm, v, n_invert);
            norm = 0.0;

            for (i = 0; i < n; i++)
            {
                jinc = compute_jinc(s[i].Type, s[i + 1].Type);

                for (k = 0; k < jinc; k++)
                {
                    dk = v[j++];

                    s[i].ks[k] += dk;
                    norm += dk * dk;
                }

                s[i].ks[0] = 2.0 * mod_2pi(s[i].ks[0] / 2.0);
            }

            return norm;
        }
コード例 #6
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        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;
        }
コード例 #7
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        public static double get_knot_th(SpiroSegment[] s, int i)
        {
            double[][] ends = { new double[4], new double[4] };

            if (i == 0)
            {
                compute_ends(s[i].ks, ends, s[i].seg_ch);
                return s[i].seg_th - ends[0][0];
            }
            else
            {
                compute_ends(s[i - 1].ks, ends, s[i - 1].seg_ch);
                return s[i - 1].seg_th + ends[1][0];
            }
        }
コード例 #8
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        public static int count_vec(SpiroSegment[] s, int nseg)
        {
            int i, n;

            n = 0;

            for (i = 0; i < nseg; i++)
                n += compute_jinc(s[i].Type, s[i + 1].Type);

            return n;
        }
コード例 #9
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        public static void compute_pderivs(ref SpiroSegment s, double[][] ends, double[][][] derivs, int jinc)
        {
            double recip_d = 2e6;
            double delta = 1.0 / recip_d;
            double[] try_ks = new double[4];
            double[][] try_ends = { new double[4], new double[4] };
            int i, j, k;

            compute_ends(s.ks, ends, s.seg_ch);
            for (i = 0; i < jinc; i++)
            {
                for (j = 0; j < 4; j++)
                    try_ks[j] = s.ks[j];

                try_ks[i] += delta;
                compute_ends(try_ks, try_ends, s.seg_ch);

                for (k = 0; k < 2; k++)
                    for (j = 0; j < 4; j++)
                        derivs[j][k][i] = recip_d * (try_ends[k][j] - ends[k][j]);
            }
        }
コード例 #10
0
ファイル: SpiroImpl.cs プロジェクト: wieslawsoltes/SpiroNet
        public static bool check_finiteness(SpiroSegment[] segs, int num_segs)
        {
            // Check if all values are "finite", return true, else return fail=false
            int i, j;

            for (i = 0; i < num_segs; ++i)
                for (j = 0; j < 4; ++j)
                    if (IsFinite(segs[i].ks[j]) == 0)
                        return false;

            return true;
        }