GDS-Render v1.2.1
bounding-box.c
Go to the documentation of this file.
1/*
2 * GDSII-Converter
3 * Copyright (C) 2018 Mario Hüttel <mario.huettel@gmx.net>
4 *
5 * This file is part of GDSII-Converter.
6 *
7 * GDSII-Converter is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * GDSII-Converter is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
18 */
19
31#include <stdio.h>
32#include <math.h>
33
35
36#define MIN(a, b) (((a) < (b)) ? (a) : (b))
37#define MAX(a, b) (((a) > (b)) ? (a) : (b))
38#define ABS_DBL(a) ((a) < 0 ? -(a) : (a))
39
41{
42 double xmin = DBL_MAX, xmax = -DBL_MAX, ymin = DBL_MAX, ymax = -DBL_MAX;
43 struct vector_2d temp_vec;
44 GList *list_item;
45
46 /* Check for errors */
47 if (!conv_func || !box || !vertices)
48 return;
49
50 for (list_item = vertices; list_item != NULL; list_item = g_list_next(list_item)) {
51 /* Convert generic vertex to vector_2d */
52 if (conv_func)
53 conv_func((void *)list_item->data, &temp_vec);
54 else
55 vector_2d_copy(&temp_vec, (struct vector_2d *)list_item->data);
56
57 /* Update bounding coordinates with vertex */
58 xmin = MIN(xmin, temp_vec.x);
59 xmax = MAX(xmax, temp_vec.x);
60 ymin = MIN(ymin, temp_vec.y);
61 ymax = MAX(ymax, temp_vec.y);
62 }
63
64 /* Fill bounding box with results */
65 box->vectors.lower_left.x = xmin;
66 box->vectors.lower_left.y = ymin;
67 box->vectors.upper_right.x = xmax;
68 box->vectors.upper_right.y = ymax;
69}
70
71void bounding_box_update_with_box(union bounding_box *destination, union bounding_box *update)
72{
73 if (!destination || !update)
74 return;
75
76 destination->vectors.lower_left.x = MIN(destination->vectors.lower_left.x,
77 update->vectors.lower_left.x);
78 destination->vectors.lower_left.y = MIN(destination->vectors.lower_left.y,
79 update->vectors.lower_left.y);
80 destination->vectors.upper_right.x = MAX(destination->vectors.upper_right.x,
81 update->vectors.upper_right.x);
82 destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y,
83 update->vectors.upper_right.y);
84}
85
87{
88 box->vectors.lower_left.x = DBL_MAX;
89 box->vectors.lower_left.y = DBL_MAX;
90 box->vectors.upper_right.x = -DBL_MAX;
91 box->vectors.upper_right.y = -DBL_MAX;
92}
93
105static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b, struct vector_2d *c,
106 struct vector_2d *m1, struct vector_2d *m2, double width)
107{
108 double angle, angle_sin, u;
109 struct vector_2d ba, bc, u_vec, v_vec, ba_norm;
110
111 if (!a || !b || !c || !m1 || !m2)
112 return;
113
114 vector_2d_subtract(&ba, a, b);
115 vector_2d_subtract(&bc, c, b);
116
117 angle = vector_2d_calculate_angle_between(&ba, &bc);
118
119 if (ABS_DBL(angle) < 0.05 || ABS_DBL(angle - M_PI) < 0.1) {
120 /* Specail cases Don*/
121 vector_2d_copy(&ba_norm, &ba);
122 vector_2d_rotate(&ba_norm, DEG2RAD(90));
123 vector_2d_normalize(&ba_norm);
124 vector_2d_scale(&ba_norm, width/2.0);
125 vector_2d_add(m1, b, &ba_norm);
126 vector_2d_subtract(m2, b, &ba_norm);
127 return;
128 }
129 angle_sin = sin(angle);
130 u = width/(2*angle_sin);
131
132 vector_2d_copy(&u_vec, &ba);
133 vector_2d_copy(&v_vec, &bc);
134 vector_2d_normalize(&u_vec);
135 vector_2d_normalize(&v_vec);
136 vector_2d_scale(&u_vec, u);
137 vector_2d_scale(&v_vec, u);
138
139 vector_2d_copy(m1, b);
140 vector_2d_add(m1, m1, &u_vec);
141 vector_2d_add(m1, m1, &v_vec);
142
143 vector_2d_copy(m2, b);
144 vector_2d_subtract(m2, m2, &u_vec);
145 vector_2d_subtract(m2, m2, &v_vec);
146}
147
148void bounding_box_update_with_path(GList *vertices, double thickness,
149 conv_generic_to_vector_2d_t conv_func, union bounding_box *box)
150{
151 GList *vertex_iterator;
152 struct vector_2d pt;
153
154 if (!vertices || !box)
155 return;
156
157 for (vertex_iterator = vertices; vertex_iterator != NULL; vertex_iterator = g_list_next(vertex_iterator)) {
158
159 if (conv_func != NULL)
160 conv_func(vertex_iterator->data, &pt);
161 else
162 (void)vector_2d_copy(&pt, (struct vector_2d *)vertex_iterator->data);
163
164 /* These are approximations.
165 * Used as long as miter point calculation is not fully implemented
166 */
167 box->vectors.lower_left.x = MIN(box->vectors.lower_left.x, pt.x - thickness/2);
168 box->vectors.lower_left.y = MIN(box->vectors.lower_left.y, pt.y - thickness/2);
169 box->vectors.upper_right.x = MAX(box->vectors.upper_right.x, pt.x + thickness/2);
170 box->vectors.upper_right.y = MAX(box->vectors.upper_right.y, pt.y + thickness/2);
171 }
172}
173
175{
176 struct vector_2d point;
177
178 if (!destination || !pt)
179 return;
180
181 if (conv_func)
182 conv_func(pt, &point);
183 else
184 (void)vector_2d_copy(&point, (struct vector_2d *)pt);
185
186 destination->vectors.lower_left.x = MIN(destination->vectors.lower_left.x, point.x);
187 destination->vectors.lower_left.y = MIN(destination->vectors.lower_left.y, point.y);
188 destination->vectors.upper_right.x = MAX(destination->vectors.upper_right.x, point.x);
189 destination->vectors.upper_right.y = MAX(destination->vectors.upper_right.y, point.y);
190}
191
192void bounding_box_get_all_points(struct vector_2d *points, union bounding_box *box)
193{
194 if (!points || !box)
195 return;
196
197 points[0].x = box->vectors.lower_left.x;
198 points[0].y = box->vectors.lower_left.y;
199 points[1].x = box->vectors.upper_right.x;
200 points[1].y = box->vectors.lower_left.y;
201 points[2].x = box->vectors.upper_right.x;
202 points[2].y = box->vectors.upper_right.y;
203 points[3].x = box->vectors.lower_left.x;
204 points[3].y = box->vectors.upper_right.y;
205}
206
207void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box)
208{
209 int i;
210 struct vector_2d input_points[4];
211
212 if (!box)
213 return;
214
215 bounding_box_get_all_points(input_points, box);
216
217 /* Reset box */
219
220 for (i = 0; i < 4; i++) {
221 input_points[i].y *= (flip_at_x ? -1 : 1);
222 vector_2d_rotate(&input_points[i], rotation_deg * M_PI / 180.0);
223 vector_2d_scale(&input_points[i], scale);
224
225 bounding_box_update_with_point(box, NULL, &input_points[i]);
226 }
227}
228
Header for calculation of bounding boxes.
void bounding_box_prepare_empty(union bounding_box *box)
Prepare an empty bounding box.
Definition: bounding-box.c:86
void vector_2d_scale(struct vector_2d *vec, double scale)
#define MIN(a, b)
Return smaller number.
Definition: bounding-box.c:36
#define DEG2RAD(a)
static void calculate_path_miter_points(struct vector_2d *a, struct vector_2d *b, struct vector_2d *c, struct vector_2d *m1, struct vector_2d *m2, double width)
Calculate path miter points for a pathwith a width and the anchors a b c.
Definition: bounding-box.c:105
void bounding_box_get_all_points(struct vector_2d *points, union bounding_box *box)
Return all four corner points of a bounding box.
Definition: bounding-box.c:192
void bounding_box_update_with_path(GList *vertices, double thickness, conv_generic_to_vector_2d_t conv_func, union bounding_box *box)
Calculate the bounding box of a path and update the given bounding box.
Definition: bounding-box.c:148
void vector_2d_rotate(struct vector_2d *vec, double angle)
struct vector_2d * vector_2d_copy(struct vector_2d *opt_res, struct vector_2d *vec)
void vector_2d_normalize(struct vector_2d *vec)
void(* conv_generic_to_vector_2d_t)(void *, struct vector_2d *)
Definition: bounding-box.h:76
double vector_2d_calculate_angle_between(struct vector_2d *a, struct vector_2d *b)
void vector_2d_subtract(struct vector_2d *res, struct vector_2d *a, struct vector_2d *b)
void vector_2d_add(struct vector_2d *res, struct vector_2d *a, struct vector_2d *b)
void bounding_box_apply_transform(double scale, double rotation_deg, bool flip_at_x, union bounding_box *box)
Apply transformations onto bounding box.
Definition: bounding-box.c:207
#define ABS_DBL(a)
Definition: bounding-box.c:38
void bounding_box_calculate_from_polygon(GList *vertices, conv_generic_to_vector_2d_t conv_func, union bounding_box *box)
Calculate bounding box of polygon.
Definition: bounding-box.c:40
void bounding_box_update_with_point(union bounding_box *destination, conv_generic_to_vector_2d_t conv_func, void *pt)
Update bounding box with a point.
Definition: bounding-box.c:174
void bounding_box_update_with_box(union bounding_box *destination, union bounding_box *update)
Update an exisitng bounding box with another one.
Definition: bounding-box.c:71
#define MAX(a, b)
Return bigger number.
Definition: bounding-box.c:37
struct vector_2d upper_right
Upper right point of the bounding box.
Definition: bounding-box.h:64
struct vector_2d lower_left
Lower left point of the bounding box.
Definition: bounding-box.h:62
Union describing a bounding box.
Definition: bounding-box.h:55
struct bounding_box::_vectors vectors