pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 /* GTS - Library for the manipulation of triangulated surfaces 00002 * Copyright (C) 1999 Stéphane Popinet 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this library; if not, write to the 00016 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 * Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include <math.h> 00021 #include "gts.h" 00022 00023 static void cluster_destroy (GtsObject * object) 00024 { 00025 GtsCluster * c = GTS_CLUSTER (object); 00026 00027 if (c->v && gts_vertex_is_unattached (c->v)) 00028 gts_object_destroy (GTS_OBJECT (c->v)); 00029 00030 /* do not forget to call destroy method of the parent */ 00031 (* GTS_OBJECT_CLASS (gts_cluster_class ())->parent_class->destroy) (object); 00032 } 00033 00034 static void cluster_add (GtsCluster * c, GtsPoint * p, gpointer data) 00035 { 00036 GtsPoint * cp; 00037 00038 g_return_if_fail (c != NULL); 00039 g_return_if_fail (c->v != NULL); 00040 g_return_if_fail (p != NULL); 00041 00042 cp = GTS_POINT (c->v); 00043 00044 cp->x += p->x; 00045 cp->y += p->y; 00046 cp->z += p->z; 00047 c->n++; 00048 } 00049 00050 static void cluster_update (GtsCluster * c) 00051 { 00052 GtsPoint * p; 00053 00054 g_return_if_fail (c != NULL); 00055 g_return_if_fail (c->v != NULL); 00056 00057 if (c->n > 1) { 00058 p = GTS_POINT (c->v); 00059 p->x /= c->n; 00060 p->y /= c->n; 00061 p->z /= c->n; 00062 } 00063 } 00064 00065 static void cluster_class_init (GtsClusterClass * klass) 00066 { 00067 klass->add = cluster_add; 00068 klass->update = cluster_update; 00069 00070 GTS_OBJECT_CLASS (klass)->destroy = cluster_destroy; 00071 } 00072 00073 static void cluster_init (GtsCluster * c) 00074 { 00075 c->v = NULL; 00076 c->n = 0; 00077 } 00078 00084 GtsClusterClass * gts_cluster_class (void) 00085 { 00086 static GtsClusterClass * klass = NULL; 00087 00088 if (klass == NULL) { 00089 GtsObjectClassInfo cluster_info = { 00090 "GtsCluster", 00091 sizeof (GtsCluster), 00092 sizeof (GtsClusterClass), 00093 (GtsObjectClassInitFunc) cluster_class_init, 00094 (GtsObjectInitFunc) cluster_init, 00095 (GtsArgSetFunc) NULL, 00096 (GtsArgGetFunc) NULL 00097 }; 00098 klass = gts_object_class_new (gts_object_class (), &cluster_info); 00099 } 00100 00101 return klass; 00102 } 00103 00112 GtsCluster * gts_cluster_new (GtsClusterClass * klass, 00113 GtsClusterId id, 00114 GtsVertexClass * vklass) 00115 { 00116 GtsCluster * c; 00117 00118 c = GTS_CLUSTER (gts_object_new (GTS_OBJECT_CLASS (klass))); 00119 c->id = id; 00120 c->v = gts_vertex_new (vklass, 0., 0., 0.); 00121 00122 return c; 00123 } 00124 00133 void gts_cluster_add (GtsCluster * c, GtsPoint * p, gpointer data) 00134 { 00135 g_return_if_fail (c != NULL); 00136 g_return_if_fail (p != NULL); 00137 00138 (* GTS_CLUSTER_CLASS (GTS_OBJECT (c)->klass)->add) (c, p, data); 00139 } 00140 00148 void gts_cluster_update (GtsCluster * c) 00149 { 00150 g_return_if_fail (c != NULL); 00151 00152 (* GTS_CLUSTER_CLASS (GTS_OBJECT (c)->klass)->update) (c); 00153 } 00154 00155 static void destroy_cluster (GtsClusterId * id, GtsObject * cluster) 00156 { 00157 gts_object_destroy (cluster); 00158 } 00159 00160 static void cluster_grid_destroy (GtsObject * object) 00161 { 00162 GtsClusterGrid * cluster_grid = GTS_CLUSTER_GRID (object); 00163 00164 g_hash_table_foreach (cluster_grid->clusters, 00165 (GHFunc) destroy_cluster, NULL); 00166 g_hash_table_destroy (cluster_grid->clusters); 00167 00168 (* GTS_OBJECT_CLASS (gts_cluster_grid_class ())->parent_class->destroy) 00169 (object); 00170 } 00171 00172 static void cluster_grid_class_init (GtsClusterGridClass * klass) 00173 { 00174 GTS_OBJECT_CLASS (klass)->destroy = cluster_grid_destroy; 00175 } 00176 00177 static gint cluster_id_equal (gconstpointer v1, 00178 gconstpointer v2) 00179 { 00180 const GtsClusterId * id1 = (const GtsClusterId *) v1; 00181 const GtsClusterId * id2 = (const GtsClusterId *) v2; 00182 return ((id1->x == id2->x) && (id1->y == id2->y) && (id1->z == id2->z)); 00183 } 00184 00185 static guint cluster_id_hash (gconstpointer key) 00186 { 00187 const GtsClusterId * id = (const GtsClusterId *) key; 00188 return id->x + id->y + id->z; 00189 } 00190 00191 static void cluster_grid_init (GtsClusterGrid * cluster_grid) 00192 { 00193 cluster_grid->surface = NULL; 00194 cluster_grid->bbox = NULL; 00195 cluster_grid->cluster_class = gts_cluster_class (); 00196 cluster_grid->clusters = g_hash_table_new (cluster_id_hash, 00197 cluster_id_equal); 00198 } 00199 00205 GtsClusterGridClass * gts_cluster_grid_class (void) 00206 { 00207 static GtsClusterGridClass * klass = NULL; 00208 00209 if (klass == NULL) { 00210 GtsObjectClassInfo cluster_grid_info = { 00211 "GtsClusterGrid", 00212 sizeof (GtsClusterGrid), 00213 sizeof (GtsClusterGridClass), 00214 (GtsObjectClassInitFunc) cluster_grid_class_init, 00215 (GtsObjectInitFunc) cluster_grid_init, 00216 (GtsArgSetFunc) NULL, 00217 (GtsArgGetFunc) NULL 00218 }; 00219 klass = gts_object_class_new (gts_object_class (), &cluster_grid_info); 00220 } 00221 00222 return klass; 00223 } 00224 00235 GtsClusterGrid * gts_cluster_grid_new (GtsClusterGridClass * klass, 00236 GtsClusterClass * cluster_class, 00237 GtsSurface * s, 00238 GtsBBox * bbox, 00239 gdouble delta) 00240 { 00241 GtsClusterGrid * cluster_grid; 00242 GtsVector size; 00243 00244 g_return_val_if_fail (klass != NULL, NULL); 00245 g_return_val_if_fail (cluster_class != NULL, NULL); 00246 g_return_val_if_fail (s != NULL, NULL); 00247 g_return_val_if_fail (bbox != NULL, NULL); 00248 g_return_val_if_fail (delta > 0., NULL); 00249 00250 size[0] = ceil ((bbox->x2 - bbox->x1)/delta); 00251 size[1] = ceil ((bbox->y2 - bbox->y1)/delta); 00252 size[2] = ceil ((bbox->z2 - bbox->z1)/delta); 00253 g_return_val_if_fail (size[0] <= 2.*G_MAXINT + 2. && 00254 size[1] <= 2.*G_MAXINT + 2. && 00255 size[2] <= 2.*G_MAXINT + 2., NULL); 00256 cluster_grid = 00257 GTS_CLUSTER_GRID (gts_object_new (GTS_OBJECT_CLASS (klass))); 00258 cluster_grid->cluster_class = cluster_class; 00259 cluster_grid->surface = s; 00260 cluster_grid->bbox = bbox; 00261 cluster_grid->size[0] = size[0]; 00262 cluster_grid->size[1] = size[1]; 00263 cluster_grid->size[2] = size[2]; 00264 00265 return cluster_grid; 00266 } 00267 00268 static GtsClusterId cluster_index (GtsPoint * p, 00269 GtsBBox * bb, 00270 GtsVector n) 00271 { 00272 GtsClusterId id = {0, 0, 0}; 00273 00274 g_return_val_if_fail (p->x >= bb->x1 && p->x <= bb->x2, id); 00275 g_return_val_if_fail (p->y >= bb->y1 && p->y <= bb->y2, id); 00276 g_return_val_if_fail (p->z >= bb->z1 && p->z <= bb->z2, id); 00277 00278 id.x = (guint) (p->x == bb->x2 ? n[0] - 1. : n[0]*(p->x - bb->x1)/(bb->x2 - bb->x1)); 00279 id.y = (guint) (p->y == bb->y2 ? n[1] - 1. : n[1]*(p->y - bb->y1)/(bb->y2 - bb->y1)); 00280 id.z = (guint) (p->z == bb->z2 ? n[2] - 1. : n[2]*(p->z - bb->z1)/(bb->z2 - bb->z1)); 00281 00282 return id; 00283 } 00284 00285 static GtsCluster * cluster_grid_add_point (GtsClusterGrid * cluster_grid, 00286 GtsPoint * p, 00287 gpointer data) 00288 { 00289 GtsClusterId id = cluster_index (p, 00290 cluster_grid->bbox, 00291 cluster_grid->size); 00292 GtsCluster * c = g_hash_table_lookup (cluster_grid->clusters, &id); 00293 00294 if (c == NULL) { 00295 c = gts_cluster_new (cluster_grid->cluster_class, id, 00296 cluster_grid->surface->vertex_class); 00297 g_hash_table_insert (cluster_grid->clusters, &c->id, c); 00298 } 00299 00300 gts_cluster_add (c, p, data); 00301 00302 return c; 00303 } 00304 00316 void gts_cluster_grid_add_triangle (GtsClusterGrid * cluster_grid, 00317 GtsPoint * p1, 00318 GtsPoint * p2, 00319 GtsPoint * p3, 00320 gpointer data) 00321 { 00322 GtsCluster * c1, * c2, * c3; 00323 00324 g_return_if_fail (cluster_grid != NULL); 00325 g_return_if_fail (p1 != NULL); 00326 g_return_if_fail (p2 != NULL); 00327 g_return_if_fail (p3 != NULL); 00328 g_return_if_fail (cluster_grid->surface != NULL); 00329 00330 c1 = cluster_grid_add_point (cluster_grid, p1, data); 00331 c2 = cluster_grid_add_point (cluster_grid, p2, data); 00332 c3 = cluster_grid_add_point (cluster_grid, p3, data); 00333 00334 if (c1 != c2 && c2 != c3 && c3 != c1) { 00335 GtsVertex * v1, * v2, * v3; 00336 GtsEdge * e1, * e2, * e3; 00337 gboolean new_edge = FALSE; 00338 00339 v1 = c1->v; v2 = c2->v; v3 = c3->v; 00340 00341 if ((e1 = GTS_EDGE (gts_vertices_are_connected (v1, v2))) == NULL) { 00342 e1 = gts_edge_new (cluster_grid->surface->edge_class, v1, v2); 00343 new_edge = TRUE; 00344 } 00345 if ((e2 = GTS_EDGE (gts_vertices_are_connected (v2, v3))) == NULL) { 00346 e2 = gts_edge_new (cluster_grid->surface->edge_class, v2, v3); 00347 new_edge = TRUE; 00348 } 00349 if ((e3 = GTS_EDGE (gts_vertices_are_connected (v3, v1))) == NULL) { 00350 e3 = gts_edge_new (cluster_grid->surface->edge_class, v3, v1); 00351 new_edge = TRUE; 00352 } 00353 if (new_edge || !gts_triangle_use_edges (e1, e2, e3)) 00354 gts_surface_add_face (cluster_grid->surface, 00355 gts_face_new (cluster_grid->surface->face_class, 00356 e1, e2, e3)); 00357 } 00358 } 00359 00360 static void update_cluster (gint * id, GtsCluster * cluster, GtsRange * stats) 00361 { 00362 gts_cluster_update (cluster); 00363 gts_range_add_value (stats, cluster->n); 00364 } 00365 00375 GtsRange gts_cluster_grid_update (GtsClusterGrid * cluster_grid) 00376 { 00377 GtsRange stats; 00378 00379 gts_range_init (&stats); 00380 g_return_val_if_fail (cluster_grid != NULL, stats); 00381 00382 g_hash_table_foreach (cluster_grid->clusters, 00383 (GHFunc) update_cluster, &stats); 00384 gts_range_update (&stats); 00385 00386 return stats; 00387 }