libgeda
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * libgeda - gEDA's library 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 #include <config.h> 00021 00022 #include <stdio.h> 00023 #ifdef HAVE_STDLIB_H 00024 #include <stdlib.h> 00025 #endif 00026 #include <ctype.h> 00027 #include <math.h> 00028 00029 #include "libgeda_priv.h" 00030 00031 #ifdef HAVE_LIBDMALLOC 00032 #include <dmalloc.h> 00033 #endif 00034 00058 void s_tile_init(TOPLEVEL * toplevel, PAGE * p_current) 00059 { 00060 int i, j; 00061 TILE *t_current; 00062 int x_size = toplevel->init_right / MAX_TILES_X; 00063 int y_size = toplevel->init_bottom / MAX_TILES_Y; 00064 int x_sum = 0; 00065 int y_sum = 0; 00066 00067 #if DEBUG 00068 printf("X, Y: %d %d\n", x_size, y_size); 00069 #endif 00070 00071 for (j = 0; j < MAX_TILES_Y; j++) { 00072 for (i = 0; i < MAX_TILES_X; i++) { 00073 t_current = &p_current->world_tiles[i][j]; 00074 00075 t_current->objects = NULL; 00076 00077 t_current->left = x_sum; 00078 t_current->right = x_sum + x_size; 00079 00080 t_current->top = y_sum; 00081 t_current->bottom = y_sum + y_size; 00082 00083 x_sum = x_sum + x_size; 00084 } 00085 x_sum = 0; 00086 y_sum = y_sum + y_size; 00087 } 00088 00089 #if DEBUG 00090 for (j = 0; j < MAX_TILES_Y; j++) { 00091 for (i = 0; i < MAX_TILES_X; i++) { 00092 t_current = &p_current->world_tiles[i][j]; 00093 printf("\n%d %d\n", i, j); 00094 printf("----------------\n"); 00095 printf("left %d top %d\n", t_current->left, t_current->top); 00096 printf("right %d bottom %d\n", t_current->right, 00097 t_current->bottom); 00098 } 00099 } 00100 #endif 00101 } 00102 00112 static void s_tile_add_line_object (TOPLEVEL *toplevel, OBJECT *object) 00113 { 00114 TILE *t_current; 00115 PAGE *p_current; 00116 GList *found; 00117 int i, j; 00118 int v, w; 00119 double x1, y1, x2, y2; 00120 double bottom; 00121 double m, b; 00122 double x_size, y_size; 00123 double x, y; 00124 int start, end; 00125 00126 #if DEBUG 00127 printf("name: %s\n", object->name); 00128 #endif 00129 00130 g_return_if_fail (object != NULL); 00131 g_return_if_fail (object->line != NULL); 00132 00133 p_current = o_get_page (toplevel, object); 00134 00135 if (p_current == NULL) { 00136 return; 00137 } 00138 00139 x_size = (double) toplevel->init_right / (double) MAX_TILES_X; 00140 y_size = (double) toplevel->init_bottom / (double) MAX_TILES_Y; 00141 00142 x1 = (int) (object->line->x[0] / x_size); 00143 x2 = (int) (object->line->x[1] / x_size); 00144 y1 = (int) (object->line->y[0] / y_size); 00145 y2 = (int) (object->line->y[1] / y_size); 00146 00147 bottom = x2 - x1; 00148 00149 if (bottom != 0.0) { 00150 m = (double) (y2 - y1) / bottom; 00151 b = y1 - m * x1; 00152 00153 start = min((int) x1, (int) x2); 00154 end = max((int) x1, (int) x2); 00155 for (i = start; i <= end; i++) { 00156 x = i; 00157 y = m * x + b; 00158 if (floor(y) != ceil(y)) { 00159 00160 v = (int) x; 00161 w = (int) floor(y); 00162 if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) { 00163 return; 00164 } 00165 /* g_assert(v < MAX_TILES_X && w < MAX_TILES_Y && v >= 0 && w >= 0); */ 00166 t_current = &p_current->world_tiles[v][w]; 00167 found = g_list_find(t_current->objects, object); 00168 00169 if (!found) { 00170 /*printf("%d %d\n", v, w);*/ 00171 t_current->objects = g_list_append(t_current->objects, 00172 object); 00173 object->tiles = g_list_append(object->tiles, t_current); 00174 } 00175 00176 v = (int) x; 00177 w = (int) ceil(y); 00178 if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) { 00179 return; 00180 } 00181 /*g_assert(v < MAX_TILES_X && w < MAX_TILES_Y && v >= 0 && w >= 0);*/ 00182 t_current = &p_current->world_tiles[v][w]; 00183 found = g_list_find(t_current->objects, object); 00184 00185 if (!found) { 00186 /*printf("%d %d\n", v, w);*/ 00187 t_current->objects = g_list_append(t_current->objects, 00188 object); 00189 object->tiles = g_list_append(object->tiles, t_current); 00190 } 00191 00192 } else { 00193 v = (int) x; 00194 w = (int) floor(y); 00195 if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) { 00196 return; 00197 } 00198 /*g_assert(v < MAX_TILES_X && w < MAX_TILES_Y && v >= 0 && w >= 0);*/ 00199 t_current = &p_current->world_tiles[v][w]; 00200 found = g_list_find(t_current->objects, object); 00201 00202 if (!found) { 00203 /*printf("%d %d\n", v, w);*/ 00204 t_current->objects = g_list_append(t_current->objects, 00205 object); 00206 object->tiles = g_list_append(object->tiles, t_current); 00207 } 00208 } 00209 } 00210 00211 if (m != 0.0) { 00212 start = min((int) y1, (int) y2); 00213 end = max((int) y1, (int) y2); 00214 for (j = start; j <= end; j++) { 00215 y = j; 00216 x = (y - b) / m; 00217 if (floor(x) != ceil(x)) { 00218 w = (int) y; 00219 v = (int) floor(x); 00220 if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) { 00221 return; 00222 } 00223 /*g_assert(v < MAX_TILES_X && w < MAX_TILES_Y && 00224 v >= 0 && w >= 0);*/ 00225 t_current = &p_current->world_tiles[v][w]; 00226 found = g_list_find(t_current->objects, object); 00227 00228 if (!found) { 00229 /*printf("%d %d\n", v, w);*/ 00230 t_current->objects = 00231 g_list_append(t_current->objects, object); 00232 object->tiles = g_list_append(object->tiles, t_current); 00233 } 00234 00235 w = (int) y; 00236 v = (int) ceil(x); 00237 if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) { 00238 return; 00239 } 00240 /* g_assert(v < MAX_TILES_X && w < MAX_TILES_Y && 00241 v >= 0 && w >= 0);*/ 00242 t_current = &p_current->world_tiles[v][w]; 00243 found = g_list_find(t_current->objects, object); 00244 00245 if (!found) { 00246 /*printf("%d %d\n", v, w);*/ 00247 t_current->objects = 00248 g_list_append(t_current->objects, object); 00249 object->tiles = g_list_append(object->tiles, t_current); 00250 } 00251 00252 } else { 00253 w = (int) y; 00254 v = (int) floor(x); 00255 if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) { 00256 return; 00257 } 00258 /*g_assert(v < MAX_TILES_X && w < MAX_TILES_Y && 00259 v >= 0 && w >= 0);*/ 00260 t_current = &p_current->world_tiles[v][w]; 00261 found = g_list_find(t_current->objects, object); 00262 00263 if (!found) { 00264 /*printf("%d %d\n", v, w);*/ 00265 t_current->objects = 00266 g_list_append(t_current->objects, object); 00267 object->tiles = g_list_append(object->tiles, t_current); 00268 } 00269 } 00270 } 00271 } 00272 } else { 00273 start = min((int) y1, (int) y2); 00274 end = max((int) y1, (int) y2); 00275 for (j = start; j <= end; j++) { 00276 00277 y = j; 00278 x = x1; 00279 v = (int) x; 00280 w = (int) y; 00281 if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) { 00282 return; 00283 } 00284 /*g_assert(v < MAX_TILES_X && w < MAX_TILES_Y && 00285 v >= 0 && w >= 0);*/ 00286 t_current = &p_current->world_tiles[v][w]; 00287 found = g_list_find(t_current->objects, object); 00288 00289 if (!found) { 00290 /*printf("%d %d\n", v, w);*/ 00291 t_current->objects = g_list_append(t_current->objects, 00292 object); 00293 object->tiles = g_list_append(object->tiles, t_current); 00294 } 00295 00296 } 00297 } 00298 } 00299 00308 void s_tile_add_object (TOPLEVEL *toplevel, OBJECT *object) 00309 { 00310 GList *iter; 00311 00312 switch (object->type) { 00313 case OBJ_NET: 00314 case OBJ_PIN: 00315 case OBJ_BUS: 00316 s_tile_add_line_object (toplevel, object); 00317 break; 00318 00319 case OBJ_COMPLEX: 00320 case OBJ_PLACEHOLDER: 00321 for (iter = object->complex->prim_objs; 00322 iter != NULL; 00323 iter = g_list_next (iter)) { 00324 s_tile_add_object (toplevel, iter->data); 00325 } 00326 } 00327 } 00328 00335 void s_tile_remove_object(OBJECT *object) 00336 { 00337 GList *iter; 00338 GList *tl_current; 00339 00340 /* Correctly deal with compound objects */ 00341 if (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER) { 00342 for (iter = object->complex->prim_objs; 00343 iter != NULL; 00344 iter = g_list_next (iter)) { 00345 s_tile_remove_object (iter->data); 00346 } 00347 } 00348 00349 for (tl_current = object->tiles; 00350 tl_current != NULL; 00351 tl_current = g_list_next (tl_current)) { 00352 TILE *t_current = (TILE*)tl_current->data; 00353 00354 /* remove object from the list of objects for this tile */ 00355 t_current->objects = g_list_remove(t_current->objects, object); 00356 } 00357 00358 /* reset the list of tiles for this object appears in */ 00359 g_list_free(object->tiles); 00360 object->tiles = NULL; 00361 } 00362 00370 void s_tile_update_object(TOPLEVEL * toplevel, OBJECT * object) 00371 { 00372 s_tile_remove_object (object); 00373 s_tile_add_object (toplevel, object); 00374 } 00375 00376 00383 GList* s_tile_get_objectlists(TOPLEVEL *toplevel, PAGE *p_current, 00384 int world_x1, int world_y1, 00385 int world_x2, int world_y2) 00386 { 00387 TILE *t_current; 00388 int x1, x2, y1, y2, x, y; 00389 double x_size, y_size; 00390 GList *objectlists = NULL; 00391 00392 x_size = (double) toplevel->init_right / (double) MAX_TILES_X; 00393 y_size = (double) toplevel->init_bottom / (double) MAX_TILES_Y; 00394 00395 x1 = (int) (world_x1 / x_size); 00396 x2 = (int) (world_x2 / x_size); 00397 y1 = (int) (world_y1 / y_size); 00398 y2 = (int) (world_y2 / y_size); 00399 00400 /* limit all tile ranges to [0, MAX_TILES-1] 00401 (paranoid error checking) */ 00402 x1= max(x1, 0); x1 = min(x1, MAX_TILES_X-1); 00403 x2= max(x2, 0); x2 = min(x2, MAX_TILES_X-1); 00404 y1= max(y1, 0); y1 = min(y1, MAX_TILES_Y-1); 00405 y2= max(y2, 0); y2 = min(y2, MAX_TILES_Y-1); 00406 00407 /* Check and correct the order of the coordinates */ 00408 if (x1 > x2) { 00409 x = x1; x1 = x2; x2 = x; 00410 } 00411 if (y1 > y2) { 00412 y = y1; y1 = y2; y2 = y; 00413 } 00414 00415 /* finally, collect all object lists from the tiles */ 00416 for (x = x1; x <= x2; x++) { 00417 for (y = y1; y <= y2; y++) { 00418 t_current = &p_current->world_tiles[x][y]; 00419 objectlists = g_list_append(objectlists, t_current->objects); 00420 } 00421 } 00422 00423 return objectlists; 00424 } 00425 00426 00432 void s_tile_print(TOPLEVEL * toplevel, PAGE *page) 00433 { 00434 TILE *t_current; 00435 GList *temp; 00436 OBJECT *o_current; 00437 int i, j; 00438 00439 for (j = 0; j < MAX_TILES_Y; j++) { 00440 for (i = 0; i < MAX_TILES_X; i++) { 00441 printf("\nTile %d %d\n", i, j); 00442 00443 t_current = &page->world_tiles[i][j]; 00444 00445 temp = t_current->objects; 00446 while (temp) { 00447 o_current = (OBJECT *) temp->data; 00448 00449 printf("%s\n", o_current->name); 00450 00451 temp = g_list_next(temp); 00452 } 00453 00454 printf("------------------\n"); 00455 } 00456 } 00457 00458 } 00459 00468 void s_tile_free_all(PAGE * p_current) 00469 { 00470 int i, j; 00471 TILE *t_current; 00472 00473 for (j = 0; j < MAX_TILES_Y; j++) { 00474 for (i = 0; i < MAX_TILES_X; i++) { 00475 t_current = &p_current->world_tiles[i][j]; 00476 if (g_list_length(t_current->objects) != 0) { 00477 fprintf(stderr, 00478 "OOPS! t_current->objects had something in it when it was freed!\n"); 00479 fprintf(stderr, "Length: %d\n", g_list_length(t_current->objects)); 00480 } 00481 g_list_free(t_current->objects); 00482 } 00483 } 00484 } 00485 00486 00487