libgeda

s_tile.c

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines