1//----------------------------------------------------------------------------
2// Anti-Grain Geometry - Version 2.4
3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4//
5// Permission to copy, use, modify, sell and distribute this software
6// is granted provided this copyright notice appears in all copies.
7// This software is provided "as is" without express or implied
8// warranty, and with no claim as to its suitability for any purpose.
9//
10//----------------------------------------------------------------------------
11// Contact: mcseem@antigrain.com
12//          mcseemagg@yahoo.com
13//          http://www.antigrain.com
14//----------------------------------------------------------------------------
15
16#include "agg_vcgen_bspline.h"
17
18namespace agg
19{
20
21    //------------------------------------------------------------------------
22    vcgen_bspline::vcgen_bspline() :
23        m_src_vertices(),
24        m_spline_x(),
25        m_spline_y(),
26        m_interpolation_step(1.0/50.0),
27        m_closed(0),
28        m_status(initial),
29        m_src_vertex(0)
30    {
31    }
32
33
34    //------------------------------------------------------------------------
35    void vcgen_bspline::remove_all()
36    {
37        m_src_vertices.remove_all();
38        m_closed = 0;
39        m_status = initial;
40        m_src_vertex = 0;
41    }
42
43
44    //------------------------------------------------------------------------
45    void vcgen_bspline::add_vertex(double x, double y, unsigned cmd)
46    {
47        m_status = initial;
48        if(is_move_to(cmd))
49        {
50            m_src_vertices.modify_last(point_d(x, y));
51        }
52        else
53        {
54            if(is_vertex(cmd))
55            {
56                m_src_vertices.add(point_d(x, y));
57            }
58            else
59            {
60                m_closed = get_close_flag(cmd);
61            }
62        }
63    }
64
65
66    //------------------------------------------------------------------------
67    void vcgen_bspline::rewind(unsigned)
68    {
69        m_cur_abscissa = 0.0;
70        m_max_abscissa = 0.0;
71        m_src_vertex = 0;
72        if(m_status == initial && m_src_vertices.size() > 2)
73        {
74            if(m_closed)
75            {
76                m_spline_x.init(m_src_vertices.size() + 8);
77                m_spline_y.init(m_src_vertices.size() + 8);
78                m_spline_x.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).x);
79                m_spline_y.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).y);
80                m_spline_x.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].x);
81                m_spline_y.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].y);
82                m_spline_x.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].x);
83                m_spline_y.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].y);
84                m_spline_x.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].x);
85                m_spline_y.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].y);
86            }
87            else
88            {
89                m_spline_x.init(m_src_vertices.size());
90                m_spline_y.init(m_src_vertices.size());
91            }
92            unsigned i;
93            for(i = 0; i < m_src_vertices.size(); i++)
94            {
95                double x = m_closed ? i + 4 : i;
96                m_spline_x.add_point(x, m_src_vertices[i].x);
97                m_spline_y.add_point(x, m_src_vertices[i].y);
98            }
99            m_cur_abscissa = 0.0;
100            m_max_abscissa = m_src_vertices.size() - 1;
101            if(m_closed)
102            {
103                m_cur_abscissa = 4.0;
104                m_max_abscissa += 5.0;
105                m_spline_x.add_point(m_src_vertices.size() + 4, m_src_vertices[0].x);
106                m_spline_y.add_point(m_src_vertices.size() + 4, m_src_vertices[0].y);
107                m_spline_x.add_point(m_src_vertices.size() + 5, m_src_vertices[1].x);
108                m_spline_y.add_point(m_src_vertices.size() + 5, m_src_vertices[1].y);
109                m_spline_x.add_point(m_src_vertices.size() + 6, m_src_vertices[2].x);
110                m_spline_y.add_point(m_src_vertices.size() + 6, m_src_vertices[2].y);
111                m_spline_x.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).x);
112                m_spline_y.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).y);
113            }
114            m_spline_x.prepare();
115            m_spline_y.prepare();
116        }
117        m_status = ready;
118    }
119
120
121
122
123
124
125    //------------------------------------------------------------------------
126    unsigned vcgen_bspline::vertex(double* x, double* y)
127    {
128        unsigned cmd = path_cmd_line_to;
129        while(!is_stop(cmd))
130        {
131            switch(m_status)
132            {
133            case initial:
134                rewind(0);
135
136            case ready:
137                if(m_src_vertices.size() < 2)
138                {
139                    cmd = path_cmd_stop;
140                    break;
141                }
142
143                if(m_src_vertices.size() == 2)
144                {
145                    *x = m_src_vertices[m_src_vertex].x;
146                    *y = m_src_vertices[m_src_vertex].y;
147                    m_src_vertex++;
148                    if(m_src_vertex == 1) return path_cmd_move_to;
149                    if(m_src_vertex == 2) return path_cmd_line_to;
150                    cmd = path_cmd_stop;
151                    break;
152                }
153
154                cmd = path_cmd_move_to;
155                m_status = polygon;
156                m_src_vertex = 0;
157
158            case polygon:
159                if(m_cur_abscissa >= m_max_abscissa)
160                {
161                    if(m_closed)
162                    {
163                        m_status = end_poly;
164                        break;
165                    }
166                    else
167                    {
168                        *x = m_src_vertices[m_src_vertices.size() - 1].x;
169                        *y = m_src_vertices[m_src_vertices.size() - 1].y;
170                        m_status = end_poly;
171                        return path_cmd_line_to;
172                    }
173                }
174
175                *x = m_spline_x.get_stateful(m_cur_abscissa);
176                *y = m_spline_y.get_stateful(m_cur_abscissa);
177                m_src_vertex++;
178                m_cur_abscissa += m_interpolation_step;
179                return (m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to;
180
181            case end_poly:
182                m_status = stop;
183                return path_cmd_end_poly | m_closed;
184
185            case stop:
186                return path_cmd_stop;
187            }
188        }
189        return cmd;
190    }
191
192
193}
194
195