blob: 332ec1e3a23ef82d244fbd7c8cf69969ce2f30d9 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#ifndef GrPoint_DEFINED
19#define GrPoint_DEFINED
20
21#include "GrTypes.h"
22#include "GrScalar.h"
reed@google.com7744c202011-05-06 19:26:26 +000023#include "SkPoint.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000024
reed@google.com7744c202011-05-06 19:26:26 +000025#define GrPoint SkPoint
26#define GrVec SkVector
27
28struct GrIPoint16 {
29 int16_t fX, fY;
30
31 void set(intptr_t x, intptr_t y) {
32 fX = GrToS16(x);
33 fY = GrToS16(y);
34 }
35};
36
37#if 0
reed@google.comac10a2d2010-12-22 21:39:39 +000038/**
39 * 2D Point struct
40 */
41struct GrPoint {
42public:
43 GrScalar fX, fY;
44
45 GrPoint() {}
46 GrPoint(GrScalar x, GrScalar y) { fX = x; fY = y; }
47
48 GrScalar x() const { return fX; }
49 GrScalar y() const { return fY; }
50
51 void set(GrScalar x, GrScalar y) {
52 fX = x;
53 fY = y;
54 }
55
56 void setAsMidPoint(const GrPoint& a, const GrPoint& b) {
57 fX = GrScalarAve(a.fX, b.fX);
58 fY = GrScalarAve(a.fY, b.fY);
59 }
60
61 void offset(GrScalar dx, GrScalar dy) {
62 fX += dx;
63 fY += dy;
64 }
65
66 GrScalar distanceToSqd(const GrPoint& p) const {
67 GrScalar dx = (p.fX - fX);
68 GrScalar dy = (p.fY - fY);
69 return GrMul(dx, dx) + GrMul(dy, dy);
70 }
71
72 GrScalar distanceTo(const GrPoint& p) const {
73 // TODO: fixed point sqrt
74 return GrFloatToScalar(sqrtf(GrScalarToFloat(distanceToSqd(p))));
75 }
76
77 GrScalar distanceToOriginSqd() const {
78 return GrMul(fX, fX) + GrMul(fY, fY);
79 }
80
81 GrScalar distanceToOrigin() const {
82 return GrFloatToScalar(sqrtf(GrScalarToFloat(distanceToOriginSqd())));
83 }
84
85 inline GrScalar distanceToLineBetweenSqd(const GrPoint& a,
86 const GrPoint& b) const;
87
88 inline GrScalar distanceToLineBetween(const GrPoint& a,
89 const GrPoint& b) const;
90
91 inline GrScalar distanceToLineSegmentBetweenSqd(const GrPoint& a,
92 const GrPoint& b) const;
93
94 inline GrScalar distanceToLineSegmentBetween(const GrPoint& a,
95 const GrPoint& b) const;
96
97 // counter-clockwise fan
98 void setRectFan(GrScalar l, GrScalar t, GrScalar r, GrScalar b) {
99 GrPoint* v = this;
100 v[0].set(l, t);
101 v[1].set(l, b);
102 v[2].set(r, b);
103 v[3].set(r, t);
104 }
105
106 void setRectFan(GrScalar l, GrScalar t, GrScalar r, GrScalar b, size_t stride) {
107 GrAssert(stride >= sizeof(GrPoint));
108 ((GrPoint*)((intptr_t)this + 0 * stride))->set(l, t);
109 ((GrPoint*)((intptr_t)this + 1 * stride))->set(l, b);
110 ((GrPoint*)((intptr_t)this + 2 * stride))->set(r, b);
111 ((GrPoint*)((intptr_t)this + 3 * stride))->set(r, t);
112 }
113
114 // counter-clockwise fan
115 void setIRectFan(int l, int t, int r, int b) {
116 GrPoint* v = this;
117 v[0].set(GrIntToScalar(l), GrIntToScalar(t));
118 v[1].set(GrIntToScalar(l), GrIntToScalar(b));
119 v[2].set(GrIntToScalar(r), GrIntToScalar(b));
120 v[3].set(GrIntToScalar(r), GrIntToScalar(t));
121 }
122
123 void setIRectFan(int l, int t, int r, int b, size_t stride) {
124 GrAssert(stride >= sizeof(GrPoint));
125 ((GrPoint*)((intptr_t)this + 0 * stride))->set(GrIntToScalar(l),
126 GrIntToScalar(t));
127 ((GrPoint*)((intptr_t)this + 1 * stride))->set(GrIntToScalar(l),
128 GrIntToScalar(b));
129 ((GrPoint*)((intptr_t)this + 2 * stride))->set(GrIntToScalar(r),
130 GrIntToScalar(b));
131 ((GrPoint*)((intptr_t)this + 3 * stride))->set(GrIntToScalar(r),
132 GrIntToScalar(t));
133 }
134
135 bool operator ==(const GrPoint& p) const {
136 return fX == p.fX && fY == p.fY;
137 }
138
139 bool operator !=(const GrPoint& p) const {
140 return fX != p.fX || fY != p.fY;
141 }
142};
143
144struct GrIPoint16 {
145 int16_t fX, fY;
146
147 void set(intptr_t x, intptr_t y) {
148 fX = GrToS16(x);
149 fY = GrToS16(y);
150 }
151};
152
153struct GrVec {
154public:
155 GrScalar fX, fY;
156
157 GrVec() {}
158 GrVec(GrScalar x, GrScalar y) { fX = x; fY = y; }
159
160 GrScalar x() const { return fX; }
161 GrScalar y() const { return fY; }
162
163 /**
164 * set x and y length of the vector.
165 */
166 void set(GrScalar x, GrScalar y) {
167 fX = x;
168 fY = y;
169 }
bsalomon@google.com205d4602011-04-25 12:43:45 +0000170
171 /**
172 * set this to (abs(v.x), abs(v.y))
173 */
174 void setAbs(const GrVec& v) {
175 fX = GrScalarAbs(v.fX);
176 fY = GrScalarAbs(v.fY);
177 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000178
179 /**
180 * set vector to point from a to b.
181 */
182 void setBetween(const GrPoint& a, const GrPoint& b) {
183 fX = b.fX - a.fX;
184 fY = b.fY - a.fY;
185 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000186
187 /**
188 * Make this vector be orthogonal to vec. Looking down vec the
189 * new vector will point left.
190 */
191 void setOrthogLeft(const GrVec& vec) {
192 // vec could be this
193 GrVec v = vec;
194 fX = -v.fY;
195 fY = v.fX;
196 }
197
198 /**
199 * Make this vector be orthogonal to vec. Looking down vec the
200 * new vector will point right.
201 */
202 void setOrthogRight(const GrVec& vec) {
203 // vec could be this
204 GrVec v = vec;
205 fX = v.fY;
206 fY = -v.fX;
207 }
208
209 /**
210 * set orthogonal to vec from a to b. Will be facing left relative to a,b
211 * vec
212 */
213 void setOrthogLeftToVecBetween(const GrPoint& a, const GrPoint& b) {
214 fX = a.fY - b.fY;
215 fY = b.fX - a.fX;
216 }
217
218 /**
219 * set orthogonal to vec from a to b. Will be facing right relative to a,b
220 * vec.
221 */
222 void setOrthogRightToVecBetween(const GrPoint& a, const GrPoint& b) {
223 fX = b.fY - a.fY;
224 fY = a.fX - b.fX;
225 }
226
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 /**
228 * length of the vector squared.
229 */
230 GrScalar lengthSqd() const {
231 return GrMul(fX, fX) + GrMul(fY, fY);
232 }
233
234 /**
235 * length of the vector.
236 */
237 GrScalar length() const {
238 // TODO: fixed point sqrt
239 return GrFloatToScalar(sqrtf(GrScalarToFloat(lengthSqd())));
240 }
241
242 /**
243 * normalizes the vector if it's length is not 0.
244 * @return true if normalized, otherwise false.
245 */
246 bool normalize() {
247 GrScalar l = lengthSqd();
248 if (l) {
249 // TODO: fixed point sqrt and invert
250 l = 1 / sqrtf(l);
251 fX *= l;
252 fY *= l;
253 return true;
254 }
255 return false;
256 }
257
258 /**
259 * Dot product of this with vec.
260 */
261 GrScalar dot(const GrVec& vec) const {
262 return GrMul(vec.fX, fX) + GrMul(vec.fY, fY);
263 }
264
265 /**
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000266 * Dot product of this vec with vector from (0,0) to a pt.
267 */
268 GrScalar dotWithVecToPt(const GrPoint& pt) const {
269 return GrMul(pt.fX, fX) + GrMul(pt.fY, fY);
270 }
271
272 /**
reed@google.comac10a2d2010-12-22 21:39:39 +0000273 * z-value of this cross vec.
274 */
275 GrScalar cross(const GrVec& vec) const {
276 return GrMul(fX, vec.fY) - GrMul(fY, vec.fX);
277 }
278
279 bool operator ==(const GrPoint& p) const {
280 return fX == p.fX && fY == p.fY;
281 }
282
283 bool operator !=(const GrPoint& p) const {
284 return fX != p.fX || fY != p.fY;
285 }
286};
287
288GrScalar GrPoint::distanceToLineBetweenSqd(const GrPoint& a,
289 const GrPoint& b) const {
290 // Let d be the distance between c (this) and line ab.
291 // The area of the triangle defined by a, b, and c is
292 // A = |b-a|*d/2. Let u = b-a and v = c-a. The cross product of
293 // u and v is aligned with the z axis and its magnitude is 2A.
294 // So d = |u x v| / |u|.
295 GrVec u, v;
296 u.setBetween(a,b);
297 v.setBetween(a,*this);
298
299 GrScalar det = u.cross(v);
300 return (GrMul(det, det)) / u.lengthSqd();
301}
302
303GrScalar GrPoint::distanceToLineBetween(const GrPoint& a,
304 const GrPoint& b) const {
305 GrVec u, v;
306 u.setBetween(a,b);
307 v.setBetween(a,*this);
308
309 GrScalar det = u.cross(v);
310 return (GrScalarAbs(det)) / u.length();
311}
312
313GrScalar GrPoint::distanceToLineSegmentBetweenSqd(const GrPoint& a,
314 const GrPoint& b) const {
315 // See comments to distanceToLineBetweenSqd. If the projection of c onto
316 // u is between a and b then this returns the same result as that
317 // function. Otherwise, it returns the distance to the closer of a and
318 // b. Let the projection of v onto u be v'. There are three cases:
319 // 1. v' points opposite to u. c is not between a and b and is closer
320 // to a than b.
321 // 2. v' points along u and has magnitude less than y. c is between
322 // a and b and the distance to the segment is the same as distance
323 // to the line ab.
324 // 3. v' points along u and has greater magnitude than u. c is not
325 // not between a and b and is closer to b than a.
326 // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
327 // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
328 // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
329 // avoid a sqrt to compute |u|.
330
331 GrVec u, v;
332 u.setBetween(a,b);
333 v.setBetween(a,*this);
334
335 GrScalar uLengthSqd = u.lengthSqd();
336 GrScalar uDotV = u.dot(v);
337
338 if (uDotV <= 0) {
339 return v.lengthSqd();
340 } else if (uDotV > uLengthSqd) {
341 return b.distanceToSqd(*this);
342 } else {
343 GrScalar det = u.cross(v);
344 return (GrMul(det, det)) / uLengthSqd;
345 }
346}
347
348GrScalar GrPoint::distanceToLineSegmentBetween(const GrPoint& a,
349 const GrPoint& b) const {
350 // TODO: fixed point sqrt
351 return GrFloatToScalar(sqrtf(GrScalarToFloat(distanceToLineSegmentBetweenSqd(a,b))));
352}
reed@google.com7744c202011-05-06 19:26:26 +0000353#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000354
355#endif
356