Root/
Source at commit 5a5bc8cbaaef2872c2e2d7cbfeab2c627721f32e created 13 years 3 months ago. By Xiangfu Liu, update the homepage to help webpage | |
---|---|
1 | /* |
2 | * coord.c - Coordinate representation and basic operations |
3 | * |
4 | * Written 2009, 2010 by Werner Almesberger |
5 | * Copyright 2009, 2010 by Werner Almesberger |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | */ |
12 | |
13 | |
14 | #include <math.h> |
15 | |
16 | #include "util.h" |
17 | #include "coord.h" |
18 | |
19 | |
20 | /* ----- unit conversion --------------------------------------------------- */ |
21 | |
22 | |
23 | double mm_to_mil(double mm, int exponent) |
24 | { |
25 | return mm*pow(MIL_IN_MM, -exponent); |
26 | } |
27 | |
28 | |
29 | double mil_to_mm(double mil, int exponent) |
30 | { |
31 | return mil*pow(MIL_IN_MM, exponent); |
32 | } |
33 | |
34 | |
35 | /* ----- convert internal units to best external unit ---------------------- */ |
36 | |
37 | |
38 | double units_to_best(unit_type u, int *mm) |
39 | { |
40 | /* |
41 | * For finding the best choice, we work with deci-micrometers and |
42 | * micro-inches. The conversion to "dum" is actually a no-op, but that |
43 | * may change if we ever pick a different internal unit than 0.1 um. |
44 | */ |
45 | |
46 | long dum = round(units_to_mm(u)*10000.0); |
47 | long uin = round(units_to_mil(u)*1000.0); |
48 | |
49 | /* remove trailing zeroes */ |
50 | |
51 | while (dum && !(dum % 10)) |
52 | dum /= 10; |
53 | while (uin && !(uin % 10)) |
54 | uin /= 10; |
55 | |
56 | /* ceil(log10(dum)) <= ceil(log10(uin)) ? */ |
57 | |
58 | while (dum && uin) { |
59 | dum /= 10; |
60 | uin /= 10; |
61 | } |
62 | if (!dum) { |
63 | *mm = 1; |
64 | return units_to_mm(u); |
65 | } else { |
66 | *mm = 0; |
67 | return units_to_mil(u); |
68 | } |
69 | } |
70 | |
71 | |
72 | /* ----- vector operations ------------------------------------------------- */ |
73 | |
74 | |
75 | struct coord normalize(struct coord v, unit_type len) |
76 | { |
77 | double f; |
78 | |
79 | f = len/hypot(v.x, v.y); |
80 | v.x *= f; |
81 | v.y *= f; |
82 | return v; |
83 | } |
84 | |
85 | |
86 | struct coord rotate(struct coord v, double angle) |
87 | { |
88 | double rad = M_PI*angle/180.0; |
89 | struct coord res; |
90 | |
91 | res.x = v.x*cos(rad)-v.y*sin(rad); |
92 | res.y = v.y*cos(rad)+v.x*sin(rad); |
93 | return res; |
94 | } |
95 | |
96 | |
97 | struct coord add_vec(struct coord a, struct coord b) |
98 | { |
99 | a.x += b.x; |
100 | a.y += b.y; |
101 | return a; |
102 | } |
103 | |
104 | |
105 | struct coord sub_vec(struct coord a, struct coord b) |
106 | { |
107 | a.x -= b.x; |
108 | a.y -= b.y; |
109 | return a; |
110 | } |
111 | |
112 | |
113 | struct coord neg_vec(struct coord v) |
114 | { |
115 | v.x = -v.x; |
116 | v.y = -v.y; |
117 | return v; |
118 | } |
119 | |
120 | |
121 | /* ----- point on circle --------------------------------------------------- */ |
122 | |
123 | |
124 | struct coord rotate_r(struct coord c, unit_type r, double angle) |
125 | { |
126 | struct coord p; |
127 | |
128 | angle = angle/180.0*M_PI; |
129 | p.x = c.x+r*cos(angle); |
130 | p.y = c.y+r*sin(angle); |
131 | return p; |
132 | } |
133 | |
134 | |
135 | double theta_vec(struct coord v) |
136 | { |
137 | double a; |
138 | |
139 | a = atan2(v.y, v.x)/M_PI*180.0; |
140 | if (a < 0) |
141 | a += 360.0; |
142 | return a; |
143 | } |
144 | |
145 | |
146 | double theta(struct coord c, struct coord p) |
147 | { |
148 | p.x -= c.x; |
149 | p.y -= c.y; |
150 | return theta_vec(p); |
151 | } |
152 | |
153 | |
154 | /* ----- sorting coordinates ----------------------------------------------- */ |
155 | |
156 | |
157 | void sort_coord(struct coord *min, struct coord *max) |
158 | { |
159 | if (min->x > max->x) |
160 | SWAP(min->x, max->x); |
161 | if (min->y > max->y) |
162 | SWAP(min->y, max->y); |
163 | |
164 | } |
165 | |
166 | |
167 | /* ----- distance calculations --------------------------------------------- */ |
168 | |
169 | |
170 | unit_type dist_point(struct coord a, struct coord b) |
171 | { |
172 | return hypot(a.x-b.x, a.y-b.y); |
173 | } |
174 | |
175 | |
176 | static unit_type dist_line_xy(unit_type px, unit_type py, |
177 | unit_type ax, unit_type ay, unit_type bx, unit_type by) |
178 | { |
179 | unit_type d_min, d; |
180 | double a, f; |
181 | |
182 | d_min = hypot(ax-px, ay-py); |
183 | d = hypot(bx-px, by-py); |
184 | if (d < d_min) |
185 | d_min = d; |
186 | if (ax != bx || ay != by) { |
187 | /* |
188 | * We make a the line vector from point B and b the vector from |
189 | * B to point P. Then we calculate the projection of b on a. |
190 | */ |
191 | ax -= bx; |
192 | ay -= by; |
193 | bx = px-bx; |
194 | by = py-by; |
195 | a = hypot(ax, ay); |
196 | f = ((double) ax*bx+(double) ay*by)/a/a; |
197 | if (f >= 0 && f <= 1) { |
198 | bx -= f*ax; |
199 | by -= f*ay; |
200 | d = hypot(bx, by); |
201 | if (d < d_min) |
202 | d_min = d; |
203 | } |
204 | } |
205 | return d_min; |
206 | } |
207 | |
208 | |
209 | unit_type dist_line(struct coord p, struct coord a, struct coord b) |
210 | { |
211 | return dist_line_xy(p.x, p.y, a.x, a.y, b.x, b.y); |
212 | } |
213 | |
214 | |
215 | unit_type dist_rect(struct coord p, struct coord a, struct coord b) |
216 | { |
217 | unit_type d_min, d; |
218 | |
219 | d_min = dist_line_xy(p.x, p.y, a.x, a.y, b.x, a.y); |
220 | d = dist_line_xy(p.x, p.y, a.x, a.y, a.x, b.y); |
221 | if (d < d_min) |
222 | d_min = d; |
223 | d = dist_line_xy(p.x, p.y, a.x, b.y, b.x, b.y); |
224 | if (d < d_min) |
225 | d_min = d; |
226 | d = dist_line_xy(p.x, p.y, b.x, a.y, b.x, b.y); |
227 | if (d < d_min) |
228 | d_min = d; |
229 | return d_min; |
230 | } |
231 | |
232 | |
233 | int inside_rect(struct coord p, struct coord a, struct coord b) |
234 | { |
235 | sort_coord(&a, &b); |
236 | if (p.x < a.x || p.x > b.x) |
237 | return 0; |
238 | if (p.y < a.y || p.y > b.y) |
239 | return 0; |
240 | return 1; |
241 | } |
242 | |
243 | |
244 | unit_type dist_circle(struct coord p, struct coord c, unit_type r) |
245 | { |
246 | unit_type d; |
247 | |
248 | d = hypot(p.x-c.x, p.y-c.y); |
249 | return fabs(d-r); |
250 | } |
251 |
Branches:
master