gerb_image.c

Go to the documentation of this file.
00001 /*
00002  * gEDA - GNU Electronic Design Automation
00003  * This files is a part of gerbv.
00004  *
00005  *   Copyright (C) 2000-2003 Stefan Petersen (spe@stacken.kth.se)
00006  *
00007  * $Id$
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
00022  */
00023 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <glib.h>
00036 #include <math.h>
00037 
00038 #include "gerbv.h"
00039 #include "gerb_image.h"
00040 #include "gerber.h"
00041 #include "amacro.h"
00042 
00043 typedef struct {
00044     int oldAperture;
00045     int newAperture;
00046 } gerb_translation_entry_t;
00047 
00048 gerbv_image_t *
00049 gerbv_create_image(gerbv_image_t *image, const gchar *type)
00050 {
00051     gerbv_destroy_image(image);
00052     
00053     /* Malloc space for image */
00054     if ((image = (gerbv_image_t *)g_malloc(sizeof(gerbv_image_t))) == NULL) {
00055        return NULL;
00056     }
00057     memset((void *)image, 0, sizeof(gerbv_image_t));
00058     
00059     /* Malloc space for image->netlist */
00060     if ((image->netlist = (gerbv_net_t *)g_malloc(sizeof(gerbv_net_t))) == NULL) {
00061        g_free(image);
00062        return NULL;
00063     }
00064     memset((void *)image->netlist, 0, sizeof(gerbv_net_t));
00065     
00066     /* Malloc space for image->info */
00067     if ((image->info = (gerbv_image_info_t *)g_malloc(sizeof(gerbv_image_info_t))) == NULL) {
00068        g_free(image->netlist);
00069        g_free(image);
00070        return NULL;
00071     }
00072     memset((void *)image->info, 0, sizeof(gerbv_image_info_t));
00073     
00074     /* Set aside position for stats struct */
00075     image->gerbv_stats = NULL;
00076     image->drill_stats = NULL;
00077 
00078     image->info->min_x = HUGE_VAL;
00079     image->info->min_y = HUGE_VAL;
00080     image->info->max_x = -HUGE_VAL;
00081     image->info->max_y = -HUGE_VAL;
00082 
00083     /* create our first layer and fill with non-zero default values */
00084     image->layers = g_new0 (gerbv_layer_t, 1);
00085     image->layers->stepAndRepeat.X = 1;
00086     image->layers->stepAndRepeat.Y = 1;
00087     image->layers->polarity = GERBV_POLARITY_DARK;
00088     
00089     /* create our first netstate and fill with non-zero default values */
00090     image->states = g_new0 (gerbv_netstate_t, 1);
00091     image->states->scaleA = 1;
00092     image->states->scaleB = 1;
00093 
00094     /* fill in some values for our first net */
00095     image->netlist->layer = image->layers;
00096     image->netlist->state = image->states;
00097     
00098     if (type == NULL)
00099        image->info->type = g_strdup ("unknown");
00100     else
00101        image->info->type = g_strdup (type);
00102 
00103     /* the individual file parsers will have to set this. */
00104     image->info->attr_list = NULL;
00105     image->info->n_attr = 0;
00106 
00107     return image;
00108 }
00109 
00110 
00111 void
00112 gerbv_destroy_image(gerbv_image_t *image)
00113 {
00114     int i;
00115     gerbv_net_t *net, *tmp;
00116     gerbv_layer_t *layer;
00117     gerbv_netstate_t *state;
00118     
00119     if(image==NULL)
00120         return;
00121         
00122     /*
00123      * Free apertures
00124      */
00125     for (i = 0; i < APERTURE_MAX; i++) 
00126        if (image->aperture[i] != NULL) {
00127            g_free(image->aperture[i]);
00128            image->aperture[i] = NULL;
00129        }
00130 
00131     /*
00132      * Free aperture macro
00133      */
00134     if (image->amacro)
00135        free_amacro(image->amacro);
00136 
00137     /*
00138      * Free format
00139      */
00140     if (image->format)
00141        g_free(image->format);
00142     
00143     /*
00144      * Free info
00145      */
00146     if (image->info) {
00147        if (image->info->name)
00148            g_free(image->info->name);
00149 
00150        if (image->info->type)
00151            g_free(image->info->type);
00152 
00153        g_free(image->info);
00154     }
00155     
00156     /*
00157      * Free netlist
00158      */
00159     for (net = image->netlist; net != NULL; ) {
00160        tmp = net; 
00161        net = net->next; 
00162        if (tmp->cirseg != NULL) {
00163            g_free(tmp->cirseg);
00164            tmp->cirseg = NULL;
00165        }
00166        if (tmp->label) {
00167               g_string_free (tmp->label, TRUE);
00168        }
00169        g_free(tmp);
00170        tmp = NULL;
00171     }
00172     for (layer = image->layers; layer != NULL; ) {
00173        gerbv_layer_t *tempLayer = layer;
00174        
00175        layer = layer->next;
00176        g_free (tempLayer);
00177     }
00178     for (state = image->states; state != NULL; ) {
00179        gerbv_netstate_t *tempState = state;
00180        
00181        state = state->next;
00182        g_free (tempState);
00183     }
00184     /* FIXME -- must write these functions. */
00185     /*   gerb_transf_free(image->transf); */
00186     /*   gerb_stats_free(image->gerb_stats); */
00187     /*   gerb_stats_free(image->drill_stats); */
00188 
00189     /*
00190      * Free and reset the final image
00191      */
00192     g_free(image);
00193     image = NULL;
00194     
00195     return;
00196 }
00197 
00198 
00199 /*
00200  * Check that the parsed gerber image is complete.
00201  * Returned errorcodes are:
00202  * 0: No problems
00203  * 1: Missing netlist
00204  * 2: Missing format
00205  * 4: Missing apertures
00206  * 8: Missing info
00207  * It could be any of above or'ed together
00208  */
00209 gerb_verify_error_t
00210 gerbv_image_verify(gerbv_image_t const* image)
00211 {
00212     gerb_verify_error_t error = GERB_IMAGE_OK;
00213     int i, n_nets;;
00214     gerbv_net_t *net;
00215 
00216     if (image->netlist == NULL) error |= GERB_IMAGE_MISSING_NETLIST;
00217     if (image->format == NULL)  error |= GERB_IMAGE_MISSING_FORMAT;
00218     if (image->info == NULL)    error |= GERB_IMAGE_MISSING_INFO;
00219 
00220     /* Count how many nets we have */
00221     n_nets = 0;
00222     if (image->netlist != NULL) {
00223       for (net = image->netlist->next ; net != NULL; net = net->next) {
00224        n_nets++;
00225       }
00226     }
00227 
00228     /* If we have nets but no apertures are defined, then complain */
00229     if( n_nets > 0) {
00230       for (i = 0; i < APERTURE_MAX && image->aperture[i] == NULL; i++);
00231       if (i == APERTURE_MAX) error |= GERB_IMAGE_MISSING_APERTURES;
00232     }
00233 
00234     return error;
00235 } /* gerb_image_verify */
00236 
00237 
00238 static void
00239 gerbv_image_interpolation(gerbv_interpolation_t interpolation)
00240 {
00241     switch (interpolation) {
00242     case GERBV_INTERPOLATION_LINEARx1:
00243        printf("linearX1");
00244        break;
00245     case GERBV_INTERPOLATION_x10:
00246        printf("linearX10");
00247        break;
00248     case GERBV_INTERPOLATION_LINEARx01:
00249        printf("linearX01");
00250        break;
00251     case GERBV_INTERPOLATION_LINEARx001:
00252        printf("linearX001");
00253        break;
00254     case GERBV_INTERPOLATION_CW_CIRCULAR:
00255        printf("CW circular");
00256        break;
00257     case GERBV_INTERPOLATION_CCW_CIRCULAR:
00258        printf("CCW circular");
00259        break;
00260     case  GERBV_INTERPOLATION_PAREA_START:
00261        printf("polygon area start");
00262        break;
00263     case  GERBV_INTERPOLATION_PAREA_END:
00264        printf("polygon area end");
00265        break;
00266     default:
00267        printf("unknown");
00268     }
00269 } /* gerb_image_interpolation */
00270 
00271 
00272 /* Dumps a written version of image to stdout */
00273 void 
00274 gerbv_image_dump(gerbv_image_t const* image)
00275 {
00276     int i, j;
00277     gerbv_aperture_t * const* aperture;
00278     gerbv_net_t const * net;
00279 
00280     /* Apertures */
00281     printf("Apertures:\n");
00282     aperture = image->aperture;
00283     for (i = 0; i < APERTURE_MAX; i++) {
00284        if (aperture[i]) {
00285            printf(" Aperture no:%d is an ", i);
00286            switch(aperture[i]->type) {
00287            case GERBV_APTYPE_CIRCLE:
00288               printf("circle");
00289               break;
00290            case GERBV_APTYPE_RECTANGLE:
00291               printf("rectangle");
00292               break;
00293            case GERBV_APTYPE_OVAL:
00294               printf("oval");
00295               break;
00296            case GERBV_APTYPE_POLYGON:
00297               printf("polygon");
00298               break;
00299            case GERBV_APTYPE_MACRO:
00300               printf("macro");
00301               break;
00302            default:
00303               printf("unknown");
00304            }
00305            for (j = 0; j < aperture[i]->nuf_parameters; j++) {
00306               printf(" %f", aperture[i]->parameter[j]);
00307            }
00308            printf("\n");
00309        }
00310     }
00311 
00312     /* Netlist */
00313     net = image->netlist;
00314     while (net){
00315        printf("(%f,%f)->(%f,%f) with %d (", net->start_x, net->start_y, 
00316               net->stop_x, net->stop_y, net->aperture);
00317        gerbv_image_interpolation(net->interpolation);
00318        printf(")\n");
00319        net = net->next;
00320     }
00321 } /* gerbv_image_dump */
00322 
00323 
00324 gerbv_layer_t *
00325 gerbv_image_return_new_layer (gerbv_layer_t *previousLayer)
00326 {
00327     gerbv_layer_t *newLayer = g_new0 (gerbv_layer_t, 1);
00328     
00329     *newLayer = *previousLayer;
00330     previousLayer->next = newLayer;
00331     /* clear this boolean so we only draw the knockout once */
00332     newLayer->knockout.firstInstance = FALSE;
00333     newLayer->next = NULL;
00334     
00335     return newLayer;
00336 } /* gerbv_image_return_new_layer */
00337 
00338 
00339 gerbv_netstate_t *
00340 gerbv_image_return_new_netstate (gerbv_netstate_t *previousState)
00341 {
00342     gerbv_netstate_t *newState = g_new0 (gerbv_netstate_t, 1);
00343     
00344     *newState = *previousState;
00345     previousState->next = newState;
00346     newState->scaleA = 1.0;
00347     newState->scaleB = 1.0;
00348     newState->next = NULL;
00349     
00350     return newState;
00351 } /* gerbv_image_return_new_netstate */
00352 
00353 gerbv_layer_t *
00354 gerbv_image_duplicate_layer (gerbv_layer_t *oldLayer) {
00355     gerbv_layer_t *newLayer = g_new (gerbv_layer_t,1);
00356     
00357     *newLayer = *oldLayer;
00358     newLayer->name = g_strdup (oldLayer->name);
00359     return newLayer;
00360 }
00361 
00362 gerbv_netstate_t *
00363 gerbv_image_duplicate_state (gerbv_netstate_t *oldState) {
00364     gerbv_netstate_t *newState = g_new (gerbv_netstate_t,1);
00365     
00366     *newState = *oldState;
00367     return newState;
00368 }
00369 
00370 gerbv_aperture_t *
00371 gerbv_image_duplicate_aperture (gerbv_aperture_t *oldAperture){
00372     gerbv_aperture_t *newAperture = g_new0 (gerbv_aperture_t,1);
00373     gerbv_simplified_amacro_t *simplifiedMacro, *tempSimplified;
00374        
00375     *newAperture = *oldAperture;
00376          
00377     /* delete the amacro section, since we really don't need it anymore
00378     now that we have the simplified section */
00379     newAperture->amacro = NULL;
00380     newAperture->simplified = NULL;
00381 
00382     /* copy any simplified macros over */
00383     tempSimplified = NULL;
00384     for (simplifiedMacro = oldAperture->simplified; simplifiedMacro != NULL; simplifiedMacro = simplifiedMacro->next) {
00385        gerbv_simplified_amacro_t *newSimplified = g_new0 (gerbv_simplified_amacro_t,1);
00386        *newSimplified = *simplifiedMacro;
00387        if (tempSimplified)
00388          tempSimplified->next = newSimplified;
00389        else
00390          newAperture->simplified = newSimplified;
00391        tempSimplified = newSimplified;
00392     }
00393     return newAperture;
00394 }
00395 
00396 void
00397 gerbv_image_copy_all_nets (gerbv_image_t *sourceImage, gerbv_image_t *newImage, gerbv_layer_t *lastLayer,
00398               gerbv_netstate_t *lastState, gerbv_net_t *lastNet, gerbv_user_transformation_t *transform,
00399               GArray *translationTable){
00400     gerbv_netstate_t *oldState,*newSavedState;
00401     gerbv_layer_t *oldLayer,*newSavedLayer;
00402     gerbv_net_t *currentNet,*newNet,*newSavedNet;
00403     int i;
00404     
00405     oldLayer = sourceImage->layers;
00406     oldState = sourceImage->states;
00407     
00408     newSavedLayer = lastLayer;
00409     newSavedState = lastState;
00410     newSavedNet = lastNet;
00411     
00412     /* when copying, skip the first net, since it's always zero due to the way we parse things */
00413     for (currentNet = sourceImage->netlist->next; currentNet; currentNet = currentNet->next){
00414       /* check for any new layers and duplicate them if needed */
00415        if (currentNet->layer != oldLayer) {
00416          newSavedLayer->next = gerbv_image_duplicate_layer (currentNet->layer);
00417          newSavedLayer = newSavedLayer->next;
00418        }
00419        /* check for any new states and duplicate them if needed */
00420        if (currentNet->state != oldState) {
00421          newSavedState->next = gerbv_image_duplicate_state (currentNet->state);
00422          newSavedState = newSavedState->next;
00423       }
00424       /* create and copy the actual net over */
00425       newNet = g_new (gerbv_net_t,1);
00426       *newNet = *currentNet;
00427       
00428       if (currentNet->cirseg) {
00429        newNet->cirseg = g_new (gerbv_cirseg_t,1);
00430        *(newNet->cirseg) = *(currentNet->cirseg);
00431       }
00432       
00433       if (currentNet->label)
00434        newNet->label = g_string_new(currentNet->label->str);
00435       
00436       newNet->state = newSavedState;
00437       newNet->layer = newSavedLayer;
00438       /* check if we need to translate the aperture number */
00439       if (translationTable) {
00440         for (i=0; i<translationTable->len; i++){
00441           gerb_translation_entry_t translationEntry=g_array_index (translationTable, gerb_translation_entry_t, i);
00442           
00443           if (translationEntry.oldAperture == newNet->aperture) {
00444             newNet->aperture = translationEntry.newAperture;
00445             break;
00446           }
00447         }
00448       }
00449       /* check if we are transforming the net (translating, scaling, etc) */
00450       if (transform) {
00451         newNet->start_x += transform->translateX;
00452         newNet->start_y += transform->translateY;
00453         newNet->stop_x += transform->translateX;
00454         newNet->stop_y += transform->translateY;
00455         if (newNet->cirseg) {
00456           newNet->cirseg->cp_x += transform->translateX;
00457           newNet->cirseg->cp_y += transform->translateY;
00458         }
00459       }
00460       if (newSavedNet)
00461        newSavedNet->next = newNet;
00462       else
00463        newImage->netlist = newNet;
00464       newSavedNet = newNet;
00465     }         
00466               
00467 }
00468 
00469 gint
00470 gerbv_image_find_existing_aperture_match (gerbv_aperture_t *checkAperture, gerbv_image_t *imageToSearch) {
00471     int i,j;
00472     gboolean isMatch;
00473     
00474     for (i = APERTURE_MIN; i < APERTURE_MAX; i++) {
00475        if (imageToSearch->aperture[i] != NULL) {
00476          if ((imageToSearch->aperture[i]->type == checkAperture->type) &&
00477              (imageToSearch->aperture[i]->simplified == NULL) &&
00478              (imageToSearch->aperture[i]->unit == checkAperture->unit)) {
00479            /* check all parameters match too */
00480            isMatch=TRUE;
00481            for (j=0; j<APERTURE_PARAMETERS_MAX; j++){
00482              if (imageToSearch->aperture[i]->parameter[j] != checkAperture->parameter[j])
00483                isMatch = FALSE;
00484            }
00485            if (isMatch)
00486              return i;
00487          }          
00488        }
00489     }
00490     return 0;
00491 }
00492 
00493 int
00494 gerbv_image_find_unused_aperture_number (int startIndex, gerbv_image_t *image){
00495     int i;
00496     
00497     for (i = startIndex; i < APERTURE_MAX; i++) {
00498        if (image->aperture[i] == NULL) {
00499          return i;
00500        }
00501     }
00502     return -1;
00503 }
00504 
00505 gerbv_image_t *
00506 gerbv_image_duplicate_image (gerbv_image_t *sourceImage, gerbv_user_transformation_t *transform) {
00507     gerbv_image_t *newImage = gerbv_create_image(NULL, sourceImage->info->type);
00508     int i;
00509     int lastUsedApertureNumber = APERTURE_MIN - 1;
00510     GArray *apertureNumberTable = g_array_new(FALSE,FALSE,sizeof(gerb_translation_entry_t));
00511     
00512     newImage->layertype = sourceImage->layertype;
00513     /* copy information layer over */
00514     *(newImage->info) = *(sourceImage->info);
00515     newImage->info->name = g_strdup (sourceImage->info->name);
00516     newImage->info->type = g_strdup (sourceImage->info->type);
00517     newImage->info->plotterFilm = g_strdup (sourceImage->info->plotterFilm);
00518     
00519     /* copy apertures over, compressing all the numbers down for a cleaner output */
00520     for (i = APERTURE_MIN; i < APERTURE_MAX; i++) {
00521        if (sourceImage->aperture[i] != NULL) {
00522          gerbv_aperture_t *newAperture = gerbv_image_duplicate_aperture (sourceImage->aperture[i]);
00523 
00524          lastUsedApertureNumber = gerbv_image_find_unused_aperture_number (lastUsedApertureNumber + 1, newImage);
00525          /* store the aperture numbers (new and old) in the translation table */
00526          gerb_translation_entry_t translationEntry={i,lastUsedApertureNumber};
00527          g_array_append_val (apertureNumberTable,translationEntry);
00528 
00529          newImage->aperture[lastUsedApertureNumber] = newAperture;
00530        }
00531     }
00532     
00533     /* step through all nets and create new layers and states on the fly, since
00534        we really don't have any other way to figure out where states and layers are used */
00535     gerbv_image_copy_all_nets (sourceImage, newImage, newImage->layers, newImage->states, NULL, transform, apertureNumberTable);
00536     g_array_free (apertureNumberTable, TRUE);
00537     return newImage;
00538 }
00539 
00540 void
00541 gerbv_image_copy_image (gerbv_image_t *sourceImage, gerbv_user_transformation_t *transform, gerbv_image_t *destinationImage) {
00542     int lastUsedApertureNumber = APERTURE_MIN - 1;
00543     int i;
00544     GArray *apertureNumberTable = g_array_new(FALSE,FALSE,sizeof(gerb_translation_entry_t));
00545     
00546     /* copy apertures over */
00547     for (i = APERTURE_MIN; i < APERTURE_MAX; i++) {
00548        if (sourceImage->aperture[i] != NULL) {
00549          gint existingAperture = gerbv_image_find_existing_aperture_match (sourceImage->aperture[i], destinationImage);
00550          
00551          /* if we already have an existing aperture in the destination image that matches what
00552             we want, just use it instead */
00553          if (existingAperture > 0) {
00554               gerb_translation_entry_t translationEntry={i,existingAperture};
00555               g_array_append_val (apertureNumberTable,translationEntry);
00556          }
00557          /* else, create a new aperture and put it in the destination image */
00558          else {
00559               gerbv_aperture_t *newAperture = gerbv_image_duplicate_aperture (sourceImage->aperture[i]);
00560          
00561               lastUsedApertureNumber = gerbv_image_find_unused_aperture_number (lastUsedApertureNumber + 1, destinationImage);
00562               /* store the aperture numbers (new and old) in the translation table */
00563               gerb_translation_entry_t translationEntry={i,lastUsedApertureNumber};
00564               g_array_append_val (apertureNumberTable,translationEntry);
00565 
00566               destinationImage->aperture[lastUsedApertureNumber] = newAperture;
00567          }
00568        }
00569     }
00570     /* find the last layer, state, and net in the linked chains */
00571     gerbv_netstate_t *lastState;
00572     gerbv_layer_t *lastLayer;
00573     gerbv_net_t *lastNet;
00574     
00575     for (lastState = destinationImage->states; lastState->next; lastState=lastState->next){}
00576     for (lastLayer = destinationImage->layers; lastLayer->next; lastLayer=lastLayer->next){}
00577     for (lastNet = destinationImage->netlist; lastNet->next; lastNet=lastNet->next){}
00578     
00579     /* and then copy them all to the destination image, using the aperture translation table we just built */
00580     gerbv_image_copy_all_nets (sourceImage, destinationImage, lastLayer, lastState, lastNet, transform, apertureNumberTable);
00581     g_array_free (apertureNumberTable, TRUE);
00582 }
00583 
00584 void
00585 gerbv_image_delete_net (gerbv_net_t *currentNet) {
00586        gerbv_net_t *tempNet;
00587        
00588        g_assert (currentNet);
00589        /* we have a match, so just zero out all the important data fields */
00590        currentNet->aperture = 0;
00591        currentNet->aperture_state = GERBV_APERTURE_STATE_OFF;
00592        
00593        /* if this is a polygon start, we need to erase all the rest of the
00594                nets in this polygon too */
00595        if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_START){
00596               for (tempNet = currentNet->next; tempNet; tempNet = tempNet->next){   
00597                      tempNet->aperture = 0;
00598                      tempNet->aperture_state = GERBV_APERTURE_STATE_OFF;
00599                      
00600                      if (tempNet->interpolation == GERBV_INTERPOLATION_PAREA_END) {
00601                             tempNet->interpolation = GERBV_INTERPOLATION_DELETED;
00602                             break;
00603                      }
00604                      /* make sure we don't leave a polygon interpolation in, since
00605                       it will still draw if it is */
00606                      tempNet->interpolation = GERBV_INTERPOLATION_DELETED;
00607               }
00608        }
00609        /* make sure we don't leave a polygon interpolation in, since
00610           it will still draw if it is */
00611        currentNet->interpolation = GERBV_INTERPOLATION_DELETED;
00612 }
00613 
00614 void
00615 gerbv_image_delete_selected_nets (gerbv_image_t *sourceImage, GArray *selectedNodeArray) {
00616        int i;
00617        gerbv_net_t *currentNet;
00618     
00619        for (currentNet = sourceImage->netlist; currentNet; currentNet = currentNet->next){ 
00620               for (i=0; i<selectedNodeArray->len; i++){
00621                      gerbv_selection_item_t sItem = g_array_index (selectedNodeArray,
00622                             gerbv_selection_item_t, i);
00623                      if (sItem.net == currentNet) {
00624                             gerbv_image_delete_net (currentNet);
00625                             
00626                      }
00627               }
00628        }
00629 }
00630 
00631 void
00632 gerbv_image_create_rectangle_object (gerbv_image_t *image, gdouble coordinateX,
00633               gdouble coordinateY, gdouble width, gdouble height) {
00634        gerbv_net_t *currentNet;
00635        
00636        /* run through and find last net pointer */
00637        for (currentNet = image->netlist; currentNet->next; currentNet = currentNet->next){}
00638        
00639        /* create the polygon start node */
00640        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00641        currentNet->interpolation = GERBV_INTERPOLATION_PAREA_START;
00642        
00643        /* draw the 4 corners */
00644        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00645        currentNet->interpolation = GERBV_INTERPOLATION_LINEARx1;
00646        currentNet->aperture_state = GERBV_APERTURE_STATE_ON;
00647        currentNet->start_x = coordinateX;
00648        currentNet->start_y = coordinateY;
00649        currentNet->stop_x = coordinateX + width;
00650        currentNet->stop_y = coordinateY;
00651        
00652        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00653        currentNet->interpolation = GERBV_INTERPOLATION_LINEARx1;
00654        currentNet->aperture_state = GERBV_APERTURE_STATE_ON;
00655        currentNet->stop_x = coordinateX + width;
00656        currentNet->stop_y = coordinateY + height;
00657        
00658        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00659        currentNet->interpolation = GERBV_INTERPOLATION_LINEARx1;
00660        currentNet->aperture_state = GERBV_APERTURE_STATE_ON;
00661        currentNet->stop_x = coordinateX;
00662        currentNet->stop_y = coordinateY + height;
00663        
00664        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00665        currentNet->interpolation = GERBV_INTERPOLATION_LINEARx1;
00666        currentNet->aperture_state = GERBV_APERTURE_STATE_ON;
00667        currentNet->stop_x = coordinateX;
00668        currentNet->stop_y = coordinateY;
00669        
00670        /* create the polygon end node */
00671        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00672        currentNet->interpolation = GERBV_INTERPOLATION_PAREA_END;
00673        
00674        return;
00675 }
00676 
00677 gerbv_net_t *
00678 gerb_image_return_aperture_index (gerbv_image_t *image, gdouble lineWidth, int *apertureIndex){
00679        gerbv_net_t *currentNet;
00680        gerbv_aperture_t *aperture=NULL;
00681        int i;
00682               
00683        /* run through and find last net pointer */
00684        for (currentNet = image->netlist; currentNet->next; currentNet = currentNet->next){}
00685        
00686        /* try to find an existing aperture that matches the requested width and type */
00687        for (i = APERTURE_MIN; i < APERTURE_MAX; i++) {
00688               if (image->aperture[i] != NULL) {
00689                      if ((image->aperture[i]->type == GERBV_APTYPE_CIRCLE) && 
00690                             (fabs (image->aperture[i]->parameter[0] - lineWidth) < 0.001)){
00691                             aperture = image->aperture[i];
00692                             *apertureIndex = i;
00693                             break;
00694                      }
00695               }
00696        }
00697 
00698        if (!aperture) {
00699               /* we didn't find a useable old aperture, so create a new one */
00700               if (!gerber_create_new_aperture (image, apertureIndex,
00701                             GERBV_APTYPE_CIRCLE, lineWidth, 0)) {
00702                      /* if we didn't succeed, then return */
00703                      return FALSE;
00704               }
00705        }
00706        return currentNet;
00707 }
00708 
00709 void
00710 gerbv_image_create_arc_object (gerbv_image_t *image, gdouble centerX, gdouble centerY,
00711               gdouble radius, gdouble startAngle, gdouble endAngle, gdouble lineWidth,
00712               gerbv_aperture_type_t apertureType) {
00713        int apertureIndex;
00714        gerbv_net_t *currentNet;
00715        gerbv_cirseg_t cirSeg = {centerX, centerY, radius, radius, startAngle, endAngle};
00716        
00717        currentNet = gerb_image_return_aperture_index(image, lineWidth, &apertureIndex);
00718        
00719        if (!currentNet)
00720               return;
00721        
00722        /* draw the arc */
00723        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00724        currentNet->interpolation = GERBV_INTERPOLATION_CCW_CIRCULAR;
00725        currentNet->aperture_state = GERBV_APERTURE_STATE_ON;
00726        currentNet->aperture = apertureIndex;
00727        currentNet->start_x = centerX + (cos(startAngle*M_PI/180) * radius);
00728        currentNet->start_y = centerY + (sin(startAngle*M_PI/180) * radius);
00729        currentNet->stop_x = centerX + (cos(endAngle*M_PI/180) * radius);
00730        currentNet->stop_y = centerY + (sin(endAngle*M_PI/180) * radius);;
00731        currentNet->cirseg = g_new0 (gerbv_cirseg_t,1);
00732        *(currentNet->cirseg) = cirSeg;
00733        
00734        return;
00735 }
00736 
00737 void
00738 gerbv_image_create_line_object (gerbv_image_t *image, gdouble startX, gdouble startY,
00739               gdouble endX, gdouble endY, gdouble lineWidth, gerbv_aperture_type_t apertureType) {
00740        int apertureIndex;
00741        gerbv_net_t *currentNet;
00742        
00743        currentNet = gerb_image_return_aperture_index(image, lineWidth, &apertureIndex);
00744        
00745        if (!currentNet)
00746               return;
00747        
00748        /* draw the line */
00749        currentNet = gerber_create_new_net (currentNet, NULL, NULL);
00750        currentNet->interpolation = GERBV_INTERPOLATION_LINEARx1;
00751        
00752        /* if the start and end coordinates are the same, use a "flash" aperture state */
00753        if ((fabs(startX - endX) < 0.001) && (fabs(startY - endY) < 0.001))
00754               currentNet->aperture_state = GERBV_APERTURE_STATE_FLASH;
00755        else
00756               currentNet->aperture_state = GERBV_APERTURE_STATE_ON;
00757        currentNet->aperture = apertureIndex;
00758        currentNet->start_x = startX;
00759        currentNet->start_y = startY;
00760        currentNet->stop_x = endX;
00761        currentNet->stop_y = endY;
00762 
00763        return;
00764 }
00765 
00766 void
00767 gerbv_image_create_window_pane_objects (gerbv_image_t *image, gdouble lowerLeftX,
00768               gdouble lowerLeftY, gdouble width, gdouble height, gdouble areaReduction,
00769               gint paneRows, gint paneColumns, gdouble paneSeparation){
00770        int i,j;
00771        gdouble startX,startY,boxWidth,boxHeight;
00772        
00773        startX = lowerLeftX + (areaReduction * width) / 2.0;
00774        startY = lowerLeftY + (areaReduction * height) / 2.0;
00775        boxWidth = (width * (1.0 - areaReduction) - (paneSeparation * (paneColumns - 1))) / paneColumns;
00776        boxHeight = (height * (1.0 - areaReduction) - (paneSeparation * (paneRows - 1))) / paneRows;
00777        
00778        for (i=0; i<paneColumns; i++){
00779               for (j=0; j<paneRows; j++) {
00780                      gerbv_image_create_rectangle_object (image, startX + (i * (boxWidth + paneSeparation)),
00781                             startY + (j * (boxHeight + paneSeparation)),boxWidth, boxHeight);
00782               }
00783        }
00784 
00785        return;
00786 }
00787               
00788 gboolean
00789 gerbv_image_reduce_area_of_selected_objects (GArray *selectionArray,
00790               gdouble areaReduction, gint paneRows, gint paneColumns, gdouble paneSeparation){
00791        int i;
00792        gdouble minX,minY,maxX,maxY;
00793        
00794        for (i=0; i<selectionArray->len; i++) {
00795               gerbv_selection_item_t sItem = g_array_index (selectionArray,gerbv_selection_item_t, i);
00796               gerbv_image_t *image = sItem.image;
00797               gerbv_net_t *currentNet = sItem.net;
00798               
00799               /* determine the object type first */
00800               minX = HUGE_VAL;
00801               maxX = -HUGE_VAL;
00802               minY = HUGE_VAL;
00803               maxY = -HUGE_VAL;
00804               
00805               if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_START) {
00806                      /* if it's a polygon, just determine the overall area of it and delete it */
00807                      currentNet->interpolation = GERBV_INTERPOLATION_DELETED;
00808                      
00809                      for (currentNet = currentNet->next; currentNet; currentNet = currentNet->next){
00810                             if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_END)
00811                                    break;
00812                             currentNet->interpolation = GERBV_INTERPOLATION_DELETED;
00813                             if (currentNet->stop_x < minX)
00814                                    minX = currentNet->stop_x;
00815                             if (currentNet->stop_y < minY)
00816                                    minY = currentNet->stop_y;
00817                             if (currentNet->stop_x > maxX)
00818                                    maxX = currentNet->stop_x;
00819                             if (currentNet->stop_y > maxY)
00820                                    maxY = currentNet->stop_y;
00821                      }
00822                      currentNet->interpolation = GERBV_INTERPOLATION_DELETED;
00823               }
00824               else if ((currentNet->interpolation == GERBV_INTERPOLATION_x10) ||
00825                             (currentNet->interpolation == GERBV_INTERPOLATION_LINEARx01) ||
00826                             (currentNet->interpolation == GERBV_INTERPOLATION_LINEARx001) ||
00827                             (currentNet->interpolation == GERBV_INTERPOLATION_LINEARx1)) {
00828                      gdouble dx=0,dy=0;
00829                      /* figure out the overall size of this element */
00830                      switch (image->aperture[currentNet->aperture]->type) {
00831                             case GERBV_APTYPE_CIRCLE :
00832                             case GERBV_APTYPE_OVAL :
00833                             case GERBV_APTYPE_POLYGON :
00834                                    dx = dy = image->aperture[currentNet->aperture]->parameter[0];
00835                                    break;
00836                             case GERBV_APTYPE_RECTANGLE :
00837                                    dx = (image->aperture[currentNet->aperture]->parameter[0]/ 2);
00838                                    dy = (image->aperture[currentNet->aperture]->parameter[1]/ 2);
00839                                    break;
00840                             default :
00841                                    break;
00842                      }
00843                      if (currentNet->start_x-dx < minX)
00844                             minX = currentNet->start_x-dx;
00845                      if (currentNet->start_y-dy < minY)
00846                             minY = currentNet->start_y-dy;
00847                      if (currentNet->start_x+dx > maxX)
00848                             maxX = currentNet->start_x+dx;
00849                      if (currentNet->start_y+dy > maxY)
00850                             maxY = currentNet->start_y+dy;
00851                             
00852                      if (currentNet->stop_x-dx < minX)
00853                             minX = currentNet->stop_x-dx;
00854                      if (currentNet->stop_y-dy < minY)
00855                             minY = currentNet->stop_y-dy;
00856                      if (currentNet->stop_x+dx > maxX)
00857                             maxX = currentNet->stop_x+dx;
00858                      if (currentNet->stop_y+dy > maxY)
00859                             maxY = currentNet->stop_y+dy;
00860                      
00861                      /* finally, delete node */
00862                      currentNet->interpolation = GERBV_INTERPOLATION_DELETED;
00863               }
00864               /* we don't current support arcs */
00865               else
00866                      return FALSE;
00867               
00868               /* create new structures */
00869               gerbv_image_create_window_pane_objects (image, minX, minY, maxX - minX, maxY - minY,
00870                      areaReduction, paneRows, paneColumns, paneSeparation);
00871        }
00872        return TRUE;
00873 }
00874 
00875 gboolean
00876 gerbv_image_move_selected_objects (GArray *selectionArray, gdouble translationX,
00877               gdouble translationY) {
00878        int i;
00879        
00880        for (i=0; i<selectionArray->len; i++) {
00881               gerbv_selection_item_t sItem = g_array_index (selectionArray,gerbv_selection_item_t, i);
00882               gerbv_net_t *currentNet = sItem.net;
00883 
00884               if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_START) {
00885                      /* if it's a polygon, step through every vertex and translate the point */
00886                      for (currentNet = currentNet->next; currentNet; currentNet = currentNet->next){
00887                             if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_END)
00888                                    break;
00889                             currentNet->start_x += translationX;
00890                             currentNet->start_y += translationY;
00891                             currentNet->stop_x += translationX;
00892                             currentNet->stop_y += translationY;
00893                      }
00894               }
00895               else {
00896                      /* otherwise, just move the single element */
00897                      currentNet->start_x += translationX;
00898                      currentNet->start_y += translationY;
00899                      currentNet->stop_x += translationX;
00900                      currentNet->stop_y += translationY;
00901               }
00902        }
00903        return TRUE;
00904 }
00905 
00906 gerbv_net_t *
00907 gerbv_image_return_next_renderable_object (gerbv_net_t *oldNet) {
00908        gerbv_net_t *currentNet=oldNet;
00909        
00910        if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_START) {
00911               /* if it's a polygon, step to the next non-polygon net */
00912               for (currentNet = currentNet->next; currentNet; currentNet = currentNet->next){
00913                      if (currentNet->interpolation == GERBV_INTERPOLATION_PAREA_END) {
00914                             return currentNet->next;
00915                      }
00916               }
00917               return NULL;
00918        }
00919        else {
00920               return currentNet->next;
00921        }
00922 }

Generated on Tue Aug 19 00:14:48 2008 for gerbv by  doxygen 1.5.6