Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* libcdr
3 : * Version: MPL 1.1 / GPLv2+ / LGPLv2+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
17 : * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
18 : *
19 : *
20 : * All Rights Reserved.
21 : *
22 : * For minor contributions see the git repository.
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
26 : * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
27 : * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
28 : * instead of those above.
29 : */
30 :
31 : #include "CDRTransforms.h"
32 : #include "CDRPath.h"
33 : #include "libcdr_utils.h"
34 :
35 :
36 0 : libcdr::CDRTransform::CDRTransform()
37 : : m_v0(1.0), m_v1(0.0), m_x0(0.0),
38 0 : m_v3(0.0), m_v4(1.0), m_y0(0.0)
39 : {
40 0 : }
41 :
42 0 : libcdr::CDRTransform::CDRTransform(double v0, double v1, double x0, double v3, double v4, double y0)
43 0 : : m_v0(v0), m_v1(v1), m_x0(x0), m_v3(v3), m_v4(v4), m_y0(y0)
44 : {
45 0 : }
46 :
47 0 : libcdr::CDRTransform::CDRTransform(const CDRTransform &trafo)
48 : : m_v0(trafo.m_v0), m_v1(trafo.m_v1), m_x0(trafo.m_x0),
49 0 : m_v3(trafo.m_v3), m_v4(trafo.m_v4), m_y0(trafo.m_y0) {}
50 :
51 :
52 0 : void libcdr::CDRTransform::applyToPoint(double &x, double &y) const
53 : {
54 0 : double tmpX = m_v0*x + m_v1*y+m_x0;
55 0 : y = m_v3*x + m_v4*y+m_y0;
56 0 : x = tmpX;
57 0 : }
58 :
59 0 : void libcdr::CDRTransform::applyToArc(double &rx, double &ry, double &rotation, bool &sweep, double &x, double &y) const
60 : {
61 : // First transform the end-point, which is the easiest
62 0 : applyToPoint(x, y);
63 :
64 : // represent ellipse as a transformed unit circle
65 0 : double v0 = m_v0*rx*cos(rotation) - m_v1*rx*sin(rotation);
66 0 : double v1 = m_v1*ry*cos(rotation) + m_v0*ry*sin(rotation);
67 0 : double v3 = m_v3*rx*cos(rotation) - m_v4*rx*sin(rotation);
68 0 : double v4 = m_v4*ry*cos(rotation) + m_v3*ry*sin(rotation);
69 :
70 : // centered implicit equation
71 0 : double A = v0*v0 + v1*v1;
72 0 : double C = v3*v3 + v4*v4;
73 0 : double B = 2.0*(v0*v3 + v1*v4);
74 :
75 : double r1, r2;
76 : // convert implicit equation to angle and halfaxis:
77 0 : if (CDR_ALMOST_ZERO(B))
78 : {
79 0 : rotation = 0;
80 0 : r1 = A;
81 0 : r2 = C;
82 : }
83 : else
84 : {
85 0 : if (CDR_ALMOST_ZERO(A-C))
86 : {
87 0 : r1 = A + B / 2.0;
88 0 : r2 = A - B / 2.0;
89 0 : rotation = M_PI / 4.0;
90 : }
91 : else
92 : {
93 0 : double radical = 1.0 + B*B /((A-C)*(A-C));
94 0 : radical = radical < 0.0 ? 0.0 : sqrt (radical);
95 :
96 0 : r1 = (A+C + radical*(A-C)) / 2.0;
97 0 : r2 = (A+C - radical*(A-C)) / 2.0;
98 0 : rotation = atan2(B,(A-C)) / 2.0;
99 : }
100 : }
101 :
102 : // Prevent sqrt of a negative number, however small it might be.
103 0 : r1 = r1 < 0.0 ? 0.0 : sqrt(r1);
104 0 : r2 = r2 < 0.0 ? 0.0 : sqrt(r2);
105 :
106 : // now r1 and r2 are half-axis:
107 0 : if ((A-C) <= 0)
108 : {
109 0 : ry = r1;
110 0 : rx = r2;
111 : }
112 : else
113 : {
114 0 : ry = r2;
115 0 : rx = r1;
116 : }
117 :
118 : // sweep is inversed each time the arc is flipped
119 0 : sweep = (m_v0*m_v4 < m_v3*m_v1);
120 0 : }
121 :
122 0 : double libcdr::CDRTransform::_getScaleX() const
123 : {
124 0 : double x0 = 0.0;
125 0 : double x1 = 1.0;
126 0 : double y0 = 0.0;
127 0 : double y1 = 0.0;
128 0 : applyToPoint(x0, y0);
129 0 : applyToPoint(x1, y1);
130 0 : return x1 - x0;
131 : }
132 :
133 0 : double libcdr::CDRTransform::getScaleX() const
134 : {
135 0 : return fabs(_getScaleX());
136 : }
137 :
138 0 : bool libcdr::CDRTransform::getFlipX() const
139 : {
140 0 : return (0 > _getScaleX());
141 : }
142 :
143 0 : double libcdr::CDRTransform::_getScaleY() const
144 : {
145 0 : double x0 = 0.0;
146 0 : double x1 = 0.0;
147 0 : double y0 = 0.0;
148 0 : double y1 = 1.0;
149 0 : applyToPoint(x0, y0);
150 0 : applyToPoint(x1, y1);
151 0 : return y1 - y0;
152 : }
153 :
154 0 : double libcdr::CDRTransform::getScaleY() const
155 : {
156 0 : return fabs(_getScaleY());
157 : }
158 :
159 0 : bool libcdr::CDRTransform::getFlipY() const
160 : {
161 0 : return (0 > _getScaleY());
162 : }
163 :
164 0 : double libcdr::CDRTransform::getRotation() const
165 : {
166 0 : double x0 = 0.0;
167 0 : double x1 = 1.0;
168 0 : double y0 = 0.0;
169 0 : double y1 = 0.0;
170 0 : applyToPoint(x0, y0);
171 0 : applyToPoint(x1, y1);
172 0 : double angle = atan2(y1-y0, x1-x0);
173 0 : if (angle < 0.0)
174 0 : angle += 2*M_PI;
175 0 : return angle;
176 : }
177 :
178 0 : double libcdr::CDRTransform::getTranslateX() const
179 : {
180 0 : double x = 0.0;
181 0 : double y = 0.0;
182 0 : applyToPoint(x, y);
183 0 : return x;
184 : }
185 :
186 0 : double libcdr::CDRTransform::getTranslateY() const
187 : {
188 0 : double x = 0.0;
189 0 : double y = 0.0;
190 0 : applyToPoint(x, y);
191 0 : return y;
192 : }
193 :
194 :
195 0 : libcdr::CDRTransforms::CDRTransforms()
196 0 : : m_trafos()
197 : {
198 0 : }
199 :
200 0 : libcdr::CDRTransforms::CDRTransforms(const CDRTransforms &trafos)
201 0 : : m_trafos(trafos.m_trafos)
202 : {
203 0 : }
204 :
205 0 : libcdr::CDRTransforms::~CDRTransforms()
206 : {
207 0 : }
208 :
209 0 : void libcdr::CDRTransforms::append(double v0, double v1, double x0, double v3, double v4, double y0)
210 : {
211 0 : append(CDRTransform(v0, v1, x0, v3, v4, y0));
212 0 : }
213 :
214 0 : void libcdr::CDRTransforms::append(const CDRTransform &trafo)
215 : {
216 0 : m_trafos.push_back(trafo);
217 0 : }
218 :
219 0 : void libcdr::CDRTransforms::clear()
220 : {
221 0 : m_trafos.clear();
222 0 : }
223 :
224 0 : bool libcdr::CDRTransforms::empty() const
225 : {
226 0 : return m_trafos.empty();
227 : }
228 :
229 0 : void libcdr::CDRTransforms::applyToPoint(double &x, double &y) const
230 : {
231 0 : for (std::vector<CDRTransform>::const_iterator iter = m_trafos.begin(); iter != m_trafos.end(); ++iter)
232 0 : iter->applyToPoint(x,y);
233 0 : }
234 :
235 0 : void libcdr::CDRTransforms::applyToArc(double &rx, double &ry, double &rotation, bool &sweep, double &x, double &y) const
236 : {
237 0 : for (std::vector<CDRTransform>::const_iterator iter = m_trafos.begin(); iter != m_trafos.end(); ++iter)
238 0 : iter->applyToArc(rx, ry, rotation, sweep, x, y);
239 0 : }
240 :
241 0 : double libcdr::CDRTransforms::_getScaleX() const
242 : {
243 0 : double x0 = 0.0;
244 0 : double x1 = 1.0;
245 0 : double y0 = 0.0;
246 0 : double y1 = 0.0;
247 0 : applyToPoint(x0, y0);
248 0 : applyToPoint(x1, y1);
249 0 : return x1 - x0;
250 : }
251 :
252 0 : double libcdr::CDRTransforms::getScaleX() const
253 : {
254 0 : return fabs(_getScaleX());
255 : }
256 :
257 0 : bool libcdr::CDRTransforms::getFlipX() const
258 : {
259 0 : return (0 > _getScaleX());
260 : }
261 :
262 0 : double libcdr::CDRTransforms::_getScaleY() const
263 : {
264 0 : double x0 = 0.0;
265 0 : double x1 = 0.0;
266 0 : double y0 = 0.0;
267 0 : double y1 = 1.0;
268 0 : applyToPoint(x0, y0);
269 0 : applyToPoint(x1, y1);
270 0 : return y1 - y0;
271 : }
272 :
273 0 : double libcdr::CDRTransforms::getScaleY() const
274 : {
275 0 : return fabs(_getScaleY());
276 : }
277 :
278 0 : bool libcdr::CDRTransforms::getFlipY() const
279 : {
280 0 : return (0 > _getScaleY());
281 : }
282 :
283 0 : double libcdr::CDRTransforms::getRotation() const
284 : {
285 0 : double x0 = 0.0;
286 0 : double x1 = 1.0;
287 0 : double y0 = 0.0;
288 0 : double y1 = 0.0;
289 0 : applyToPoint(x0, y0);
290 0 : applyToPoint(x1, y1);
291 0 : double angle = atan2(y1-y0, x1-x0);
292 0 : if (angle < 0.0)
293 0 : angle += 2*M_PI;
294 0 : return angle;
295 : }
296 :
297 0 : double libcdr::CDRTransforms::getTranslateX() const
298 : {
299 0 : double x = 0.0;
300 0 : double y = 0.0;
301 0 : applyToPoint(x, y);
302 0 : return x;
303 : }
304 :
305 0 : double libcdr::CDRTransforms::getTranslateY() const
306 : {
307 0 : double x = 0.0;
308 0 : double y = 0.0;
309 0 : applyToPoint(x, y);
310 0 : return y;
311 : }
312 :
313 :
314 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|