Anti-Grain Geometry Tutorial
agg_trans_single_path.cpp
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_math.h"
17 #include "agg_vertex_sequence.h"
18 #include "agg_trans_single_path.h"
19 
20 namespace agg
21 {
22 
23  //------------------------------------------------------------------------
24  trans_single_path::trans_single_path() :
25  m_base_length(0.0),
26  m_kindex(0.0),
27  m_status(initial),
28  m_preserve_x_scale(true)
29  {
30  }
31 
32  //------------------------------------------------------------------------
33  void trans_single_path::reset()
34  {
35  m_src_vertices.remove_all();
36  m_kindex = 0.0;
37  m_status = initial;
38  }
39 
40  //------------------------------------------------------------------------
41  void trans_single_path::move_to(double x, double y)
42  {
43  if(m_status == initial)
44  {
45  m_src_vertices.modify_last(vertex_dist(x, y));
46  m_status = making_path;
47  }
48  else
49  {
50  line_to(x, y);
51  }
52  }
53 
54  //------------------------------------------------------------------------
55  void trans_single_path::line_to(double x, double y)
56  {
57  if(m_status == making_path)
58  {
59  m_src_vertices.add(vertex_dist(x, y));
60  }
61  }
62 
63 
64  //------------------------------------------------------------------------
65  void trans_single_path::finalize_path()
66  {
67  if(m_status == making_path && m_src_vertices.size() > 1)
68  {
69  unsigned i;
70  double dist;
71  double d;
72 
73  m_src_vertices.close(false);
74  if(m_src_vertices.size() > 2)
75  {
76  if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 <
77  m_src_vertices[m_src_vertices.size() - 3].dist)
78  {
79  d = m_src_vertices[m_src_vertices.size() - 3].dist +
80  m_src_vertices[m_src_vertices.size() - 2].dist;
81 
82  m_src_vertices[m_src_vertices.size() - 2] =
83  m_src_vertices[m_src_vertices.size() - 1];
84 
85  m_src_vertices.remove_last();
86  m_src_vertices[m_src_vertices.size() - 2].dist = d;
87  }
88  }
89 
90  dist = 0.0;
91  for(i = 0; i < m_src_vertices.size(); i++)
92  {
93  vertex_dist& v = m_src_vertices[i];
94  double d = v.dist;
95  v.dist = dist;
96  dist += d;
97  }
98  m_kindex = (m_src_vertices.size() - 1) / dist;
99  m_status = ready;
100  }
101  }
102 
103 
104 
105  //------------------------------------------------------------------------
106  double trans_single_path::total_length() const
107  {
108  if(m_base_length >= 1e-10) return m_base_length;
109  return (m_status == ready) ?
110  m_src_vertices[m_src_vertices.size() - 1].dist :
111  0.0;
112  }
113 
114 
115  //------------------------------------------------------------------------
116  void trans_single_path::transform(double *x, double *y) const
117  {
118  if(m_status == ready)
119  {
120  if(m_base_length > 1e-10)
121  {
122  *x *= m_src_vertices[m_src_vertices.size() - 1].dist /
123  m_base_length;
124  }
125 
126  double x1 = 0.0;
127  double y1 = 0.0;
128  double dx = 1.0;
129  double dy = 1.0;
130  double d = 0.0;
131  double dd = 1.0;
132  if(*x < 0.0)
133  {
134  // Extrapolation on the left
135  //--------------------------
136  x1 = m_src_vertices[0].x;
137  y1 = m_src_vertices[0].y;
138  dx = m_src_vertices[1].x - x1;
139  dy = m_src_vertices[1].y - y1;
140  dd = m_src_vertices[1].dist - m_src_vertices[0].dist;
141  d = *x;
142  }
143  else
144  if(*x > m_src_vertices[m_src_vertices.size() - 1].dist)
145  {
146  // Extrapolation on the right
147  //--------------------------
148  unsigned i = m_src_vertices.size() - 2;
149  unsigned j = m_src_vertices.size() - 1;
150  x1 = m_src_vertices[j].x;
151  y1 = m_src_vertices[j].y;
152  dx = x1 - m_src_vertices[i].x;
153  dy = y1 - m_src_vertices[i].y;
154  dd = m_src_vertices[j].dist - m_src_vertices[i].dist;
155  d = *x - m_src_vertices[j].dist;
156  }
157  else
158  {
159  // Interpolation
160  //--------------------------
161  unsigned i = 0;
162  unsigned j = m_src_vertices.size() - 1;
163  if(m_preserve_x_scale)
164  {
165  unsigned k;
166  for(i = 0; (j - i) > 1; )
167  {
168  if(*x < m_src_vertices[k = (i + j) >> 1].dist)
169  {
170  j = k;
171  }
172  else
173  {
174  i = k;
175  }
176  }
177  d = m_src_vertices[i].dist;
178  dd = m_src_vertices[j].dist - d;
179  d = *x - d;
180  }
181  else
182  {
183  i = unsigned(*x * m_kindex);
184  j = i + 1;
185  dd = m_src_vertices[j].dist - m_src_vertices[i].dist;
186  d = ((*x * m_kindex) - i) * dd;
187  }
188  x1 = m_src_vertices[i].x;
189  y1 = m_src_vertices[i].y;
190  dx = m_src_vertices[j].x - x1;
191  dy = m_src_vertices[j].y - y1;
192  }
193  double x2 = x1 + dx * d / dd;
194  double y2 = y1 + dy * d / dd;
195  *x = x2 - *y * dy / dd;
196  *y = y2 + *y * dx / dd;
197  }
198  }
199 
200 
201 }
202 
Definition: agg_arc.cpp:24