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 /* when copying, skip the first net, since it's always zero due to the way we parse things */
435 for (currentNet
= sourceImage
->netlist
->next
; currentNet
; currentNet
= currentNet
->next
){
436 /* check for any new layers and duplicate them if needed */
437 if (currentNet
->layer
!= oldLayer
) {
438 newSavedLayer
->next
= gerbv_image_duplicate_layer (currentNet
->layer
);
439 newSavedLayer
= newSavedLayer
->next
;
441 /* check for any new states and duplicate them if needed */
442 if (currentNet
->state
!= oldState
) {
443 newSavedState
->next
= gerbv_image_duplicate_state (currentNet
->state
);
444 newSavedState
= newSavedState
->next
;
446 /* create and copy the actual net over */
447 newNet
= g_new (gerbv_net_t
,1);
448 *newNet
= *currentNet
;
450 if (currentNet
->cirseg
) {
451 newNet
->cirseg
= g_new (gerbv_cirseg_t
,1);
452 *(newNet
->cirseg
) = *(currentNet
->cirseg
);
455 if (currentNet
->label
)
456 newNet
->label
= g_string_new(currentNet
->label
->str
);
458 newNet
->state
= newSavedState
;
459 newNet
->layer
= newSavedLayer
;
460 /* check if we need to translate the aperture number */
461 if (translationTable
) {
462 for (i
=0; i
<translationTable
->len
; i
++){
463 gerb_translation_entry_t translationEntry
=g_array_index (translationTable
, gerb_translation_entry_t
, i
);
465 if (translationEntry
.oldAperture
== newNet
->aperture
) {
466 newNet
->aperture
= translationEntry
.newAperture
;
471 /* check if we are transforming the net (translating, scaling, etc) */
473 newNet
->start_x
+= transform
->translateX
;
474 newNet
->start_y
+= transform
->translateY
;
475 newNet
->stop_x
+= transform
->translateX
;
476 newNet
->stop_y
+= transform
->translateY
;
477 if (newNet
->cirseg
) {
478 newNet
->cirseg
->cp_x
+= transform
->translateX
;
479 newNet
->cirseg
->cp_y
+= transform
->translateY
;
483 newSavedNet
->next
= newNet
;
485 newImage
->netlist
= newNet
;
486 newSavedNet
= newNet
;
492 gerbv_image_find_existing_aperture_match (gerbv_aperture_t
*checkAperture
, gerbv_image_t
*imageToSearch
) {
496 for (i
= APERTURE_MIN
; i
< APERTURE_MAX
; i
++) {
497 if (imageToSearch
->aperture
[i
] != NULL
) {
498 if ((imageToSearch
->aperture
[i
]->type
== checkAperture
->type
) &&
499 (imageToSearch
->aperture
[i
]->simplified
== NULL
) &&
500 (imageToSearch
->aperture
[i
]->unit
== checkAperture
->unit
)) {
501 /* check all parameters match too */
503 for (j
=0; j
<APERTURE_PARAMETERS_MAX
; j
++){
504 if (imageToSearch
->aperture
[i
]->parameter
[j
] != checkAperture
->parameter
[j
])
516 gerbv_image_find_unused_aperture_number (int startIndex
, gerbv_image_t
*image
){
519 for (i
= startIndex
; i
< APERTURE_MAX
; i
++) {
520 if (image
->aperture
[i
] == NULL
) {
528 gerbv_image_duplicate_image (gerbv_image_t
*sourceImage
, gerbv_user_transformation_t
*transform
) {
529 gerbv_image_t
*newImage
= gerbv_create_image(NULL
, sourceImage
->info
->type
);
531 int lastUsedApertureNumber
= APERTURE_MIN
- 1;
532 GArray
*apertureNumberTable
= g_array_new(FALSE
,FALSE
,sizeof(gerb_translation_entry_t
));
534 newImage
->layertype
= sourceImage
->layertype
;
535 /* copy information layer over */
536 *(newImage
->info
) = *(sourceImage
->info
);
537 newImage
->info
->name
= g_strdup (sourceImage
->info
->name
);
538 newImage
->info
->type
= g_strdup (sourceImage
->info
->type
);
539 newImage
->info
->plotterFilm
= g_strdup (sourceImage
->info
->plotterFilm
);
541 /* copy apertures over, compressing all the numbers down for a cleaner output */
542 for (i
= APERTURE_MIN
; i
< APERTURE_MAX
; i
++) {
543 if (sourceImage
->aperture
[i
] != NULL
) {
544 gerbv_aperture_t
*newAperture
= gerbv_image_duplicate_aperture (sourceImage
->aperture
[i
]);
546 lastUsedApertureNumber
= gerbv_image_find_unused_aperture_number (lastUsedApertureNumber
+ 1, newImage
);
547 /* store the aperture numbers (new and old) in the translation table */
548 gerb_translation_entry_t translationEntry
={i
,lastUsedApertureNumber
};
549 g_array_append_val (apertureNumberTable
,translationEntry
);
551 newImage
->aperture
[lastUsedApertureNumber
] = newAperture
;
555 /* step through all nets and create new layers and states on the fly, since
556 we really don't have any other way to figure out where states and layers are used */
557 gerbv_image_copy_all_nets (sourceImage
, newImage
, newImage
->layers
, newImage
->states
, NULL
, transform
, apertureNumberTable
);
558 g_array_free (apertureNumberTable
, TRUE
);
563 gerbv_image_copy_image (gerbv_image_t
*sourceImage
, gerbv_user_transformation_t
*transform
, gerbv_image_t
*destinationImage
) {
564 int lastUsedApertureNumber
= APERTURE_MIN
- 1;
566 GArray
*apertureNumberTable
= g_array_new(FALSE
,FALSE
,sizeof(gerb_translation_entry_t
));
568 /* copy apertures over */
569 for (i
= APERTURE_MIN
; i
< APERTURE_MAX
; i
++) {
570 if (sourceImage
->aperture
[i
] != NULL
) {
571 gint existingAperture
= gerbv_image_find_existing_aperture_match (sourceImage
->aperture
[i
], destinationImage
);
573 /* if we already have an existing aperture in the destination image that matches what
574 we want, just use it instead */
575 if (existingAperture
> 0) {
576 gerb_translation_entry_t translationEntry
={i
,existingAperture
};
577 g_array_append_val (apertureNumberTable
,translationEntry
);
579 /* else, create a new aperture and put it in the destination image */
581 gerbv_aperture_t
*newAperture
= gerbv_image_duplicate_aperture (sourceImage
->aperture
[i
]);
583 lastUsedApertureNumber
= gerbv_image_find_unused_aperture_number (lastUsedApertureNumber
+ 1, destinationImage
);
584 /* store the aperture numbers (new and old) in the translation table */
585 gerb_translation_entry_t translationEntry
={i
,lastUsedApertureNumber
};
586 g_array_append_val (apertureNumberTable
,translationEntry
);
588 destinationImage
->aperture
[lastUsedApertureNumber
] = newAperture
;
592 /* find the last layer, state, and net in the linked chains */
593 gerbv_netstate_t
*lastState
;
594 gerbv_layer_t
*lastLayer
;
595 gerbv_net_t
*lastNet
;
597 for (lastState
= destinationImage
->states
; lastState
->next
; lastState
=lastState
->next
){}
598 for (lastLayer
= destinationImage
->layers
; lastLayer
->next
; lastLayer
=lastLayer
->next
){}
599 for (lastNet
= destinationImage
->netlist
; lastNet
->next
; lastNet
=lastNet
->next
){}
601 /* and then copy them all to the destination image, using the aperture translation table we just built */
602 gerbv_image_copy_all_nets (sourceImage
, destinationImage
, lastLayer
, lastState
, lastNet
, transform
, apertureNumberTable
);
603 g_array_free (apertureNumberTable
, TRUE
);
607 gerbv_image_delete_net (gerbv_net_t
*currentNet
) {
608 gerbv_net_t
*tempNet
;
610 g_assert (currentNet
);
611 /* we have a match, so just zero out all the important data fields */
612 currentNet
->aperture
= 0;
613 currentNet
->aperture_state
= GERBV_APERTURE_STATE_OFF
;
615 /* if this is a polygon start, we need to erase all the rest of the
616 nets in this polygon too */
617 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
){
618 for (tempNet
= currentNet
->next
; tempNet
; tempNet
= tempNet
->next
){
619 tempNet
->aperture
= 0;
620 tempNet
->aperture_state
= GERBV_APERTURE_STATE_OFF
;
622 if (tempNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
) {
623 tempNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
626 /* make sure we don't leave a polygon interpolation in, since
627 it will still draw if it is */
628 tempNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
631 /* make sure we don't leave a polygon interpolation in, since
632 it will still draw if it is */
633 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
637 gerbv_image_delete_selected_nets (gerbv_image_t
*sourceImage
, GArray
*selectedNodeArray
) {
639 gerbv_net_t
*currentNet
;
641 for (currentNet
= sourceImage
->netlist
; currentNet
; currentNet
= currentNet
->next
){
642 for (i
=0; i
<selectedNodeArray
->len
; i
++){
643 gerbv_selection_item_t sItem
= g_array_index (selectedNodeArray
,
644 gerbv_selection_item_t
, i
);
645 if (sItem
.net
== currentNet
) {
646 gerbv_image_delete_net (currentNet
);
654 gerbv_image_create_rectangle_object (gerbv_image_t
*image
, gdouble coordinateX
,
655 gdouble coordinateY
, gdouble width
, gdouble height
) {
656 gerbv_net_t
*currentNet
;
658 /* run through and find last net pointer */
659 for (currentNet
= image
->netlist
; currentNet
->next
; currentNet
= currentNet
->next
){}
661 /* create the polygon start node */
662 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
663 currentNet
->interpolation
= GERBV_INTERPOLATION_PAREA_START
;
665 /* draw the 4 corners */
666 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
667 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
668 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
669 currentNet
->start_x
= coordinateX
;
670 currentNet
->start_y
= coordinateY
;
671 currentNet
->stop_x
= coordinateX
+ width
;
672 currentNet
->stop_y
= coordinateY
;
674 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
675 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
676 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
677 currentNet
->stop_x
= coordinateX
+ width
;
678 currentNet
->stop_y
= coordinateY
+ height
;
680 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
681 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
682 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
683 currentNet
->stop_x
= coordinateX
;
684 currentNet
->stop_y
= coordinateY
+ height
;
686 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
687 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
688 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
689 currentNet
->stop_x
= coordinateX
;
690 currentNet
->stop_y
= coordinateY
;
692 /* create the polygon end node */
693 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
694 currentNet
->interpolation
= GERBV_INTERPOLATION_PAREA_END
;
700 gerb_image_return_aperture_index (gerbv_image_t
*image
, gdouble lineWidth
, int *apertureIndex
){
701 gerbv_net_t
*currentNet
;
702 gerbv_aperture_t
*aperture
=NULL
;
705 /* run through and find last net pointer */
706 for (currentNet
= image
->netlist
; currentNet
->next
; currentNet
= currentNet
->next
){}
708 /* try to find an existing aperture that matches the requested width and type */
709 for (i
= APERTURE_MIN
; i
< APERTURE_MAX
; i
++) {
710 if (image
->aperture
[i
] != NULL
) {
711 if ((image
->aperture
[i
]->type
== GERBV_APTYPE_CIRCLE
) &&
712 (fabs (image
->aperture
[i
]->parameter
[0] - lineWidth
) < 0.001)){
713 aperture
= image
->aperture
[i
];
721 /* we didn't find a useable old aperture, so create a new one */
722 if (!gerber_create_new_aperture (image
, apertureIndex
,
723 GERBV_APTYPE_CIRCLE
, lineWidth
, 0)) {
724 /* if we didn't succeed, then return */
732 gerbv_image_create_arc_object (gerbv_image_t
*image
, gdouble centerX
, gdouble centerY
,
733 gdouble radius
, gdouble startAngle
, gdouble endAngle
, gdouble lineWidth
,
734 gerbv_aperture_type_t apertureType
) {
736 gerbv_net_t
*currentNet
;
737 gerbv_cirseg_t cirSeg
= {centerX
, centerY
, radius
, radius
, startAngle
, endAngle
};
739 currentNet
= gerb_image_return_aperture_index(image
, lineWidth
, &apertureIndex
);
745 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
746 currentNet
->interpolation
= GERBV_INTERPOLATION_CCW_CIRCULAR
;
747 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
748 currentNet
->aperture
= apertureIndex
;
749 currentNet
->start_x
= centerX
+ (cos(startAngle
*M_PI
/180) * radius
);
750 currentNet
->start_y
= centerY
+ (sin(startAngle
*M_PI
/180) * radius
);
751 currentNet
->stop_x
= centerX
+ (cos(endAngle
*M_PI
/180) * radius
);
752 currentNet
->stop_y
= centerY
+ (sin(endAngle
*M_PI
/180) * radius
);;
753 currentNet
->cirseg
= g_new0 (gerbv_cirseg_t
,1);
754 *(currentNet
->cirseg
) = cirSeg
;
760 gerbv_image_create_line_object (gerbv_image_t
*image
, gdouble startX
, gdouble startY
,
761 gdouble endX
, gdouble endY
, gdouble lineWidth
, gerbv_aperture_type_t apertureType
) {
763 gerbv_net_t
*currentNet
;
765 currentNet
= gerb_image_return_aperture_index(image
, lineWidth
, &apertureIndex
);
771 currentNet
= gerber_create_new_net (currentNet
, NULL
, NULL
);
772 currentNet
->interpolation
= GERBV_INTERPOLATION_LINEARx1
;
774 /* if the start and end coordinates are the same, use a "flash" aperture state */
775 if ((fabs(startX
- endX
) < 0.001) && (fabs(startY
- endY
) < 0.001))
776 currentNet
->aperture_state
= GERBV_APERTURE_STATE_FLASH
;
778 currentNet
->aperture_state
= GERBV_APERTURE_STATE_ON
;
779 currentNet
->aperture
= apertureIndex
;
780 currentNet
->start_x
= startX
;
781 currentNet
->start_y
= startY
;
782 currentNet
->stop_x
= endX
;
783 currentNet
->stop_y
= endY
;
789 gerbv_image_create_window_pane_objects (gerbv_image_t
*image
, gdouble lowerLeftX
,
790 gdouble lowerLeftY
, gdouble width
, gdouble height
, gdouble areaReduction
,
791 gint paneRows
, gint paneColumns
, gdouble paneSeparation
){
793 gdouble startX
,startY
,boxWidth
,boxHeight
;
795 startX
= lowerLeftX
+ (areaReduction
* width
) / 2.0;
796 startY
= lowerLeftY
+ (areaReduction
* height
) / 2.0;
797 boxWidth
= (width
* (1.0 - areaReduction
) - (paneSeparation
* (paneColumns
- 1))) / paneColumns
;
798 boxHeight
= (height
* (1.0 - areaReduction
) - (paneSeparation
* (paneRows
- 1))) / paneRows
;
800 for (i
=0; i
<paneColumns
; i
++){
801 for (j
=0; j
<paneRows
; j
++) {
802 gerbv_image_create_rectangle_object (image
, startX
+ (i
* (boxWidth
+ paneSeparation
)),
803 startY
+ (j
* (boxHeight
+ paneSeparation
)),boxWidth
, boxHeight
);
811 gerbv_image_reduce_area_of_selected_objects (GArray
*selectionArray
,
812 gdouble areaReduction
, gint paneRows
, gint paneColumns
, gdouble paneSeparation
){
814 gdouble minX
,minY
,maxX
,maxY
;
816 for (i
=0; i
<selectionArray
->len
; i
++) {
817 gerbv_selection_item_t sItem
= g_array_index (selectionArray
,gerbv_selection_item_t
, i
);
818 gerbv_image_t
*image
= sItem
.image
;
819 gerbv_net_t
*currentNet
= sItem
.net
;
821 /* determine the object type first */
827 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
) {
828 /* if it's a polygon, just determine the overall area of it and delete it */
829 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
831 for (currentNet
= currentNet
->next
; currentNet
; currentNet
= currentNet
->next
){
832 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
)
834 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
835 if (currentNet
->stop_x
< minX
)
836 minX
= currentNet
->stop_x
;
837 if (currentNet
->stop_y
< minY
)
838 minY
= currentNet
->stop_y
;
839 if (currentNet
->stop_x
> maxX
)
840 maxX
= currentNet
->stop_x
;
841 if (currentNet
->stop_y
> maxY
)
842 maxY
= currentNet
->stop_y
;
844 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
846 else if ((currentNet
->interpolation
== GERBV_INTERPOLATION_x10
) ||
847 (currentNet
->interpolation
== GERBV_INTERPOLATION_LINEARx01
) ||
848 (currentNet
->interpolation
== GERBV_INTERPOLATION_LINEARx001
) ||
849 (currentNet
->interpolation
== GERBV_INTERPOLATION_LINEARx1
)) {
851 /* figure out the overall size of this element */
852 switch (image
->aperture
[currentNet
->aperture
]->type
) {
853 case GERBV_APTYPE_CIRCLE
:
854 case GERBV_APTYPE_OVAL
:
855 case GERBV_APTYPE_POLYGON
:
856 dx
= dy
= image
->aperture
[currentNet
->aperture
]->parameter
[0];
858 case GERBV_APTYPE_RECTANGLE
:
859 dx
= (image
->aperture
[currentNet
->aperture
]->parameter
[0]/ 2);
860 dy
= (image
->aperture
[currentNet
->aperture
]->parameter
[1]/ 2);
865 if (currentNet
->start_x
-dx
< minX
)
866 minX
= currentNet
->start_x
-dx
;
867 if (currentNet
->start_y
-dy
< minY
)
868 minY
= currentNet
->start_y
-dy
;
869 if (currentNet
->start_x
+dx
> maxX
)
870 maxX
= currentNet
->start_x
+dx
;
871 if (currentNet
->start_y
+dy
> maxY
)
872 maxY
= currentNet
->start_y
+dy
;
874 if (currentNet
->stop_x
-dx
< minX
)
875 minX
= currentNet
->stop_x
-dx
;
876 if (currentNet
->stop_y
-dy
< minY
)
877 minY
= currentNet
->stop_y
-dy
;
878 if (currentNet
->stop_x
+dx
> maxX
)
879 maxX
= currentNet
->stop_x
+dx
;
880 if (currentNet
->stop_y
+dy
> maxY
)
881 maxY
= currentNet
->stop_y
+dy
;
883 /* finally, delete node */
884 currentNet
->interpolation
= GERBV_INTERPOLATION_DELETED
;
886 /* we don't current support arcs */
890 /* create new structures */
891 gerbv_image_create_window_pane_objects (image
, minX
, minY
, maxX
- minX
, maxY
- minY
,
892 areaReduction
, paneRows
, paneColumns
, paneSeparation
);
898 gerbv_image_move_selected_objects (GArray
*selectionArray
, gdouble translationX
,
899 gdouble translationY
) {
902 for (i
=0; i
<selectionArray
->len
; i
++) {
903 gerbv_selection_item_t sItem
= g_array_index (selectionArray
,gerbv_selection_item_t
, i
);
904 gerbv_net_t
*currentNet
= sItem
.net
;
906 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
) {
907 /* if it's a polygon, step through every vertex and translate the point */
908 for (currentNet
= currentNet
->next
; currentNet
; currentNet
= currentNet
->next
){
909 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
)
911 currentNet
->start_x
+= translationX
;
912 currentNet
->start_y
+= translationY
;
913 currentNet
->stop_x
+= translationX
;
914 currentNet
->stop_y
+= translationY
;
918 /* otherwise, just move the single element */
919 currentNet
->start_x
+= translationX
;
920 currentNet
->start_y
+= translationY
;
921 currentNet
->stop_x
+= translationX
;
922 currentNet
->stop_y
+= translationY
;
929 gerbv_image_return_next_renderable_object (gerbv_net_t
*oldNet
) {
930 gerbv_net_t
*currentNet
=oldNet
;
932 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_START
) {
933 /* if it's a polygon, step to the next non-polygon net */
934 for (currentNet
= currentNet
->next
; currentNet
; currentNet
= currentNet
->next
){
935 if (currentNet
->interpolation
== GERBV_INTERPOLATION_PAREA_END
) {
936 return currentNet
->next
;
942 return currentNet
->next
;