Anti-Grain Geometry Tutorial
agg_trans_double_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_trans_double_path.h"
18 
19 namespace agg
20 {
21 
22  //------------------------------------------------------------------------
23  trans_double_path::trans_double_path() :
24  m_kindex1(0.0),
25  m_kindex2(0.0),
26  m_base_length(0.0),
27  m_base_height(1.0),
28  m_status1(initial),
29  m_status2(initial),
30  m_preserve_x_scale(true)
31  {
32  }
33 
34 
35  //------------------------------------------------------------------------
36  void trans_double_path::reset()
37  {
38  m_src_vertices1.remove_all();
39  m_src_vertices2.remove_all();
40  m_kindex1 = 0.0;
41  m_kindex1 = 0.0;
42  m_status1 = initial;
43  m_status2 = initial;
44  }
45 
46 
47  //------------------------------------------------------------------------
48  void trans_double_path::move_to1(double x, double y)
49  {
50  if(m_status1 == initial)
51  {
52  m_src_vertices1.modify_last(vertex_dist(x, y));
53  m_status1 = making_path;
54  }
55  else
56  {
57  line_to1(x, y);
58  }
59  }
60 
61 
62  //------------------------------------------------------------------------
63  void trans_double_path::line_to1(double x, double y)
64  {
65  if(m_status1 == making_path)
66  {
67  m_src_vertices1.add(vertex_dist(x, y));
68  }
69  }
70 
71 
72  //------------------------------------------------------------------------
73  void trans_double_path::move_to2(double x, double y)
74  {
75  if(m_status2 == initial)
76  {
77  m_src_vertices2.modify_last(vertex_dist(x, y));
78  m_status2 = making_path;
79  }
80  else
81  {
82  line_to2(x, y);
83  }
84  }
85 
86 
87  //------------------------------------------------------------------------
88  void trans_double_path::line_to2(double x, double y)
89  {
90  if(m_status2 == making_path)
91  {
92  m_src_vertices2.add(vertex_dist(x, y));
93  }
94  }
95 
96 
97  //------------------------------------------------------------------------
98  double trans_double_path::finalize_path(vertex_storage& vertices)
99  {
100  unsigned i;
101  double dist;
102  double d;
103 
104  vertices.close(false);
105  if(vertices.size() > 2)
106  {
107  if(vertices[vertices.size() - 2].dist * 10.0 <
108  vertices[vertices.size() - 3].dist)
109  {
110  d = vertices[vertices.size() - 3].dist +
111  vertices[vertices.size() - 2].dist;
112 
113  vertices[vertices.size() - 2] =
114  vertices[vertices.size() - 1];
115 
116  vertices.remove_last();
117  vertices[vertices.size() - 2].dist = d;
118  }
119  }
120 
121  dist = 0;
122  for(i = 0; i < vertices.size(); i++)
123  {
124  vertex_dist& v = vertices[i];
125  d = v.dist;
126  v.dist = dist;
127  dist += d;
128  }
129 
130  return (vertices.size() - 1) / dist;
131  }
132 
133 
134  //------------------------------------------------------------------------
135  void trans_double_path::finalize_paths()
136  {
137  if(m_status1 == making_path && m_src_vertices1.size() > 1 &&
138  m_status2 == making_path && m_src_vertices2.size() > 1)
139  {
140  m_kindex1 = finalize_path(m_src_vertices1);
141  m_kindex2 = finalize_path(m_src_vertices2);
142  m_status1 = ready;
143  m_status2 = ready;
144  }
145  }
146 
147 
148  //------------------------------------------------------------------------
149  double trans_double_path::total_length1() const
150  {
151  if(m_base_length >= 1e-10) return m_base_length;
152  return (m_status1 == ready) ?
153  m_src_vertices1[m_src_vertices1.size() - 1].dist :
154  0.0;
155  }
156 
157 
158  //------------------------------------------------------------------------
159  double trans_double_path::total_length2() const
160  {
161  if(m_base_length >= 1e-10) return m_base_length;
162  return (m_status2 == ready) ?
163  m_src_vertices2[m_src_vertices2.size() - 1].dist :
164  0.0;
165  }
166 
167 
168  //------------------------------------------------------------------------
169  void trans_double_path::transform1(const vertex_storage& vertices,
170  double kindex, double kx,
171  double *x, double* y) const
172  {
173  double x1 = 0.0;
174  double y1 = 0.0;
175  double dx = 1.0;
176  double dy = 1.0;
177  double d = 0.0;
178  double dd = 1.0;
179  *x *= kx;
180  if(*x < 0.0)
181  {
182  // Extrapolation on the left
183  //--------------------------
184  x1 = vertices[0].x;
185  y1 = vertices[0].y;
186  dx = vertices[1].x - x1;
187  dy = vertices[1].y - y1;
188  dd = vertices[1].dist - vertices[0].dist;
189  d = *x;
190  }
191  else
192  if(*x > vertices[vertices.size() - 1].dist)
193  {
194  // Extrapolation on the right
195  //--------------------------
196  unsigned i = vertices.size() - 2;
197  unsigned j = vertices.size() - 1;
198  x1 = vertices[j].x;
199  y1 = vertices[j].y;
200  dx = x1 - vertices[i].x;
201  dy = y1 - vertices[i].y;
202  dd = vertices[j].dist - vertices[i].dist;
203  d = *x - vertices[j].dist;
204  }
205  else
206  {
207  // Interpolation
208  //--------------------------
209  unsigned i = 0;
210  unsigned j = vertices.size() - 1;
211  if(m_preserve_x_scale)
212  {
213  unsigned k;
214  for(i = 0; (j - i) > 1; )
215  {
216  if(*x < vertices[k = (i + j) >> 1].dist)
217  {
218  j = k;
219  }
220  else
221  {
222  i = k;
223  }
224  }
225  d = vertices[i].dist;
226  dd = vertices[j].dist - d;
227  d = *x - d;
228  }
229  else
230  {
231  i = unsigned(*x * kindex);
232  j = i + 1;
233  dd = vertices[j].dist - vertices[i].dist;
234  d = ((*x * kindex) - i) * dd;
235  }
236  x1 = vertices[i].x;
237  y1 = vertices[i].y;
238  dx = vertices[j].x - x1;
239  dy = vertices[j].y - y1;
240  }
241  *x = x1 + dx * d / dd;
242  *y = y1 + dy * d / dd;
243  }
244 
245 
246  //------------------------------------------------------------------------
247  void trans_double_path::transform(double *x, double *y) const
248  {
249  if(m_status1 == ready && m_status2 == ready)
250  {
251  if(m_base_length > 1e-10)
252  {
253  *x *= m_src_vertices1[m_src_vertices1.size() - 1].dist /
254  m_base_length;
255  }
256 
257  double x1 = *x;
258  double y1 = *y;
259  double x2 = *x;
260  double y2 = *y;
261  double dd = m_src_vertices2[m_src_vertices2.size() - 1].dist /
262  m_src_vertices1[m_src_vertices1.size() - 1].dist;
263 
264  transform1(m_src_vertices1, m_kindex1, 1.0, &x1, &y1);
265  transform1(m_src_vertices2, m_kindex2, dd, &x2, &y2);
266 
267  *x = x1 + *y * (x2 - x1) / m_base_height;
268  *y = y1 + *y * (y2 - y1) / m_base_height;
269  }
270  }
271 
272 }
273 
Definition: agg_arc.cpp:24