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