2 * gEDA - GNU Electronic Design Automation
3 * This files is a part of gerbv.
5 * Copyright (C) 2000-2003 Stefan Petersen (spe@stacken.kth.se)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
24 /** \file gerb_image.c
25 \brief This file contains general files for handling the gerbv_image_t structure
39 #include "gerb_image.h"
46 } gerb_translation_entry_t
;
49 gerbv_create_image(gerbv_image_t
*image
, const gchar
*type
)
51 gerbv_destroy_image(image
);
53 /* Malloc space for image */
54 if ((image
= (gerbv_image_t
*)g_malloc(sizeof(gerbv_image_t
))) == NULL
) {
57 memset((void *)image
, 0, sizeof(gerbv_image_t
));
59 /* Malloc space for image->netlist */
60 if ((image
->netlist
= (gerbv_net_t
*)g_malloc(sizeof(gerbv_net_t
))) == NULL
) {
64 memset((void *)image
->netlist
, 0, sizeof(gerbv_net_t
));
66 /* Malloc space for image->info */
67 if ((image
->info
= (gerbv_image_info_t
*)g_malloc(sizeof(gerbv_image_info_t
))) == NULL
) {
68 g_free(image
->netlist
);
72 memset((void *)image
->info
, 0, sizeof(gerbv_image_info_t
));
74 /* Set aside position for stats struct */
75 image
->gerbv_stats
= NULL
;
76 image
->drill_stats
= NULL
;
78 image
->info
->min_x
= HUGE_VAL
;
79 image
->info
->min_y
= HUGE_VAL
;
80 image
->info
->max_x
= -HUGE_VAL
;
81 image
->info
->max_y
= -HUGE_VAL
;
83 /* create our first layer and fill with non-zero default values */
84 image
->layers
= g_new0 (gerbv_layer_t
, 1);
85 image
->layers
->stepAndRepeat
.X
= 1;
86 image
->layers
->stepAndRepeat
.Y
= 1;
87 image
->layers
->polarity
= GERBV_POLARITY_DARK
;
89 /* create our first netstate and fill with non-zero default values */
90 image
->states
= g_new0 (gerbv_netstate_t
, 1);
91 image
->states
->scaleA
= 1;
92 image
->states
->scaleB
= 1;
94 /* fill in some values for our first net */
95 image
->netlist
->layer
= image
->layers
;
96 image
->netlist
->state
= image
->states
;
99 image
->info
->type
= g_strdup ("unknown");
101 image
->info
->type
= g_strdup (type
);
103 /* the individual file parsers will have to set this. */
104 image
->info
->attr_list
= NULL
;
105 image
->info
->n_attr
= 0;
112 gerbv_destroy_image(gerbv_image_t
*image
)
115 gerbv_net_t
*net
, *tmp
;
116 gerbv_layer_t
*layer
;
117 gerbv_netstate_t
*state
;
118 gerbv_simplified_amacro_t
*sam
,*sam2
;
126 for (i
= 0; i
< APERTURE_MAX
; i
++)
127 if (image
->aperture
[i
] != NULL
) {
128 for (sam
= image
->aperture
[i
]->simplified
; sam
!= NULL
; ){
134 g_free(image
->aperture
[i
]);
135 image
->aperture
[i
] = NULL
;
139 * Free aperture macro
143 free_amacro(image
->amacro
);
150 g_free(image
->format
);
156 g_free(image
->info
->name
);
157 g_free(image
->info
->type
);
158 gerbv_attribute_destroy_HID_attribute (image
->info
->attr_list
, image
->info
->n_attr
);
165 for (net
= image
->netlist
; net
!= NULL
; ) {
168 if (tmp
->cirseg
!= NULL
) {
173 g_string_free (tmp
->label
, TRUE
);
178 for (layer
= image
->layers
; layer
!= NULL
; ) {
179 gerbv_layer_t
*tempLayer
= layer
;
184 for (state
= image
->states
; state
!= NULL
; ) {
185 gerbv_netstate_t
*tempState
= state
;
190 gerbv_stats_destroy(image
->gerbv_stats
);
191 gerbv_drill_stats_destroy(image
->drill_stats
);
194 * Free and reset the final image
204 * Check that the parsed gerber image is complete.
205 * Returned errorcodes are:
209 * 4: Missing apertures
211 * It could be any of above or'ed together
214 gerbv_image_verify(gerbv_image_t
const* image
)
216 gerb_verify_error_t error
= GERB_IMAGE_OK
;
220 if (image
->netlist
== NULL
) error
|= GERB_IMAGE_MISSING_NETLIST
;
221 if (image
->format
== NULL
) error
|= GERB_IMAGE_MISSING_FORMAT
;
222 if (image
->info
== NULL
) error
|= GERB_IMAGE_MISSING_INFO
;
224 /* Count how many nets we have */
226 if (image
->netlist
!= NULL
) {
227 for (net
= image
->netlist
->next
; net
!= NULL
; net
= net
->next
) {
232 /* If we have nets but no apertures are defined, then complain */
234 for (i
= 0; i
< APERTURE_MAX
&& image
->aperture
[i
] == NULL
; i
++);
235 if (i
== APERTURE_MAX
) error
|= GERB_IMAGE_MISSING_APERTURES
;
239 } /* gerb_image_verify */
243 gerbv_image_interpolation(gerbv_interpolation_t interpolation
)
245 switch (interpolation
) {
246 case GERBV_INTERPOLATION_LINEARx1
:
249 case GERBV_INTERPOLATION_x10
:
252 case GERBV_INTERPOLATION_LINEARx01
:
255 case GERBV_INTERPOLATION_LINEARx001
:
256 printf("linearX001");
258 case GERBV_INTERPOLATION_CW_CIRCULAR
:
259 printf("CW circular");
261 case GERBV_INTERPOLATION_CCW_CIRCULAR
:
262 printf("CCW circular");
264 case GERBV_INTERPOLATION_PAREA_START
:
265 printf("polygon area start");
267 case GERBV_INTERPOLATION_PAREA_END
:
268 printf("polygon area end");
273 } /* gerb_image_interpolation */
276 gerbv_image_aperture_state(gerbv_aperture_state_t state
)
279 case GERBV_APERTURE_STATE_OFF
:
280 printf("..state off");
282 case GERBV_APERTURE_STATE_ON
:
283 printf("..state on");
285 case GERBV_APERTURE_STATE_FLASH
:
286 printf("..state flash");
289 printf("..state unknown");
293 /* Dumps a written version of image to stdout */
295 gerbv_image_dump(gerbv_image_t
const* image
)
298 gerbv_aperture_t
* const* aperture
;
299 gerbv_net_t
const * net
;
302 printf("Apertures:\n");
303 aperture
= image
->aperture
;
304 for (i
= 0; i
< APERTURE_MAX
; i
++) {
306 printf(" Aperture no:%d is an ", i
);
307 switch(aperture
[i
]->type
) {
308 case GERBV_APTYPE_CIRCLE
:
311 case GERBV_APTYPE_RECTANGLE
:
314 case GERBV_APTYPE_OVAL
:
317 case GERBV_APTYPE_POLYGON
:
320 case GERBV_APTYPE_MACRO
:
326 for (j
= 0; j
< aperture
[i
]->nuf_parameters
; j
++) {
327 printf(" %f", aperture
[i
]->parameter
[j
]);
334 net
= image
->netlist
;
336 printf("(%f,%f)->(%f,%f) with %d (", net
->start_x
, net
->start_y
,
337 net
->stop_x
, net
->stop_y
, net
->aperture
);
338 gerbv_image_interpolation(net
->interpolation
);
339 gerbv_image_aperture_state(net
->aperture_state
);
343 } /* gerbv_image_dump */
347 gerbv_image_return_new_layer (gerbv_layer_t
*previousLayer
)
349 gerbv_layer_t
*newLayer
= g_new0 (gerbv_layer_t
, 1);
351 *newLayer
= *previousLayer
;
352 previousLayer
->next
= newLayer
;
353 /* clear this boolean so we only draw the knockout once */
354 newLayer
->knockout
.firstInstance
= FALSE
;
355 newLayer
->next
= NULL
;
358 } /* gerbv_image_return_new_layer */
362 gerbv_image_return_new_netstate (gerbv_netstate_t
*previousState
)
364 gerbv_netstate_t
*newState
= g_new0 (gerbv_netstate_t
, 1);
366 *newState
= *previousState
;
367 previousState
->next
= newState
;
368 newState
->scaleA
= 1.0;
369 newState
->scaleB
= 1.0;
370 newState
->next
= NULL
;
373 } /* gerbv_image_return_new_netstate */
376 gerbv_image_duplicate_layer (gerbv_layer_t
*oldLayer
) {
377 gerbv_layer_t
*newLayer
= g_new (gerbv_layer_t
,1);
379 *newLayer
= *oldLayer
;
380 newLayer
->name
= g_strdup (oldLayer
->name
);
385 gerbv_image_duplicate_state (gerbv_netstate_t
*oldState
) {
386 gerbv_netstate_t
*newState
= g_new (gerbv_netstate_t
,1);
388 *newState
= *oldState
;
393 gerbv_image_duplicate_aperture (gerbv_aperture_t
*oldAperture
){
394 gerbv_aperture_t
*newAperture
= g_new0 (gerbv_aperture_t
,1);
395 gerbv_simplified_amacro_t
*simplifiedMacro
, *tempSimplified
;
397 *newAperture
= *oldAperture
;
399 /* delete the amacro section, since we really don't need it anymore
400 now that we have the simplified section */
401 newAperture
->amacro
= NULL
;
402 newAperture
->simplified
= NULL
;
404 /* copy any simplified macros over */
405 tempSimplified
= NULL
;
406 for (simplifiedMacro
= oldAperture
->simplified
; simplifiedMacro
!= NULL
; simplifiedMacro
= simplifiedMacro
->next
) {
407 gerbv_simplified_amacro_t
*newSimplified
= g_new0 (gerbv_simplified_amacro_t
,1);
408 *newSimplified
= *simplifiedMacro
;
410 tempSimplified
->next
= newSimplified
;
412 newAperture
->simplified
= newSimplified
;
413 tempSimplified
= newSimplified
;
419 gerbv_image_copy_all_nets (gerbv_image_t
*sourceImage
, gerbv_image_t
*newImage
, gerbv_layer_t
*lastLayer
,
420 gerbv_netstate_t
*lastState
, gerbv_net_t
*lastNet
, gerbv_user_transformation_t
*transform
,
421 GArray
*translationTable
){
422 gerbv_netstate_t
*oldState
,*newSavedState
;
423 gerbv_layer_t
*oldLayer
,*newSavedLayer
;
424 gerbv_net_t
*currentNet
,*newNet
,*newSavedNet
;
427 oldLayer
= sourceImage
->layers
;
428 oldState
= sourceImage
->states
;
430 newSavedLayer
= lastLayer
;
431 newSavedState
= lastState
;
432 newSavedNet
= lastNet
;
434 for (currentNet
= sourceImage
->netlist
; currentNet
; currentNet
= currentNet
->next
){
435 /* check for any new layers and duplicate them if needed */
436 if (currentNet
->layer
!= oldLayer
) {
437 newSavedLayer
->next
= gerbv_image_duplicate_layer (currentNet
->layer
);
438 newSavedLayer
= newSavedLayer
->next
;
440 /* check for any new states and duplicate them if needed */
441 if (currentNet
->state
!= oldState
) {
442 newSavedState
->next
= gerbv_image_duplicate_state (currentNet
->state
);
443 newSavedState
= newSavedState
->next
;
445 /* create and copy the actual net over */
446 newNet
= g_new (gerbv_net_t
,1);
447 *newNet
= *currentNet
;
449 if (currentNet
->cirseg
) {
450 newNet
->cirseg
= g_new (gerbv_cirseg_t
,1);
451 *(newNet
->cirseg
) = *(currentNet
->cirseg
);
454 if (currentNet
->label
)
455 newNet
->label
= g_string_new(currentNet
->label
->str
);
457 newNet
->state
= newSavedState
;
458 newNet
->layer
= newSavedLayer
;
459 /* check if we need to translate the aperture number */
460 if (translationTable
) {
461 for (i
=0; i
<translationTable
->len
; i
++){
462 gerb_translation_entry_t translationEntry
=g_array_index (translationTable
, gerb_translation_entry_t
, i
);
464 if (translationEntry
.oldAperture
== newNet
->aperture
) {
465 newNet
->aperture
= translationEntry
.newAperture
;
470 /* check if we are transforming the net (translating, scaling, etc) */
472 newNet
->start_x
+= transform
->translateX
;
473 newNet
->start_y
+= transform
->translateY
;
474 newNet
->stop_x
+= transform
->translateX
;
475 newNet
->stop_y
+= transform
->translateY
;
476 if (newNet
->cirseg
) {
477 newNet
->cirseg
->cp_x
+= transform
->translateX
;
478 newNet
->cirseg
->cp_y
+= transform
->translateY
;
482 newSavedNet
->next
= newNet
;
484 newImage
->netlist
= newNet
;
485 newSavedNet
= newNet
;
491 gerbv_image_find_existing_aperture_match (gerbv_aperture_t
*checkAperture
, gerbv_image_t
*imageToSearch
) {
495 for (i
= 0; i
< APERTURE_MAX
; i
++) {
496 if (imageToSearch
->aperture
[i
] != NULL
) {
497 if ((imageToSearch
->aperture
[i
]->type
== checkAperture
->type
) &&
498 (imageToSearch
->aperture
[i
]->simplified
== NULL
) &&
499 (imageToSearch
->aperture
[i
]->unit
== checkAperture
->unit
)) {
500 /* check all parameters match too */
502 for (j
=0; j
<APERTURE_PARAMETERS_MAX
; j
++){
503 if (imageToSearch
->aperture
[i
]->parameter
[j
] != checkAperture
->parameter
[j
])
515 gerbv_image_find_unused_aperture_number (int startIndex
, gerbv_image_t
*image
){
518 for (i
= startIndex
; i
< APERTURE_MAX
; i
++) {
519 if (image
->aperture
[i
] == NULL
) {
527 gerbv_image_duplicate_image (gerbv_image_t
*sourceImage
, gerbv_user_transformation_t
*transform
) {
528 gerbv_image_t
*newImage
= gerbv_create_image(NULL
, sourceImage
->info
->type
);
530 int lastUsedApertureNumber
= APERTURE_MIN
- 1;
531 GArray
*apertureNumberTable
= g_array_new(FALSE
,FALSE
,sizeof(gerb_translation_entry_t
));
533 newImage
->layertype
= sourceImage
->layertype
;
534 /* copy information layer over */
535 *(newImage
->info
) = *(sourceImage
->info
);
536 newImage
->info
->name
= g_strdup (sourceImage
->info
->name
);
537 newImage
->info
->type
= g_strdup (sourceImage
->info
->type
);
538 newImage
->info
->plotterFilm
= g_strdup (sourceImage
->info
->plotterFilm
);
539 newImage
->info
->attr_list
= gerbv_attribute_dup (sourceImage
->info
->attr_list
,
540 sourceImage
->info
->n_attr
);
542 /* copy apertures over, compressing all the numbers down for a cleaner output, and
543 moving and apertures less than 10 up to the correct range */
544 for (i
= 0; i
< APERTURE_MAX
; i
++) {
545 if (sourceImage
->aperture
[i
] != NULL
) {
546 gerbv_aperture_t
*newAperture
= gerbv_image_duplicate_aperture (sourceImage
->aperture
[i
]);
548 lastUsedApertureNumber
= gerbv_image_find_unused_aperture_number (lastUsedApertureNumber
+ 1, newImage
);
549 /* store the aperture numbers (new and old) in the translation table */
550 gerb_translation_entry_t translationEntry
={i
,lastUsedApertureNumber
};
551 g_array_append_val (apertureNumberTable
,translationEntry
);
553 newImage
->aperture
[lastUsedApertureNumber
] = newAperture
;
557 /* step through all nets and create new layers and states on the fly, since
558 we really don't have any other way to figure out where states and layers are used */
559 gerbv_image_copy_all_nets (sourceImage
, newImage
, newImage
->layers
, newImage
->states
, NULL
, transform
, apertureNumberTable
);
560 g_array_free (apertureNumberTable
, TRUE
);
565 gerbv_image_copy_image (gerbv_image_t
*sourceImage
, gerbv_user_transformation_t
*transform
, gerbv_image_t
*destinationImage
) {
566 int lastUsedApertureNumber
= APERTURE_MIN
- 1;
568 GArray
*apertureNumberTable
= g_array_new(FALSE
,FALSE
,sizeof(gerb_translation_entry_t
));
570 /* copy apertures over */
571 for (i
= 0; i
< APERTURE_MAX
; i
++) {
572 if (sourceImage
->aperture
[i
] != NULL
) {
573 gint existingAperture
= gerbv_image_find_existing_aperture_match (sourceImage
->aperture
[i
], destinationImage
);
575 /* if we already have an existing aperture in the destination image that matches what
576 we want, just use it instead */
577 if (existingAperture
> 0) {
578 gerb_translation_entry_t translationEntry
={i
,existingAperture
};
579 g_array_append_val (apertureNumberTable
,translationEntry
);
581 /* else, create a new aperture and put it in the destination image */
583 gerbv_aperture_t
*newAperture
= gerbv_image_duplicate_aperture (sourceImage
->aperture
[i
]);
585 lastUsedApertureNumber
= gerbv_image_find_unused_aperture_number (lastUsedApertureNumber
+ 1, destinationImage
);
586 /* store the aperture numbers (new and old) in the translation table */
587 gerb_translation_entry_t translationEntry
={i
,lastUsedApertureNumber
};
588 g_array_append_val (apertureNumberTable
,translationEntry
);
590 destinationImage
->aperture
[lastUsedApertureNumber
] = newAperture
;
594 /* find the last layer, state, and net in the linked chains */
595 gerbv_netstate_t
*lastState
;
596 gerbv_layer_t
*lastLayer
;
597 gerbv_net_t
*lastNet
;
599 for (lastState
= destinationImage
->states
; lastState
->next
; lastState
=lastState
->next
){}
600 for (lastLayer
= destinationImage
->layers
; lastLayer
->next
; lastLayer
=lastLayer
->next
){}
601 for (lastNet
= destinationImage
->netlist
; lastNet
->next
; lastNet
=lastNet
->next
){}
603 /* and then copy them all to the destination image, using the aperture translation table we just built */
604 gerbv_image_copy_all_nets (sourceImage
, destinationImage
, lastLayer
, lastState
, lastNet
, transform
, apertureNumberTable
);
605 g_array_free (apertureNumberTable
, TRUE
);
609 gerbv_image_delete_net (gerbv_net_t
*currentNet
) {
610 gerbv_net_t
*tempNet
;
612 g_assert (currentNet
);
613 /* we have a match, so just zero out all the important data fields */
614 currentNet
->aperture
= 0;
615 currentNet
->aperture_state
= GERBV_APERTURE_STATE_OFF
;
617 /* if this is a polygon start, we need to erase all the rest of the
618 nets in this polygon too */
619 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
){
620 for (tempNet
= currentNet
->next
; tempNet
; tempNet
= tempNet
->next
){
621 tempNet
->aperture
= 0;
622 tempNet
->aperture_state
= GERBV_APERTURE_STATE_OFF
;
624 if (tempNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
) {
625 tempNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
628 /* make sure we don't leave a polygon interpolation in, since
629 it will still draw if it is */
630 tempNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
633 /* make sure we don't leave a polygon interpolation in, since
634 it will still draw if it is */
635 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
639 gerbv_image_delete_selected_nets (gerbv_image_t
*sourceImage
, GArray
*selectedNodeArray
) {
641 gerbv_net_t
*currentNet
;
643 for (currentNet
= sourceImage
->netlist
; currentNet
; currentNet
= currentNet
->next
){
644 for (i
=0; i
<selectedNodeArray
->len
; i
++){
645 gerbv_selection_item_t sItem
= g_array_index (selectedNodeArray
,
646 gerbv_selection_item_t
, i
);
647 if (sItem
.net
== currentNet
) {
648 gerbv_image_delete_net (currentNet
);
656 gerbv_image_create_rectangle_object (gerbv_image_t
*image
, gdouble coordinateX
,
657 gdouble coordinateY
, gdouble width
, gdouble height
) {
658 gerbv_net_t
*currentNet
;
660 /* run through and find last net pointer */
661 for (currentNet
= image
->netlist
; currentNet
->next
; currentNet
= currentNet
->next
){}
663 /* create the polygon start node */
664 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
665 currentNet
->interpolation
= GERBV_INTERPOLATION_PAREA_START
;
667 /* go to start point (we need this to create correct RS274X export code) */
668 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
669 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
670 currentNet
->aperture_state
= GERBV_APERTURE_STATE_OFF
;
671 currentNet
->start_x
= coordinateX
;
672 currentNet
->start_y
= coordinateY
;
673 currentNet
->stop_x
= coordinateX
;
674 currentNet
->stop_y
= coordinateY
;
676 /* draw the 4 corners */
677 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
678 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
679 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
680 currentNet
->start_x
= coordinateX
;
681 currentNet
->start_y
= coordinateY
;
682 currentNet
->stop_x
= coordinateX
+ width
;
683 currentNet
->stop_y
= coordinateY
;
684 gerber_update_min_and_max (¤tNet
->boundingBox
,currentNet
->stop_x
,currentNet
->stop_y
,
686 gerber_update_image_min_max (¤tNet
->boundingBox
, 0, 0, image
);
688 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
689 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
690 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
691 currentNet
->stop_x
= coordinateX
+ width
;
692 currentNet
->stop_y
= coordinateY
+ height
;
693 gerber_update_min_and_max (¤tNet
->boundingBox
,currentNet
->stop_x
,currentNet
->stop_y
,
695 gerber_update_image_min_max (¤tNet
->boundingBox
, 0, 0, image
);
697 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
698 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
699 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
700 currentNet
->stop_x
= coordinateX
;
701 currentNet
->stop_y
= coordinateY
+ height
;
702 gerber_update_min_and_max (¤tNet
->boundingBox
,currentNet
->stop_x
,currentNet
->stop_y
,
704 gerber_update_image_min_max (¤tNet
->boundingBox
, 0, 0, image
);
706 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
707 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
708 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
709 currentNet
->stop_x
= coordinateX
;
710 currentNet
->stop_y
= coordinateY
;
711 gerber_update_min_and_max (¤tNet
->boundingBox
,currentNet
->stop_x
,currentNet
->stop_y
,
713 gerber_update_image_min_max (¤tNet
->boundingBox
, 0, 0, image
);
715 /* create the polygon end node */
716 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
717 currentNet
->interpolation
= GERBV_INTERPOLATION_PAREA_END
;
723 gerb_image_return_aperture_index (gerbv_image_t
*image
, gdouble lineWidth
, int *apertureIndex
){
724 gerbv_net_t
*currentNet
;
725 gerbv_aperture_t
*aperture
=NULL
;
728 /* run through and find last net pointer */
729 for (currentNet
= image
->netlist
; currentNet
->next
; currentNet
= currentNet
->next
){}
731 /* try to find an existing aperture that matches the requested width and type */
732 for (i
= 0; i
< APERTURE_MAX
; i
++) {
733 if (image
->aperture
[i
] != NULL
) {
734 if ((image
->aperture
[i
]->type
== GERBV_APTYPE_CIRCLE
) &&
735 (fabs (image
->aperture
[i
]->parameter
[0] - lineWidth
) < 0.001)){
736 aperture
= image
->aperture
[i
];
744 /* we didn't find a useable old aperture, so create a new one */
745 if (!gerber_create_new_aperture (image
, apertureIndex
,
746 GERBV_APTYPE_CIRCLE
, lineWidth
, 0)) {
747 /* if we didn't succeed, then return */
755 gerbv_image_create_arc_object (gerbv_image_t
*image
, gdouble centerX
, gdouble centerY
,
756 gdouble radius
, gdouble startAngle
, gdouble endAngle
, gdouble lineWidth
,
757 gerbv_aperture_type_t apertureType
) {
759 gerbv_net_t
*currentNet
;
760 gerbv_cirseg_t cirSeg
= {centerX
, centerY
, radius
, radius
, startAngle
, endAngle
};
762 currentNet
= gerb_image_return_aperture_index(image
, lineWidth
, &apertureIndex
);
768 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
769 currentNet
->interpolation
= GERBV_INTERPOLATION_CCW_CIRCULAR
;
770 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
771 currentNet
->aperture
= apertureIndex
;
772 currentNet
->start_x
= centerX
+ (cos(startAngle
*M_PI
/180) * radius
);
773 currentNet
->start_y
= centerY
+ (sin(startAngle
*M_PI
/180) * radius
);
774 currentNet
->stop_x
= centerX
+ (cos(endAngle
*M_PI
/180) * radius
);
775 currentNet
->stop_y
= centerY
+ (sin(endAngle
*M_PI
/180) * radius
);;
776 currentNet
->cirseg
= g_new0 (gerbv_cirseg_t
,1);
777 *(currentNet
->cirseg
) = cirSeg
;
779 gdouble angleDiff
= currentNet
->cirseg
->angle2
- currentNet
->cirseg
->angle1
;
780 gint i
, steps
= abs(angleDiff
);
781 for (i
=0; i
<=steps
; i
++){
782 gdouble tempX
= currentNet
->cirseg
->cp_x
+ currentNet
->cirseg
->width
/ 2.0 *
783 cos ((currentNet
->cirseg
->angle1
+
784 (angleDiff
* i
) / steps
)*M_PI
/180);
785 gdouble tempY
= currentNet
->cirseg
->cp_y
+ currentNet
->cirseg
->width
/ 2.0 *
786 sin ((currentNet
->cirseg
->angle1
+
787 (angleDiff
* i
) / steps
)*M_PI
/180);
788 gerber_update_min_and_max (¤tNet
->boundingBox
,
790 lineWidth
/2,lineWidth
/2,
791 lineWidth
/2,lineWidth
/2);
793 gerber_update_image_min_max (¤tNet
->boundingBox
, 0, 0, image
);
798 gerbv_image_create_line_object (gerbv_image_t
*image
, gdouble startX
, gdouble startY
,
799 gdouble endX
, gdouble endY
, gdouble lineWidth
, gerbv_aperture_type_t apertureType
) {
801 gerbv_net_t
*currentNet
;
803 currentNet
= gerb_image_return_aperture_index(image
, lineWidth
, &apertureIndex
);
809 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
810 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
812 /* if the start and end coordinates are the same, use a "flash" aperture state */
813 if ((fabs(startX
- endX
) < 0.001) && (fabs(startY
- endY
) < 0.001))
814 currentNet
->aperture_state
= GERBV_APERTURE_STATE_FLASH
;
816 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
817 currentNet
->aperture
= apertureIndex
;
818 currentNet
->start_x
= startX
;
819 currentNet
->start_y
= startY
;
820 currentNet
->stop_x
= endX
;
821 currentNet
->stop_y
= endY
;
823 gerber_update_min_and_max (¤tNet
->boundingBox
,currentNet
->stop_x
,currentNet
->stop_y
,
824 lineWidth
/2,lineWidth
/2,lineWidth
/2,lineWidth
/2);
825 gerber_update_min_and_max (¤tNet
->boundingBox
,currentNet
->start_x
,currentNet
->start_y
,
826 lineWidth
/2,lineWidth
/2,lineWidth
/2,lineWidth
/2);
827 gerber_update_image_min_max (¤tNet
->boundingBox
, 0, 0, image
);
832 gerbv_image_create_window_pane_objects (gerbv_image_t
*image
, gdouble lowerLeftX
,
833 gdouble lowerLeftY
, gdouble width
, gdouble height
, gdouble areaReduction
,
834 gint paneRows
, gint paneColumns
, gdouble paneSeparation
){
836 gdouble startX
,startY
,boxWidth
,boxHeight
;
838 startX
= lowerLeftX
+ (areaReduction
* width
) / 2.0;
839 startY
= lowerLeftY
+ (areaReduction
* height
) / 2.0;
840 boxWidth
= (width
* (1.0 - areaReduction
) - (paneSeparation
* (paneColumns
- 1))) / paneColumns
;
841 boxHeight
= (height
* (1.0 - areaReduction
) - (paneSeparation
* (paneRows
- 1))) / paneRows
;
843 for (i
=0; i
<paneColumns
; i
++){
844 for (j
=0; j
<paneRows
; j
++) {
845 gerbv_image_create_rectangle_object (image
, startX
+ (i
* (boxWidth
+ paneSeparation
)),
846 startY
+ (j
* (boxHeight
+ paneSeparation
)),boxWidth
, boxHeight
);
854 gerbv_image_reduce_area_of_selected_objects (GArray
*selectionArray
,
855 gdouble areaReduction
, gint paneRows
, gint paneColumns
, gdouble paneSeparation
){
857 gdouble minX
,minY
,maxX
,maxY
;
859 for (i
=0; i
<selectionArray
->len
; i
++) {
860 gerbv_selection_item_t sItem
= g_array_index (selectionArray
,gerbv_selection_item_t
, i
);
861 gerbv_image_t
*image
= sItem
.image
;
862 gerbv_net_t
*currentNet
= sItem
.net
;
864 /* determine the object type first */
870 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
) {
871 /* if it's a polygon, just determine the overall area of it and delete it */
872 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
874 for (currentNet
= currentNet
->next
; currentNet
; currentNet
= currentNet
->next
){
875 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
)
877 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
878 if (currentNet
->stop_x
< minX
)
879 minX
= currentNet
->stop_x
;
880 if (currentNet
->stop_y
< minY
)
881 minY
= currentNet
->stop_y
;
882 if (currentNet
->stop_x
> maxX
)
883 maxX
= currentNet
->stop_x
;
884 if (currentNet
->stop_y
> maxY
)
885 maxY
= currentNet
->stop_y
;
887 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
889 else if ((currentNet
->interpolation
== GERBV_INTERPOLATION_x10
) ||
890 (currentNet
->interpolation
== GERBV_INTERPOLATION_LINEARx01
) ||
891 (currentNet
->interpolation
== GERBV_INTERPOLATION_LINEARx001
) ||
892 (currentNet
->interpolation
== GERBV_INTERPOLATION_LINEARx1
)) {
894 /* figure out the overall size of this element */
895 switch (image
->aperture
[currentNet
->aperture
]->type
) {
896 case GERBV_APTYPE_CIRCLE
:
897 case GERBV_APTYPE_OVAL
:
898 case GERBV_APTYPE_POLYGON
:
899 dx
= dy
= image
->aperture
[currentNet
->aperture
]->parameter
[0];
901 case GERBV_APTYPE_RECTANGLE
:
902 dx
= (image
->aperture
[currentNet
->aperture
]->parameter
[0]/ 2);
903 dy
= (image
->aperture
[currentNet
->aperture
]->parameter
[1]/ 2);
908 if (currentNet
->start_x
-dx
< minX
)
909 minX
= currentNet
->start_x
-dx
;
910 if (currentNet
->start_y
-dy
< minY
)
911 minY
= currentNet
->start_y
-dy
;
912 if (currentNet
->start_x
+dx
> maxX
)
913 maxX
= currentNet
->start_x
+dx
;
914 if (currentNet
->start_y
+dy
> maxY
)
915 maxY
= currentNet
->start_y
+dy
;
917 if (currentNet
->stop_x
-dx
< minX
)
918 minX
= currentNet
->stop_x
-dx
;
919 if (currentNet
->stop_y
-dy
< minY
)
920 minY
= currentNet
->stop_y
-dy
;
921 if (currentNet
->stop_x
+dx
> maxX
)
922 maxX
= currentNet
->stop_x
+dx
;
923 if (currentNet
->stop_y
+dy
> maxY
)
924 maxY
= currentNet
->stop_y
+dy
;
926 /* finally, delete node */
927 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
929 /* we don't current support arcs */
933 /* create new structures */
934 gerbv_image_create_window_pane_objects (image
, minX
, minY
, maxX
- minX
, maxY
- minY
,
935 areaReduction
, paneRows
, paneColumns
, paneSeparation
);
941 gerbv_image_move_selected_objects (GArray
*selectionArray
, gdouble translationX
,
942 gdouble translationY
) {
945 for (i
=0; i
<selectionArray
->len
; i
++) {
946 gerbv_selection_item_t sItem
= g_array_index (selectionArray
,gerbv_selection_item_t
, i
);
947 gerbv_net_t
*currentNet
= sItem
.net
;
949 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
) {
950 /* if it's a polygon, step through every vertex and translate the point */
951 for (currentNet
= currentNet
->next
; currentNet
; currentNet
= currentNet
->next
){
952 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
)
954 currentNet
->start_x
+= translationX
;
955 currentNet
->start_y
+= translationY
;
956 currentNet
->stop_x
+= translationX
;
957 currentNet
->stop_y
+= translationY
;
961 /* otherwise, just move the single element */
962 currentNet
->start_x
+= translationX
;
963 currentNet
->start_y
+= translationY
;
964 currentNet
->stop_x
+= translationX
;
965 currentNet
->stop_y
+= translationY
;
972 gerbv_image_return_next_renderable_object (gerbv_net_t
*oldNet
) {
973 gerbv_net_t
*currentNet
=oldNet
;
975 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
) {
976 /* if it's a polygon, step to the next non-polygon net */
977 for (currentNet
= currentNet
->next
; currentNet
; currentNet
= currentNet
->next
){
978 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
) {
979 return currentNet
->next
;
985 return currentNet
->next
;
990 gerbv_image_create_dummy_apertures (gerbv_image_t
*parsed_image
) {
991 gerbv_net_t
*currentNet
;
993 /* run through and find last net pointer */
994 for (currentNet
= parsed_image
->netlist
; currentNet
->next
; currentNet
= currentNet
->next
){
995 if (parsed_image
->aperture
[currentNet
->aperture
] == NULL
) {
996 parsed_image
->aperture
[currentNet
->aperture
] = g_new0 (gerbv_aperture_t
, 1);
997 parsed_image
->aperture
[currentNet
->aperture
]->type
= GERBV_APTYPE_CIRCLE
;
998 parsed_image
->aperture
[currentNet
->aperture
]->parameter
[0] = 0;
999 parsed_image
->aperture
[currentNet
->aperture
]->parameter
[1] = 0;