PCBNew locate code refactoring.

* Move various locate functions into the appropriate board item object.
* Unified best zoom for all frames derived from PCB_BASE_FRAME.
* Remove track.cpp as it is no longer needed.
* Dead code removal.
* Remove scary frame window pointer member from board item objects.
* Add draw bounding box to gerber draw item for debugging purposes.
This commit is contained in:
Wayne Stambaugh 2011-09-13 09:29:43 -04:00
parent ba39dac223
commit efc93aa52b
41 changed files with 1802 additions and 2183 deletions

View File

@ -1,41 +1,28 @@
/* Do not modify this file, it was automatically generated by the /* Do not modify this file, it was automatically generated by the
* PNG2cpp CMake script, using a *.png file as input. * PNG2cpp CMake script, using a *.png file as input.
*/ */
#include "bitmaps.h" #include "bitmaps.h"
static const char png[] = { static const char png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c,
0xce, 0x00, 0x00, 0x00, 0x09, 0x76, 0x70, 0x41, 0x67, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0xb1, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0x63, 0xf8, 0xff, 0xff, 0x3f,
0x1a, 0x00, 0x07, 0xb2, 0x66, 0x2f, 0x00, 0x00, 0x01, 0x64, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0x03, 0x3d, 0x30, 0x82, 0xd1, 0xc0, 0xc0, 0x24, 0x50, 0x20, 0x20, 0x40, 0x4d, 0xcc, 0x90, 0xc6,
0xd5, 0x96, 0xb1, 0x4e, 0x02, 0x41, 0x10, 0x86, 0xbf, 0xb9, 0xbb, 0xa5, 0x38, 0xa3, 0x31, 0x21, 0xc0, 0x8a, 0x61, 0x91, 0x50, 0x01, 0xd7, 0x6e, 0xa1, 0x7c, 0xce, 0x2f, 0x42, 0x05, 0x9c, 0x9f,
0xda, 0x28, 0x34, 0x1a, 0xe9, 0xa4, 0x35, 0x3c, 0x03, 0xa1, 0xb1, 0xb2, 0xb0, 0xf7, 0x21, 0xe4, 0xa8, 0x86, 0x73, 0x38, 0x9f, 0x30, 0x84, 0x32, 0xb0, 0xc1, 0x2d, 0x12, 0x49, 0x62, 0xe0, 0x15,
0x11, 0x78, 0x05, 0x0b, 0x5e, 0x81, 0xc6, 0xc6, 0x52, 0x63, 0x30, 0x34, 0x24, 0x58, 0x99, 0xa0, 0xcc, 0xe1, 0xfc, 0xa1, 0x74, 0x56, 0xe8, 0xbf, 0xd2, 0x39, 0xea, 0x61, 0x91, 0x3a, 0xee, 0x77,
0x84, 0x82, 0xc4, 0x12, 0x84, 0x53, 0xb8, 0x1d, 0x0b, 0x90, 0x28, 0x9c, 0xd1, 0x18, 0xee, 0x12, 0x82, 0x99, 0x1c, 0xb6, 0x70, 0x8b, 0x40, 0xde, 0x14, 0xca, 0xe3, 0xfc, 0x46, 0x4d, 0x4b, 0x40,
0xff, 0x6e, 0x27, 0x9b, 0xf9, 0xb2, 0xff, 0xec, 0xce, 0x8e, 0x00, 0x04, 0x41, 0x50, 0x02, 0xca, 0x58, 0xb4, 0x99, 0xe7, 0x9d, 0x40, 0x06, 0x87, 0xc3, 0xa8, 0x45, 0xa3, 0x16, 0x8d, 0x5a, 0x34,
0x02, 0x79, 0x44, 0x0c, 0x9f, 0x24, 0x00, 0x22, 0x7c, 0x89, 0x2d, 0xac, 0xbf, 0x51, 0x08, 0xb4, 0x6a, 0xd1, 0xa8, 0x45, 0xa3, 0x16, 0x8d, 0x4c, 0x8b, 0x04, 0xd3, 0x04, 0xf9, 0x69, 0x62, 0x51,
0x80, 0x8a, 0x31, 0xa6, 0x2a, 0xa3, 0xd1, 0xa8, 0x08, 0xd4, 0x54, 0x2d, 0xfd, 0xd7, 0xc1, 0xd2, 0x13, 0xd0, 0xa2, 0x4c, 0x0e, 0x7b, 0xb8, 0x45, 0x40, 0xc0, 0x08, 0xb4, 0xe8, 0xbe, 0x58, 0x3b,
0xee, 0x48, 0xd0, 0x2f, 0xe1, 0x7e, 0xca, 0xc7, 0xb8, 0x06, 0xe0, 0x4c, 0x86, 0xc3, 0xe1, 0x35, 0xcf, 0x27, 0xb1, 0x2e, 0x9e, 0x0f, 0xd4, 0xc2, 0x42, 0xb9, 0x5c, 0x1f, 0x79, 0xb3, 0x79, 0x85,
0x50, 0x38, 0xb9, 0x38, 0xa6, 0xf1, 0x54, 0xc7, 0x71, 0x1c, 0x56, 0xa5, 0x75, 0x6f, 0x83, 0xfa, 0x51, 0x5b, 0x41, 0x59, 0x9c, 0xb2, 0x02, 0x99, 0x5c, 0x01, 0xd4, 0xc4, 0x82, 0x99, 0xdc, 0x7a,
0x79, 0x93, 0x94, 0x97, 0xea, 0x7a, 0x6a, 0xed, 0xe1, 0xcb, 0xdb, 0x0b, 0xb7, 0x0f, 0x37, 0xac, 0x18, 0xcd, 0x2d, 0x5a, 0x63, 0x00, 0xe2, 0xb1, 0x17, 0xfe, 0x13, 0xe0, 0x61, 0xbb, 0x00, 0x00,
0x9d, 0xba, 0x20, 0xe1, 0xca, 0x40, 0xc1, 0x65, 0x40, 0xe3, 0xf1, 0x8e, 0xa3, 0xbd, 0xc2, 0xae, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
0xa3, 0xaa, 0x66, 0x62, 0x43, 0x5c, 0xd7, 0x99, 0x79, 0xb2, 0x3a, 0x89, 0x11, 0x42, 0x1b, 0xa2, };
0xaa, 0x38, 0xaa, 0x8a, 0xaa, 0x12, 0x97, 0x3e, 0xf2, 0x4f, 0x41, 0xd6, 0x26, 0x04, 0x4a, 0xea,
0x44, 0xc4, 0x06, 0x9a, 0xe6, 0x8e, 0xff, 0x44, 0x1a, 0x65, 0x9d, 0xc6, 0x68, 0x9d, 0xb5, 0x09, const BITMAP_OPAQUE erc_green_xpm[1] = {{ png, sizeof( png ), "erc_green_xpm" }};
0xd4, 0x68, 0x06, 0x8b, 0x1d, 0x34, 0xaf, 0x11, 0x89, 0xbe, 0xa3, 0x44, 0x40, 0xd6, 0xc6, 0x06,
0xd2, 0xa5, 0x1a, 0x41, 0xac, 0x35, 0x22, 0xf9, 0xce, 0x90, 0x64, 0xaf, 0xd3, 0xff, 0x7e, 0xeb, //EOF
0x48, 0x14, 0x34, 0x6b, 0x41, 0xe3, 0x18, 0x7d, 0x9b, 0xdb, 0xe7, 0xa9, 0x6a, 0xd3, 0x37, 0x7e,
0x21, 0xed, 0xa7, 0x19, 0x5c, 0xf5, 0x71, 0x3c, 0x89, 0x9a, 0x83, 0xfe, 0xa4, 0xf1, 0xf3, 0x84,
0xfd, 0xad, 0x03, 0x54, 0xb5, 0x2b, 0x9d, 0x76, 0xbb, 0x08, 0xd4, 0x7a, 0xfd, 0x1e, 0xf7, 0xbd,
0x56, 0xc4, 0xc7, 0x2f, 0x11, 0xa8, 0x08, 0xb8, 0x2c, 0x44, 0x45, 0xc8, 0x6c, 0x66, 0xc8, 0x6d,
0xe7, 0xa6, 0xe3, 0x16, 0x40, 0xa7, 0xdd, 0x2e, 0x01, 0x65, 0x20, 0x0f, 0x98, 0x9f, 0xa7, 0x8e,
0x08, 0xf8, 0x62, 0x4c, 0x24, 0x04, 0x5a, 0x02, 0x95, 0x9d, 0x6c, 0xb6, 0xfa, 0x0e, 0x74, 0x04,
0x22, 0x77, 0x71, 0x16, 0xc1, 0x16, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
0x60, 0x82,
};
const BITMAP_OPAQUE erc_green_xpm[1] = {{ png, sizeof( png ), "erc_green_xpm" }};
//EOF

View File

@ -8,65 +8,65 @@
static const char png[] = { static const char png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c,
0xce, 0x00, 0x00, 0x03, 0x8b, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xc5, 0x56, 0x5b, 0x4b, 0x54, 0xce, 0x00, 0x00, 0x03, 0x97, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xbd, 0x56, 0xeb, 0x4b, 0x93,
0x51, 0x14, 0xf6, 0x2f, 0x94, 0x52, 0x56, 0x8e, 0xa3, 0x20, 0x5e, 0xa2, 0xcc, 0x0a, 0x2b, 0x21, 0x51, 0x18, 0xef, 0x4f, 0x28, 0x4c, 0x0a, 0xf3, 0x32, 0xa3, 0xb4, 0xa2, 0xb2, 0x30, 0x4b, 0x13,
0x6b, 0x28, 0xb5, 0x54, 0xb0, 0x42, 0xc4, 0x27, 0x89, 0x8c, 0x54, 0x90, 0x4a, 0x9d, 0xb1, 0xf1, 0xdd, 0x94, 0xbc, 0x40, 0x45, 0x51, 0x54, 0x52, 0x99, 0x7d, 0x08, 0x44, 0x52, 0x33, 0x34, 0x37,
0x92, 0xa4, 0x29, 0x68, 0x92, 0xd4, 0x43, 0x5a, 0x69, 0xea, 0xa0, 0xa8, 0x0f, 0x29, 0x3e, 0x28, 0x2f, 0xb3, 0x85, 0x74, 0xb1, 0xd0, 0x08, 0x4c, 0x83, 0xb4, 0x24, 0x29, 0x28, 0xc3, 0x02, 0x5b,
0x4a, 0xde, 0x22, 0x15, 0xd4, 0xbc, 0xa6, 0x28, 0x46, 0x48, 0x85, 0x05, 0x81, 0xa9, 0x8c, 0x33, 0xe8, 0xbc, 0x10, 0xd8, 0x07, 0x9b, 0xe4, 0x07, 0x35, 0x35, 0x0b, 0x2f, 0x28, 0x26, 0xa2, 0x78,
0x79, 0x39, 0x7b, 0x9c, 0xaf, 0x75, 0xb6, 0xe3, 0x61, 0x46, 0x9d, 0x52, 0x18, 0xeb, 0xc0, 0xe2, 0x9b, 0xd3, 0xbd, 0xef, 0xb6, 0x5f, 0xcf, 0x7b, 0xa6, 0xaf, 0x9b, 0x6e, 0xba, 0x0f, 0xab, 0xc1,
0x9c, 0xd9, 0xfb, 0xdb, 0xfb, 0x5b, 0xeb, 0x5b, 0x6b, 0xaf, 0x3d, 0x76, 0x00, 0xec, 0xfe, 0x85, 0xb3, 0xf3, 0x9e, 0x73, 0x7e, 0xe7, 0xf9, 0x9d, 0xf3, 0x3c, 0xbf, 0xf7, 0x39, 0xef, 0x06, 0x00,
0x49, 0x1f, 0x6a, 0xb5, 0xeb, 0xb1, 0xd4, 0x54, 0xd9, 0x55, 0xdb, 0x9a, 0xd3, 0x79, 0x0b, 0xa2, 0x1b, 0xfe, 0x87, 0x89, 0x0f, 0x72, 0xb9, 0x6f, 0x40, 0x56, 0x96, 0xd7, 0x69, 0xd7, 0x9a, 0xa7,
0xf4, 0x74, 0xa7, 0x43, 0x19, 0x19, 0x72, 0xbd, 0x46, 0xe3, 0xb9, 0x60, 0x4b, 0xcb, 0xce, 0x76, 0xd4, 0x86, 0x28, 0x27, 0xc7, 0x73, 0x9b, 0x52, 0xe9, 0xa3, 0xab, 0xa8, 0xd8, 0x35, 0xe3, 0x4a,
0xd1, 0xa7, 0xa4, 0x38, 0x07, 0x48, 0x44, 0x6a, 0xb5, 0xec, 0x4a, 0x59, 0x99, 0xc7, 0xfc, 0xea, 0xcb, 0xcf, 0x97, 0xe8, 0x14, 0x0a, 0xef, 0x63, 0x22, 0x91, 0x5c, 0xee, 0x75, 0xea, 0xc5, 0x0b,
0xaa, 0x02, 0xb6, 0xb4, 0x8e, 0x0e, 0x1f, 0x10, 0xd1, 0x03, 0x89, 0x48, 0x0c, 0xb3, 0xbc, 0xdc, 0xff, 0x49, 0x93, 0x49, 0x06, 0x57, 0x5a, 0x53, 0xd3, 0x01, 0x10, 0xd1, 0x6d, 0x91, 0x48, 0x38,
0x6b, 0xb7, 0x88, 0x32, 0xff, 0x2f, 0x91, 0xd1, 0x58, 0x4a, 0xa0, 0xf7, 0x58, 0x5e, 0xbe, 0x05, 0xe6, 0xcb, 0x97, 0xbb, 0xff, 0x15, 0x91, 0xca, 0x2e, 0x91, 0xd1, 0x28, 0x03, 0xcf, 0x5b, 0x5a,
0xc6, 0xce, 0x6f, 0x5a, 0x6c, 0x34, 0x16, 0xf3, 0x79, 0x83, 0xe1, 0x0d, 0x96, 0x96, 0xce, 0x6d, 0x47, 0x0e, 0x84, 0x79, 0xc1, 0x1c, 0xcd, 0x2f, 0xf9, 0x68, 0x6c, 0x74, 0x48, 0x74, 0x0d, 0x66,
0x41, 0x10, 0x42, 0x98, 0x3e, 0x5a, 0xdb, 0x80, 0x96, 0x96, 0x63, 0xd6, 0x89, 0x18, 0x2b, 0x84, 0x33, 0x87, 0x99, 0x19, 0x2d, 0xfa, 0xfa, 0x82, 0xed, 0x90, 0x25, 0x13, 0x9c, 0x23, 0x8c, 0x01,
0xf8, 0x68, 0x34, 0x39, 0xe8, 0xed, 0x3d, 0x49, 0xbf, 0x37, 0x12, 0xcd, 0x60, 0xfd, 0x49, 0x4a, 0x03, 0x03, 0x79, 0x98, 0x9e, 0x0e, 0x5b, 0x45, 0x62, 0x36, 0x6b, 0x98, 0x8f, 0xde, 0xde, 0x44,
0xf2, 0xc5, 0xe2, 0xa2, 0x25, 0x99, 0xc1, 0xa0, 0xe6, 0x73, 0xcd, 0xcd, 0x15, 0x88, 0x8c, 0xdc, 0xd4, 0xd4, 0xec, 0xb3, 0x4f, 0xc4, 0xf3, 0x11, 0xe4, 0x7c, 0x0a, 0x0b, 0x0b, 0xf3, 0x48, 0x4d,
0x07, 0xa5, 0x52, 0x96, 0x6d, 0x85, 0xe8, 0x06, 0x07, 0xf6, 0xf4, 0xb4, 0xa0, 0xa4, 0xc4, 0x03, 0x95, 0x60, 0x7e, 0x3e, 0x7c, 0x85, 0xa3, 0x57, 0x10, 0x7e, 0x26, 0x93, 0x09, 0xf5, 0xf5, 0x55,
0x2b, 0x2b, 0xe6, 0x51, 0x45, 0xf3, 0xb9, 0x91, 0x91, 0x6e, 0xfe, 0x7e, 0xfc, 0x38, 0x09, 0x1f, 0xa8, 0xae, 0xde, 0x0b, 0x8e, 0x93, 0xae, 0x20, 0x1a, 0x87, 0xc1, 0xa0, 0x47, 0x4c, 0xcc, 0x56,
0x3f, 0x9e, 0xa6, 0xcd, 0xcd, 0x9d, 0xa9, 0xe2, 0x73, 0xf7, 0xef, 0x5f, 0x47, 0x72, 0xb2, 0x0c, 0xbc, 0x79, 0xb3, 0xc7, 0x71, 0xe8, 0x78, 0xbe, 0x89, 0x39, 0x4b, 0x4e, 0x8e, 0xc2, 0xd4, 0x54,
0x2a, 0x95, 0xec, 0xa1, 0x15, 0x22, 0xd1, 0x66, 0xa1, 0xd7, 0x6b, 0x91, 0x90, 0xe0, 0x4c, 0xf2, 0xd8, 0x0a, 0x27, 0x3f, 0x31, 0x36, 0xf6, 0x0b, 0x5d, 0x5d, 0xad, 0x34, 0x37, 0x81, 0xac, 0x2c,
0x98, 0x13, 0x3d, 0xe7, 0x9b, 0xc4, 0xc7, 0x87, 0xd0, 0xe6, 0x0c, 0x5d, 0x5d, 0x4d, 0xa8, 0xae, 0x61, 0x33, 0xd6, 0x44, 0x97, 0xd9, 0xda, 0x6f, 0xdf, 0xea, 0x71, 0xee, 0x9c, 0x3b, 0x6a, 0x6b,
0x3e, 0x0c, 0x41, 0x30, 0xc7, 0x8c, 0x93, 0x19, 0x10, 0x1c, 0x2c, 0xe7, 0x8e, 0xaa, 0xd5, 0xce, 0xf7, 0x3b, 0x26, 0xe2, 0xb8, 0x87, 0x0c, 0x5c, 0x5c, 0x9c, 0x8b, 0xd6, 0xd6, 0x40, 0xab, 0x5c,
0x59, 0x56, 0x8b, 0x81, 0xb1, 0x16, 0xbe, 0x61, 0x5c, 0x9c, 0x3f, 0x74, 0x3a, 0x73, 0x69, 0x06, 0x9c, 0xa6, 0x51, 0x33, 0x3e, 0x7d, 0x2a, 0x83, 0x5a, 0xfd, 0x98, 0x61, 0xd2, 0xd2, 0xa2, 0x28,
0xf1, 0xeb, 0xd7, 0x2c, 0x14, 0x8a, 0x3d, 0xf4, 0x1e, 0x24, 0xd9, 0xf4, 0xe4, 0xb1, 0xab, 0x99, 0xcc, 0xd6, 0x9b, 0xb1, 0xac, 0x7d, 0xf2, 0x44, 0x8e, 0x07, 0x0f, 0xb6, 0x43, 0xa3, 0x09, 0x58,
0x33, 0x97, 0x69, 0x95, 0x01, 0x93, 0x93, 0xfd, 0x08, 0x0d, 0xb5, 0x47, 0x53, 0x93, 0xf7, 0x9f, 0xeb, 0x44, 0x17, 0x18, 0xb8, 0xb9, 0x59, 0x8d, 0x8a, 0x8a, 0xdd, 0x14, 0x06, 0xe9, 0x62, 0x82,
0xab, 0x8e, 0xb1, 0x5c, 0x4e, 0x54, 0x50, 0xa0, 0xc4, 0xd8, 0x98, 0xaf, 0x29, 0x4f, 0xe2, 0x26, 0xef, 0xb2, 0x71, 0x85, 0x22, 0x8e, 0x62, 0x7f, 0x91, 0x3d, 0x97, 0x97, 0xdf, 0x83, 0x56, 0x6b,
0x02, 0x45, 0x51, 0x8b, 0xe8, 0xe8, 0x03, 0xb4, 0xf9, 0x4b, 0x8e, 0x49, 0x4e, 0x0e, 0xc3, 0xfc, 0xbd, 0x19, 0x0d, 0x1b, 0xbf, 0x74, 0x29, 0x88, 0x42, 0x1b, 0x80, 0x86, 0x86, 0x75, 0x54, 0xc7,
0xfc, 0x59, 0x13, 0x91, 0x8a, 0x8f, 0x95, 0x95, 0xe5, 0x22, 0x3d, 0x5d, 0xfe, 0xe7, 0x62, 0x58, 0x71, 0x43, 0x14, 0x9a, 0x71, 0x64, 0x64, 0x78, 0x59, 0x85, 0x46, 0x43, 0xc6, 0x21, 0x3a, 0xda,
0x23, 0x0a, 0xe7, 0x0b, 0x5a, 0x5b, 0x5f, 0xa3, 0xa6, 0x66, 0x5d, 0x9a, 0x34, 0x3e, 0x96, 0x93, 0x03, 0x1d, 0x1d, 0x82, 0x50, 0x66, 0xd1, 0xd9, 0xa9, 0x45, 0x69, 0xa9, 0x9f, 0xb8, 0x19, 0xb3,
0x13, 0x83, 0xc2, 0x42, 0x77, 0x22, 0xba, 0xc9, 0x7f, 0x57, 0x55, 0x3d, 0x25, 0xf2, 0xe3, 0xa6, 0x79, 0x14, 0x13, 0x13, 0xc3, 0x88, 0x8c, 0xdc, 0x44, 0x21, 0x0e, 0x5d, 0x4b, 0x75, 0x4b, 0xf2,
0x0a, 0xad, 0x30, 0x29, 0x11, 0x84, 0xfa, 0xfa, 0x23, 0x68, 0x6b, 0xfb, 0x0b, 0x91, 0x98, 0x5c, 0xfd, 0xc8, 0x76, 0x96, 0x98, 0x78, 0x04, 0x73, 0x73, 0x82, 0x20, 0x22, 0xc8, 0xc9, 0x24, 0x7a,
0x41, 0xf8, 0x8c, 0x1f, 0x3f, 0xa6, 0x29, 0xa9, 0x72, 0x93, 0x34, 0xf5, 0x04, 0x35, 0x22, 0x2c, 0x7a, 0xbe, 0xe2, 0xcc, 0x19, 0x77, 0xe8, 0x74, 0xe1, 0x84, 0xf9, 0x42, 0xe3, 0x46, 0xa4, 0xa4,
0xcc, 0x0d, 0x7d, 0x7d, 0x27, 0x69, 0x5e, 0x74, 0x68, 0x0e, 0x9f, 0x3e, 0x8d, 0xe1, 0xc9, 0x13, 0xec, 0x82, 0x5e, 0x2f, 0x60, 0xe2, 0xd8, 0x1a, 0xb5, 0xfa, 0x15, 0x92, 0x92, 0x3c, 0x98, 0x90,
0x37, 0x3a, 0x0e, 0x22, 0xe6, 0x03, 0x61, 0xb5, 0x24, 0xad, 0x3d, 0xbe, 0x7e, 0xf5, 0x43, 0x7b, 0xd6, 0x7c, 0x8f, 0x2c, 0x79, 0x52, 0xb2, 0x45, 0x05, 0x05, 0x29, 0xe8, 0xee, 0x3e, 0x4c, 0xbb,
0xfb, 0x36, 0x0e, 0x2c, 0x63, 0x75, 0xdc, 0xbb, 0x98, 0x18, 0x1f, 0xca, 0xc7, 0x39, 0x2a, 0xeb, 0x4f, 0x64, 0xfd, 0x67, 0xcf, 0xf2, 0x90, 0x9f, 0xef, 0x4b, 0xaa, 0x94, 0x12, 0xe6, 0x11, 0x1b,
0xef, 0x98, 0x9e, 0x1e, 0x45, 0x48, 0x88, 0x3d, 0x16, 0x16, 0xfc, 0x4d, 0x98, 0x37, 0x34, 0xbe, 0x53, 0x2a, 0xaf, 0x60, 0x64, 0xe4, 0x28, 0x61, 0xee, 0x8b, 0xfd, 0xe7, 0xcf, 0xfd, 0xd9, 0x29,
0x8a, 0xd8, 0x58, 0x77, 0xca, 0x57, 0x00, 0x97, 0xb6, 0xa7, 0xa7, 0x01, 0x51, 0x51, 0xfb, 0x79, 0xd7, 0x25, 0xe2, 0xf9, 0x13, 0x74, 0x02, 0x13, 0x3e, 0x7f, 0x7e, 0x8d, 0xf7, 0xef, 0xf7, 0x52,
0xd9, 0x6f, 0xab, 0x33, 0x08, 0x42, 0x2a, 0x27, 0xca, 0xca, 0xba, 0x89, 0x6f, 0xdf, 0x22, 0xf8, 0xbf, 0x8c, 0x39, 0x49, 0x48, 0x08, 0x21, 0x25, 0x05, 0x50, 0x5f, 0x4a, 0x76, 0x9e, 0x8d, 0xbd,
0x77, 0x75, 0x75, 0x81, 0xb8, 0x50, 0x4a, 0xbe, 0x20, 0xe4, 0xf0, 0x71, 0x95, 0x2a, 0x1c, 0x73, 0x7d, 0xfb, 0x94, 0x8d, 0x19, 0x8d, 0x6a, 0x5a, 0x63, 0xc4, 0xf1, 0xe3, 0x12, 0xb4, 0xb5, 0x1d,
0x73, 0xf1, 0xfc, 0x3b, 0x3f, 0xff, 0xae, 0x14, 0xe1, 0xb6, 0x88, 0x18, 0x0b, 0x26, 0x6f, 0x0d, 0x62, 0x79, 0x5b, 0x97, 0xc8, 0x92, 0xa7, 0x1f, 0x18, 0x1a, 0xfa, 0x8d, 0x3b, 0x77, 0x7c, 0xa9,
0xa8, 0xad, 0x7d, 0x81, 0xd1, 0xd1, 0x6c, 0x53, 0x59, 0x5f, 0x42, 0x5d, 0xdd, 0x11, 0xa9, 0x9c, 0xdf, 0x4e, 0xea, 0xfa, 0x83, 0x88, 0x88, 0x8d, 0x18, 0x1d, 0x0d, 0x65, 0xf3, 0x16, 0xcc, 0x00,
0x19, 0xbb, 0xca, 0xe5, 0xd4, 0x68, 0x1e, 0x61, 0x6a, 0xea, 0x19, 0xc7, 0x44, 0x44, 0x1c, 0x45, 0x93, 0x7a, 0x61, 0xe1, 0x0e, 0x5a, 0x37, 0x8c, 0xfe, 0xfe, 0xef, 0x38, 0x79, 0xd2, 0x0d, 0xb3,
0x67, 0xe7, 0x5a, 0xce, 0xb6, 0xdd, 0xeb, 0x04, 0x61, 0x14, 0x13, 0x13, 0xfd, 0x64, 0x8d, 0xe4, 0xb3, 0x61, 0xeb, 0x97, 0xa0, 0xe5, 0x53, 0x55, 0x2e, 0xbe, 0x4f, 0x07, 0xe9, 0x9f, 0xa7, 0xc4,
0xe1, 0x02, 0x2e, 0x5c, 0x70, 0xc0, 0x97, 0x2f, 0x7e, 0xd2, 0x01, 0x5d, 0xcb, 0xe5, 0x24, 0x06, 0xbe, 0xa6, 0x9c, 0x79, 0x2c, 0xe6, 0x63, 0x09, 0xf3, 0x8e, 0x08, 0x39, 0xc8, 0xe5, 0x41, 0x0c,
0x06, 0xde, 0xd2, 0xf8, 0x3b, 0xfc, 0xfc, 0x39, 0x85, 0xa0, 0xa0, 0xbd, 0x14, 0xdd, 0xd9, 0x9d, 0x5b, 0x59, 0x59, 0x80, 0xdc, 0x5c, 0x1f, 0x51, 0x40, 0x4e, 0x12, 0xdd, 0x58, 0x0c, 0x4d, 0x31,
0x35, 0x55, 0xc6, 0xca, 0xc9, 0x56, 0xa0, 0xd5, 0xce, 0xa0, 0xbf, 0xbf, 0x91, 0xb4, 0x77, 0xdc, 0x6b, 0xf3, 0xf2, 0xae, 0x8a, 0xb1, 0x5f, 0xce, 0xe5, 0x2d, 0x36, 0x57, 0x55, 0xf5, 0x94, 0xb5,
0xd4, 0x72, 0x18, 0xab, 0x24, 0x29, 0x75, 0x94, 0x47, 0x2d, 0xb5, 0x9d, 0x62, 0x24, 0x26, 0x3a, 0x49, 0x49, 0x51, 0xf8, 0xf0, 0x61, 0xb9, 0x5a, 0x38, 0x49, 0x74, 0x8c, 0xda, 0x79, 0x3a, 0x81,
0x49, 0xd2, 0xee, 0x20, 0xa2, 0x78, 0xa9, 0xaf, 0xe5, 0xe5, 0xdd, 0xe6, 0xda, 0x5b, 0xb6, 0x24, 0x8e, 0xa9, 0x2b, 0x36, 0xd6, 0x5b, 0x8c, 0xfd, 0x32, 0x26, 0x9a, 0x5a, 0x03, 0xc3, 0xe8, 0xf5,
0x11, 0x73, 0x47, 0xc2, 0x28, 0x95, 0x11, 0xa8, 0xac, 0xf4, 0x92, 0xa4, 0xdd, 0x41, 0x44, 0x17, 0xd3, 0x90, 0xc9, 0xdc, 0x30, 0x38, 0x18, 0x22, 0xd6, 0x48, 0xa7, 0x88, 0x2c, 0x8e, 0x5a, 0xd8,
0x29, 0x9a, 0x5e, 0x0c, 0x0f, 0x77, 0xe3, 0xda, 0x35, 0x4f, 0x74, 0x77, 0x9f, 0xd8, 0xd4, 0xd1, 0x4e, 0xdb, 0xdb, 0x5b, 0x28, 0xc9, 0x42, 0xec, 0xc3, 0xed, 0x54, 0x72, 0x2d, 0xc3, 0x34, 0x36,
0x19, 0x0b, 0x20, 0x4c, 0x1f, 0x86, 0x86, 0x3a, 0x11, 0x18, 0xe8, 0x88, 0xf1, 0xf1, 0x53, 0x52, 0x7e, 0x44, 0x7c, 0xfc, 0x16, 0x9b, 0xd0, 0x3a, 0x4d, 0x64, 0x30, 0xa4, 0x51, 0x19, 0x29, 0xa2,
0x23, 0xde, 0xd1, 0x7d, 0x24, 0x96, 0xf6, 0xab, 0x57, 0x9e, 0xdc, 0x74, 0x3a, 0xff, 0x2d, 0xef, 0x17, 0xf7, 0x2c, 0x54, 0x2a, 0x09, 0x93, 0xf5, 0x6a, 0xcc, 0x4d, 0xd4, 0xd5, 0x15, 0xe1, 0xfa,
0x1d, 0xbd, 0x7e, 0x0d, 0xa3, 0xd1, 0x78, 0x99, 0xce, 0x93, 0x15, 0x22, 0xf1, 0x2a, 0x2f, 0x2d, 0xf5, 0x18, 0x2a, 0x3d, 0x3b, 0x6d, 0x42, 0xeb, 0x34, 0x91, 0x10, 0x82, 0xfe, 0xfe, 0x60, 0x2a,
0xb5, 0x7e, 0x95, 0x8b, 0x72, 0x6d, 0x94, 0x6c, 0x2b, 0x8c, 0x65, 0x73, 0x55, 0x88, 0x07, 0xd6, 0x92, 0x81, 0xa4, 0xc0, 0x10, 0xbb, 0x77, 0x94, 0x35, 0x66, 0x49, 0x91, 0x0e, 0x89, 0x84, 0xab,
0x68, 0x71, 0x95, 0x2b, 0x95, 0x07, 0x1d, 0x32, 0x32, 0x5c, 0xb4, 0x45, 0x45, 0xee, 0xb3, 0xb6, 0xbc, 0xbc, 0xdc, 0xfe, 0x55, 0xee, 0xcc, 0x45, 0xe8, 0x08, 0x43, 0x25, 0xc8, 0x6c, 0x73, 0x95,
0xb4, 0xcc, 0x4c, 0xb9, 0xfe, 0xde, 0x3d, 0x97, 0x33, 0x16, 0x7f, 0xb7, 0xa8, 0xd5, 0xb8, 0xa6, 0xa7, 0xa7, 0x7b, 0x6c, 0x56, 0x2a, 0x25, 0xd3, 0x25, 0x25, 0x7e, 0x13, 0xae, 0x34, 0x95, 0xca,
0xa4, 0xb8, 0x28, 0x6c, 0x69, 0x69, 0x69, 0x4e, 0xde, 0x9b, 0xfe, 0xd7, 0xed, 0xb6, 0xfd, 0x06, 0x47, 0x97, 0x99, 0x29, 0x09, 0xb6, 0xf9, 0xdc, 0x22, 0xfd, 0xfb, 0x2a, 0x14, 0x12, 0x99, 0x2b,
0xf5, 0x7b, 0x75, 0x19, 0x48, 0x1d, 0x69, 0x95, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0x2d, 0x3b, 0xdb, 0x73, 0xff, 0xaa, 0xef, 0xba, 0x7f, 0x6d, 0x7f, 0x01, 0x03, 0xc2, 0x73, 0xc0,
0xae, 0x42, 0x60, 0x82, 0xbc, 0xef, 0xab, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
}; };
const BITMAP_OPAQUE ercwarn_xpm[1] = {{ png, sizeof( png ), "ercwarn_xpm" }}; const BITMAP_OPAQUE ercwarn_xpm[1] = {{ png, sizeof( png ), "ercwarn_xpm" }};

View File

@ -8,188 +8,189 @@
static const char png[] = { static const char png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x57, 0x02, 0xf9, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x57, 0x02, 0xf9,
0x87, 0x00, 0x00, 0x0b, 0x40, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xd5, 0x9a, 0x7d, 0x6c, 0x5b, 0x87, 0x00, 0x00, 0x0b, 0x49, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xd5, 0x9a, 0x7f, 0x6c, 0x5b,
0xd7, 0x79, 0xc6, 0x7f, 0xe7, 0x5c, 0x52, 0xa4, 0x68, 0x52, 0xa2, 0x68, 0x8a, 0x22, 0x25, 0x51, 0xd7, 0x75, 0xc7, 0x3f, 0xf7, 0x3e, 0x52, 0xfc, 0x21, 0x8a, 0xa2, 0x18, 0x8a, 0x22, 0x25, 0xea,
0x9f, 0x96, 0x64, 0x58, 0x96, 0xa5, 0x26, 0xb1, 0x3a, 0x77, 0x4e, 0x0a, 0x17, 0x4d, 0x5b, 0xac, 0xb7, 0x25, 0x19, 0x96, 0x15, 0xa9, 0x49, 0x6c, 0x2f, 0xce, 0x8f, 0xc2, 0xc5, 0xb2, 0x16, 0x2b,
0x98, 0x87, 0xb5, 0x81, 0xbb, 0x06, 0x6d, 0x93, 0xb4, 0x45, 0xda, 0xb5, 0xd8, 0xd0, 0x01, 0x5d, 0xe6, 0xa1, 0x6d, 0xe0, 0xae, 0x41, 0xdb, 0x24, 0x6d, 0x91, 0xfe, 0x1a, 0x86, 0x0e, 0xe8, 0x32,
0x86, 0x75, 0x5d, 0xb6, 0x6e, 0x0b, 0x8a, 0x74, 0x5b, 0xb0, 0xbf, 0x96, 0x14, 0x4d, 0xd1, 0xf4, 0xac, 0xeb, 0xb2, 0x75, 0x5b, 0xd0, 0xac, 0xdb, 0x82, 0xfe, 0xd5, 0xa4, 0x68, 0x80, 0x64, 0x6b,
0x23, 0x4b, 0xb0, 0x2e, 0x83, 0x91, 0x01, 0x43, 0x31, 0xac, 0x5f, 0x2e, 0xdc, 0x6e, 0x31, 0x6c, 0xd3, 0x04, 0xeb, 0x32, 0x18, 0x29, 0x50, 0x14, 0x45, 0x7f, 0x7a, 0x88, 0xdb, 0x3a, 0xb0, 0xdd,
0x35, 0x8e, 0x6a, 0x59, 0xb6, 0x98, 0xc8, 0x96, 0x23, 0x59, 0x91, 0x48, 0x51, 0xd4, 0x07, 0x3f, 0x2a, 0xaa, 0x65, 0xcb, 0x92, 0x23, 0x5b, 0xb6, 0x65, 0xd9, 0xa2, 0x48, 0x51, 0xa2, 0x28, 0xf2,
0xee, 0xbd, 0xe7, 0xec, 0x0f, 0x7e, 0x84, 0xa2, 0x44, 0x8a, 0xaa, 0xed, 0x01, 0xbd, 0x80, 0x74, 0xbd, 0x77, 0xef, 0xfe, 0xe0, 0x0f, 0x8b, 0x14, 0x49, 0xc9, 0xb1, 0x3d, 0xa0, 0x17, 0x78, 0x7a,
0x2f, 0x2f, 0xc9, 0xf7, 0x9c, 0xe7, 0xbc, 0xcf, 0xf3, 0x3e, 0xe7, 0x9c, 0x4b, 0xa1, 0xb5, 0xe6, 0x57, 0xef, 0x91, 0xe7, 0xde, 0x73, 0xce, 0xf7, 0x7c, 0xcf, 0xb9, 0xf7, 0x52, 0x68, 0xad, 0xf9,
0x37, 0xf9, 0x70, 0xdc, 0x89, 0xa0, 0x42, 0x08, 0x09, 0x18, 0x80, 0xb8, 0x03, 0xe1, 0x6d, 0xad, 0x7d, 0x6e, 0x8e, 0xdb, 0x21, 0x54, 0x08, 0x21, 0x01, 0x03, 0x10, 0xb7, 0x41, 0xbc, 0xad, 0xb5,
0xb5, 0x7d, 0xc7, 0x00, 0x08, 0x21, 0x1a, 0xce, 0x9c, 0x39, 0xf3, 0x99, 0xae, 0x68, 0xc7, 0xe7, 0xb6, 0x6f, 0x9b, 0x02, 0x42, 0x88, 0x86, 0x23, 0x47, 0x8e, 0x7c, 0xba, 0xab, 0xb3, 0xe3, 0xf3,
0x0d, 0xc3, 0xe1, 0xb9, 0xad, 0xc1, 0x95, 0xd2, 0xc9, 0xd4, 0xda, 0x99, 0x93, 0x27, 0x4f, 0xfe, 0x86, 0xe1, 0xf0, 0xde, 0x52, 0xe1, 0x4a, 0xe9, 0x64, 0x6a, 0xe5, 0xc8, 0xc1, 0x83, 0x07, 0xff,
0xc9, 0xcb, 0x2f, 0xbf, 0xbc, 0x7c, 0x47, 0x00, 0x1c, 0x3b, 0x76, 0xac, 0x6f, 0xa0, 0xbf, 0xe7, 0xf2, 0xf5, 0xd7, 0x5f, 0x5f, 0xbc, 0x2d, 0x0a, 0xdc, 0x7b, 0xef, 0xbd, 0x7d, 0x03, 0xfd, 0x3d,
0x1f, 0x40, 0x37, 0xdc, 0xf6, 0xb1, 0x37, 0x24, 0x6d, 0xa1, 0xc0, 0xc7, 0x1e, 0x79, 0xe8, 0x13, 0xff, 0x06, 0xba, 0xe1, 0x96, 0xdb, 0xde, 0x90, 0xb4, 0x85, 0x83, 0x1f, 0x7d, 0xfc, 0xd1, 0x8f,
0x4b, 0x42, 0x88, 0x3f, 0xd5, 0x5a, 0xdb, 0x8e, 0xdb, 0x3c, 0xfa, 0x8e, 0x7f, 0xfc, 0xfb, 0x27, 0x5f, 0x13, 0x42, 0xfc, 0x95, 0xd6, 0xda, 0x76, 0xdc, 0x62, 0xeb, 0x3b, 0xfe, 0xfd, 0x5f, 0xff,
0x7f, 0x5f, 0x6b, 0xdd, 0xa0, 0xb5, 0x22, 0xbd, 0xb9, 0x41, 0x6a, 0x6d, 0x09, 0xad, 0xd5, 0x2d, 0xe5, 0x03, 0x5a, 0xeb, 0x06, 0xad, 0x15, 0x99, 0xb5, 0x34, 0xa9, 0x95, 0x6b, 0x68, 0xad, 0x6e,
0xc7, 0x76, 0x35, 0xf8, 0x68, 0x09, 0xb4, 0xa2, 0x94, 0xc2, 0xe7, 0xf3, 0xfe, 0x16, 0xe0, 0x05, 0x5a, 0xb6, 0xab, 0xa1, 0x89, 0x96, 0x60, 0x2b, 0x4a, 0x29, 0x9a, 0x9a, 0x7c, 0x7f, 0x00, 0xf8,
0x56, 0x77, 0x02, 0x20, 0x9e, 0x79, 0xe6, 0x99, 0x8f, 0xb8, 0x5c, 0xae, 0x71, 0x29, 0xa5, 0x90, 0x80, 0xe5, 0x6a, 0x0a, 0x88, 0xe7, 0x9f, 0x7f, 0xfe, 0xc3, 0x2e, 0x97, 0x6b, 0xaf, 0x94, 0x52,
0x52, 0x22, 0xa5, 0x2c, 0x64, 0x50, 0xa1, 0x94, 0x42, 0x6b, 0x8d, 0x65, 0x59, 0xdb, 0xae, 0x9f, 0x48, 0x29, 0x91, 0x52, 0x16, 0x3c, 0xa8, 0x50, 0x4a, 0xa1, 0xb5, 0xc6, 0xb2, 0xac, 0x4d, 0xfd,
0x7c, 0xf2, 0x49, 0x23, 0x67, 0xa9, 0x77, 0x6a, 0x65, 0xa3, 0xb5, 0x26, 0x9b, 0xdd, 0x60, 0xfa, 0x67, 0x9e, 0x79, 0xc6, 0x30, 0x6d, 0x7b, 0x9f, 0x56, 0x36, 0x5a, 0x6b, 0xb2, 0xd9, 0x34, 0x67,
0x8d, 0xff, 0xc6, 0xe1, 0xbc, 0xf5, 0x71, 0xea, 0x08, 0xdd, 0x8d, 0xcf, 0xd7, 0x8c, 0x61, 0x38, 0xde, 0xfe, 0x31, 0x0e, 0xe7, 0xcd, 0xdb, 0xa9, 0x23, 0x7c, 0x37, 0x4d, 0x4d, 0xcd, 0x18, 0x86,
0x30, 0x73, 0x39, 0x07, 0xe0, 0xda, 0x91, 0x42, 0x4f, 0x3f, 0xfd, 0xf4, 0x47, 0xfb, 0xfb, 0xfb, 0x03, 0x33, 0x97, 0x73, 0x00, 0xae, 0xaa, 0x10, 0x7a, 0xee, 0xb9, 0xe7, 0x3e, 0xd2, 0xdf, 0xdf,
0x9f, 0x1d, 0x1b, 0x1b, 0x6b, 0x14, 0x42, 0x14, 0x47, 0xb6, 0xf4, 0x7e, 0x79, 0xd5, 0x2a, 0x5e, 0xff, 0xc2, 0xd8, 0xd8, 0x98, 0x47, 0x08, 0x51, 0xb4, 0x6c, 0xe9, 0xfd, 0x46, 0xd6, 0x2a, 0xf6,
0x17, 0xcf, 0xb9, 0x5c, 0x8e, 0x5f, 0x4e, 0x5c, 0x28, 0x01, 0x93, 0x0e, 0x49, 0x73, 0x4b, 0x13, 0x8b, 0xf7, 0x6c, 0x36, 0xcb, 0x6f, 0x4e, 0x9e, 0x28, 0x29, 0x26, 0x1d, 0x92, 0xe6, 0x16, 0x3f,
0x2e, 0xb7, 0x6b, 0x4f, 0x9d, 0x5d, 0x98, 0x8f, 0xf3, 0xda, 0xc5, 0xd7, 0x89, 0x44, 0x02, 0x8c, 0x2e, 0xb7, 0xeb, 0x86, 0x26, 0x3b, 0x7f, 0x39, 0xce, 0x5b, 0xe3, 0xe7, 0x88, 0x46, 0x83, 0x8c,
0x8c, 0xf6, 0x03, 0x20, 0xa5, 0x2e, 0x0d, 0xa2, 0xad, 0x4a, 0x1a, 0x46, 0x6e, 0xa3, 0x99, 0x61, 0x8c, 0xf6, 0x03, 0x20, 0xa5, 0x2e, 0x19, 0xd1, 0x56, 0xa5, 0x18, 0x46, 0x6e, 0x82, 0x99, 0x61,
0x1c, 0x1d, 0x1a, 0x1a, 0x6a, 0x74, 0xbb, 0xdd, 0xd8, 0xb6, 0x8d, 0x6d, 0xdb, 0x58, 0x96, 0x95, 0xec, 0x19, 0x1a, 0x1a, 0xf2, 0xb8, 0xdd, 0x6e, 0x6c, 0xdb, 0xc6, 0xb6, 0x6d, 0x2c, 0xcb, 0xca,
0x97, 0xbf, 0x6d, 0x6f, 0xc9, 0x42, 0x29, 0x48, 0x21, 0x4b, 0x52, 0x4a, 0x74, 0x59, 0xa6, 0x1c, 0x87, 0xbf, 0x6d, 0x97, 0x79, 0xa1, 0x24, 0xa4, 0xe0, 0xa5, 0xbc, 0xa7, 0x44, 0xe9, 0x33, 0x0e,
0x86, 0x03, 0x84, 0xdc, 0xf3, 0x68, 0xbf, 0x1e, 0x9b, 0xe7, 0xf8, 0xbd, 0x23, 0x2c, 0xde, 0x5c, 0xc3, 0x01, 0x42, 0xde, 0xb0, 0xb5, 0xcf, 0xcd, 0x5c, 0xe6, 0xfe, 0x07, 0x46, 0x58, 0xb8, 0x92,
0x41, 0xa9, 0x7c, 0x3b, 0xd2, 0x30, 0xd0, 0x08, 0x94, 0x52, 0x58, 0xb6, 0xa2, 0x58, 0xe1, 0x76, 0x40, 0xa9, 0xfc, 0x38, 0xd2, 0x30, 0xd0, 0x05, 0xd9, 0x96, 0xad, 0x28, 0x32, 0x5c, 0x55, 0xdf,
0xcc, 0xad, 0xd6, 0x1a, 0xd3, 0x34, 0x49, 0xa7, 0xd3, 0x08, 0x21, 0xb0, 0x6d, 0x1b, 0x8f, 0xc7, 0x6a, 0xad, 0x31, 0x4d, 0x93, 0x4c, 0x26, 0x83, 0x10, 0x02, 0xdb, 0xb6, 0xf1, 0x7a, 0xbd, 0xe4,
0x43, 0x2e, 0x97, 0xdb, 0x92, 0x8d, 0xca, 0xeb, 0x6c, 0x36, 0x8b, 0x99, 0xcb, 0xa1, 0x75, 0x21, 0x72, 0xb9, 0x32, 0x6f, 0x54, 0xf6, 0xb3, 0xd9, 0x2c, 0xa6, 0x95, 0x43, 0xeb, 0x82, 0x07, 0x0c,
0x03, 0x86, 0x44, 0xb0, 0x77, 0x9f, 0xf1, 0xfa, 0x3c, 0x48, 0x43, 0xd2, 0xec, 0xdf, 0x47, 0xb1, 0x89, 0xe0, 0xc6, 0xf3, 0x8c, 0xaf, 0xc9, 0x8b, 0x34, 0x24, 0xcd, 0x81, 0x46, 0x8a, 0x43, 0x14,
0x89, 0x62, 0x2c, 0xa5, 0x15, 0xca, 0xb6, 0x44, 0x55, 0x00, 0x5a, 0x6b, 0x2a, 0xa9, 0x53, 0xed, 0x65, 0x29, 0xad, 0x50, 0xb6, 0x25, 0x6a, 0x2a, 0xa0, 0xb5, 0xa6, 0x12, 0x3a, 0xb5, 0xee, 0xd5,
0xbc, 0xd3, 0xb5, 0xd6, 0x7a, 0x0b, 0x85, 0x8a, 0xfa, 0xd9, 0x93, 0x60, 0x5d, 0x4e, 0xfe, 0xf7, 0xfa, 0x45, 0x2f, 0x15, 0x21, 0x54, 0x8c, 0x9f, 0x1b, 0x0a, 0x58, 0x97, 0x93, 0x5f, 0xff, 0xf2,
0x17, 0x97, 0x90, 0x52, 0x12, 0x5f, 0x4e, 0xe1, 0x72, 0x3b, 0x09, 0xec, 0x13, 0x68, 0x5d, 0xc8, 0x14, 0x52, 0x4a, 0xe2, 0x8b, 0x29, 0x5c, 0x6e, 0x27, 0xc1, 0x46, 0x81, 0xd6, 0x85, 0x38, 0xb4,
0xae, 0xad, 0x6a, 0x1b, 0xd9, 0xad, 0x80, 0x28, 0xa7, 0x98, 0x21, 0x0a, 0x29, 0x2f, 0x50, 0xb0, 0x55, 0xfd, 0x44, 0x76, 0x33, 0x4a, 0x50, 0x18, 0x44, 0x6b, 0x8d, 0x21, 0x0a, 0x2e, 0x2f, 0x40,
0xde, 0xe3, 0xc0, 0x40, 0x3b, 0x1d, 0x1d, 0xfb, 0x71, 0xb9, 0x1b, 0x10, 0xa2, 0x10, 0x5f, 0xbe, 0x70, 0xbb, 0x6d, 0xc7, 0x40, 0x3b, 0x1d, 0x1d, 0x77, 0xe0, 0x72, 0x37, 0x20, 0x44, 0x41, 0xbe,
0x3d, 0x38, 0xe5, 0x1a, 0x70, 0x6c, 0xf7, 0x0a, 0xb5, 0xad, 0x63, 0xf5, 0x82, 0x10, 0x85, 0x0e, 0x14, 0x68, 0xad, 0x37, 0xc5, 0x80, 0x63, 0x73, 0xae, 0x50, 0x9b, 0x26, 0xb6, 0x5d, 0x25, 0x44,
0xeb, 0x02, 0x00, 0x87, 0xe1, 0xa5, 0xaf, 0xeb, 0x38, 0x4a, 0x5b, 0xb7, 0x5c, 0x85, 0x7c, 0x8d, 0x61, 0xc2, 0xba, 0xa0, 0x80, 0x43, 0x36, 0xd2, 0xd7, 0x75, 0x3f, 0x4a, 0x5b, 0x37, 0xcd, 0x42,
0x61, 0x9d, 0x5e, 0xcf, 0x0a, 0xad, 0x15, 0x4a, 0xd9, 0xa2, 0x2e, 0x00, 0xbb, 0xd1, 0x65, 0xa7, 0x4d, 0x9e, 0x88, 0xce, 0xac, 0x66, 0x85, 0xd6, 0x0a, 0xa5, 0x6c, 0xb1, 0x2d, 0x05, 0xb6, 0x82,
0x7b, 0xb6, 0xb2, 0x4b, 0x19, 0x58, 0x4f, 0xa5, 0x80, 0xc6, 0xdb, 0x32, 0x9f, 0x58, 0xcf, 0x6d, 0x4b, 0xb5, 0x67, 0x45, 0x2b, 0x69, 0xad, 0x59, 0x5d, 0x59, 0x01, 0x3c, 0xb7, 0xa4, 0x9e, 0x58,
0x94, 0xc2, 0xa8, 0x5a, 0x22, 0xae, 0xcc, 0x40, 0xf9, 0x5f, 0x3d, 0x14, 0xd2, 0x4a, 0x63, 0x2b, 0xcd, 0xa5, 0x4b, 0x62, 0x54, 0xbd, 0x20, 0xae, 0xf4, 0xc0, 0xc6, 0x6b, 0x2b, 0x08, 0x69, 0xad,
0x05, 0x5a, 0xf3, 0x6f, 0xff, 0x7e, 0x9a, 0x8b, 0xaf, 0xfd, 0x0a, 0xbf, 0xdf, 0xcf, 0x6a, 0x32, 0xf3, 0xcc, 0xa5, 0x14, 0x68, 0xcd, 0x7f, 0xff, 0xcf, 0x61, 0xc6, 0xdf, 0xfa, 0x1d, 0x81, 0x40,
0xc9, 0x5f, 0x3d, 0xfe, 0x25, 0xae, 0xcd, 0x5e, 0xe3, 0x9f, 0xbf, 0xfe, 0x2c, 0x91, 0x48, 0x3b, 0x80, 0xe5, 0x64, 0x92, 0xbf, 0x7f, 0xea, 0x4b, 0x9c, 0x9f, 0x3d, 0xcf, 0x37, 0xbe, 0xf9, 0x02,
0x0b, 0x0b, 0xf3, 0x7c, 0xfa, 0x93, 0x0f, 0x31, 0x38, 0x70, 0x80, 0xbf, 0x7d, 0xe2, 0x6b, 0xb8, 0xd1, 0x68, 0x3b, 0xf3, 0xf3, 0x97, 0xf9, 0xd4, 0x27, 0x1e, 0x65, 0x70, 0x60, 0x07, 0xff, 0xf4,
0xdc, 0x6e, 0x56, 0x56, 0x12, 0x8c, 0x8d, 0x8e, 0xf0, 0x07, 0xa7, 0x1e, 0xe0, 0xcc, 0xf7, 0x9e, 0xf4, 0xd7, 0x70, 0xb9, 0xdd, 0x24, 0x12, 0x4b, 0x8c, 0x8d, 0x8e, 0xf0, 0x67, 0x87, 0x1e, 0xe6,
0x67, 0x63, 0x76, 0x16, 0xad, 0x14, 0xaa, 0xa1, 0x81, 0x0f, 0xfe, 0xd9, 0x63, 0xa5, 0x41, 0x2a, 0xc8, 0x77, 0x5e, 0x26, 0x3d, 0x3b, 0x8b, 0x56, 0x0a, 0xd5, 0xd0, 0xc0, 0xfb, 0xff, 0xfa, 0xc9,
0x02, 0x90, 0x3b, 0x01, 0x28, 0xd7, 0xc0, 0x6e, 0x14, 0xaa, 0xbc, 0xd6, 0x5a, 0x17, 0xaa, 0x90, 0x7c, 0x9c, 0xe5, 0x21, 0x24, 0xaa, 0xd2, 0x68, 0xd1, 0x7a, 0xf5, 0xac, 0xbd, 0xf1, 0x5e, 0xd9,
0x62, 0xea, 0xf2, 0x34, 0x89, 0x95, 0x24, 0x2d, 0x81, 0xfd, 0x2c, 0x27, 0x56, 0xc8, 0x65, 0xb3, 0xd7, 0x5a, 0x17, 0x58, 0x48, 0x31, 0x79, 0xfa, 0x0c, 0x4b, 0x89, 0x24, 0x2d, 0xc1, 0x3b, 0x58,
0x4c, 0x4d, 0x4f, 0xb3, 0x99, 0xce, 0xf0, 0xbb, 0x27, 0x4f, 0xb2, 0x99, 0xce, 0x70, 0x69, 0xea, 0x5c, 0x4a, 0x90, 0xcb, 0x66, 0x99, 0x3c, 0x73, 0x86, 0xb5, 0xcc, 0x3a, 0x7f, 0x72, 0xf0, 0x20,
0x32, 0xa6, 0x99, 0xe3, 0xad, 0xa5, 0x25, 0x22, 0xed, 0xed, 0x1c, 0x18, 0x18, 0x64, 0xea, 0xf2, 0x6b, 0x99, 0x75, 0x4e, 0x4d, 0x9e, 0xc6, 0x34, 0x73, 0x5c, 0xbd, 0x76, 0x8d, 0x68, 0x7b, 0x3b,
0x15, 0xb4, 0x56, 0x24, 0x5e, 0xbd, 0xc8, 0xd8, 0xa1, 0xc3, 0xdc, 0x73, 0xd7, 0xdd, 0xec, 0x9b, 0x3b, 0x06, 0x06, 0x99, 0x3c, 0x3d, 0x85, 0xd6, 0x8a, 0xa5, 0xdf, 0x8e, 0x33, 0xb6, 0x6b, 0x37,
0x5f, 0xc0, 0x34, 0xf3, 0x15, 0xce, 0xb6, 0xec, 0xda, 0x55, 0xa8, 0x32, 0x03, 0xb5, 0x40, 0xcc, 0xf7, 0xdc, 0x75, 0x37, 0x8d, 0x97, 0xe7, 0x31, 0xcd, 0x3c, 0xc3, 0xd9, 0x96, 0x5d, 0x9f, 0x85,
0xcc, 0xcc, 0xd0, 0xda, 0xda, 0x8a, 0xdf, 0xef, 0x2f, 0x69, 0x20, 0x9f, 0x62, 0x4d, 0xb8, 0xad, 0x2a, 0x3d, 0x50, 0x4f, 0x89, 0xe9, 0xe9, 0x69, 0x5a, 0x5b, 0x5b, 0x09, 0x04, 0x02, 0xd7, 0x59,
0x8d, 0xcd, 0x74, 0x86, 0xb9, 0xb9, 0xeb, 0x34, 0x37, 0x35, 0x21, 0x04, 0xb4, 0x85, 0x42, 0x78, 0xc8, 0x56, 0x80, 0x26, 0xd2, 0xd6, 0xc6, 0x5a, 0x66, 0x9d, 0xb9, 0xb9, 0x0b, 0x34, 0xfb, 0xfd,
0xbd, 0xfb, 0xf8, 0xd1, 0x8f, 0x7e, 0x88, 0xd7, 0xbb, 0x8f, 0x70, 0x5b, 0x1b, 0x00, 0x7e, 0x7f, 0x08, 0x01, 0x6d, 0xe1, 0x30, 0x3e, 0x5f, 0x23, 0x3f, 0xfd, 0xe9, 0x4f, 0xf0, 0xf9, 0x1a, 0x89,
0x33, 0xf1, 0xf8, 0x32, 0xf1, 0x78, 0x9c, 0xf6, 0x70, 0x18, 0xa5, 0x14, 0xee, 0x48, 0x98, 0x6b, 0xb4, 0xb5, 0x01, 0x10, 0x08, 0x34, 0x13, 0x8f, 0x2f, 0x12, 0x8f, 0xc7, 0x69, 0x8f, 0x44, 0x50,
0x53, 0xbf, 0x42, 0x2b, 0x8d, 0xd5, 0xdc, 0xb4, 0xa3, 0x91, 0xdd, 0x16, 0x11, 0x97, 0x03, 0xd5, 0x4a, 0xe1, 0x8e, 0x46, 0x38, 0x3f, 0xf9, 0x3b, 0xb4, 0xd2, 0x58, 0xcd, 0xfe, 0xaa, 0x89, 0xec,
0x5a, 0xa3, 0x0b, 0x0d, 0x3c, 0xfc, 0xf1, 0x8f, 0x96, 0x2a, 0x90, 0x10, 0x12, 0x43, 0x4a, 0x46, 0x96, 0x04, 0x71, 0x25, 0xcc, 0x74, 0x61, 0x80, 0xc7, 0x3e, 0xf6, 0x91, 0x12, 0x03, 0x09, 0x21,
0x47, 0x86, 0x39, 0x74, 0x70, 0xb0, 0xd4, 0x86, 0xd3, 0xe9, 0x04, 0xe0, 0x2f, 0xff, 0xfc, 0x8b, 0x31, 0xa4, 0x64, 0x74, 0x64, 0x98, 0x5d, 0x3b, 0x07, 0x4b, 0x63, 0x38, 0x9d, 0x4e, 0x00, 0xfe,
0xa5, 0xb6, 0x0d, 0xc3, 0x40, 0x2b, 0xc5, 0x7b, 0x3e, 0xff, 0x87, 0xd8, 0xb6, 0xfd, 0xb6, 0x59, 0xee, 0x6f, 0xbe, 0x58, 0x1a, 0xdb, 0x30, 0x0c, 0xb4, 0x52, 0xbc, 0xe7, 0xf3, 0x9f, 0xc5, 0xb6,
0x0a, 0x91, 0xa7, 0x53, 0xde, 0x07, 0xaa, 0x03, 0xa8, 0xcc, 0x42, 0xb5, 0x73, 0x22, 0x91, 0x20, 0xed, 0xeb, 0xc9, 0x52, 0x88, 0x3c, 0x9c, 0xf2, 0x79, 0xa0, 0xb6, 0x02, 0x95, 0x5e, 0xa8, 0x75,
0x99, 0x4c, 0x92, 0xcd, 0x66, 0xf1, 0x7a, 0xbd, 0x79, 0xb7, 0x2e, 0x88, 0x18, 0xe0, 0xf9, 0x17, 0x4f, 0x24, 0x12, 0x24, 0x93, 0x49, 0x72, 0xb9, 0x1c, 0x3e, 0x9f, 0xaf, 0xe0, 0x41, 0x55, 0x9a,
0xbe, 0xcf, 0xf9, 0x89, 0x5f, 0x12, 0x0e, 0x87, 0x59, 0x59, 0x59, 0xe1, 0x89, 0xaf, 0x7c, 0x99, 0xc8, 0xcb, 0xaf, 0x7c, 0x8f, 0xe3, 0x27, 0x7f, 0x43, 0x24, 0x12, 0x21, 0x91, 0x48, 0xf0, 0xf4,
0xab, 0x33, 0x31, 0xbe, 0xfe, 0xec, 0xb7, 0x39, 0x3c, 0x72, 0x98, 0xc9, 0xd7, 0x26, 0x79, 0xe4, 0x57, 0xbe, 0xcc, 0xd9, 0xe9, 0x19, 0xbe, 0xf9, 0xc2, 0x7f, 0xb0, 0x7b, 0x64, 0x37, 0x13, 0x6f,
0x13, 0x0f, 0x32, 0x7c, 0xe8, 0x20, 0x8f, 0xff, 0xcd, 0x57, 0xf1, 0xf9, 0x7c, 0xac, 0xaf, 0xaf, 0x4d, 0xf0, 0xf8, 0xc7, 0x1f, 0x61, 0x78, 0xd7, 0x4e, 0x9e, 0xfa, 0xc7, 0xaf, 0xd2, 0xd4, 0xd4,
0xd3, 0xdf, 0xd7, 0xc3, 0xc3, 0x1f, 0x7f, 0x90, 0xd3, 0x2f, 0xbd, 0xc4, 0xdc, 0xb5, 0xd9, 0xbc, 0xc4, 0xea, 0xea, 0x2a, 0xfd, 0x7d, 0x3d, 0x3c, 0xf6, 0xb1, 0x47, 0x38, 0xfc, 0xda, 0x6b, 0xcc,
0x37, 0xb8, 0x1b, 0xf9, 0xf4, 0x67, 0x3f, 0x8b, 0x94, 0xb2, 0x08, 0xaa, 0xba, 0x06, 0xea, 0xf1, 0x9d, 0x9f, 0xcd, 0xe7, 0x06, 0xb7, 0x87, 0x4f, 0x7d, 0xe6, 0x33, 0x48, 0x29, 0x8b, 0x4a, 0xd5,
0x04, 0x21, 0x04, 0xab, 0xab, 0xab, 0x44, 0x22, 0x11, 0xa4, 0x94, 0x6c, 0x6e, 0x6e, 0xe6, 0x29, 0x8e, 0x81, 0xed, 0xe4, 0x04, 0x21, 0x04, 0xc9, 0x64, 0x92, 0x68, 0x34, 0x0a, 0xc0, 0xda, 0xda,
0x64, 0xab, 0x92, 0x17, 0xcc, 0xdd, 0x78, 0x93, 0xee, 0x9e, 0x5e, 0xee, 0xbd, 0xef, 0xdd, 0x64, 0x5a, 0x89, 0x46, 0x8b, 0xd7, 0xdc, 0xc5, 0x4b, 0x74, 0xf7, 0xf4, 0xf2, 0xc0, 0x83, 0xef, 0x26,
0x73, 0x26, 0xb9, 0x5c, 0x8e, 0x37, 0x66, 0xaf, 0x83, 0x10, 0xdc, 0x73, 0xcf, 0x51, 0x10, 0x82, 0x9b, 0x33, 0xc9, 0xe5, 0x72, 0xbc, 0x3d, 0x7b, 0x01, 0x84, 0xe0, 0x9e, 0x7b, 0xf6, 0x80, 0x10,
0x37, 0x66, 0xaf, 0x61, 0x9a, 0x26, 0x9b, 0xe9, 0x0c, 0x87, 0x47, 0x8e, 0x10, 0x69, 0xef, 0xe0, 0xbc, 0x3d, 0x7b, 0x1e, 0xd3, 0x34, 0x59, 0xcb, 0xac, 0xb3, 0x7b, 0xe4, 0x4e, 0xa2, 0xed, 0x1d,
0xc6, 0x9b, 0x0b, 0x28, 0xa5, 0x58, 0x5b, 0x4d, 0xd2, 0xd7, 0x15, 0x65, 0xe4, 0xd0, 0x21, 0x3c, 0x5c, 0xbc, 0x34, 0x8f, 0x52, 0x8a, 0x95, 0xe5, 0x24, 0x7d, 0x5d, 0x9d, 0x8c, 0xec, 0xda, 0x85,
0x4e, 0x03, 0xd3, 0x34, 0xf3, 0x14, 0xb2, 0xdf, 0x2e, 0xa3, 0xdb, 0x00, 0xd8, 0xb6, 0x5d, 0xca, 0xd7, 0x69, 0x60, 0x9a, 0x66, 0x1e, 0x42, 0xf6, 0x75, 0x1a, 0xdd, 0xa4, 0x80, 0x6d, 0xdb, 0x25,
0xc0, 0xe4, 0xe4, 0x24, 0x53, 0x53, 0x53, 0x24, 0x93, 0xc9, 0xaa, 0xc2, 0xf5, 0x78, 0x3c, 0x38, 0x0f, 0x4c, 0x4c, 0x4c, 0x30, 0x39, 0x39, 0x49, 0x32, 0x99, 0xac, 0x1a, 0xb8, 0x00, 0x5e, 0xaf,
0x9d, 0xce, 0xad, 0x02, 0x2e, 0x78, 0x41, 0x77, 0xb4, 0x93, 0x95, 0x44, 0x9c, 0x33, 0x3f, 0xfd, 0x17, 0xa7, 0xd3, 0x59, 0x7a, 0xa6, 0xec, 0x42, 0x1e, 0x50, 0x8a, 0xee, 0xce, 0x18, 0x89, 0xa5,
0x09, 0x81, 0x80, 0x1f, 0x29, 0x04, 0xd1, 0xce, 0x76, 0x9a, 0x7c, 0x5e, 0x7e, 0xfa, 0x93, 0x1f, 0x38, 0x47, 0x7e, 0xf1, 0x73, 0x82, 0xc1, 0x00, 0x52, 0x08, 0x3a, 0x63, 0xed, 0xf8, 0x9b, 0x7c,
0xd3, 0xe4, 0xf3, 0xd2, 0x15, 0xed, 0x40, 0x08, 0x41, 0x70, 0x7f, 0x80, 0xe9, 0xcb, 0x53, 0xac, 0xfc, 0xe2, 0xe7, 0x3f, 0xc3, 0xdf, 0xe4, 0xa3, 0xab, 0xb3, 0x03, 0x21, 0x04, 0xa1, 0x3b, 0x82,
0x24, 0xe2, 0x74, 0x47, 0x3b, 0xd1, 0x4a, 0x11, 0x6c, 0x0d, 0xb1, 0x99, 0x4e, 0xb3, 0xb4, 0xf4, 0x9c, 0x39, 0x3d, 0x49, 0x62, 0x29, 0x4e, 0x77, 0x67, 0x0c, 0xad, 0x14, 0xa1, 0xd6, 0x30, 0x6b,
0x16, 0x2e, 0x8f, 0x27, 0xdf, 0x86, 0x52, 0x28, 0xab, 0x0e, 0x1f, 0x10, 0x42, 0x10, 0x0e, 0x87, 0x99, 0x0c, 0xd7, 0xae, 0x5d, 0xc5, 0xe5, 0xf5, 0xe6, 0x49, 0x42, 0x29, 0x94, 0xb5, 0x8d, 0x3c,
0x89, 0xc5, 0x62, 0x0c, 0x0d, 0x0d, 0x55, 0x15, 0xf5, 0x36, 0xc1, 0x6b, 0x50, 0x85, 0xf9, 0xff, 0x20, 0x84, 0x20, 0x12, 0x89, 0x30, 0x33, 0x33, 0xc3, 0xd0, 0xd0, 0xd0, 0xb6, 0x82, 0x3a, 0x4f,
0x03, 0x1f, 0x3e, 0xb9, 0x8d, 0x8e, 0x83, 0x03, 0xfd, 0x7c, 0xe9, 0xb1, 0x2f, 0x6c, 0xa3, 0xe8, 0x71, 0x0a, 0x55, 0xa8, 0xff, 0x1f, 0xfe, 0xd0, 0xc1, 0x4d, 0x70, 0x1c, 0x1c, 0xe8, 0xe7, 0x4b,
0x17, 0xbf, 0xf0, 0xb9, 0x2d, 0xf7, 0x94, 0x56, 0xbc, 0xf7, 0x03, 0xef, 0xaf, 0xf8, 0x7e, 0x3e, 0x4f, 0x7e, 0x61, 0x13, 0x44, 0xbf, 0xf8, 0x85, 0xcf, 0x95, 0x3d, 0x53, 0x5a, 0xf1, 0x87, 0xef,
0xb6, 0xd2, 0x4a, 0xd7, 0xe5, 0x03, 0xa1, 0x50, 0x88, 0x50, 0x28, 0x54, 0xd3, 0xdc, 0x2a, 0xef, 0x7b, 0x6f, 0xc5, 0xf7, 0xc9, 0xd7, 0x42, 0x5a, 0xe9, 0x6d, 0xe5, 0x81, 0x70, 0x38, 0x4c, 0x38,
0xdb, 0x05, 0xfa, 0x00, 0x7c, 0xeb, 0x3b, 0xff, 0xc2, 0xeb, 0xb3, 0x73, 0x34, 0x35, 0x35, 0x11, 0x1c, 0xae, 0x99, 0xdc, 0xaa, 0xe5, 0x84, 0x22, 0x7c, 0x00, 0x5e, 0xfc, 0xcf, 0xef, 0x72, 0x6e,
0x5f, 0x5e, 0xe2, 0x89, 0xaf, 0xfc, 0x05, 0x97, 0x2e, 0x5f, 0xe1, 0xb9, 0xef, 0xbe, 0xc0, 0x5d, 0x76, 0x0e, 0xbf, 0xdf, 0x4f, 0x7c, 0xf1, 0x1a, 0x4f, 0x7f, 0xe5, 0x6f, 0x39, 0x75, 0x7a, 0x8a,
0x77, 0xdd, 0xcd, 0x85, 0x0b, 0xe7, 0x79, 0xf0, 0x23, 0x1f, 0xe6, 0x1d, 0xa3, 0x23, 0x7c, 0xf9, 0x97, 0xbe, 0xfd, 0x0a, 0x77, 0xdd, 0x75, 0x37, 0x27, 0x4e, 0x1c, 0xe7, 0x91, 0x0f, 0x7f, 0x88,
0xaf, 0xbf, 0x4a, 0x38, 0x12, 0x21, 0x95, 0x4a, 0x11, 0x0a, 0xb6, 0xf0, 0xe8, 0xa7, 0x1e, 0xe2, 0x77, 0x8d, 0x8e, 0xf0, 0xe5, 0x7f, 0xf8, 0x2a, 0x91, 0x68, 0x94, 0x54, 0x2a, 0x45, 0x38, 0xd4,
0xa5, 0x7f, 0xfd, 0x3e, 0xf1, 0xc5, 0x9b, 0xec, 0xf3, 0x7a, 0xc9, 0x64, 0xb3, 0x3c, 0xf2, 0xe8, 0xc2, 0x13, 0x9f, 0x7c, 0x94, 0xd7, 0xfe, 0xeb, 0x7b, 0xc4, 0x17, 0xae, 0xd0, 0xe8, 0xf3, 0xb1,
0xa3, 0x45, 0x0d, 0x88, 0xba, 0x7d, 0x60, 0xa7, 0x5a, 0x5f, 0x4b, 0xdc, 0xe5, 0x14, 0x5a, 0x59, 0x9e, 0xcd, 0xf2, 0xf8, 0x13, 0x4f, 0x14, 0x63, 0x40, 0x6c, 0x3b, 0x0f, 0x54, 0xe3, 0xfa, 0x4d,
0x59, 0xc5, 0x30, 0x0c, 0x46, 0x46, 0x46, 0x90, 0x86, 0x03, 0xcb, 0x34, 0x59, 0xbc, 0xb9, 0x88, 0xf5, 0x4f, 0x99, 0x32, 0x94, 0x20, 0x94, 0x48, 0x2c, 0x63, 0x18, 0x06, 0x23, 0x23, 0x23, 0x48,
0xcb, 0xe5, 0x66, 0x70, 0x70, 0x10, 0x97, 0xcb, 0xcd, 0xe2, 0xe2, 0x22, 0x96, 0x69, 0x82, 0x10, 0xc3, 0x81, 0x65, 0x9a, 0x2c, 0x5c, 0x59, 0xc0, 0xe5, 0x72, 0x33, 0x38, 0x38, 0x88, 0xcb, 0xe5,
0x04, 0x02, 0x01, 0xfa, 0xfa, 0xfa, 0x48, 0xae, 0xa6, 0xd0, 0x4a, 0x61, 0x9b, 0x39, 0x06, 0x07, 0x66, 0x61, 0x61, 0x01, 0xcb, 0x34, 0x41, 0x08, 0x82, 0xc1, 0x20, 0x7d, 0x7d, 0x7d, 0x24, 0x97,
0x0e, 0x70, 0xef, 0x7d, 0xef, 0xc6, 0xef, 0xf5, 0x60, 0x99, 0x66, 0x9e, 0x42, 0x4a, 0x55, 0xd7, 0x53, 0x68, 0xa5, 0xb0, 0xcd, 0x1c, 0x83, 0x03, 0x3b, 0x78, 0xe0, 0xc1, 0x77, 0x13, 0xf0, 0x79,
0x40, 0x9e, 0xc7, 0xba, 0xaa, 0x99, 0x55, 0x76, 0x3a, 0x93, 0xc9, 0x94, 0x95, 0xca, 0x82, 0x0f, 0xb1, 0x4c, 0x33, 0x0f, 0x21, 0xa5, 0x6a, 0xc7, 0x40, 0x3e, 0x11, 0xe9, 0x9a, 0xc9, 0xac, 0xb2,
0x28, 0x1b, 0xa5, 0x6c, 0x06, 0x0e, 0xf4, 0xd2, 0xdc, 0xe4, 0x25, 0x36, 0x73, 0x85, 0xb6, 0x50, 0xbf, 0xbe, 0xbe, 0x5e, 0x56, 0xac, 0xe5, 0xab, 0xd1, 0xfc, 0x35, 0xb0, 0xa3, 0x97, 0x66, 0xbf,
0x10, 0x21, 0x04, 0xbd, 0xbd, 0x51, 0x02, 0xfe, 0x66, 0x26, 0x26, 0xce, 0x13, 0xf0, 0x37, 0xd3, 0x8f, 0x99, 0xe9, 0x29, 0xda, 0xc2, 0x21, 0x84, 0x10, 0xf4, 0xf6, 0x76, 0x12, 0x0c, 0x34, 0x73,
0xdf, 0xdb, 0x8d, 0x10, 0x10, 0x09, 0x87, 0x48, 0xc4, 0x97, 0x58, 0x98, 0xbf, 0xc1, 0x40, 0x7f, 0xf2, 0xe4, 0x71, 0x82, 0x81, 0x66, 0xfa, 0x7b, 0xbb, 0x11, 0x02, 0xa2, 0x91, 0x30, 0x4b, 0xf1,
0x2f, 0x4a, 0xd9, 0x84, 0xc2, 0x61, 0x92, 0xa9, 0x14, 0x17, 0xce, 0x9f, 0xa3, 0xc1, 0xe3, 0xcd, 0x6b, 0xcc, 0x5f, 0xbe, 0xc8, 0x40, 0x7f, 0x2f, 0x4a, 0xd9, 0x84, 0x23, 0x11, 0x92, 0xa9, 0x14,
0x53, 0x48, 0xd9, 0x68, 0xa5, 0xab, 0x1b, 0x59, 0xe5, 0xcc, 0xb1, 0x16, 0x88, 0x96, 0x96, 0x16, 0x27, 0x8e, 0xbf, 0x49, 0x83, 0xd7, 0x97, 0x87, 0x90, 0xb2, 0xd1, 0x4a, 0xd7, 0x4e, 0x64, 0x95,
0xa6, 0xa7, 0xa7, 0xf1, 0x78, 0x3c, 0x78, 0x3c, 0x1e, 0x94, 0x52, 0x48, 0x29, 0x4b, 0x14, 0xfa, 0x95, 0x63, 0x3d, 0x25, 0x5a, 0x5a, 0x5a, 0x38, 0x7b, 0xf6, 0x2c, 0x1e, 0x8f, 0x07, 0xaf, 0xd7,
0xc0, 0xfd, 0x27, 0xb6, 0x71, 0xb8, 0xab, 0xb3, 0x93, 0x3f, 0xfe, 0xdc, 0xa7, 0xb6, 0xc5, 0xfc, 0x5b, 0xe2, 0xec, 0x22, 0x84, 0xde, 0xf7, 0xd0, 0x81, 0x4d, 0x18, 0xee, 0x8a, 0xc5, 0xf8, 0x8b,
0xcc, 0x27, 0x3f, 0xb6, 0x55, 0x03, 0x4a, 0xf1, 0xdb, 0xf7, 0x1e, 0xa7, 0x72, 0xdf, 0x2a, 0xcf, 0xcf, 0x7d, 0x72, 0x93, 0xcc, 0x4f, 0x7f, 0xe2, 0xa3, 0xe5, 0x31, 0xa0, 0x14, 0xf7, 0x3d, 0x70,
0x10, 0x45, 0x5d, 0x22, 0xde, 0x0d, 0xc4, 0xfe, 0xfd, 0xfb, 0x09, 0x04, 0x02, 0x84, 0xc3, 0x61, 0x3f, 0x95, 0xfb, 0x56, 0x79, 0x84, 0x28, 0xb6, 0x15, 0xc4, 0x5b, 0x29, 0x11, 0x0a, 0x85, 0x58,
0x5c, 0x2e, 0x17, 0x9b, 0x9b, 0x9b, 0x28, 0x3b, 0x4f, 0x1f, 0x80, 0x6f, 0x7c, 0xeb, 0x79, 0x96, 0x5c, 0x5c, 0x24, 0x12, 0x89, 0xe0, 0x72, 0xb9, 0xf2, 0x54, 0x4a, 0x1e, 0x42, 0x00, 0xdf, 0x7a,
0x57, 0x92, 0x84, 0x42, 0x21, 0x66, 0xae, 0xce, 0xf0, 0x77, 0x8f, 0x3f, 0xc6, 0xd5, 0x2b, 0x57, 0xf1, 0x65, 0x16, 0x13, 0x49, 0xc2, 0xe1, 0x30, 0xd3, 0x67, 0xa7, 0xf9, 0xe7, 0xa7, 0x9e, 0xe4,
0x79, 0xe5, 0xe7, 0x67, 0x4b, 0x31, 0xde, 0x71, 0xf4, 0x9d, 0x1c, 0x1a, 0x3e, 0xc4, 0xf3, 0xcf, 0xec, 0xd4, 0x59, 0x8e, 0x1d, 0x7d, 0xa3, 0x24, 0xe3, 0x5d, 0x7b, 0xf6, 0xb1, 0x6b, 0x78, 0x17,
0x3d, 0xc7, 0x81, 0xc1, 0x21, 0x16, 0x6f, 0x2e, 0xa0, 0x85, 0xe4, 0x43, 0x0f, 0x7c, 0x88, 0xeb, 0x2f, 0xbf, 0xf4, 0x12, 0x3b, 0x06, 0x87, 0x58, 0xb8, 0x32, 0x8f, 0x16, 0x92, 0x0f, 0x3e, 0xfc,
0xff, 0xf9, 0x4f, 0x0c, 0xb8, 0x12, 0x38, 0x1a, 0x9b, 0xb8, 0x79, 0xf3, 0x26, 0x9e, 0xdf, 0xfb, 0x41, 0x2e, 0xfc, 0xe0, 0xeb, 0x0c, 0xb8, 0x96, 0x70, 0x78, 0xfc, 0x5c, 0xb9, 0x72, 0x05, 0xef,
0x1a, 0x86, 0x21, 0xd1, 0x5a, 0xcb, 0x9a, 0x22, 0x2e, 0xa2, 0xae, 0x05, 0xa2, 0xdc, 0x79, 0x17, 0x9f, 0x7e, 0x0d, 0xc3, 0x90, 0x68, 0xad, 0x65, 0xdd, 0x20, 0x2e, 0x6a, 0x5d, 0x4f, 0x89, 0x12,
0x17, 0x17, 0xd9, 0xd8, 0xd8, 0x20, 0x93, 0xc9, 0x90, 0x5a, 0x4b, 0x95, 0xaa, 0x50, 0x3a, 0x9b, 0x6d, 0x2a, 0xc5, 0xc2, 0xc2, 0x02, 0xe9, 0x74, 0x9a, 0x6c, 0x36, 0xcb, 0x72, 0x2a, 0x55, 0x62,
0xa5, 0xaf, 0xaf, 0x9f, 0x60, 0x30, 0xc8, 0x8d, 0x1b, 0x6f, 0x62, 0x5a, 0x26, 0xeb, 0x1b, 0xeb, 0xa1, 0x4c, 0x36, 0x4b, 0x5f, 0x5f, 0x3f, 0xa1, 0x50, 0x88, 0x8b, 0x17, 0x2f, 0x61, 0x5a, 0x26,
0xb4, 0x05, 0x03, 0x34, 0xb7, 0x04, 0x58, 0x5d, 0x49, 0xb0, 0xb1, 0xb1, 0x8e, 0x65, 0x5b, 0x04, 0xab, 0xe9, 0x55, 0xda, 0x42, 0x41, 0x9a, 0x5b, 0x82, 0x2c, 0x27, 0x96, 0x48, 0xa7, 0x57, 0xb1,
0x5b, 0x9a, 0x19, 0x18, 0x1c, 0x64, 0x70, 0x68, 0x88, 0xb3, 0x3f, 0x3b, 0x83, 0xd2, 0x0a, 0x37, 0x6c, 0x8b, 0x50, 0x4b, 0x33, 0x03, 0x83, 0x83, 0x0c, 0x0e, 0x0d, 0xf1, 0xc6, 0xff, 0x1e, 0x41,
0x26, 0x81, 0xc0, 0x7e, 0x0c, 0x8f, 0x1f, 0x7b, 0x63, 0x85, 0x55, 0xdb, 0x42, 0x48, 0x07, 0x4a, 0x69, 0x85, 0x1b, 0x93, 0x60, 0xf0, 0x0e, 0x0c, 0x6f, 0x00, 0x3b, 0x9d, 0x60, 0xd9, 0xb6, 0x10,
0xab, 0xea, 0x65, 0xb4, 0x32, 0x65, 0xd5, 0x3a, 0x5e, 0x6d, 0x2a, 0x51, 0xf4, 0x11, 0xad, 0x35, 0xd2, 0x81, 0xd2, 0xaa, 0x36, 0x8d, 0x56, 0xba, 0xac, 0xd6, 0xc4, 0x6b, 0x15, 0x75, 0xc5, 0x3c,
0x87, 0x0f, 0x0d, 0x31, 0x7d, 0x25, 0x46, 0x62, 0xf9, 0x2d, 0xa2, 0x1d, 0x61, 0xa4, 0x94, 0x74, 0xa2, 0xb5, 0x66, 0xf7, 0xae, 0x21, 0xce, 0x4c, 0xcd, 0xb0, 0xb4, 0x78, 0x95, 0xce, 0x8e, 0x08,
0x44, 0x3b, 0x79, 0x6b, 0x61, 0x81, 0xc4, 0x6a, 0x0a, 0xa4, 0x83, 0xce, 0xae, 0x4e, 0xa4, 0x14, 0x52, 0x4a, 0x3a, 0x3a, 0x63, 0x5c, 0x9d, 0x9f, 0x67, 0x69, 0x39, 0x05, 0xd2, 0x41, 0xac, 0x2b,
0x18, 0x9e, 0x7d, 0x9c, 0x7b, 0xe5, 0x7f, 0x00, 0x88, 0x74, 0x76, 0xa0, 0x94, 0x22, 0x15, 0x1c, 0x86, 0x94, 0x02, 0xc3, 0xdb, 0xc8, 0x9b, 0xc7, 0x7e, 0x05, 0x40, 0x34, 0xd6, 0x81, 0x52, 0x8a,
0xe3, 0xe7, 0x8b, 0x31, 0x20, 0x4d, 0xce, 0x71, 0x90, 0x3e, 0x59, 0x58, 0x20, 0x99, 0xb6, 0xda, 0x54, 0x68, 0x8c, 0xa3, 0x0b, 0x33, 0x40, 0x86, 0x9c, 0x63, 0x27, 0x7d, 0xb2, 0xb0, 0x40, 0x32,
0x35, 0x03, 0x3b, 0x4d, 0x27, 0x76, 0x7a, 0x2d, 0xa5, 0xa4, 0xad, 0xad, 0x8d, 0x40, 0x20, 0x80, 0x6d, 0xb5, 0xa5, 0x07, 0xaa, 0x95, 0x13, 0xd5, 0xfe, 0x37, 0x0c, 0x83, 0xb6, 0xb6, 0x36, 0x82,
0x6d, 0xdb, 0x44, 0xbb, 0x7a, 0xd8, 0xd8, 0x4c, 0xe3, 0x71, 0xbb, 0xb9, 0xef, 0x5d, 0xe3, 0xdc, 0xc1, 0x20, 0xb6, 0x6d, 0xd3, 0xd9, 0xd5, 0x43, 0x3a, 0x9d, 0xc1, 0xeb, 0x71, 0xf3, 0xe0, 0xfe,
0xf7, 0xae, 0x71, 0x10, 0xa2, 0xb4, 0x26, 0x08, 0x05, 0x5b, 0x79, 0xff, 0x07, 0x7f, 0x07, 0x2a, 0xbd, 0x3c, 0xb8, 0x7f, 0x2f, 0x08, 0x51, 0x5a, 0x13, 0x84, 0x43, 0xad, 0xbc, 0xf7, 0xfd, 0x7f,
0xf6, 0x1d, 0xef, 0x7f, 0xdf, 0xfd, 0xf9, 0x01, 0x2c, 0xfb, 0xd7, 0x7b, 0xf7, 0x09, 0xe0, 0x04, 0x0c, 0x15, 0xfb, 0x8e, 0x0f, 0xfd, 0xd1, 0x43, 0xc5, 0x05, 0x5d, 0xe9, 0x4f, 0xef, 0xdd, 0x07,
0xfa, 0xed, 0x9b, 0x48, 0x21, 0x39, 0x77, 0xfe, 0xc2, 0x24, 0xb0, 0x5a, 0x53, 0xc4, 0x42, 0x08, 0x80, 0x03, 0xe8, 0xeb, 0x0f, 0x91, 0x42, 0xf2, 0xe6, 0xf1, 0x13, 0x13, 0xc0, 0x72, 0xdd, 0x20,
0xd6, 0xd7, 0xd7, 0x99, 0x9d, 0x9d, 0x65, 0x78, 0x78, 0x18, 0x21, 0x44, 0x69, 0x51, 0xef, 0x72, 0x16, 0x42, 0xb0, 0xba, 0xba, 0xca, 0xec, 0xec, 0x2c, 0xc3, 0xc3, 0xc3, 0x08, 0x21, 0xc8, 0xe5,
0xb9, 0x10, 0x42, 0x60, 0x59, 0x16, 0xb9, 0x5c, 0x0e, 0x87, 0x23, 0x1f, 0xc6, 0xe1, 0x70, 0x30, 0x72, 0x00, 0xb8, 0xdd, 0x6e, 0x84, 0x10, 0x58, 0x96, 0x45, 0x2e, 0x97, 0xc3, 0xe1, 0xc8, 0x8b,
0x32, 0x32, 0xc2, 0x8b, 0x2f, 0xbe, 0x40, 0x28, 0xe0, 0xa7, 0xb1, 0xd1, 0x8d, 0x61, 0x18, 0x88, 0x71, 0x38, 0x1c, 0x8c, 0x8c, 0x8c, 0xf0, 0xea, 0xab, 0xaf, 0xd0, 0x1a, 0xf4, 0xe3, 0x71, 0x7b,
0xc2, 0x8e, 0x85, 0x61, 0x18, 0x5b, 0xce, 0xc5, 0x6b, 0x10, 0x85, 0xca, 0xa5, 0x4a, 0x3b, 0x21, 0x90, 0x86, 0xc4, 0x90, 0x06, 0x86, 0x61, 0x20, 0x0d, 0x03, 0x43, 0x4a, 0xa4, 0x61, 0x20, 0xa5,
0xc9, 0x64, 0xd2, 0x34, 0x84, 0x58, 0xb2, 0x95, 0xad, 0x2d, 0xcb, 0x46, 0xd9, 0x96, 0x36, 0x2d, 0xcc, 0x3f, 0x93, 0xb2, 0x20, 0xab, 0xc8, 0x5e, 0x0a, 0x65, 0xdb, 0x24, 0x12, 0x09, 0xcb, 0x90,
0x53, 0x9d, 0xfd, 0xc5, 0x2b, 0x57, 0x7e, 0xf0, 0x5f, 0x3f, 0x7c, 0x01, 0x48, 0x55, 0xa5, 0x50, 0xf2, 0xaa, 0xad, 0x6c, 0x6d, 0x59, 0x36, 0xca, 0xb6, 0xb4, 0x69, 0x99, 0xea, 0x8d, 0x5f, 0x1e,
0x71, 0xf4, 0x2f, 0x5f, 0xbe, 0x4c, 0x4b, 0x4b, 0x0b, 0xcb, 0xcb, 0xcb, 0x74, 0x76, 0x76, 0x92, 0x9b, 0xfa, 0xe1, 0x8f, 0x7e, 0xf2, 0x0a, 0x90, 0xaa, 0x09, 0xa1, 0xa2, 0xf5, 0x4f, 0x9f, 0x3e,
0x48, 0x24, 0x30, 0x4d, 0x93, 0xee, 0xee, 0x6e, 0x16, 0x16, 0x16, 0x98, 0x9b, 0x9b, 0xa3, 0xad, 0x4d, 0x4b, 0x4b, 0x0b, 0x8b, 0x8b, 0x8b, 0xc4, 0x62, 0x31, 0xe2, 0xf1, 0x38, 0x96, 0x65, 0xd1,
0xad, 0x0d, 0x9f, 0xcf, 0x57, 0xa2, 0x51, 0x77, 0x77, 0x37, 0x0f, 0x3f, 0xfc, 0x08, 0xb1, 0x58, 0xdd, 0xdd, 0xcd, 0xfc, 0xfc, 0x3c, 0x73, 0x73, 0x73, 0xb4, 0xb5, 0xb5, 0xe1, 0xf7, 0xfb, 0x4b,
0x8c, 0x5c, 0x2e, 0x57, 0x97, 0x01, 0x6a, 0xad, 0x31, 0x2a, 0xa6, 0x33, 0xdf, 0x7c, 0xee, 0x7b, 0x30, 0xea, 0xee, 0xee, 0xe6, 0xb1, 0xc7, 0x1e, 0xe7, 0xdc, 0xb9, 0x73, 0x64, 0xb3, 0xd9, 0xda,
0x6f, 0x9e, 0x3d, 0x7b, 0xf6, 0x8f, 0x2a, 0x09, 0x02, 0x5c, 0x07, 0xae, 0x6b, 0x9d, 0x5f, 0xa7, 0x6b, 0xe7, 0x8a, 0x31, 0x8d, 0x86, 0xeb, 0x75, 0x97, 0x65, 0x59, 0x7c, 0xeb, 0xc5, 0x6f, 0x5f,
0xd6, 0x74, 0xe2, 0xa3, 0x47, 0x8f, 0x32, 0x3b, 0x3b, 0x4b, 0x30, 0x18, 0x2c, 0xdd, 0xcb, 0x64, 0x3a, 0x7a, 0xf4, 0xe8, 0x9f, 0x57, 0x02, 0x04, 0xb8, 0x00, 0x5c, 0xd0, 0x3a, 0xbf, 0x4e, 0xad,
0x32, 0x4c, 0x4c, 0x4c, 0xe0, 0x76, 0xbb, 0x19, 0x1d, 0x1d, 0xa5, 0xb1, 0xb1, 0xb1, 0x62, 0x47, 0x9b, 0x89, 0xf7, 0xec, 0xd9, 0xc3, 0xec, 0xec, 0x2c, 0xa1, 0x50, 0xa8, 0x8c, 0xf7, 0x4f, 0x9e,
0xc1, 0x45, 0x57, 0x57, 0x17, 0x1d, 0x1d, 0x1d, 0x35, 0x57, 0x71, 0xd5, 0x36, 0xc7, 0x00, 0x4c, 0x3c, 0x89, 0xc7, 0xe3, 0x61, 0x74, 0x74, 0x14, 0x8f, 0xc7, 0x53, 0xb1, 0xa3, 0xe0, 0xa2, 0xab,
0xd3, 0xe4, 0xf4, 0xe9, 0xd3, 0xeb, 0xc0, 0x0f, 0xaa, 0xec, 0x4e, 0xeb, 0xaa, 0x22, 0xb6, 0x2c, 0xab, 0x8b, 0x58, 0x2c, 0x56, 0x77, 0xf9, 0x59, 0x6b, 0x73, 0x0c, 0xc0, 0x34, 0x4d, 0x0e, 0x1f,
0x6b, 0x4b, 0xb0, 0xde, 0xde, 0xde, 0x12, 0x28, 0xad, 0x35, 0xf1, 0x78, 0x9c, 0xe1, 0xe1, 0xe1, 0x3e, 0xbc, 0x72, 0xf4, 0xe8, 0xd1, 0x1f, 0xd6, 0xd8, 0x9d, 0xd6, 0x35, 0x83, 0xd8, 0xb2, 0xac,
0xd2, 0x02, 0xa6, 0x9a, 0x46, 0x1c, 0x0e, 0x47, 0xd5, 0xb9, 0x53, 0x79, 0x05, 0xab, 0xcc, 0x7c, 0x32, 0x61, 0xbd, 0xbd, 0xbd, 0x25, 0xa5, 0x94, 0x52, 0xc4, 0xe3, 0x71, 0x86, 0x87, 0x87, 0x4b,
0x71, 0x52, 0x28, 0xa5, 0xd4, 0xc5, 0x51, 0xde, 0xd3, 0xf3, 0x81, 0x4a, 0x11, 0x17, 0xa7, 0xb0, 0x0b, 0x98, 0x5a, 0x31, 0x62, 0x18, 0x46, 0xcd, 0xcc, 0xbd, 0x71, 0x09, 0x5a, 0xe9, 0xf9, 0xe2,
0xc5, 0xc0, 0x9d, 0x9d, 0x9d, 0x5b, 0x3a, 0x5f, 0x8f, 0xd0, 0x6b, 0x01, 0x2d, 0x07, 0x52, 0x8d, 0xaa, 0x4e, 0x4a, 0xa9, 0x8b, 0x56, 0xbe, 0xa1, 0xf3, 0x81, 0xca, 0x20, 0x2e, 0x96, 0xb0, 0xc5,
0x62, 0x7b, 0x02, 0x50, 0x59, 0x46, 0x63, 0xb1, 0x18, 0x99, 0x4c, 0x06, 0xc3, 0x30, 0x70, 0x38, 0x41, 0x63, 0xb1, 0x58, 0xd9, 0xe4, 0xb7, 0x13, 0xe8, 0x5b, 0x95, 0x1f, 0xd5, 0x68, 0xfb, 0x1d,
0x1c, 0x34, 0x35, 0x35, 0xd5, 0xd5, 0xe9, 0x7a, 0x41, 0x94, 0x4f, 0x59, 0x7e, 0x9d, 0xa7, 0x45, 0x1f, 0x70, 0x54, 0xd2, 0xe8, 0xcc, 0xcc, 0x0c, 0xeb, 0xeb, 0xeb, 0x18, 0x86, 0x81, 0xc3, 0xe1,
0xbb, 0x3a, 0xf1, 0xc1, 0x83, 0x07, 0xf3, 0xeb, 0x53, 0xb7, 0x9b, 0xb9, 0xb9, 0x39, 0x4c, 0xd3, 0xc0, 0xef, 0xf7, 0x6f, 0x6b, 0xd2, 0xdb, 0x55, 0x62, 0x63, 0xc9, 0xf2, 0x4e, 0x4e, 0x8b, 0xb6,
0xdc, 0x6d, 0x8b, 0xbd, 0x6e, 0x10, 0xe5, 0x94, 0xd9, 0x4d, 0xe8, 0x7b, 0xa6, 0x50, 0xb5, 0x6a, 0xcc, 0xc4, 0x3b, 0x77, 0xee, 0xcc, 0xaf, 0x4f, 0xdd, 0x6e, 0x2e, 0x5c, 0xb8, 0xb0, 0xe5, 0x26,
0x71, 0xed, 0xda, 0x35, 0x9c, 0x4e, 0x27, 0xcd, 0xcd, 0xcd, 0xa5, 0xea, 0xb3, 0xd3, 0x11, 0x8f, 0xd5, 0x8d, 0x28, 0xb1, 0x11, 0x32, 0x5b, 0x05, 0xfa, 0x0d, 0x43, 0xa8, 0xfa, 0x01, 0x89, 0x62,
0xc7, 0x89, 0xc5, 0x62, 0x5b, 0x3a, 0xd5, 0xd3, 0xd3, 0x43, 0x7b, 0x7b, 0x3b, 0x6b, 0x6b, 0x6b, 0x76, 0x76, 0x16, 0xa7, 0xd3, 0x49, 0x20, 0x10, 0xc0, 0xe7, 0xf3, 0xd5, 0x1c, 0x70, 0x69, 0x69,
0x4c, 0x4e, 0x4e, 0x6e, 0x19, 0xf5, 0xf6, 0xf6, 0x76, 0xa2, 0xd1, 0xe8, 0xad, 0x67, 0xa0, 0xb8, 0x89, 0xe9, 0xe9, 0xe9, 0xb2, 0xf7, 0x3d, 0x3d, 0x3d, 0xb4, 0xb7, 0xb7, 0xb3, 0xb2, 0xb2, 0xc2,
0x88, 0xae, 0x36, 0xba, 0xd1, 0x68, 0x94, 0x8d, 0x8d, 0x0d, 0x2e, 0x5d, 0xba, 0x44, 0x24, 0x12, 0xc4, 0xc4, 0x44, 0x99, 0xd5, 0xdb, 0xdb, 0xdb, 0xe9, 0xec, 0xec, 0xbc, 0x79, 0x0f, 0x14, 0x0b,
0xe1, 0xc8, 0x91, 0x23, 0x3b, 0x7e, 0xd6, 0xef, 0xf7, 0x73, 0xe4, 0xc8, 0x91, 0x2d, 0x42, 0x6e, 0xb2, 0x6a, 0x4d, 0x4a, 0x49, 0x67, 0x67, 0x27, 0xab, 0xab, 0xab, 0x9c, 0x3a, 0x75, 0x8a, 0x68,
0x68, 0xc8, 0x3f, 0xb4, 0xf1, 0x7a, 0xbd, 0x8c, 0x8d, 0x8d, 0x6d, 0x11, 0x6f, 0xde, 0x0f, 0xb8, 0x34, 0xca, 0x9d, 0x77, 0xde, 0x59, 0xf5, 0xb3, 0xcd, 0xcd, 0xcd, 0x8c, 0x8e, 0x8e, 0x96, 0x59,
0x3d, 0x14, 0xaa, 0xc5, 0x45, 0xc3, 0x30, 0x68, 0x6f, 0x6f, 0x67, 0x75, 0x75, 0x95, 0xf9, 0xf9, 0xb5, 0xa1, 0x21, 0x7f, 0x68, 0xe3, 0xf3, 0xf9, 0x18, 0x1b, 0x1b, 0x2b, 0x0b, 0x5e, 0xc3, 0x30,
0x79, 0x32, 0x99, 0x0c, 0xe3, 0xe3, 0xe3, 0xdb, 0x32, 0x91, 0x48, 0x24, 0x98, 0x9a, 0x9a, 0xda, 0x6e, 0xcd, 0x21, 0x5f, 0x3d, 0x0f, 0x14, 0x93, 0x55, 0x47, 0x47, 0x07, 0xa9, 0x54, 0x8a, 0x4b,
0x02, 0x3e, 0x10, 0x08, 0x30, 0x3a, 0x3a, 0x4a, 0x32, 0x99, 0x64, 0x62, 0x62, 0x62, 0xcb, 0xe7, 0x97, 0x2e, 0xb1, 0xbe, 0xbe, 0xce, 0xbe, 0x7d, 0xfb, 0xaa, 0x7a, 0x60, 0x72, 0x72, 0xb2, 0x0c,
0xa3, 0xd1, 0x28, 0xbd, 0xbd, 0xbd, 0xb7, 0x46, 0x21, 0x21, 0x84, 0xeb, 0xd4, 0xa9, 0x53, 0xee, 0xeb, 0xa1, 0x50, 0x88, 0xd1, 0xd1, 0x51, 0x96, 0x97, 0x97, 0x39, 0x71, 0xe2, 0x44, 0xd9, 0xbb,
0xca, 0xa9, 0x44, 0xf1, 0x08, 0x87, 0xc3, 0x08, 0x21, 0x90, 0x52, 0x32, 0x3e, 0x3e, 0x8e, 0xd6, 0xae, 0xae, 0x2e, 0x7a, 0x7b, 0x7b, 0x6f, 0x0e, 0x42, 0x42, 0x08, 0xd7, 0xa1, 0x43, 0x87, 0xdc,
0x9a, 0x8b, 0x17, 0x2f, 0x92, 0x4c, 0x26, 0x09, 0x04, 0x02, 0x5b, 0x78, 0xdd, 0xda, 0xda, 0x4a, 0x95, 0xa5, 0x44, 0xb1, 0x45, 0xa3, 0x51, 0x84, 0x10, 0x48, 0x29, 0xd9, 0xbb, 0x77, 0x2f, 0x00,
0x28, 0x14, 0x2a, 0x75, 0xde, 0x34, 0x4d, 0xce, 0x9d, 0x3b, 0x57, 0xca, 0xce, 0x89, 0x13, 0x27, 0xe3, 0xe3, 0xe3, 0x24, 0x12, 0x09, 0x82, 0xc1, 0x60, 0x19, 0xae, 0x5b, 0x5b, 0x5b, 0x09, 0x87,
0xb6, 0x19, 0x67, 0xf9, 0xb5, 0x52, 0xca, 0x21, 0x84, 0xd8, 0xa7, 0xb5, 0xde, 0xa8, 0x05, 0x40, 0xc3, 0x25, 0x0f, 0x58, 0x96, 0xc5, 0xb1, 0x63, 0xc7, 0x4a, 0xde, 0x39, 0x70, 0xe0, 0xc0, 0xa6,
0x96, 0x3f, 0x5d, 0x04, 0x7c, 0xd9, 0x6c, 0xd6, 0x55, 0x6b, 0xc7, 0xba, 0x52, 0x94, 0x2e, 0x97, 0xc4, 0xb9, 0xb1, 0xaf, 0x94, 0x72, 0x08, 0x21, 0x1a, 0xb5, 0xd6, 0xe9, 0x7a, 0x0a, 0xc8, 0x8d,
0x6b, 0x47, 0x33, 0xaa, 0x56, 0x55, 0xca, 0x17, 0x4c, 0x3b, 0x3d, 0xed, 0x29, 0x7b, 0x6d, 0x00, 0xa7, 0x8b, 0x40, 0x53, 0x36, 0x9b, 0x75, 0xd5, 0xdb, 0xb1, 0xae, 0xb4, 0x50, 0x43, 0x43, 0x43,
0xcd, 0x42, 0x08, 0x6f, 0xbd, 0x19, 0x70, 0x03, 0x8d, 0x96, 0x65, 0x39, 0xea, 0x29, 0x67, 0xa6, 0xd5, 0x64, 0x54, 0x8b, 0xe7, 0x2b, 0xaf, 0x5a, 0xec, 0x57, 0x28, 0x99, 0x9b, 0x85, 0x10, 0xbe,
0x69, 0x72, 0xf5, 0xea, 0x55, 0x92, 0xc9, 0x24, 0xe9, 0x74, 0x9a, 0xb5, 0xb5, 0x35, 0x7a, 0x7a, 0xed, 0x7a, 0xc0, 0x0d, 0x78, 0x2c, 0xcb, 0x72, 0x6e, 0x87, 0xce, 0x4c, 0xd3, 0x64, 0x6a, 0x6a,
0x7a, 0xaa, 0x96, 0x47, 0xa7, 0xd3, 0xc9, 0xb1, 0x63, 0xc7, 0x6a, 0x96, 0xcd, 0x8a, 0xf7, 0x24, 0x8a, 0xe5, 0xe5, 0x65, 0x32, 0x99, 0x0c, 0x2b, 0x2b, 0x2b, 0xf4, 0xf4, 0xf4, 0xd4, 0xa4, 0x47,
0xd0, 0x08, 0xe4, 0x84, 0x10, 0x99, 0x6a, 0xa6, 0xe6, 0xa8, 0xc8, 0x86, 0xb4, 0x6d, 0x5b, 0x99, 0xa7, 0xd3, 0xc9, 0xfe, 0xfd, 0xfb, 0xeb, 0xd2, 0x66, 0xc5, 0x3b, 0x03, 0xf0, 0x00, 0x39, 0x21,
0xa6, 0xa9, 0x5d, 0x2e, 0x97, 0x28, 0xba, 0xa9, 0x52, 0x2a, 0xbf, 0x5b, 0x56, 0xd1, 0x78, 0x4f, 0xc4, 0x7a, 0xad, 0xa4, 0xe6, 0xa8, 0xf0, 0x86, 0xb4, 0x6d, 0xdb, 0x36, 0x4d, 0x53, 0xbb, 0x5c,
0x4f, 0x4f, 0xe9, 0xb5, 0xd3, 0xe9, 0x2c, 0xed, 0xb2, 0xd5, 0xb3, 0xa2, 0xab, 0xf5, 0x9e, 0x6d, 0x2e, 0xe1, 0x70, 0x38, 0x4a, 0xab, 0x23, 0xc3, 0x30, 0xca, 0x06, 0x50, 0x4a, 0x95, 0x61, 0xd6,
0xdb, 0x08, 0x21, 0xac, 0x42, 0x9f, 0xc4, 0x4e, 0x4b, 0xdf, 0x9d, 0x00, 0x98, 0x80, 0x39, 0x3f, 0xe9, 0x74, 0x96, 0x76, 0xd9, 0xb6, 0xb3, 0xa2, 0xab, 0xf7, 0xce, 0xb6, 0x6d, 0x84, 0x10, 0x56,
0x3f, 0xff, 0x1f, 0x4f, 0x3d, 0xf5, 0xd4, 0xa9, 0xe3, 0xc7, 0x8f, 0x6b, 0x51, 0x88, 0xba, 0x57, 0x61, 0x4e, 0xa2, 0xda, 0xd2, 0xb7, 0x9a, 0x02, 0x26, 0x60, 0x5e, 0xbe, 0x7c, 0xf9, 0xfb, 0xcf,
0x83, 0xf9, 0x75, 0x1c, 0xb5, 0xec, 0x7b, 0xfa, 0xd5, 0x57, 0x5f, 0x95, 0x8b, 0x8b, 0x8b, 0x2f, 0x3e, 0xfb, 0xec, 0xa1, 0xfb, 0xee, 0xbb, 0xef, 0x1d, 0x65, 0xc6, 0x77, 0x9a, 0x51, 0x37, 0xb6,
0x02, 0xb9, 0x62, 0xbf, 0xaa, 0x7e, 0xa7, 0xcc, 0xc6, 0x05, 0xe0, 0x03, 0x7c, 0x91, 0x48, 0x24, 0xf1, 0xf1, 0x71, 0xb1, 0xb0, 0xb0, 0xf0, 0x2a, 0x90, 0x2b, 0xce, 0xab, 0xe6, 0x58, 0x1b, 0xd2,
0x12, 0x0c, 0x06, 0x07, 0x85, 0x10, 0x4e, 0xad, 0xb5, 0x28, 0xa4, 0xf3, 0x8e, 0x1f, 0x52, 0x4a, 0xb8, 0x00, 0x9a, 0x80, 0xa6, 0x68, 0x34, 0x1a, 0x0d, 0x85, 0x42, 0x83, 0x42, 0x08, 0xa7, 0xd6,
0x0b, 0xd0, 0x9b, 0x9b, 0x9b, 0x73, 0x33, 0x33, 0x33, 0x6f, 0x00, 0xeb, 0x40, 0x4a, 0x6b, 0xbd, 0x5a, 0x14, 0xf0, 0x78, 0xdb, 0x9b, 0x94, 0xd2, 0x12, 0x42, 0xe8, 0x74, 0x3a, 0x3d, 0x37, 0x3d,
0x3b, 0x80, 0xb2, 0x51, 0x70, 0x03, 0x1e, 0xa0, 0xa1, 0xf0, 0x7b, 0x07, 0xa3, 0x56, 0x0a, 0x6f, 0x3d, 0xfd, 0x36, 0xb0, 0x0a, 0xa4, 0xb4, 0xd6, 0x5b, 0x2b, 0xb0, 0xc1, 0x7a, 0x6e, 0xc0, 0x0b,
0xf3, 0x61, 0x15, 0xa6, 0xcc, 0x39, 0x20, 0x03, 0x6c, 0xea, 0x5d, 0x9e, 0x92, 0x8b, 0x6a, 0xf4, 0x34, 0x14, 0x7e, 0xef, 0x60, 0xd4, 0x73, 0xe1, 0x2d, 0x6e, 0x56, 0xa1, 0x64, 0xce, 0x01, 0xeb,
0x28, 0x64, 0xc4, 0x28, 0xd0, 0x4c, 0xfc, 0x3f, 0x02, 0xb0, 0xf5, 0x1e, 0x1e, 0xed, 0x8b, 0xdf, 0xc0, 0x9a, 0xde, 0xe2, 0x94, 0x5c, 0xd4, 0x0a, 0xd8, 0x82, 0x47, 0x8c, 0x02, 0xcc, 0xc4, 0xff,
0xf4, 0x9f, 0xdb, 0xfc, 0x1f, 0x45, 0xe2, 0x2c, 0x7d, 0x65, 0x42, 0xd5, 0x87, 0x00, 0x00, 0x00, 0xa3, 0x02, 0xb6, 0xbe, 0x81, 0xa3, 0x7d, 0xf1, 0xfb, 0xfe, 0x73, 0x9b, 0xff, 0x03, 0xce, 0xd3,
0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x2b, 0x55, 0x21, 0x2a, 0xd7, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
0x60, 0x82,
}; };
const BITMAP_OPAQUE icon_pcbcalculator_xpm[1] = {{ png, sizeof( png ), "icon_pcbcalculator_xpm" }}; const BITMAP_OPAQUE icon_pcbcalculator_xpm[1] = {{ png, sizeof( png ), "icon_pcbcalculator_xpm" }};

View File

@ -59,7 +59,7 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( CVPCB_MAINFRAME* father,
icon.CopyFromBitmap( KiBitmap( icon_cvpcb_xpm ) ); icon.CopyFromBitmap( KiBitmap( icon_cvpcb_xpm ) );
SetIcon( icon ); SetIcon( icon );
SetBoard( new BOARD( NULL, this ) ); SetBoard( new BOARD( NULL ) );
SetScreen( new PCB_SCREEN() ); SetScreen( new PCB_SCREEN() );
LoadSettings(); LoadSettings();
@ -68,6 +68,7 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( CVPCB_MAINFRAME* father,
if( (m_LastGridSizeId <= 0) || if( (m_LastGridSizeId <= 0) ||
(m_LastGridSizeId > (ID_POPUP_GRID_USER - ID_POPUP_GRID_LEVEL_1000)) ) (m_LastGridSizeId > (ID_POPUP_GRID_USER - ID_POPUP_GRID_LEVEL_1000)) )
m_LastGridSizeId = ID_POPUP_GRID_LEVEL_500 - ID_POPUP_GRID_LEVEL_1000; m_LastGridSizeId = ID_POPUP_GRID_LEVEL_500 - ID_POPUP_GRID_LEVEL_1000;
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
// Initialize some display options // Initialize some display options

View File

@ -41,10 +41,11 @@
#include "class_GERBER.h" #include "class_GERBER.h"
/**********************************************************/ #define SHOW_BOUNDING_BOX 0 // Set to 1 to draw the bounding box for debugging purposes.
GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( BOARD_ITEM* aParent, GERBER_IMAGE* aGerberparams ) : GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( BOARD_ITEM* aParent, GERBER_IMAGE* aGerberparams ) :
BOARD_ITEM( aParent, TYPE_GERBER_DRAW_ITEM ) BOARD_ITEM( aParent, TYPE_GERBER_DRAW_ITEM )
/**********************************************************/
{ {
m_imageParams = aGerberparams; m_imageParams = aGerberparams;
m_Layer = 0; m_Layer = 0;
@ -339,10 +340,8 @@ bool GERBER_DRAW_ITEM::HasNegativeItems()
} }
/*********************************************************************/
void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode,
const wxPoint& aOffset ) const wxPoint& aOffset )
/*********************************************************************/
{ {
static D_CODE dummyD_CODE( 0 ); // used when a D_CODE is not found. default D_CODE to draw a flashed item static D_CODE dummyD_CODE( 0 ); // used when a D_CODE is not found. default D_CODE to draw a flashed item
int color, alt_color; int color, alt_color;
@ -486,6 +485,14 @@ void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode,
} }
break; break;
} }
#if SHOW_BOUNDING_BOX
/* Draw the component boundary box */
{
EDA_RECT boundaryBox = GetBoundingBox();
GRRect( &aPanel->m_ClipBox, aDC, boundaryBox, 0, BROWN );
}
#endif
} }
/** /**

View File

@ -139,6 +139,7 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
// this is due to negative objects (drawn using background color) that create artefacct // this is due to negative objects (drawn using background color) that create artefacct
// on other images when drawn on screen // on other images when drawn on screen
bool useBufferBitmap = false; bool useBufferBitmap = false;
if( (aDrawMode == GR_COPY) || ( aDrawMode == GR_OR ) ) if( (aDrawMode == GR_COPY) || ( aDrawMode == GR_OR ) )
useBufferBitmap = true; useBufferBitmap = true;
@ -173,9 +174,11 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
bool doBlit = false; // this flag requests an image transfert to actual screen when true. bool doBlit = false; // this flag requests an image transfert to actual screen when true.
bool end = false; bool end = false;
for( int layer = 0; !end; layer++ ) for( int layer = 0; !end; layer++ )
{ {
int active_layer = ( (GERBVIEW_FRAME*) m_PcbFrame )->getActiveLayer(); int active_layer = ( (GERBVIEW_FRAME*) aPanel->GetParent() )->getActiveLayer();
if( layer == active_layer ) // active layer will be drawn after other layers if( layer == active_layer ) // active layer will be drawn after other layers
continue; continue;
@ -205,6 +208,7 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
layerDC.SetDeviceOrigin(0,0); layerDC.SetDeviceOrigin(0,0);
layerDC.SetLogicalOrigin( 0, 0 ); layerDC.SetLogicalOrigin( 0, 0 );
layerDC.SetUserScale( 1, 1 ); layerDC.SetUserScale( 1, 1 );
if( aDrawMode == GR_COPY ) if( aDrawMode == GR_COPY )
{ {
// Use the layer bitmap itself as a mask when blitting. The bitmap // Use the layer bitmap itself as a mask when blitting. The bitmap
@ -212,8 +216,7 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
layerDC.SelectObject( wxNullBitmap ); layerDC.SelectObject( wxNullBitmap );
layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) ); layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) );
layerDC.SelectObject( *layerBitmap ); layerDC.SelectObject( *layerBitmap );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxCOPY, true );
&layerDC, 0, 0, wxCOPY, true );
} }
else if( aDrawMode == GR_OR ) else if( aDrawMode == GR_OR )
{ {
@ -224,9 +227,9 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
// the cpu cycles needed to create the monochromatic bitmap above, and // the cpu cycles needed to create the monochromatic bitmap above, and
// the extra time needed to do bit indexing into the monochromatic bitmap // the extra time needed to do bit indexing into the monochromatic bitmap
// on the blit above. // on the blit above.
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxOR );
&layerDC, 0, 0, wxOR );
} }
// Restore actual values and clear bitmpap for next drawing // Restore actual values and clear bitmpap for next drawing
layerDC.SetDeviceOrigin( dev_org.x, dev_org.y ); layerDC.SetDeviceOrigin( dev_org.x, dev_org.y );
layerDC.SetLogicalOrigin( logical_org.x, logical_org.y ); layerDC.SetLogicalOrigin( logical_org.x, logical_org.y );
@ -256,7 +259,7 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
int dcode_highlight = 0; int dcode_highlight = 0;
if( layer == ( (GERBVIEW_FRAME*) m_PcbFrame )->getActiveLayer() ) if( layer == ( (GERBVIEW_FRAME*) aPanel->GetParent() )->getActiveLayer() )
dcode_highlight = gerber->m_Selected_Tool; dcode_highlight = gerber->m_Selected_Tool;
int layerdrawMode = GR_COPY; int layerdrawMode = GR_COPY;
@ -277,6 +280,7 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
if( dcode_highlight && dcode_highlight == gerb_item->m_DCode ) if( dcode_highlight && dcode_highlight == gerb_item->m_DCode )
drawMode |= GR_SURBRILL; drawMode |= GR_SURBRILL;
gerb_item->Draw( aPanel, plotDC, drawMode ); gerb_item->Draw( aPanel, plotDC, drawMode );
doBlit = true; doBlit = true;
} }
@ -297,14 +301,12 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
layerDC.SelectObject( wxNullBitmap ); layerDC.SelectObject( wxNullBitmap );
layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) ); layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) );
layerDC.SelectObject( *layerBitmap ); layerDC.SelectObject( *layerBitmap );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxCOPY, true );
&layerDC, 0, 0, wxCOPY, true );
} }
else if( aDrawMode == GR_OR ) else if( aDrawMode == GR_OR )
{ {
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxOR );
&layerDC, 0, 0, wxOR );
} }
} }

View File

@ -47,7 +47,7 @@ GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME * aFrame, FILE * aFile
{ {
m_gerbview_frame = aFrame; m_gerbview_frame = aFrame;
m_file = aFile; m_file = aFile;
m_pcb = new BOARD( NULL, m_gerbview_frame ); m_pcb = new BOARD( NULL );
} }
GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER() GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER()

View File

@ -44,7 +44,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( wxWindow* father,
m_SelLayerBox = NULL; m_SelLayerBox = NULL;
m_DCodeSelector = NULL; m_DCodeSelector = NULL;
m_displayMode = 0; m_displayMode = 0;
m_drillFileHistory.SetBaseId(ID_GERBVIEW_DRILL_FILE1); m_drillFileHistory.SetBaseId( ID_GERBVIEW_DRILL_FILE1 );
if( DrawPanel ) if( DrawPanel )
DrawPanel->m_Block_Enable = true; DrawPanel->m_Block_Enable = true;
@ -56,7 +56,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( wxWindow* father,
SetScreen( ScreenPcb ); SetScreen( ScreenPcb );
SetBoard( new BOARD( NULL, this ) ); SetBoard( new BOARD( NULL ) );
GetBoard()->SetEnabledLayers( FULL_LAYERS ); // All 32 layers enabled at first. GetBoard()->SetEnabledLayers( FULL_LAYERS ); // All 32 layers enabled at first.
GetBoard()->SetVisibleLayers( FULL_LAYERS ); // All 32 layers visible. GetBoard()->SetVisibleLayers( FULL_LAYERS ); // All 32 layers visible.
@ -74,7 +74,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( wxWindow* father,
// initialize parameters in m_LayersManager // initialize parameters in m_LayersManager
LoadSettings(); LoadSettings();
SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
ReCreateMenuBar(); ReCreateMenuBar();
ReCreateHToolbar(); ReCreateHToolbar();
@ -144,34 +144,6 @@ void GERBVIEW_FRAME::OnCloseWindow( wxCloseEvent& Event )
} }
double GERBVIEW_FRAME::BestZoom()
{
// gives a minimal value to zoom, if no item in list
if( GetBoard()->m_Drawings == NULL )
return 160.0;
EDA_RECT bbox;
BOARD_ITEM* item = GetBoard()->m_Drawings;
bbox = ( (GERBER_DRAW_ITEM*) item )->GetBoundingBox();
for( ; item; item = item->Next() )
{
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
bbox.Merge( gerb_item->GetBoundingBox() );
}
wxSize size = DrawPanel->GetClientSize();
double x = (double) bbox.GetWidth() / (double) size.x;
double y = (double) bbox.GetHeight() / (double) size.y;
GetScreen()->SetScrollCenterPosition( bbox.Centre() );
double best_zoom = MAX( x, y );
return best_zoom;
}
void GERBVIEW_FRAME::LoadSettings() void GERBVIEW_FRAME::LoadSettings()
{ {
wxConfig* config = wxGetApp().m_EDA_Config; wxConfig* config = wxGetApp().m_EDA_Config;

View File

@ -52,8 +52,8 @@ private:
// a gerber file // a gerber file
public: GERBVIEW_FRAME( wxWindow* father, const wxString& title, public: GERBVIEW_FRAME( wxWindow* father, const wxString& title,
const wxPoint& pos, const wxSize& size, const wxPoint& pos, const wxSize& size,
long style = KICAD_DEFAULT_DRAWFRAME_STYLE ); long style = KICAD_DEFAULT_DRAWFRAME_STYLE );
~GERBVIEW_FRAME(); ~GERBVIEW_FRAME();
@ -68,7 +68,6 @@ public: GERBVIEW_FRAME( wxWindow* father, const wxString& title,
void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); void OnLeftClick( wxDC* DC, const wxPoint& MousePos );
void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); void OnLeftDClick( wxDC* DC, const wxPoint& MousePos );
bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
double BestZoom();
/** /**
* Function ReportMessage * Function ReportMessage

View File

@ -357,8 +357,7 @@ public:
int m_Flags; // flags for editing and other uses. int m_Flags; // flags for editing and other uses.
unsigned long m_TimeStamp; // Time stamp used for logical links unsigned long m_TimeStamp; // Time stamp used for logical links
int m_Selected; /* Used by block commands, and selective int m_Selected; /* Used by block commands, and selective editing */
* editing */
// member used in undo/redo function // member used in undo/redo function
EDA_ITEM* m_Image; // Link to an image copy to save a copy of EDA_ITEM* m_Image; // Link to an image copy to save a copy of

View File

@ -182,7 +182,6 @@ set(PCBNEW_SRCS
tool_pcb.cpp tool_pcb.cpp
toolbars_update_user_interface.cpp toolbars_update_user_interface.cpp
tracepcb.cpp tracepcb.cpp
track.cpp
tr_modif.cpp tr_modif.cpp
trpiste.cpp trpiste.cpp
work.cpp work.cpp

View File

@ -39,7 +39,7 @@ void PCB_EDIT_FRAME::Attribut_Track( TRACK* track, wxDC* DC, bool Flag_On )
return; return;
DrawPanel->CrossHairOff( DC ); // Erase cursor shape DrawPanel->CrossHairOff( DC ); // Erase cursor shape
Track = MarkTrace( GetBoard(), track, &nb_segm, NULL, NULL, true ); Track = GetBoard()->MarkTrace( track, &nb_segm, NULL, NULL, true );
DrawTraces( DrawPanel, DC, Track, nb_segm, GR_OR | GR_SURBRILL ); DrawTraces( DrawPanel, DC, Track, nb_segm, GR_OR | GR_SURBRILL );
for( ; (Track != NULL) && (nb_segm > 0); nb_segm-- ) for( ; (Track != NULL) && (nb_segm > 0); nb_segm-- )

View File

@ -105,32 +105,48 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard )
double PCB_BASE_FRAME::BestZoom( void ) double PCB_BASE_FRAME::BestZoom( void )
{ {
int dx, dy; int dx, dy;
double ii, jj; double zx, zy;
wxSize size; wxSize size;
wxPoint center;
if( m_Pcb == NULL ) if( m_Pcb != NULL && m_Pcb->ComputeBoundingBox() )
return 32.0; {
dx = m_Pcb->m_BoundaryBox.GetWidth();
dy = m_Pcb->m_BoundaryBox.GetHeight();
center = m_Pcb->m_BoundaryBox.Centre();
}
else
{
if( m_Draw_Sheet_Ref )
{
dx = GetScreen()->ReturnPageSize().x;
dy = GetScreen()->ReturnPageSize().y;
}
else
{
dx = GetScreen()->ReturnPageSize().x;
dy = GetScreen()->ReturnPageSize().y;
}
m_Pcb->ComputeBoundingBox(); center = wxPoint( dx / 2, dy / 2 );
}
dx = m_Pcb->m_BoundaryBox.GetWidth();
dy = m_Pcb->m_BoundaryBox.GetHeight();
size = DrawPanel->GetClientSize(); size = DrawPanel->GetClientSize();
if( size.x ) if( size.x )
ii = (double)(dx + ( size.x / 2) ) / (double) size.x; zx = (double) dx / (double) size.x;
else else
ii = 32.0; zx = 32.0;
if ( size.y ) if ( size.y )
jj = (double)( dy + (size.y / 2) ) / (double) size.y; zy = (double) dy / (double) size.y;
else else
jj = 32.0; zy = 32.0;
double bestzoom = MAX( ii, jj ); double bestzoom = MAX( zx, zy );
GetScreen()->SetScrollCenterPosition( m_Pcb->m_BoundaryBox.Centre() ); GetScreen()->SetScrollCenterPosition( center );
return bestzoom ; return bestzoom;
} }

View File

@ -19,26 +19,67 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD_DESIGN_SETTINGS boardDesignSettings; BOARD_DESIGN_SETTINGS boardDesignSettings;
/**
* Function SortPadsByXCoord
* is used to sort a pad list by x coordinate value.
*/
static int SortPadsByXCoord( const void* aRef, const void* aComp )
{
D_PAD* ref = *(LISTE_PAD*) aRef;
D_PAD* comp = *(LISTE_PAD*) aComp;
return ref->m_Pos.x - comp->m_Pos.x;
}
TRACK* GetTraceByEndPoint( TRACK* aStartTrace, TRACK* aEndTrace,
const wxPoint& aPosition, int aLayerMask )
{
if( aStartTrace == NULL )
return NULL;
for( TRACK* trace = aStartTrace; trace != NULL; trace = trace->Next() )
{
if( trace->GetState( IS_DELETED | BUSY ) == 0 )
{
if( aPosition == trace->m_Start )
{
if( aLayerMask & trace->ReturnMaskLayer() )
return trace;
}
if( aPosition == trace->m_End )
{
if( aLayerMask & trace->ReturnMaskLayer() )
return trace;
}
}
if( trace == aEndTrace )
break;
}
return NULL;
}
/*****************/ /*****************/
/* Class BOARD: */ /* Class BOARD: */
/*****************/ /*****************/
BOARD::BOARD( EDA_ITEM* parent, PCB_BASE_FRAME* frame ) : BOARD::BOARD( EDA_ITEM* aParent ) :
BOARD_ITEM( (BOARD_ITEM*)parent, TYPE_PCB ), BOARD_ITEM( (BOARD_ITEM*) aParent, TYPE_PCB ),
m_NetClasses( this ) m_NetClasses( this )
{ {
m_PcbFrame = frame;
m_Status_Pcb = 0; // Status word: bit 1 = calculate. m_Status_Pcb = 0; // Status word: bit 1 = calculate.
SetBoardDesignSettings(&boardDesignSettings); SetBoardDesignSettings( &boardDesignSettings );
SetColorsSettings(&g_ColorsSettings); SetColorsSettings( &g_ColorsSettings );
m_NbNodes = 0; // Number of connected pads. m_NbNodes = 0; // Number of connected pads.
m_NbNoconnect = 0; // Number of unconnected nets. m_NbNoconnect = 0; // Number of unconnected nets.
m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the
// zone contour currently in // zone contour currently in progress
// progress m_NetInfo = new NETINFO_LIST( this ); // handle nets info list (name, design constraints ..
m_NetInfo = new NETINFO_LIST( this ); // handle nets info list (name,
// design constraints ..
m_NetInfo->BuildListOfNets(); // prepare pads and nets lists containers. m_NetInfo->BuildListOfNets(); // prepare pads and nets lists containers.
for( int layer = 0; layer < NB_COPPER_LAYERS; ++layer ) for( int layer = 0; layer < NB_COPPER_LAYERS; ++layer )
@ -47,12 +88,10 @@ BOARD::BOARD( EDA_ITEM* parent, PCB_BASE_FRAME* frame ) :
m_Layer[layer].m_Type = LT_SIGNAL; m_Layer[layer].m_Type = LT_SIGNAL;
} }
// Initial parameters for the default NETCLASS come from the global // Initial parameters for the default NETCLASS come from the global preferences
// preferences // within g_DesignSettings via the NETCLASS() constructor. Should the user
// within g_DesignSettings via the NETCLASS() constructor. // eventually load a board from a disk file, then these defaults will get
// Should user eventually load a board from a disk file, then these // overwritten during load.
// defaults
// will get overwritten during load.
m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) ); m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) );
m_ViaSizeSelector = 0; m_ViaSizeSelector = 0;
m_TrackWidthSelector = 0; m_TrackWidthSelector = 0;
@ -64,9 +103,6 @@ BOARD::BOARD( EDA_ITEM* parent, PCB_BASE_FRAME* frame ) :
BOARD::~BOARD() BOARD::~BOARD()
{ {
if( m_PcbFrame->GetScreen() )
m_PcbFrame->GetScreen()->ClearUndoRedoList();
while( m_ZoneDescriptorList.size() ) while( m_ZoneDescriptorList.size() )
{ {
ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0]; ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
@ -87,20 +123,124 @@ BOARD::~BOARD()
} }
/* void BOARD::chainMarkedSegments( wxPoint& aPosition, int aLayerMask, TRACK_PTRS* aList )
* Function PushHightLight {
* save current hight light info for later use TRACK* pt_segm; // The current segment being analyzed.
*/ TRACK* pt_via; // The via identified, eventually destroy
TRACK* SegmentCandidate; // The end segment to destroy (or NULL = pt_segm
int NbSegm;
if( m_Track == NULL )
return;
/* Set the BUSY flag of all connected segments, first search starting at
* aPosition
* Search ends when:
* - a pad is found (end of a track)
* - a segment end has more than one other segment end connected
* - and obviously when no connected item found
* Vias are a special case, because we must see others segment connected
* on others layers and they change the layer mask. They can be a track
* end or not
* They will be analyzer later, and vias on terminal points of the track
* will be considered as part of this track if they do not connect segments
* of an other track together and will be considered as part of an other
* track if when removing the via, the segments of that other track are
* disconnected
*/
for( ; ; )
{
if( GetPadFast( aPosition, aLayerMask ) != NULL )
return;
/* Test for a via: a via changes the layer mask and can connect a lot
* of segments at location aPosition. When found, the via is just
* pushed in list. Vias will be examined later, when all connected
* segment are found and push in list. This is because when a via
* is found we do not know at this time the number of connected items
* and we do not know if this via is on the track or finish the track
*/
pt_via = m_Track->GetVia( NULL, aPosition, aLayerMask );
if( pt_via )
{
aLayerMask = pt_via->ReturnMaskLayer();
aList->push_back( pt_via );
}
/* Now we search all segments connected to point aPosition
* if only 1 segment: this segment is candidate
* if > 1 segment:
* end of track (more than 2 segment connected at this location)
*/
pt_segm = m_Track;
SegmentCandidate = NULL;
NbSegm = 0;
while( ( pt_segm = GetTraceByEndPoint( pt_segm, NULL, aPosition, aLayerMask ) ) != NULL )
{
if( pt_segm->GetState( BUSY ) ) // already found and selected: skip it
{
pt_segm = pt_segm->Next();
continue;
}
if( pt_segm == pt_via ) // just previously found: skip it
{
pt_segm = pt_segm->Next();
continue;
}
NbSegm++;
if( NbSegm == 1 ) /* First time we found a connected item: pt_segm is candidate */
{
SegmentCandidate = pt_segm;
pt_segm = pt_segm->Next();
}
else /* More than 1 segment connected -> this location is an end of the track */
{
return;
}
}
if( SegmentCandidate ) // A candidate is found: flag it an push it in list
{
/* Initialize parameters to search items connected to this
* candidate:
* we must analyze connections to its other end
*/
aLayerMask = SegmentCandidate->ReturnMaskLayer();
if( aPosition == SegmentCandidate->m_Start )
{
aPosition = SegmentCandidate->m_End;
}
else
{
aPosition = SegmentCandidate->m_Start;
}
pt_segm = m_Track; /* restart list of tracks to analyze */
/* flag this item an push it in list of selected items */
aList->push_back( SegmentCandidate );
SegmentCandidate->SetState( BUSY, ON );
}
else
{
return;
}
}
}
void BOARD::PushHightLight() void BOARD::PushHightLight()
{ {
m_hightLightPrevious = m_hightLight; m_hightLightPrevious = m_hightLight;
} }
/*
* Function PopHightLight
* retrieve a previously saved hight light info
*/
void BOARD::PopHightLight() void BOARD::PopHightLight()
{ {
m_hightLight = m_hightLightPrevious; m_hightLight = m_hightLightPrevious;
@ -108,15 +248,6 @@ void BOARD::PopHightLight()
} }
/**
* Function SetCurrentNetClass
* Must be called after a netclass selection (or after a netclass parameter
* change
* Initialize vias and tracks values displayed in combo boxes of the auxiliary
* toolbar and some other parameters (netclass name ....)
* @param aNetClassName = the new netclass name
* @return true if lists of tracks and vias sizes are modified
*/
bool BOARD::SetCurrentNetClass( const wxString& aNetClassName ) bool BOARD::SetCurrentNetClass( const wxString& aNetClassName )
{ {
NETCLASS* netClass = m_NetClasses.Find( aNetClassName ); NETCLASS* netClass = m_NetClasses.Find( aNetClassName );
@ -165,10 +296,6 @@ bool BOARD::SetCurrentNetClass( const wxString& aNetClassName )
} }
/**
* Function GetBiggestClearanceValue
* @return the biggest clearance value found in NetClasses list
*/
int BOARD::GetBiggestClearanceValue() int BOARD::GetBiggestClearanceValue()
{ {
int clearance = m_NetClasses.GetDefault()->GetClearance(); int clearance = m_NetClasses.GetDefault()->GetClearance();
@ -184,11 +311,6 @@ int BOARD::GetBiggestClearanceValue()
} }
/**
* Function GetCurrentMicroViaSize
* @return the current micro via size,
* that is the current netclass value
*/
int BOARD::GetCurrentMicroViaSize() int BOARD::GetCurrentMicroViaSize()
{ {
NETCLASS* netclass = m_NetClasses.Find( m_CurrentNetClassName ); NETCLASS* netclass = m_NetClasses.Find( m_CurrentNetClassName );
@ -197,11 +319,6 @@ int BOARD::GetCurrentMicroViaSize()
} }
/**
* Function GetCurrentMicroViaDrill
* @return the current micro via drill,
* that is the current netclass value
*/
int BOARD::GetCurrentMicroViaDrill() int BOARD::GetCurrentMicroViaDrill()
{ {
NETCLASS* netclass = m_NetClasses.Find( m_CurrentNetClassName ); NETCLASS* netclass = m_NetClasses.Find( m_CurrentNetClassName );
@ -380,11 +497,13 @@ LAYER_T LAYER::ParseType( const char* aType )
return LAYER_T( -1 ); return LAYER_T( -1 );
} }
int BOARD::GetCopperLayerCount() const int BOARD::GetCopperLayerCount() const
{ {
return GetBoardDesignSettings()->GetCopperLayerCount(); return GetBoardDesignSettings()->GetCopperLayerCount();
} }
void BOARD::SetCopperLayerCount( int aCount ) void BOARD::SetCopperLayerCount( int aCount )
{ {
GetBoardDesignSettings()->SetCopperLayerCount( aCount ); GetBoardDesignSettings()->SetCopperLayerCount( aCount );
@ -548,13 +667,6 @@ int BOARD::GetLayerColor( int aLayer )
} }
/**
* Function IsModuleLayerVisible
* expects either of the two layers on which a module can reside, and returns
* whether that layer is visible.
* @param layer One of the two allowed layers for modules: LAYER_N_FRONT or LAYER_N_BACK
* @return bool - true if the layer is visible, else false.
*/
bool BOARD::IsModuleLayerVisible( int layer ) bool BOARD::IsModuleLayerVisible( int layer )
{ {
if( layer==LAYER_N_FRONT ) if( layer==LAYER_N_FRONT )
@ -834,23 +946,6 @@ bool BOARD::ComputeBoundingBox( bool aBoardEdgesOnly )
} }
} }
if( !hasItems && m_PcbFrame )
{
if( m_PcbFrame->m_Draw_Sheet_Ref )
{
area.SetOrigin( 0, 0 );
area.SetEnd( m_PcbFrame->GetScreen()->ReturnPageSize().x,
m_PcbFrame->GetScreen()->ReturnPageSize().y );
}
else
{
area.SetOrigin( -m_PcbFrame->GetScreen()->ReturnPageSize().x / 2,
-m_PcbFrame->GetScreen()->ReturnPageSize().y / 2 );
area.SetEnd( m_PcbFrame->GetScreen()->ReturnPageSize().x / 2,
m_PcbFrame->GetScreen()->ReturnPageSize().y / 2 );
}
}
m_BoundaryBox = area; m_BoundaryBox = area;
return hasItems; return hasItems;
@ -858,9 +953,6 @@ bool BOARD::ComputeBoundingBox( bool aBoardEdgesOnly )
// virtual, see pcbstruct.h // virtual, see pcbstruct.h
/* Display board statistics: pads, nets, connections.. count
*/
void BOARD::DisplayInfo( EDA_DRAW_FRAME* frame ) void BOARD::DisplayInfo( EDA_DRAW_FRAME* frame )
{ {
wxString txt; wxString txt;
@ -1174,12 +1266,6 @@ SEARCH_RESULT BOARD::Visit( INSPECTOR* inspector, const void* testData,
*/ */
/**
* Function FindNet
* searches for a net with the given netcode.
* @param aNetcode The netcode to search for.
* @return NETINFO_ITEM* - the net or NULL if not found.
*/
NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
{ {
// the first valid netcode is 1 and the last is m_NetInfo->GetCount()-1. // the first valid netcode is 1 and the last is m_NetInfo->GetCount()-1.
@ -1202,12 +1288,6 @@ NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
} }
/**
* Function FindNet overlaid
* searches for a net with the given name.
* @param aNetname A Netname to search for.
* @return NETINFO_ITEM* - the net or NULL if not found.
*/
NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
{ {
// the first valid netcode is 1. // the first valid netcode is 1.
@ -1286,6 +1366,125 @@ NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
} }
TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment,
PICKED_ITEMS_LIST* aItemsListPicker )
{
if( aSegment->m_Start == aPosition || aSegment->m_End == aPosition )
return NULL;
/* A via is a good lock point */
if( aSegment->Type() == TYPE_VIA )
{
aPosition = aSegment->m_Start;
return aSegment;
}
/* Calculation coordinate of intermediate point relative to
* the start point of aSegment
*/
wxPoint delta = aSegment->m_End - aSegment->m_Start;
// Not yet in use:
#if 0
int ox, oy, fx, fy;
if( aRefSegm )
{
ox = aRefSegm->m_Start.x - aSegment->m_Start.x;
oy = aRefSegm->m_Start.y - aSegment->m_Start.y;
fx = aRefSegm->m_End.x - aSegment->m_Start.x;
fy = aRefSegm->m_End.y - aSegment->m_Start.y;
}
#endif
// calculate coordinates of aPosition relative to aSegment->m_Start
wxPoint newPoint = aPosition - aSegment->m_Start;
// newPoint must be on aSegment:
// Ensure newPoint.y/newPoint.y = delta.y/delta.x
if( delta.x == 0 )
newPoint.x = 0; /* horizontal segment*/
else
newPoint.y = wxRound(( (double)newPoint.x * delta.y ) / delta.x);
/* Create the intermediate point (that is to say creation of a new
* segment, beginning at the intermediate point.
*/
newPoint.x += aSegment->m_Start.x;
newPoint.y += aSegment->m_Start.y;
TRACK* newTrack = aSegment->Copy();
if( aItemsListPicker )
{
ITEM_PICKER picker( newTrack, UR_NEW );
aItemsListPicker->PushItem( picker );
}
DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
wxASSERT( list );
list->Insert( newTrack, aSegment->Next() );
if( aItemsListPicker )
{
ITEM_PICKER picker( aSegment, UR_CHANGED );
picker.m_Link = aSegment->Copy();
aItemsListPicker->PushItem( picker );
}
/* Correct pointer at the end of the new segment. */
newTrack->end = aSegment->end;
newTrack->SetState( END_ONPAD, aSegment->GetState( END_ONPAD ) );
/* Set connections info relative to the new point
*/
/* Old segment now ends at new point. */
aSegment->m_End = newPoint;
aSegment->end = newTrack;
aSegment->SetState( END_ONPAD, OFF );
/* The new segment begins at the new point. */
newTrack->m_Start = newPoint;
newTrack->start = aSegment;
newTrack->SetState( BEGIN_ONPAD, OFF );
D_PAD * pad = GetPad( newTrack, START );
if ( pad )
{
newTrack->start = pad;
newTrack->SetState( BEGIN_ONPAD, ON );
aSegment->end = pad;
aSegment->SetState( END_ONPAD, ON );
}
aPosition = newPoint;
return newTrack;
}
BOARD_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, int aLayerMask )
{
for( MODULE* module = m_Modules; module; module = module->Next() )
{
D_PAD* pad = module->GetPad( aPosition, aLayerMask );
if( pad )
return pad;
}
/* No pad has been located so check for a segment of the trace. */
TRACK* trace = GetTraceByEndPoint( m_Track, NULL, aPosition, aLayerMask );
if( trace == NULL )
trace = GetTrace( aPosition, aLayerMask );
return trace;
}
MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
{ {
struct FindModule : public INSPECTOR struct FindModule : public INSPECTOR
@ -1320,20 +1519,185 @@ MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
} }
// Sort nets by decreasing pad count MODULE* BOARD::GetModule( const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked )
{
MODULE* pt_module;
MODULE* module = NULL;
MODULE* Altmodule = NULL;
int min_dim = 0x7FFFFFFF;
int alt_min_dim = 0x7FFFFFFF;
int layer;
pt_module = m_Modules;
for( ; pt_module; pt_module = (MODULE*) pt_module->Next() )
{
// is the ref point within the module's bounds?
if( !pt_module->HitTest( aPosition ) )
continue;
// if caller wants to ignore locked modules, and this one is locked, skip it.
if( aIgnoreLocked && pt_module->IsLocked() )
continue;
/* Calculate priority: the priority is given to the layer of the
* module and the copper layer if the module layer is indelible,
* adhesive copper, a layer if cmp module layer is indelible,
* adhesive component.
*/
layer = pt_module->GetLayer();
if( layer==ADHESIVE_N_BACK || layer==SILKSCREEN_N_BACK )
layer = LAYER_N_BACK;
else if( layer==ADHESIVE_N_FRONT || layer==SILKSCREEN_N_FRONT )
layer = LAYER_N_FRONT;
/* Test of minimum size to choosing the best candidate. */
EDA_RECT bb = pt_module->GetFootPrintRect();
int offx = bb.GetX() + bb.GetWidth() / 2;
int offy = bb.GetY() + bb.GetHeight() / 2;
//off x & offy point to the middle of the box.
int dist = abs( aPosition.x - offx ) + abs( aPosition.y - offy );
//int dist = MIN(lx, ly); // to pick the smallest module (kinda
// screwy with same-sized modules -- this is bad!)
if( aActiveLayer == layer )
{
if( dist <= min_dim )
{
/* better footprint shown on the active layer */
module = pt_module;
min_dim = dist;
}
}
else if( aVisibleOnly && IsModuleLayerVisible( layer ) )
{
if( dist <= alt_min_dim )
{
/* better footprint shown on other layers */
Altmodule = pt_module;
alt_min_dim = dist;
}
}
}
if( module )
{
return module;
}
if( Altmodule )
{
return Altmodule;
}
return NULL;
}
TRACK* BOARD::GetTrace( const wxPoint& aPosition, int aLayer )
{
return m_Track->GetTrace( aPosition, aLayer );
}
TRACK* BOARD::GetVia( const wxPoint& aPosition, int aLayer )
{
TRACK* track;
for( track = m_Track; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA
|| track->m_Start != aPosition
|| track->GetState( BUSY | IS_DELETED ) )
continue;
if( aLayer < 0 || track->IsOnLayer( aLayer ) )
break;
}
return track;
}
D_PAD* BOARD::GetPad( TRACK* aTrace, int aEnd )
{
D_PAD* pad = NULL;
wxPoint pos;
int aLayerMask = g_TabOneLayerMask[ aTrace->GetLayer() ];
if( aEnd == START )
{
pos = aTrace->m_Start;
}
else
{
pos = aTrace->m_End;
}
for( MODULE* module = m_Modules; module; module = module->Next() )
{
pad = module->GetPad( pos, aLayerMask );
if( pad != NULL )
break;
}
return pad;
}
D_PAD* BOARD::GetPad( const wxPoint& aPosition, int aLayerMask )
{
D_PAD* pad = NULL;
for( MODULE* module = m_Modules; module && ( pad == NULL ); module = module->Next() )
{
pad = module->GetPad( aPosition, aLayerMask );
}
return pad;
}
D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, int aLayerMask )
{
for( unsigned i=0; i<GetPadsCount(); ++i )
{
D_PAD* pad = m_NetInfo->GetPad(i);
if( pad->m_Pos != aPosition )
continue;
/* Pad found, it must be on the correct layer */
if( pad->m_layerMask & aLayerMask )
return pad;
}
return NULL;
}
void BOARD::CreateSortedPadListByXCoord( std::vector<D_PAD*>* aVector )
{
aVector->insert( aVector->end(), m_NetInfo->m_PadsFullList.begin(),
m_NetInfo->m_PadsFullList.end() );
qsort( &(*aVector)[0], GetPadsCount(), sizeof( D_PAD*), SortPadsByXCoord );
}
static bool s_SortByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b ) static bool s_SortByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
{ {
return b->GetNodesCount() < a->GetNodesCount(); return b->GetNodesCount() < a->GetNodesCount();
} }
/**
* Function ReturnSortedNetnamesList
* @param aNames An array string to fill with net names.
* @param aSortbyPadsCount : true = sort by active pads count, false = no sort
* (i.e. leave the sort by net names)
* @return int - net names count.
*/
int BOARD::ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount ) int BOARD::ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
{ {
if( m_NetInfo->GetCount() == 0 ) if( m_NetInfo->GetCount() == 0 )
@ -1439,10 +1803,6 @@ out:
} }
/*
* Function RedrawAreasOutlines
* Redraw all areas outlines on layer aLayer ( redraw all if aLayer < 0 )
*/
void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode, int aLayer ) void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode, int aLayer )
{ {
if( !aDC ) if( !aDC )
@ -1458,10 +1818,6 @@ void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode
} }
/**
* Function RedrawFilledAreas
* Redraw all areas outlines on layer aLayer ( redraw all if aLayer < 0 )
*/
void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode, int aLayer ) void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode, int aLayer )
{ {
if( !aDC ) if( !aDC )
@ -1477,18 +1833,6 @@ void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode,
} }
/**
* Function HitTestForAnyFilledArea
* tests if the given wxPoint is within the bounds of a filled area of this
* zone.
* the test is made on zones on layer from aStartLayer to aEndLayer
* Note: if a zone has its flag BUSY (in .m_State) is set, it is ignored.
* @param aRefPos A wxPoint to test
* @param aStartLayer the first layer to test
* @param aEndLayer the last layer (-1 to ignore it) to test
* @return ZONE_CONTAINER* return a pointer to the ZONE_CONTAINER found, else
* NULL
*/
ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos, ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos,
int aStartLayer, int aStartLayer,
int aEndLayer ) int aEndLayer )
@ -1519,19 +1863,6 @@ ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos,
} }
/**
* Function SetAreasNetCodesFromNetNames
* Set the .m_NetCode member of all copper areas, according to the area Net
* Name
* The SetNetCodesFromNetNames is an equivalent to net name, for fast
* comparisons.
* However the Netcode is an arbitrary equivalence, it must be set after each
* netlist read
* or net change
* Must be called after pad netcodes are calculated
* @return : error count
* For non copper areas, netcode is set to 0
*/
int BOARD::SetAreasNetCodesFromNetNames( void ) int BOARD::SetAreasNetCodesFromNetNames( void )
{ {
int error_count = 0; int error_count = 0;
@ -1565,15 +1896,248 @@ int BOARD::SetAreasNetCodesFromNetNames( void )
} }
TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount, int* aLength, int* aLengthDie, bool aReorder )
{
wxCHECK( aTrace != NULL, NULL );
int NbSegmBusy;
TRACK_PTRS trackList;
if( aCount )
*aCount = 0;
if( aLength )
*aLength = 0;
// Ensure the flag BUSY of all tracks of the board is cleared
// because we use it to mark segments of the track
for( TRACK* track = m_Track; track; track = track->Next() )
track->SetState( BUSY, OFF );
/* Set flags of the initial track segment */
aTrace->SetState( BUSY, ON );
int layerMask = aTrace->ReturnMaskLayer();
trackList.push_back( aTrace );
/* Examine the initial track segment : if it is really a segment, this is
* easy.
* If it is a via, one must search for connected segments.
* If <=2, this via connect 2 segments (or is connected to only one
* segment) and this via and these 2 segments are a part of a track.
* If > 2 only this via is flagged (the track has only this via)
*/
if( aTrace->Type() == TYPE_VIA )
{
TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL;
Segm1 = GetTraceByEndPoint( m_Track, NULL, aTrace->m_Start, layerMask );
if( Segm1 )
{
Segm2 = GetTraceByEndPoint( Segm1->Next(), NULL, aTrace->m_Start, layerMask );
}
if( Segm2 )
{
Segm3 = GetTraceByEndPoint( Segm2->Next(), NULL, aTrace->m_Start, layerMask );
}
if( Segm3 ) // More than 2 segments are connected to this via. the track" is only this via
{
if( aCount )
*aCount = 1;
return aTrace;
}
if( Segm1 ) // search for others segments connected to the initial segment start point
{
layerMask = Segm1->ReturnMaskLayer();
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
}
if( Segm2 ) // search for others segments connected to the initial segment end point
{
layerMask = Segm2->ReturnMaskLayer();
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
}
}
else // mark the chain using both ends of the initial segment
{
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
chainMarkedSegments( aTrace->m_End, layerMask, &trackList );
}
// Now examine selected vias and flag them if they are on the track
// If a via is connected to only one or 2 segments, it is flagged (is on
// the track)
// If a via is connected to more than 2 segments, it is a track end, and it
// is removed from the list
// go through the list backwards.
for( int i = trackList.size() - 1; i>=0; --i )
{
TRACK* via = trackList[i];
if( via->Type() != TYPE_VIA )
continue;
if( via == aTrace )
continue;
via->SetState( BUSY, ON ); // Try to flag it. the flag will be cleared later if needed
layerMask = via->ReturnMaskLayer();
TRACK* track = GetTraceByEndPoint( m_Track, NULL, via->m_Start, layerMask );
// GetTrace does not consider tracks flagged BUSY.
// So if no connected track found, this via is on the current track
// only: keep it
if( track == NULL )
continue;
/* If a track is found, this via connects also others segments of an
* other track. This case happens when the vias ends the selected
* track but must we consider this via is on the selected track, or
* on an other track.
* (this is important when selecting a track for deletion: must this
* via be deleted or not?)
* We consider here this via on the track if others segment connected
* to this via remain connected when removing this via.
* We search for all others segment connected together:
* if there are on the same layer, the via is on the selected track
* if there are on different layers, the via is on an other track
*/
int layer = track->GetLayer();
while( ( track = GetTraceByEndPoint( track->Next(), NULL,
via->m_Start, layerMask ) ) != NULL )
{
if( layer != track->GetLayer() )
{
// The via connects segments of an other track: it is removed
// from list because it is member of an other track
via->SetState( BUSY, OFF );
break;
}
}
}
/* Rearrange the track list in order to have flagged segments linked
* from firstTrack so the NbSegmBusy segments are consecutive segments
* in list, the first item in the full track list is firstTrack, and
* the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
* are the flagged segments
*/
NbSegmBusy = 0;
TRACK* firstTrack;
for( firstTrack = m_Track; firstTrack; firstTrack = firstTrack->Next() )
{
// Search for the first flagged BUSY segments
if( firstTrack->GetState( BUSY ) )
{
NbSegmBusy = 1;
break;
}
}
if( firstTrack == NULL )
return NULL;
double full_len = 0;
double lenDie = 0;
if( aReorder )
{
DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
wxASSERT( list );
/* Rearrange the chain starting at firstTrack
* All others flagged items are moved from their position to the end
* of the flagged list
*/
TRACK* next;
for( TRACK* track = firstTrack->Next(); track; track = next )
{
next = track->Next();
if( track->GetState( BUSY ) ) // move it!
{
NbSegmBusy++;
track->UnLink();
list->Insert( track, firstTrack->Next() );
if( aLength )
full_len += track->GetLength();
if( aLengthDie ) // Add now length die.
{
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
}
else if( aLength )
{
NbSegmBusy = 0;
for( TRACK* track = firstTrack; track; track = track->Next() )
{
if( track->GetState( BUSY ) )
{
NbSegmBusy++;
track->SetState( BUSY, OFF );
full_len += track->GetLength();
// Add now length die.
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
if( aLength )
*aLength = wxRound( full_len );
if( aLengthDie )
*aLengthDie = wxRound( lenDie );
if( aCount )
*aCount = NbSegmBusy;
return firstTrack;
}
#if defined(DEBUG) #if defined(DEBUG)
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void BOARD::Show( int nestLevel, std::ostream& os ) void BOARD::Show( int nestLevel, std::ostream& os )
{ {
BOARD_ITEM* p; BOARD_ITEM* p;

View File

@ -1,6 +1,7 @@
/*************************************************/ /**
/* class_board.h - Class BOARD to handle a board */ * @file class_board.h
/*************************************************/ * @brief Class BOARD to handle a board
*/
#ifndef CLASS_BOARD_H #ifndef CLASS_BOARD_H
#define CLASS_BOARD_H #define CLASS_BOARD_H
@ -12,8 +13,29 @@
class ZONE_CONTAINER; class ZONE_CONTAINER;
class TRACK;
#define HISTORY_MAX_COUNT 8
// Used to buffer item candidates when search for items on the same track
typedef std::vector<TRACK*> TRACK_PTRS;
/**
* Function GetTraceByEndPoint
* returns a trace starting at \a aStartTrace and ending at \a aEndTrace that has an
* end point at \a aPosition on \a aLayerMask.
*
* @param aStartTrace Pointer to the TRACK object to begin the search.
* @param aEndTrace Pointer to the TRACK object to end then search.
* @param aPosition The wxPoint to check the trace end points against.
* @param aLayerMask The layer or layers to search.
* @return A pointer to the TRACK or SEGVIA object if found, else NULL.
*/
TRACK* GetTraceByEndPoint( TRACK* aStartTrace, TRACK* aEndTrace,
const wxPoint& aPosition, int aLayerMask );
/** /**
* Enum LAYER_T * Enum LAYER_T
* gives the allowed types of layers, same as Specctra DSN spec. * gives the allowed types of layers, same as Specctra DSN spec.
@ -41,7 +63,6 @@ struct LAYER
// int m_Color; // int m_Color;
// bool m_Visible; // ? use flags in m_Color instead ? // bool m_Visible; // ? use flags in m_Color instead ?
/** /**
* Function ShowType * Function ShowType
* converts a LAYER_T enum to a const char* * converts a LAYER_T enum to a const char*
@ -78,8 +99,7 @@ public:
bool operator ==( const VIA_DIMENSION& other ) const bool operator ==( const VIA_DIMENSION& other ) const
{ {
return (m_Diameter == other.m_Diameter) return (m_Diameter == other.m_Diameter) && (m_Drill == other.m_Drill);
&& (m_Drill == other.m_Drill);
} }
@ -87,14 +107,17 @@ public:
{ {
if( m_Diameter != other.m_Diameter ) if( m_Diameter != other.m_Diameter )
return m_Diameter < other.m_Diameter; return m_Diameter < other.m_Diameter;
return m_Drill < other.m_Drill; return m_Drill < other.m_Drill;
} }
}; };
// Helper class to handle hight light nets // Helper class to handle hight light nets
class HIGHT_LIGHT_INFO class HIGHT_LIGHT_INFO
{ {
friend class BOARD; friend class BOARD;
protected: protected:
int m_netCode; // net selected for hightlight (-1 when no net selected ) int m_netCode; // net selected for hightlight (-1 when no net selected )
bool m_hightLightOn; // hightlight active bool m_hightLightOn; // hightlight active
@ -112,51 +135,52 @@ protected:
} }
}; };
/** /**
* Class BOARD * Class BOARD
* holds information pertinent to a PCBNEW printed circuit board. * holds information pertinent to a PCBNEW printed circuit board.
*/ */
#define HISTORY_MAX_COUNT 8
class BOARD : public BOARD_ITEM class BOARD : public BOARD_ITEM
{ {
friend class PCB_EDIT_FRAME; friend class PCB_EDIT_FRAME;
private: private:
typedef std::vector<MARKER_PCB*> MARKERS; // @todo: switch to boost:ptr_vector, and change ~BOARD() typedef std::vector<MARKER_PCB*> MARKERS; // @todo: switch to boost:ptr_vector, and change ~BOARD()
MARKERS m_markers; ///< MARKER_PCBs for clearance problems, owned by pointer
MARKERS m_markers; ///< MARKER_PCBs for clearance problems, owned by pointer
typedef std::vector<ZONE_CONTAINER*> ZONE_CONTAINERS; // @todo: switch to boost::ptr_vector, and change ~BOARD() typedef std::vector<ZONE_CONTAINER*> ZONE_CONTAINERS; // @todo: switch to boost::ptr_vector, and change ~BOARD()
ZONE_CONTAINERS m_ZoneDescriptorList; ///< edge zone descriptors, owned by pointer
LAYER m_Layer[NB_COPPER_LAYERS]; ZONE_CONTAINERS m_ZoneDescriptorList; ///< edge zone descriptors, owned by pointer
// if true m_hightLight_NetCode is used
HIGHT_LIGHT_INFO m_hightLight; // current hight light data LAYER m_Layer[NB_COPPER_LAYERS];
HIGHT_LIGHT_INFO m_hightLightPrevious; // a previously stored hight light data // if true m_hightLight_NetCode is used
HIGHT_LIGHT_INFO m_hightLight; // current hight light data
HIGHT_LIGHT_INFO m_hightLightPrevious; // a previously stored hight light data
public: public:
PCB_BASE_FRAME* m_PcbFrame; // Window of visualization EDA_RECT m_BoundaryBox; // Board size and position
EDA_RECT m_BoundaryBox; // Board size and position int m_Status_Pcb; // Flags used in ratsnet calculation and update
int m_Status_Pcb; // Flags used in ratsnet calculation and update int m_NbNodes; // Active pads (pads attached to a net ) count
int m_NbNodes; // Active pads (pads attached to a net ) count int m_NbNoconnect; // Active ratsnet count (rastnests not already connected by tracks)
int m_NbNoconnect; // Active ratsnet count (rastnests not already connected by tracks)
DLIST<BOARD_ITEM> m_Drawings; // linked list of lines & texts DLIST<BOARD_ITEM> m_Drawings; // linked list of lines & texts
DLIST<MODULE> m_Modules; // linked list of MODULEs DLIST<MODULE> m_Modules; // linked list of MODULEs
DLIST<TRACK> m_Track; // linked list of TRACKs and SEGVIAs DLIST<TRACK> m_Track; // linked list of TRACKs and SEGVIAs
DLIST<SEGZONE> m_Zone; // linked list of SEGZONEs DLIST<SEGZONE> m_Zone; // linked list of SEGZONEs
NETINFO_LIST* m_NetInfo; // nets info list (name, design constraints .. NETINFO_LIST* m_NetInfo; // nets info list (name, design constraints ..
std::vector<RATSNEST_ITEM> m_FullRatsnest; // Rastnest list for the BOARD std::vector<RATSNEST_ITEM> m_FullRatsnest; // Ratsnest list for the BOARD
std::vector<RATSNEST_ITEM> m_LocalRatsnest; /* Rastnest list relative to a given footprint std::vector<RATSNEST_ITEM> m_LocalRatsnest; /* Ratsnest list relative to a given footprint
* (used while moving a footprint) */ * (used while moving a footprint) */
ZONE_CONTAINER* m_CurrentZoneContour; // zone contour currently in progress ZONE_CONTAINER* m_CurrentZoneContour; // zone contour currently in progress
NETCLASSES m_NetClasses; ///< List of current netclasses. There is always the default netclass NETCLASSES m_NetClasses; ///< List of current netclasses. There is always the default netclass
wxString m_CurrentNetClassName; /* Current net class name used to display netclass info. wxString m_CurrentNetClassName; /* Current net class name used to display netclass info.
* this is also the last used netclass after starting a track * this is also the last used netclass after starting a track
*/ */
// handling of vias and tracks size: // handling of vias and tracks size:
@ -167,6 +191,7 @@ public:
std::vector <int> m_TrackWidthList; // tracks widths (max count = HISTORY_MAX_COUNT) std::vector <int> m_TrackWidthList; // tracks widths (max count = HISTORY_MAX_COUNT)
// The first value is the current netclass track width // The first value is the current netclass track width
unsigned m_ViaSizeSelector; // index for m_ViaSizeList to select the value unsigned m_ViaSizeSelector; // index for m_ViaSizeList to select the value
// 0 is the index selection of the default value Netclass // 0 is the index selection of the default value Netclass
unsigned m_TrackWidthSelector; // index for m_TrackWidthList to select the value unsigned m_TrackWidthSelector; // index for m_TrackWidthList to select the value
@ -174,9 +199,25 @@ private:
BOARD_DESIGN_SETTINGS* m_boardDesignSettings; // Link to current design settings BOARD_DESIGN_SETTINGS* m_boardDesignSettings; // Link to current design settings
COLORS_DESIGN_SETTINGS* m_colorsSettings; // Link to current colors settings COLORS_DESIGN_SETTINGS* m_colorsSettings; // Link to current colors settings
/**********************************/ /**
* Function chainMarkedSegments
* add all trace segments to \a aList attached to a trace found at \a aPosition on
* \a aLayerMask.
* <p>
* The BUSY flag of all connected segments is set. Vias are also put in list but
* their flags BUSY is not set.
* </p>
* @param aPosition A wxPoint object contatining thhe reference coordinate of the
* to search.
* @param aLayerMask The allowed layers for segments to search (1 layer when starting
* point is on a segment, but more than one when starting point is
* on a via)
* @param aList The track list to fill with flagged segments.
*/
void chainMarkedSegments( wxPoint& aPosition, int aLayerMask, TRACK_PTRS* aList );
public: public:
BOARD( EDA_ITEM* aParent, PCB_BASE_FRAME* frame ); BOARD( EDA_ITEM* aParent );
~BOARD(); ~BOARD();
/** /**
@ -207,7 +248,7 @@ public:
* @param aBoardItem The item to add to this board. * @param aBoardItem The item to add to this board.
* @param aControl An int which can vary how the item is added. * @param aControl An int which can vary how the item is added.
*/ */
void Add( BOARD_ITEM* aBoardItem, int aControl = 0 ); void Add( BOARD_ITEM* aBoardItem, int aControl = 0 );
#define ADD_APPEND 1 ///< aControl flag for Add( aControl ), appends not inserts #define ADD_APPEND 1 ///< aControl flag for Add( aControl ), appends not inserts
@ -217,9 +258,10 @@ public:
* removes the given single item from this BOARD and deletes its memory. * removes the given single item from this BOARD and deletes its memory.
* @param aBoardItem The item to remove from this board and delete * @param aBoardItem The item to remove from this board and delete
*/ */
void Delete( BOARD_ITEM* aBoardItem ) void Delete( BOARD_ITEM* aBoardItem )
{ {
wxASSERT( aBoardItem ); // developers should run DEBUG versions and fix such calls with NULL wxASSERT( aBoardItem ); // developers should run DEBUG versions and fix calls with NULL
if( aBoardItem ) if( aBoardItem )
delete Remove( aBoardItem ); delete Remove( aBoardItem );
} }
@ -227,8 +269,7 @@ public:
/** /**
* Function Remove * Function Remove
* removes \a aBoardItem from this BOARD and returns it to caller without * removes \a aBoardItem from this BOARD and returns it to caller without deleting it.
* deleting it.
* @param aBoardItem The item to remove from this board. * @param aBoardItem The item to remove from this board.
* @return BOARD_ITEM* \a aBoardItem which was passed in. * @return BOARD_ITEM* \a aBoardItem which was passed in.
*/ */
@ -239,14 +280,13 @@ public:
* Function DeleteMARKERs * Function DeleteMARKERs
* deletes ALL MARKERS from the board. * deletes ALL MARKERS from the board.
*/ */
void DeleteMARKERs(); void DeleteMARKERs();
/** /**
* Function DeleteZONEOutlines * Function DeleteZONEOutlines
* deletes ALL zone outlines from the board. * deletes ALL zone outlines from the board.
*/ */
void DeleteZONEOutlines(); void DeleteZONEOutlines();
/** /**
* Function GetMARKER * Function GetMARKER
@ -258,6 +298,7 @@ public:
{ {
if( (unsigned) index < m_markers.size() ) if( (unsigned) index < m_markers.size() )
return m_markers[index]; return m_markers[index];
return NULL; return NULL;
} }
@ -333,7 +374,7 @@ public:
* Function GetCopperLayerCount * Function GetCopperLayerCount
* @return int - The number of copper layers in the BOARD. * @return int - The number of copper layers in the BOARD.
*/ */
int GetCopperLayerCount() const; int GetCopperLayerCount() const;
void SetCopperLayerCount( int aCount ); void SetCopperLayerCount( int aCount );
@ -344,7 +385,7 @@ public:
* Returns a bit-mask of all the layers that are enabled * Returns a bit-mask of all the layers that are enabled
* @return int - the enabled layers in bit-mapped form. * @return int - the enabled layers in bit-mapped form.
*/ */
int GetEnabledLayers() const; int GetEnabledLayers() const;
/** /**
* Function SetEnabledLayers * Function SetEnabledLayers
@ -384,7 +425,7 @@ public:
* Returns a bit-mask of all the layers that are visible * Returns a bit-mask of all the layers that are visible
* @return int - the visible layers in bit-mapped form. * @return int - the visible layers in bit-mapped form.
*/ */
int GetVisibleLayers() const; int GetVisibleLayers() const;
/** /**
* Function SetVisibleLayers * Function SetVisibleLayers
@ -404,7 +445,7 @@ public:
* @return int - the visible element bitmap or-ed from enum PCB_VISIBLE * @return int - the visible element bitmap or-ed from enum PCB_VISIBLE
* @see enum PCB_VISIBLE * @see enum PCB_VISIBLE
*/ */
int GetVisibleElements() const; int GetVisibleElements() const;
/** /**
* Function SetVisibleElements * Function SetVisibleElements
@ -455,9 +496,9 @@ public:
* returns the color of a pcb visible element. * returns the color of a pcb visible element.
* @see enum PCB_VISIBLE * @see enum PCB_VISIBLE
*/ */
int GetVisibleElementColor( int aPCB_VISIBLE ); int GetVisibleElementColor( int aPCB_VISIBLE );
void SetVisibleElementColor( int aPCB_VISIBLE, int aColor );
void SetVisibleElementColor( int aPCB_VISIBLE, int aColor );
/** /**
* Function GetBoardDesignSettings * Function GetBoardDesignSettings
@ -515,7 +556,7 @@ public:
* @return bool - true if aLayerName was legal and unique amoung other * @return bool - true if aLayerName was legal and unique amoung other
* layer names at other layer indices and aLayerIndex was within range, else false. * layer names at other layer indices and aLayerIndex was within range, else false.
*/ */
bool SetLayerName( int aLayerIndex, const wxString& aLayerName ); bool SetLayerName( int aLayerIndex, const wxString& aLayerName );
/** /**
* Function GetLayerType * Function GetLayerType
@ -525,7 +566,7 @@ public:
* @return LAYER_T - the layer type, or LAYER_T(-1) if the * @return LAYER_T - the layer type, or LAYER_T(-1) if the
* index was out of range. * index was out of range.
*/ */
LAYER_T GetLayerType( int aLayerIndex ) const; LAYER_T GetLayerType( int aLayerIndex ) const;
/** /**
* Function SetLayerType * Function SetLayerType
@ -535,30 +576,32 @@ public:
* @param aLayerType The new layer type. * @param aLayerType The new layer type.
* @return bool - true if aLayerType was legal and aLayerIndex was within range, else false. * @return bool - true if aLayerType was legal and aLayerIndex was within range, else false.
*/ */
bool SetLayerType( int aLayerIndex, LAYER_T aLayerType ); bool SetLayerType( int aLayerIndex, LAYER_T aLayerType );
/** /**
* Function SetLayerColor * Function SetLayerColor
* changes a layer color for any valid layer, including non-copper ones. * changes a layer color for any valid layer, including non-copper ones.
*/ */
void SetLayerColor( int aLayer, int aColor ); void SetLayerColor( int aLayer, int aColor );
/** /**
* Function GetLayerColor * Function GetLayerColor
* gets a layer color for any valid layer, including non-copper ones. * gets a layer color for any valid layer, including non-copper ones.
*/ */
int GetLayerColor( int aLayer ); int GetLayerColor( int aLayer );
/* Functions to get some items count */ /* Functions to get some items count */
int GetNumSegmTrack(); int GetNumSegmTrack();
int GetNumSegmZone();
int GetNumSegmZone();
unsigned GetNoconnectCount(); // Return the number of missing links. unsigned GetNoconnectCount(); // Return the number of missing links.
/** /**
* Function GetNumRatsnests * Function GetNumRatsnests
* @return int - The number of rats * @return int - The number of rats
*/ */
unsigned GetRatsnestsCount() unsigned GetRatsnestsCount()
{ {
return m_FullRatsnest.size(); return m_FullRatsnest.size();
} }
@ -574,7 +617,7 @@ public:
* Function GetPadsCount * Function GetPadsCount
* @return the number of pads in board * @return the number of pads in board
*/ */
unsigned GetPadsCount() unsigned GetPadsCount()
{ {
return m_NetInfo->GetPadsCount(); return m_NetInfo->GetPadsCount();
} }
@ -585,7 +628,7 @@ public:
* @param aBoardEdgesOnly is true if we are interested in board edge segments only. * @param aBoardEdgesOnly is true if we are interested in board edge segments only.
* @return bool - True if items (or board edge segments) were found. * @return bool - True if items (or board edge segments) were found.
*/ */
bool ComputeBoundingBox( bool aBoardEdgesOnly = false ); bool ComputeBoundingBox( bool aBoardEdgesOnly = false );
/** /**
* Function DisplayInfo * Function DisplayInfo
@ -594,7 +637,7 @@ public:
* Is virtual from EDA_ITEM. * Is virtual from EDA_ITEM.
* @param frame A EDA_DRAW_FRAME in which to print status information. * @param frame A EDA_DRAW_FRAME in which to print status information.
*/ */
void DisplayInfo( EDA_DRAW_FRAME* frame ); void DisplayInfo( EDA_DRAW_FRAME* frame );
/** /**
* Function Draw. * Function Draw.
@ -604,8 +647,8 @@ public:
* @param aDrawMode = GR_COPY, GR_OR ... (not always used) * @param aDrawMode = GR_COPY, GR_OR ... (not always used)
* @param aOffset = an draw offset value (default = 0,0) * @param aOffset = an draw offset value (default = 0,0)
*/ */
void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
int aDrawMode, const wxPoint& aOffset = ZeroOffset ); int aDrawMode, const wxPoint& aOffset = ZeroOffset );
/** /**
* Function DrawHighLight * Function DrawHighLight
@ -616,7 +659,7 @@ public:
* @param aDC = the curent device context * @param aDC = the curent device context
* @param aNetCode is the net number to highlight or to dim. * @param aNetCode is the net number to highlight or to dim.
*/ */
void DrawHighLight( EDA_DRAW_PANEL* aDrawPanel, wxDC* aDC, int aNetCode ); void DrawHighLight( EDA_DRAW_PANEL* aDrawPanel, wxDC* aDC, int aNetCode );
/** /**
* Function Visit * Function Visit
@ -651,6 +694,36 @@ public:
*/ */
NETINFO_ITEM* FindNet( const wxString& aNetname ) const; NETINFO_ITEM* FindNet( const wxString& aNetname ) const;
/**
* Function CreateLockPoint
* creates an intermediate point on \a aSegment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( wxPoint& aRefPoint, TRACK* aSegment,
PICKED_ITEMS_LIST* aItemsListPicker );
/**
* Function GetLockPoint
* returns the object at the end of a trace locacted at \a aPosition on \a aLayer.
*
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayerMask A layer or layers to mask the hit test.
* @return A pointer to the board item if found or NULL if not found.
*/
BOARD_ITEM* GetLockPoint( const wxPoint& aPosition, int aLayerMask );
/** /**
* Function FindModuleByReference * Function FindModuleByReference
* searches for a MODULE within this board with the given * searches for a MODULE within this board with the given
@ -660,15 +733,95 @@ public:
* @return MODULE* - If found, the MODULE having the given reference * @return MODULE* - If found, the MODULE having the given reference
* designator, else NULL. * designator, else NULL.
*/ */
MODULE* FindModuleByReference( const wxString& aReference ) const; MODULE* FindModuleByReference( const wxString& aReference ) const;
/**
* Function Locate_Prefered_Module
* locates a footprint at \a aPosition on \a aActiveLayer.
* <p>
* If several footprints are are at \a aPosition, then the priority is the closest on the
* active layer, then closest to \a aPosition. The distance is calculatedvia manhattan
* distance from the center of the bounding rectangle to \a aposition.
* </p>
* @param aPosition A wxPoint object containing the position to hit test.
* @param aActiveLayer The layer to test.
* @param aVisibleOnly Search only the visible layers if true.
* @param aIgnoreLocked Ignore locked modules when true.
* @return MODULE* The best module or NULL if none.
*/
MODULE* GetModule( const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked = false );
/**
* Function GetTrace
* returns a trace segment or via at \a aPosition on \a aLayer.
*
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to search. Use -1 for a don't care.
* @return A pointer to the TRACK or SEGVIA object if found, else NULL.
*/
TRACK* GetTrace( const wxPoint& aPosition, int aLayer );
/**
* Function GetVia
* finds the first via at \a aPosition on \a aLayer.
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to search. Use -1 for a don't care.
* @return TRACK* A point a to the SEGVIA object if found, else NULL.
*/
TRACK* GetVia( const wxPoint& aPosition, int aLayer = -1 );
/**
* Function GetPad
* returns the pad connected to the beginning or end of \a aTrace at \a aEnd
*
* @param aTrace A pointer to the trace to test for a pad connection.
* @param aEnd The end point of \a aTrace to test for a pad connection.
* @return A pointer to a D_PAD object if connection found or NULL if not found.
*/
D_PAD* GetPad( TRACK* aTrace, int aEnd );
/**
* Function GetPad
* finds a pad \a aPosition on \a aLayer.
*
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayerMask A layer or layers to mask the hit test.
* @return A pointer to a D_PAD object if found or NULL if not found.
*/
D_PAD* GetPad( const wxPoint& aPosition, int aLayerMask = ALL_LAYERS );
/**
* Function GetPadFast
* return pad found at \a aPosition on \a aLayer uning the fast search method.
* <p>
* The fast search method only works if the pad list has already exists.
* </p>
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayer A layer or layers to mask the hit test.
* @return A pointer to a D_PAD object if found or NULL if not found.
*/
D_PAD* GetPadFast( const wxPoint& aPosition, int aLayer );
/** /**
* Function ReturnSortedNetnamesList * Function ReturnSortedNetnamesList
* @param aNames An array string to fill with net names. * @param aNames An array string to fill with net names.
* @param aSortbyPadsCount : true = sort by active pads count, false = no sort (i.e. leave the sort by net names) * @param aSortbyPadsCount : true = sort by active pads count, false = no sort (i.e.
* leave the sort by net names)
* @return int - net names count. * @return int - net names count.
*/ */
int ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount ); int ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount );
/**
* Function CreateSortedPadListByXCoord
* clears then fills \a aVector with all pads on the board and sorts them by
* increasing x coordinate.
*
* @note Do not delete any pointers in \a aVector. The pointers are only references to
* pads which are owned by the BOARD.
* @param aVector Where to put the pad pointers.
*/
void CreateSortedPadListByXCoord( std::vector<D_PAD*>* aVector );
/**************************************/ /**************************************/
/** /**
@ -678,9 +831,9 @@ public:
/** /**
* Function SynchronizeNetsAndNetClasses * Function SynchronizeNetsAndNetClasses
* copies NETCLASS info to each NET, based on NET membership in a NETCLASS. * copies NETCLASS info to each NET, based on NET membership in a NETCLASS.
* Must be called after a Design Rules edition, or after reading a netlist (or editing the list of nets) * Must be called after a Design Rules edition, or after reading a netlist (or editing
* Also this function removes the non existing nets in netclasses and add net nets in default netclass * the list of nets). Also this function removes the non existing nets in netclasses
* (this happens after reading a netlist) * and add net nets in default netclass (this happens after reading a netlist)
*/ */
void SynchronizeNetsAndNetClasses(); void SynchronizeNetsAndNetClasses();
@ -706,7 +859,7 @@ public:
* ( using the default netclass value or a preset value ) * ( using the default netclass value or a preset value )
* the default netclass is always in m_TrackWidthList[0] * the default netclass is always in m_TrackWidthList[0]
*/ */
int GetCurrentTrackWidth() int GetCurrentTrackWidth()
{ {
return m_TrackWidthList[m_TrackWidthSelector]; return m_TrackWidthList[m_TrackWidthSelector];
} }
@ -718,7 +871,7 @@ public:
* ( using the default netclass value or a preset value ) * ( using the default netclass value or a preset value )
* the default netclass is always in m_TrackWidthList[0] * the default netclass is always in m_TrackWidthList[0]
*/ */
int GetCurrentViaSize() int GetCurrentViaSize()
{ {
return m_ViasDimensionsList[m_ViaSizeSelector].m_Diameter; return m_ViasDimensionsList[m_ViaSizeSelector].m_Diameter;
} }
@ -742,14 +895,14 @@ public:
* @return the current micro via size, * @return the current micro via size,
* that is the current netclass value * that is the current netclass value
*/ */
int GetCurrentMicroViaSize(); int GetCurrentMicroViaSize();
/** /**
* Function GetCurrentMicroViaDrill * Function GetCurrentMicroViaDrill
* @return the current micro via drill, * @return the current micro via drill,
* that is the current netclass value * that is the current netclass value
*/ */
int GetCurrentMicroViaDrill(); int GetCurrentMicroViaDrill();
/***************************************************************************/ /***************************************************************************/
@ -761,7 +914,6 @@ public:
*/ */
bool Save( FILE* aFile ) const; bool Save( FILE* aFile ) const;
/** /**
* Function GetClass * Function GetClass
* returns the class name. * returns the class name.
@ -809,10 +961,10 @@ public:
* Function RedrawAreasOutlines * Function RedrawAreasOutlines
* Redraw all areas outlines on layer aLayer ( redraw all if aLayer < 0 ) * Redraw all areas outlines on layer aLayer ( redraw all if aLayer < 0 )
*/ */
void RedrawAreasOutlines( EDA_DRAW_PANEL* aPanel, void RedrawAreasOutlines( EDA_DRAW_PANEL* aPanel,
wxDC* aDC, wxDC* aDC,
int aDrawMode, int aDrawMode,
int aLayer ); int aLayer );
/** /**
* Function RedrawFilledAreas * Function RedrawFilledAreas
@ -906,7 +1058,7 @@ public:
* @param style = style of last corner * @param style = style of last corner
* @return 1 if Ok, 0 if area removed * @return 1 if Ok, 0 if area removed
*/ */
int CompleteArea( ZONE_CONTAINER* area_to_complete, int style ); int CompleteArea( ZONE_CONTAINER* area_to_complete, int style );
/** /**
* Function TestAreaPolygon * Function TestAreaPolygon
@ -919,7 +1071,7 @@ public:
* 1 if intersecting sides, but no intersecting arcs * 1 if intersecting sides, but no intersecting arcs
* Also sets utility2 flag of area with return value * Also sets utility2 flag of area with return value
*/ */
int TestAreaPolygon( ZONE_CONTAINER* CurrArea ); int TestAreaPolygon( ZONE_CONTAINER* CurrArea );
/** /**
* Function ClipAreaPolygon * Function ClipAreaPolygon
@ -937,11 +1089,11 @@ public:
* 1 if intersecting sides * 1 if intersecting sides
* Also sets areas->utility1 flags if areas are modified * Also sets areas->utility1 flags if areas are modified
*/ */
int ClipAreaPolygon( PICKED_ITEMS_LIST* aNewZonesList, int ClipAreaPolygon( PICKED_ITEMS_LIST* aNewZonesList,
ZONE_CONTAINER* aCurrArea, ZONE_CONTAINER* aCurrArea,
bool bMessageBoxArc, bool bMessageBoxArc,
bool bMessageBoxInt, bool bMessageBoxInt,
bool bRetainArcs = true ); bool bRetainArcs = true );
/** /**
* Process an area that has been modified, by clipping its polygon against * Process an area that has been modified, by clipping its polygon against
@ -965,8 +1117,8 @@ public:
/** /**
* Function CombineAllAreasInNet * Function CombineAllAreasInNet
* Checks all copper areas in net for intersections, combining them if found * Checks all copper areas in net for intersections, combining them if found
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in
* can be NULL * undo commands can be NULL
* @param aNetCode = net to consider * @param aNetCode = net to consider
* @param bMessageBox : if true display warning message box * @param bMessageBox : if true display warning message box
* @param bUseUtility : if true, don't check areas if both utility flags are 0 * @param bUseUtility : if true, don't check areas if both utility flags are 0
@ -981,8 +1133,8 @@ public:
/** /**
* Function RemoveArea * Function RemoveArea
* remove copper area from net, and put it in a deleted list (if exists) * remove copper area from net, and put it in a deleted list (if exists)
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in
* can be NULL * undo commands can be NULL
* @param area_to_remove = area to delete or put in deleted list * @param area_to_remove = area to delete or put in deleted list
*/ */
void RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove ); void RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove );
@ -1004,13 +1156,13 @@ public:
* 1 if intersection * 1 if intersection
* 2 if arcs intersect * 2 if arcs intersect
*/ */
int TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test ); int TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test );
/** /**
* Function CombineAreas * Function CombineAreas
* If possible, combine 2 copper areas * If possible, combine 2 copper areas
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in
* can be NULL * undo commands can be NULL
* @param area_ref = the main area (zone) * @param area_ref = the main area (zone)
* @param area_to_combine = the zone that can be merged with area_ref * @param area_to_combine = the zone that can be merged with area_ref
* area_ref must be BEFORE area_to_combine * area_ref must be BEFORE area_to_combine
@ -1019,9 +1171,9 @@ public:
* 1 if intersection * 1 if intersection
* 2 if arcs intersect * 2 if arcs intersect
*/ */
int CombineAreas( PICKED_ITEMS_LIST* aDeletedList, int CombineAreas( PICKED_ITEMS_LIST* aDeletedList,
ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ref,
ZONE_CONTAINER* area_to_combine ); ZONE_CONTAINER* area_to_combine );
/** /**
* Function Test_Drc_Areas_Outlines_To_Areas_Outlines * Function Test_Drc_Areas_Outlines_To_Areas_Outlines
@ -1034,8 +1186,8 @@ public:
* @param aCreate_Markers: if true create DRC markers. False: do not creates anything * @param aCreate_Markers: if true create DRC markers. False: do not creates anything
* @return errors count * @return errors count
*/ */
int Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine, int Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine,
bool aCreate_Markers ); bool aCreate_Markers );
/****** function relative to ratsnest calculations: */ /****** function relative to ratsnest calculations: */
@ -1045,6 +1197,29 @@ public:
* @param aNetcode = netcode to analyze. if -1, analyze all nets * @param aNetcode = netcode to analyze. if -1, analyze all nets
*/ */
void Test_Connections_To_Copper_Areas( int aNetcode = -1 ); void Test_Connections_To_Copper_Areas( int aNetcode = -1 );
/**
* Function MarkTrace
* marks a chain of track segments connected to aTrace.
* Each segment is marked by setting the BUSY bit into m_Flags. Electrical
* continuity is detected by walking each segment, and finally the segments
* are rearranged into a contiguous chain within the given list.
*
* @param aTrace The trace segment to test for connections.
* @param aCount A pointer to an integer where to return the number of interesting
* segments.
* @param aLength A pointer to an integer where to return the length of the track
* @param aLengthDie A pointer to an integer where to return the extra lengths
* inside integrated circuits from the pads connected to this
* track to the die (if any)
* @param aReorder True to reorder the interesting segments (useful for track
* edition or deletion) in this case the flag BUSY is set (the
* user is responsible for flag clearing). False for no reorder:
* useful when we want just calculate the track length in this
* case, flags are reset
* @return A point to a TRACK object that is the first in the chain of interesting segments.
*/
TRACK* MarkTrace( TRACK* aTrace, int* aCount, int* aLength, int* aLengthDie, bool aReorder );
}; };
#endif // #ifndef CLASS_BOARD_H #endif // #ifndef CLASS_BOARD_H

View File

@ -819,6 +819,22 @@ D_PAD* MODULE::FindPadByName( const wxString& aPadName ) const
} }
D_PAD* MODULE::GetPad( const wxPoint& aPosition, int aLayerMask )
{
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
{
/* ... and on the correct layer. */
if( ( pad->m_layerMask & aLayerMask ) == 0 )
continue;
if( pad->HitTest( aPosition ) )
return pad;
}
return NULL;
}
// see class_module.h // see class_module.h
SEARCH_RESULT MODULE::Visit( INSPECTOR* inspector, const void* testData, SEARCH_RESULT MODULE::Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] ) const KICAD_T scanTypes[] )

View File

@ -298,6 +298,16 @@ public:
D_PAD* FindPadByName( const wxString& aPadName ) const; D_PAD* FindPadByName( const wxString& aPadName ) const;
/**
* Function GetPad
* return a pad at \a aPosition on \a aLayerMask
*
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayerMask A layer or layers to mask the hit test.
* @return A pointer to a D_PAD object if found or NULL if not found.
*/
D_PAD* GetPad( const wxPoint& aPosition, int aLayerMask = ALL_LAYERS );
/** /**
* Function Visit * Function Visit
* should be re-implemented for each derived class in order to handle * should be re-implemented for each derived class in order to handle

View File

@ -152,14 +152,15 @@ TRACK::TRACK( const TRACK& Source ) :
} }
/* Because of the way SEGVIA and SEGZONE are derived from TRACK and because there are
* virtual functions being used, we can no longer simply copy a TRACK and
* expect it to be a via or zone. We must construct a true SEGVIA or SEGZONE so its constructor
* can initialize the virtual function table properly. This factory type of
* function called Copy() can duplicate either a TRACK, SEGVIA, or SEGZONE.
*/
TRACK* TRACK::Copy() const TRACK* TRACK::Copy() const
{ {
/* Because of the way SEGVIA and SEGZONE are derived from TRACK and because
* there are virtual functions being used, we can no longer simply copy a
* TRACK and expect it to be a via or zone. We must construct a true SEGVIA
* or SEGZONE so its constructor can initialize the virtual function table
* properly. This factory type of function called Copy() can duplicate either
* a TRACK, SEGVIA, or SEGZONE.
*/
if( Type() == TYPE_TRACK ) if( Type() == TYPE_TRACK )
return new TRACK( *this ); return new TRACK( *this );
@ -173,30 +174,14 @@ TRACK* TRACK::Copy() const
} }
/**
* Function GetClearance (virtual)
* returns the clearance in internal units. If \a aItem is not NULL then the
* returned clearance is the greater of this object's clearance and
* aItem's clearance. If \a aItem is NULL, then this objects
* clearance
* is returned.
* @param aItem is another BOARD_CONNECTED_ITEM or NULL
* @return int - the clearance in internal units.
*/
int TRACK::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const int TRACK::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
{ {
// Currently tracks have no specific clearance parameter // Currently tracks have no specific clearance parameter on a per track or per
// on a per track or per segment basis. // segment basis. The NETCLASS clearance is used
// the NETCLASS clearance is used
return BOARD_CONNECTED_ITEM::GetClearance( aItem ); return BOARD_CONNECTED_ITEM::GetClearance( aItem );
} }
/**
* Function GetDrillValue
* calculate the drill value for vias (m_Drill if > 0, or default drill value for the Netclass
* @return real drill_value
*/
int TRACK::GetDrillValue() const int TRACK::GetDrillValue() const
{ {
if( Type() != TYPE_VIA ) if( Type() != TYPE_VIA )
@ -215,7 +200,6 @@ int TRACK::GetDrillValue() const
} }
// return true if segment length = 0
bool TRACK::IsNull() bool TRACK::IsNull()
{ {
if( ( Type() != TYPE_VIA ) && ( m_Start == m_End ) ) if( ( Type() != TYPE_VIA ) && ( m_Start == m_End ) )
@ -225,24 +209,17 @@ bool TRACK::IsNull()
} }
/* Return: int TRACK::IsPointOnEnds( const wxPoint& aPosition, int aDistance )
* STARTPOINT if point if near (dist = min_dist) star point
* ENDPOINT if point if near (dist = min_dist) end point
* STARTPOINT|ENDPOINT if point if near (dist = min_dist) both ends
* 0 if no
* if min_dist < 0: min_dist = track_width/2
*/
int TRACK::IsPointOnEnds( const wxPoint& point, int min_dist )
{ {
int result = 0; int result = 0;
if( min_dist < 0 ) if( aDistance < 0 )
min_dist = m_Width / 2; aDistance = m_Width / 2;
int dx = m_Start.x - point.x; int dx = m_Start.x - aPosition.x;
int dy = m_Start.y - point.y; int dy = m_Start.y - aPosition.y;
if( min_dist == 0 ) if( aDistance == 0 )
{ {
if( (dx == 0) && (dy == 0 ) ) if( (dx == 0) && (dy == 0 ) )
result |= STARTPOINT; result |= STARTPOINT;
@ -251,14 +228,14 @@ int TRACK::IsPointOnEnds( const wxPoint& point, int min_dist )
{ {
double dist = hypot( (double)dx, (double) dy ); double dist = hypot( (double)dx, (double) dy );
if( min_dist >= (int) dist ) if( aDistance >= (int) dist )
result |= STARTPOINT; result |= STARTPOINT;
} }
dx = m_End.x - point.x; dx = m_End.x - aPosition.x;
dy = m_End.y - point.y; dy = m_End.y - aPosition.y;
if( min_dist == 0 ) if( aDistance == 0 )
{ {
if( (dx == 0) && (dy == 0 ) ) if( (dx == 0) && (dy == 0 ) )
result |= ENDPOINT; result |= ENDPOINT;
@ -267,7 +244,7 @@ int TRACK::IsPointOnEnds( const wxPoint& point, int min_dist )
{ {
double dist = hypot( (double) dx, (double) dy ); double dist = hypot( (double) dx, (double) dy );
if( min_dist >= (int) dist ) if( aDistance >= (int) dist )
result |= ENDPOINT; result |= ENDPOINT;
} }
@ -331,12 +308,6 @@ EDA_RECT TRACK::GetBoundingBox() const
} }
/**
* Function Rotate
* Rotate this object.
* @param aRotCentre - the rotation point.
* @param aAngle - the rotation angle in 0.1 degree.
*/
void TRACK::Rotate( const wxPoint& aRotCentre, int aAngle ) void TRACK::Rotate( const wxPoint& aRotCentre, int aAngle )
{ {
RotatePoint( &m_Start, aRotCentre, aAngle ); RotatePoint( &m_Start, aRotCentre, aAngle );
@ -344,29 +315,18 @@ void TRACK::Rotate( const wxPoint& aRotCentre, int aAngle )
} }
/**
* Function Flip
* Flip this object, i.e. change the board side for this object
* @param aCentre - the rotation point.
*/
void TRACK::Flip( const wxPoint& aCentre ) void TRACK::Flip( const wxPoint& aCentre )
{ {
m_Start.y = aCentre.y - (m_Start.y - aCentre.y); m_Start.y = aCentre.y - (m_Start.y - aCentre.y);
m_End.y = aCentre.y - (m_End.y - aCentre.y); m_End.y = aCentre.y - (m_End.y - aCentre.y);
if( Type() == TYPE_VIA ) if( Type() != TYPE_VIA )
{
// Huh? Wouldn't it be better to us Type() != VIA and get rid of these brackets?
}
else
{ {
SetLayer( ChangeSideNumLayer( GetLayer() ) ); SetLayer( ChangeSideNumLayer( GetLayer() ) );
} }
} }
// see class_track.h
// SEGVIA and SEGZONE inherit this version
SEARCH_RESULT TRACK::Visit( INSPECTOR* inspector, const void* testData, SEARCH_RESULT TRACK::Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] ) const KICAD_T scanTypes[] )
{ {
@ -400,9 +360,6 @@ bool SEGVIA::IsOnLayer( int layer_number ) const
} }
/* Return the mask layer for this.
* for a via, there is more than one layer used
*/
int TRACK::ReturnMaskLayer() int TRACK::ReturnMaskLayer()
{ {
if( Type() == TYPE_VIA ) if( Type() == TYPE_VIA )
@ -435,14 +392,6 @@ int TRACK::ReturnMaskLayer()
} }
/** Set the .m_Layer member param:
* For a via m_Layer contains the 2 layers :
* top layer and bottom layer used by the via.
* The via connect all layers from top layer to bottom layer
* 4 bits for the first layer and 4 next bits for the secaon layer
* @param top_layer = first layer connected by the via
* @param bottom_layer = last layer connected by the via
*/
void SEGVIA::SetLayerPair( int top_layer, int bottom_layer ) void SEGVIA::SetLayerPair( int top_layer, int bottom_layer )
{ {
if( Shape() == VIA_THROUGH ) if( Shape() == VIA_THROUGH )
@ -458,13 +407,6 @@ void SEGVIA::SetLayerPair( int top_layer, int bottom_layer )
} }
/**
* Function ReturnLayerPair
* Return the 2 layers used by the via (the via actually uses
* all layers between these 2 layers)
* @param top_layer = pointer to the first layer (can be null)
* @param bottom_layer = pointer to the last layer (can be null)
*/
void SEGVIA::ReturnLayerPair( int* top_layer, int* bottom_layer ) const void SEGVIA::ReturnLayerPair( int* top_layer, int* bottom_layer ) const
{ {
int b_layer = LAYER_N_BACK; int b_layer = LAYER_N_BACK;
@ -506,9 +448,6 @@ TRACK* TRACK::GetBestInsertPoint( BOARD* aPcb )
} }
/* Search (within the track linked list) the first segment matching the netcode
* ( the linked list is always sorted by net codes )
*/
TRACK* TRACK::GetStartNetCode( int NetCode ) TRACK* TRACK::GetStartNetCode( int NetCode )
{ {
TRACK* Track = this; TRACK* Track = this;
@ -538,9 +477,6 @@ TRACK* TRACK::GetStartNetCode( int NetCode )
} }
/* Search (within the track linked list) the last segment matching the netcode
* ( the linked list is always sorted by net codes )
*/
TRACK* TRACK::GetEndNetCode( int NetCode ) TRACK* TRACK::GetEndNetCode( int NetCode )
{ {
TRACK* NextS, * Track = this; TRACK* NextS, * Track = this;
@ -760,6 +696,226 @@ void TRACK::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint&
} }
int TRACK::GetEndSegments( int aCount, TRACK** aStartTrack, TRACK** aEndTrack )
{
TRACK* Track, * via, * segm, * TrackListEnd;
int NbEnds, layerMask, ii, ok = 0;
if( aCount <= 1 )
{
*aStartTrack = *aEndTrack = this;
return 1;
}
/* Calculation of the limit analysis. */
*aStartTrack = *aEndTrack = NULL;
TrackListEnd = Track = this;
ii = 0;
for( ; ( Track != NULL ) && ( ii < aCount ); ii++, Track = Track->Next() )
{
TrackListEnd = Track;
Track->m_Param = 0;
}
/* Calculate the extremes. */
NbEnds = 0;
Track = this;
ii = 0;
for( ; ( Track != NULL ) && ( ii < aCount ); ii++, Track = Track->Next() )
{
if( Track->Type() == TYPE_VIA )
continue;
layerMask = Track->ReturnMaskLayer();
via = GetVia( TrackListEnd, Track->m_Start, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTraceByEndPoint( this, TrackListEnd, Track->m_Start, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
*aStartTrack = Track; NbEnds++;
break;
case 1:
int BeginPad, EndPad;
*aEndTrack = Track;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
ok = 1;
return ok;
}
}
layerMask = Track->ReturnMaskLayer();
via = GetVia( TrackListEnd, Track->m_End, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTraceByEndPoint( this, TrackListEnd, Track->m_End, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
int BeginPad, EndPad;
*aStartTrack = Track;
NbEnds++;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
break;
case 1:
*aEndTrack = Track;
ok = 1;
return ok;
}
}
}
return ok;
}
TRACK* TRACK::GetTrace( const wxPoint& aPosition, int aLayer )
{
for( TRACK* track = this; track; track = track->Next() )
{
int layer = track->GetLayer();
if( track->GetState( BUSY | IS_DELETED ) )
{
// D( printf( "track %p is BUSY | IS_DELETED. BUSY=%d IS_DELETED=%d\n",
// track, track->GetState( BUSY ),
// track->GetState( IS_DELETED ) );)
continue;
}
if( GetBoard()->GetBoardDesignSettings()->IsLayerVisible( layer ) == false )
continue;
if( track->Type() == TYPE_VIA ) /* VIA encountered. */
{
if( track->HitTest( aPosition ) )
return track;
}
else
{
if( (g_TabOneLayerMask[layer] & aLayer) == 0 )
continue; /* Segments on different layers. */
if( track->HitTest( aPosition ) )
return track;
}
}
return NULL;
}
TRACK* TRACK::GetVia( const wxPoint& aPosition, int aLayer )
{
TRACK* track;
for( track = this; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA )
continue;
if( !track->HitTest( aPosition ) )
continue;
if( track->GetState( BUSY | IS_DELETED ) )
continue;
if( aLayer < 0 )
break;
if( track->IsOnLayer( aLayer ) )
break;
}
return track;
}
TRACK* TRACK::GetVia( TRACK* aEndTrace, const wxPoint& aPosition, int aLayer )
{
TRACK* trace;
for( trace = this; trace != NULL; trace = trace->Next() )
{
if( trace->Type() == TYPE_VIA )
{
if( aPosition == trace->m_Start )
{
if( trace->GetState( BUSY | IS_DELETED ) == 0 )
{
if( aLayer & trace->ReturnMaskLayer() )
return trace;
}
}
}
if( trace == aEndTrace )
break;
}
return NULL;
}
void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint& aOffset ) void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint& aOffset )
{ {
int color; int color;
@ -830,17 +986,19 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint
else else
{ {
GRCircle( &panel->m_ClipBox, DC, m_Start + aOffset,radius, 0, color ); GRCircle( &panel->m_ClipBox, DC, m_Start + aOffset,radius, 0, color );
if ( fast_draw ) if ( fast_draw )
return; return;
GRCircle( &panel->m_ClipBox, DC, m_Start + aOffset, inner_radius, 0, color ); GRCircle( &panel->m_ClipBox, DC, m_Start + aOffset, inner_radius, 0, color );
} }
// Draw the via hole if the display option allows it // Draw the via hole if the display option allows it
if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW ) if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW )
{ {
if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW) // Display all drill holes requested if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW) // Display all drill holes requested
|| ( (drill_radius > 0 ) && !IsDrillDefault() ) ) // Or Display non default holes requested || ( (drill_radius > 0 ) && !IsDrillDefault() ) ) // Or Display non default holes
{ { // requested.
if( fillvia ) if( fillvia )
{ {
bool blackpenstate = false; bool blackpenstate = false;
@ -977,7 +1135,6 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint
} }
// see class_track.h
void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame ) void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame )
{ {
wxString msg; wxString msg;
@ -991,7 +1148,7 @@ void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame )
{ {
int trackLen = 0; int trackLen = 0;
int lenDie = 0; int lenDie = 0;
MarkTrace( board, this, NULL, &trackLen, &lenDie, false ); board->MarkTrace( this, NULL, &trackLen, &lenDie, false );
msg = frame->CoordinateToString( trackLen ); msg = frame->CoordinateToString( trackLen );
frame->AppendMsgPanel( _( "Track Len" ), msg, DARKCYAN ); frame->AppendMsgPanel( _( "Track Len" ), msg, DARKCYAN );
@ -1026,13 +1183,6 @@ void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame )
} }
/*
* Function DisplayInfoBase
* has knowledge about the frame and how and where to put status information
* about this object into the frame's message panel.
* Display info about the track segment only, and does not calculate the full track length
* @param frame A EDA_DRAW_FRAME in which to print status information.
*/
void TRACK::DisplayInfoBase( EDA_DRAW_FRAME* frame ) void TRACK::DisplayInfoBase( EDA_DRAW_FRAME* frame )
{ {
wxString msg; wxString msg;
@ -1148,12 +1298,6 @@ void TRACK::DisplayInfoBase( EDA_DRAW_FRAME* frame )
} }
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool TRACK::HitTest( const wxPoint& refPos ) bool TRACK::HitTest( const wxPoint& refPos )
{ {
int radius = m_Width >> 1; int radius = m_Width >> 1;
@ -1180,13 +1324,6 @@ bool TRACK::HitTest( const wxPoint& refPos )
} }
/**
* Function HitTest (overlaid)
* tests if the given EDA_RECT intersect this object.
* For now, an ending point must be inside this rect.
* @param refArea an EDA_RECT to test
* @return bool - true if a hit, else false
*/
bool TRACK::HitTest( EDA_RECT& refArea ) bool TRACK::HitTest( EDA_RECT& refArea )
{ {
if( refArea.Contains( m_Start ) ) if( refArea.Contains( m_Start ) )
@ -1231,13 +1368,6 @@ wxString TRACK::GetSelectMenuText() const
#if defined(DEBUG) #if defined(DEBUG)
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void TRACK::Show( int nestLevel, std::ostream& os ) void TRACK::Show( int nestLevel, std::ostream& os )
{ {
NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
@ -1258,13 +1388,6 @@ void TRACK::Show( int nestLevel, std::ostream& os )
} }
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void SEGVIA::Show( int nestLevel, std::ostream& os ) void SEGVIA::Show( int nestLevel, std::ostream& os )
{ {
const char* cp; const char* cp;

View File

@ -1,6 +1,7 @@
/*******************************************************************/ /**
/* class_track.h: definitions relatives to tracks, vias and zones */ * @file class_track.h
/*******************************************************************/ * @brief Class definitions for tracks, vias, and zones.
*/
#ifndef CLASS_TRACK_H #ifndef CLASS_TRACK_H
#define CLASS_TRACK_H #define CLASS_TRACK_H
@ -16,6 +17,9 @@
* to the near neighbor internal layer */ * to the near neighbor internal layer */
#define VIA_NOT_DEFINED 0 /* not yet used */ #define VIA_NOT_DEFINED 0 /* not yet used */
#define IGNORE_LAYERS -1
/***/ /***/
class TRACK : public BOARD_CONNECTED_ITEM class TRACK : public BOARD_CONNECTED_ITEM
@ -105,7 +109,7 @@ public:
* @param aFile The FILE to write to. * @param aFile The FILE to write to.
* @return bool - true if success writing else false. * @return bool - true if success writing else false.
*/ */
bool Save( FILE* aFile ) const; bool Save( FILE* aFile ) const;
/** /**
* Function GetBestInsertPoint * Function GetBestInsertPoint
@ -115,24 +119,24 @@ public:
* @param aPcb The BOARD to search for the insertion point. * @param aPcb The BOARD to search for the insertion point.
* @return TRACK* - the item found in the linked list (or NULL if no track) * @return TRACK* - the item found in the linked list (or NULL if no track)
*/ */
TRACK* GetBestInsertPoint( BOARD* aPcb ); TRACK* GetBestInsertPoint( BOARD* aPcb );
/* Search (within the track linked list) the first segment matching the netcode /* Search (within the track linked list) the first segment matching the netcode
* ( the linked list is always sorted by net codes ) * ( the linked list is always sorted by net codes )
*/ */
TRACK* GetStartNetCode( int NetCode ); TRACK* GetStartNetCode( int NetCode );
/* Search (within the track linked list) the last segment matching the netcode /* Search (within the track linked list) the last segment matching the netcode
* ( the linked list is always sorted by net codes ) * ( the linked list is always sorted by net codes )
*/ */
TRACK* GetEndNetCode( int NetCode ); TRACK* GetEndNetCode( int NetCode );
/** /**
* Function GetLength * Function GetLength
* returns the length of the track using the hypotenuse calculation. * returns the length of the track using the hypotenuse calculation.
* @return double - the length of the track * @return double - the length of the track
*/ */
double GetLength() const double GetLength() const
{ {
int dx = m_Start.x - m_End.x; int dx = m_Start.x - m_End.x;
int dy = m_Start.y - m_End.y; int dy = m_Start.y - m_End.y;
@ -141,9 +145,53 @@ public:
} }
/**
* Function GetEndSegments
* get the end points connected to the track.
*
* @param aCount The maximum number of connected segments to test.
* @param aStartTrack The beginning segment connected to the trace.
* @param aEndTrack The end segment connected to the trace.
* @return A 1 if the end points are valid or a 0 when a trace is a closed loop.
*/
int GetEndSegments( int aCount, TRACK** aStartTrack, TRACK** aEndTrack );
/**
* Function GetTrace
* returns a trace segment or via at \a aPosition on \a aLayer starting from this
* trace.
*
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to search. Use -1 for a don't care.
* @return A pointer to the TRACK or SEGVIA object if found, else NULL.
*/
TRACK* GetTrace( const wxPoint& aPosition, int aLayer );
/**
* Function GetVia
* finds the first SEGVIA object at \a aPosition on \a aLayer starting at the trace.
*
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to match, pass -1 for a don't care.
* @return A pointer to a TRACK object ( actually a SEGVIA ) if found, else NULL.
*/
TRACK* GetVia( const wxPoint& aPosition, int aLayer = IGNORE_LAYERS );
/**
* Function GetVia
* finds the first SEGVIA object at \a aPosition on \a aLayer starting at the trace
* and ending at \a aEndTrace.
*
* @param aEndTrace Pointer to the last TRACK object to end search.
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to match, pass -1 for a don't care.
* @return A pointer to a TRACK object ( actually a SEGVIA ) if found, else NULL.
*/
TRACK* GetVia( TRACK* aEndTrace, const wxPoint& aPosition, int aLayer );
/* Display on screen: */ /* Display on screen: */
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode,
const wxPoint& aOffset = ZeroOffset ); const wxPoint& aOffset = ZeroOffset );
/* divers */ /* divers */
int Shape() const { return m_Shape & 0xFF; } int Shape() const { return m_Shape & 0xFF; }
@ -196,15 +244,20 @@ public:
* TRACK segment or SEGVIA physically resides. * TRACK segment or SEGVIA physically resides.
* @return int - a layer mask, see pcbstruct.h's LAYER_BACK, etc. * @return int - a layer mask, see pcbstruct.h's LAYER_BACK, etc.
*/ */
int ReturnMaskLayer(); int ReturnMaskLayer();
int IsPointOnEnds( const wxPoint& point, int min_dist = 0 ); /**
* Function IsPointOnEnds
* returns #STARTPOINT or #ENDPOINT if the start or end point is within \a aDistance
* of \a aPosition otherwise 0 is returned.
*/
int IsPointOnEnds( const wxPoint& aPosition, int aDistance = 0 );
/** /**
* Function IsNull * Function IsNull
* returns true if segment length is zero. * returns true if segment length is zero.
*/ */
bool IsNull(); bool IsNull();
/** /**
* Function DisplayInfo * Function DisplayInfo
@ -214,7 +267,7 @@ public:
* Display info about the track segment and the full track length * Display info about the track segment and the full track length
* @param frame A EDA_DRAW_FRAME in which to print status information. * @param frame A EDA_DRAW_FRAME in which to print status information.
*/ */
void DisplayInfo( EDA_DRAW_FRAME* frame ); void DisplayInfo( EDA_DRAW_FRAME* frame );
/** /**
* Function DisplayInfoBase * Function DisplayInfoBase
@ -223,13 +276,13 @@ public:
* Display info about the track segment only, and does not calculate the full track length * Display info about the track segment only, and does not calculate the full track length
* @param frame A EDA_DRAW_FRAME in which to print status information. * @param frame A EDA_DRAW_FRAME in which to print status information.
*/ */
void DisplayInfoBase( EDA_DRAW_FRAME* frame ); void DisplayInfoBase( EDA_DRAW_FRAME* frame );
/** /**
* Function ShowWidth * Function ShowWidth
* returns the width of the track in displayable user units. * returns the width of the track in displayable user units.
*/ */
wxString ShowWidth() const; wxString ShowWidth() const;
/** /**
* Function Visit * Function Visit
@ -244,8 +297,8 @@ public:
* @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan, * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
* else SCAN_CONTINUE, and determined by the inspector. * else SCAN_CONTINUE, and determined by the inspector.
*/ */
SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] ); const KICAD_T scanTypes[] );
/** /**
@ -254,7 +307,7 @@ public:
* @param refPos A wxPoint to test * @param refPos A wxPoint to test
* @return bool - true if a hit, else false * @return bool - true if a hit, else false
*/ */
bool HitTest( const wxPoint& refPos ); bool HitTest( const wxPoint& refPos );
/** /**
* Function HitTest (overlaid) * Function HitTest (overlaid)
@ -263,7 +316,7 @@ public:
* @param refArea an EDA_RECT to test * @param refArea an EDA_RECT to test
* @return bool - true if a hit, else false * @return bool - true if a hit, else false
*/ */
bool HitTest( EDA_RECT& refArea ); bool HitTest( EDA_RECT& refArea );
/** /**
* Function GetClass * Function GetClass
@ -348,9 +401,8 @@ public:
} }
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode,
const wxPoint& aOffset = ZeroOffset ); const wxPoint& aOffset = ZeroOffset );
/** /**
* Function IsOnLayer * Function IsOnLayer
@ -359,10 +411,28 @@ public:
* @param aLayer the layer to test for. * @param aLayer the layer to test for.
* @return bool - true if on given layer, else false. * @return bool - true if on given layer, else false.
*/ */
bool IsOnLayer( int aLayer ) const; bool IsOnLayer( int aLayer ) const;
void SetLayerPair( int top_layer, int bottom_layer ); /**
void ReturnLayerPair( int* top_layer, int* bottom_layer ) const; * Function SetLayerPair
* set the .m_Layer member for a via m_Layer contains the 2 layers :
* top layer and bottom layer used by the via.
* The via connect all layers from top layer to bottom layer
* 4 bits for the first layer and 4 next bits for the second layer
* @param top_layer = first layer connected by the via
* @param bottom_layer = last layer connected by the via
*/
void SetLayerPair( int top_layer, int bottom_layer );
/**
* Function ReturnLayerPair
* return the 2 layers used by the via (the via actually uses all layers between
* these 2 layers)
*
* @param top_layer = pointer to the first layer (can be null)
* @param bottom_layer = pointer to the last layer (can be null)
*/
void ReturnLayerPair( int* top_layer, int* bottom_layer ) const;
/** /**
* Function GetPosition * Function GetPosition
@ -375,7 +445,7 @@ public:
} }
void SetPosition( const wxPoint& aPoint ) { m_Start = aPoint; m_End = aPoint; } void SetPosition( const wxPoint& aPoint ) { m_Start = aPoint; m_End = aPoint; }
/** /**
* Function GetClass * Function GetClass

View File

@ -857,43 +857,26 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& refPos )
} }
/** bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& aPosition, int aMinDistance )
* Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* Choose the nearest corner
* "near" means grid size (or CORNER_MIN_DIST if grid is not known)
* Set m_CornerSelection to corner index in .m_Poly-&gtcorner or -1 if no corner found
* @return true if a corner found
* @param refPos : A wxPoint to test
*/
bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
{ {
m_CornerSelection = -1; // Set to not found m_CornerSelection = -1; // Set to not found
#define CORNER_MIN_DIST 100 // distance (in internal units) to detect a corner in a zone outline int x, y;
int min_dist = CORNER_MIN_DIST + 1; int closestDistance = aMinDistance;
if( GetBoard() && GetBoard()->m_PcbFrame )
{
// Use grid size because it is known
wxRealPoint grid = GetBoard()->m_PcbFrame->DrawPanel->GetGrid();
min_dist = wxRound( MIN( grid.x, grid.y ) );
}
wxPoint delta;
unsigned lim = m_Poly->corner.size(); unsigned lim = m_Poly->corner.size();
for( unsigned item_pos = 0; item_pos < lim; item_pos++ ) for( unsigned item_pos = 0; item_pos < lim; item_pos++ )
{ {
delta.x = refPos.x - m_Poly->corner[item_pos].x; x = aPosition.x - m_Poly->corner[item_pos].x;
delta.y = refPos.y - m_Poly->corner[item_pos].y; y = aPosition.y - m_Poly->corner[item_pos].y;
// Calculate a distance:
int dist = MAX( abs( delta.x ), abs( delta.y ) );
if( dist < min_dist ) // this corner is a candidate: // Calculate a distance:
int dist = MAX( abs( x ), abs( y ) );
if( dist < closestDistance ) // this corner is a candidate:
{ {
m_CornerSelection = item_pos; m_CornerSelection = item_pos;
min_dist = dist; closestDistance = dist;
} }
} }
@ -901,31 +884,13 @@ bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
} }
/** bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& aPosition, int aMinDistance )
* Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* choose the nearest segment
* "near" means grid size (or EDGE_MIN_DIST if grid is not known)
* Set m_CornerSelection to -1 if nothing found, or index of the starting corner of edge
* in .m_Poly-&gtcorner
* @return true if found
* @param refPos : A wxPoint to test
*/
bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
{ {
unsigned lim = m_Poly->corner.size(); unsigned lim = m_Poly->corner.size();
m_CornerSelection = -1; // Set to not found m_CornerSelection = -1; // Set to not found
#define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline int closestDistance = aMinDistance;
int min_dist = EDGE_MIN_DIST+1;
if( GetBoard() && GetBoard()->m_PcbFrame )
{
// Use grid size because it is known
wxRealPoint grid = GetBoard()->m_PcbFrame->DrawPanel->GetGrid();
min_dist = wxRound( MIN( grid.x, grid.y ) );
}
unsigned first_corner_pos = 0; unsigned first_corner_pos = 0;
@ -945,17 +910,17 @@ bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
} }
/* test the dist between segment and ref point */ /* test the dist between segment and ref point */
int dist = (int) GetPointToLineSegmentDistance( refPos.x, int dist = (int) GetPointToLineSegmentDistance( aPosition.x,
refPos.y, aPosition.y,
m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].x,
m_Poly->corner[item_pos].y, m_Poly->corner[item_pos].y,
m_Poly->corner[end_segm].x, m_Poly->corner[end_segm].x,
m_Poly->corner[end_segm].y ); m_Poly->corner[end_segm].y );
if( dist < min_dist ) if( dist < closestDistance )
{ {
m_CornerSelection = item_pos; m_CornerSelection = item_pos;
min_dist = dist; closestDistance = dist;
} }
} }

View File

@ -12,6 +12,10 @@
#include "class_zone_setting.h" #include "class_zone_setting.h"
#define CORNER_MIN_DIST 100 // distance (in internal units) to detect a corner in a zone outline
#define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline
/* a small class used when filling areas with segments */ /* a small class used when filling areas with segments */
class SEGMENT class SEGMENT
{ {
@ -246,21 +250,23 @@ public:
/** /**
* Function HitTestForCorner * Function HitTestForCorner
* tests if the given wxPoint near a corner * tests if \a aPosition is with \a aDistance a zone corner.
* Set m_CornerSelection to -1 if nothing found, or index of corner * Set m_CornerSelection to -1 if nothing found, or index of corner
* @return true if found * @return true if found
* @param refPos : A wxPoint to test * @param aPosition A wxPoint to test
* @param aMinDistance The minimum distance with \a aPosition that will still yield a hit.
*/ */
bool HitTestForCorner( const wxPoint& refPos ); bool HitTestForCorner( const wxPoint& aPosition, int aMinDistance = CORNER_MIN_DIST );
/** /**
* Function HitTestForEdge * Function HitTestForEdge
* tests if the given wxPoint is near a segment defined by 2 corners. * tests if the given wxPoint is near a segment defined by 2 corners.
* Set m_CornerSelection to -1 if nothing found, or index of the starting corner of vertice * Set m_CornerSelection to -1 if nothing found, or index of the starting corner of vertice
* @return true if found * @return true if found
* @param refPos : A wxPoint to test * @param aPosition A wxPoint to test
* @param aMinDistance The minimum distance with \a aPosition that will still yield a hit.
*/ */
bool HitTestForEdge( const wxPoint& refPos ); bool HitTestForEdge( const wxPoint& aPosition, int aMinDistance = EDGE_MIN_DIST );
/** /**
* Function HitTest (overlayed) * Function HitTest (overlayed)

View File

@ -153,7 +153,7 @@ void clean_vias( BOARD * aPcb )
if( track->m_Shape != VIA_THROUGH ) if( track->m_Shape != VIA_THROUGH )
continue; continue;
D_PAD* pad = Fast_Locate_Pad_Connecte( aPcb, track->m_Start, ALL_CU_LAYERS ); D_PAD* pad = aPcb->GetPadFast( track->m_Start, ALL_CU_LAYERS );
if( pad && (pad->m_layerMask & EXTERNAL_LAYERS) == EXTERNAL_LAYERS ) // redundant Via if( pad && (pad->m_layerMask & EXTERNAL_LAYERS) == EXTERNAL_LAYERS ) // redundant Via
{ {
@ -225,7 +225,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame, wxDC* DC )
D_PAD* pad; D_PAD* pad;
pad = Fast_Locate_Pad_Connecte( frame->GetBoard(), segment->m_Start, masklayer ); pad = frame->GetBoard()->GetPadFast( segment->m_Start, masklayer );
if( pad != NULL ) if( pad != NULL )
{ {
@ -233,7 +233,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame, wxDC* DC )
type_end |= START_ON_PAD; type_end |= START_ON_PAD;
} }
pad = Fast_Locate_Pad_Connecte( frame->GetBoard(), segment->m_End, masklayer ); pad = frame->GetBoard()->GetPadFast( segment->m_End, masklayer );
if( pad != NULL ) if( pad != NULL )
{ {
@ -601,8 +601,7 @@ static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extre
if( extremite == START ) if( extremite == START )
{ {
/* We do not have a pad */ /* We do not have a pad */
if( Fast_Locate_Pad_Connecte( Pcb, pt_ref->m_Start, if( Pcb->GetPadFast( pt_ref->m_Start, g_TabOneLayerMask[pt_ref->GetLayer()] ) )
g_TabOneLayerMask[pt_ref->GetLayer()] ) )
return NULL; return NULL;
/* change the common point coordinate of pt_segm tu use the other point /* change the common point coordinate of pt_segm tu use the other point
@ -621,8 +620,7 @@ static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extre
else /* extremite == END */ else /* extremite == END */
{ {
/* We do not have a pad */ /* We do not have a pad */
if( Fast_Locate_Pad_Connecte( Pcb, pt_ref->m_End, if( Pcb->GetPadFast( pt_ref->m_End, g_TabOneLayerMask[pt_ref->GetLayer()] ) )
g_TabOneLayerMask[pt_ref->GetLayer()] ) )
return NULL; return NULL;
/* change the common point coordinate of pt_segm tu use the other point /* change the common point coordinate of pt_segm tu use the other point
@ -782,7 +780,7 @@ static void Gen_Raccord_Track( PCB_EDIT_FRAME* frame, wxDC* DC )
{ {
TRACK* newTrack; TRACK* newTrack;
other = GetTrace( other, segment->m_Start, layerMask ); other = frame->GetBoard()->GetTrace( other, segment->m_Start, layerMask );
if( other == NULL ) if( other == NULL )
break; break;
@ -831,7 +829,7 @@ static void Gen_Raccord_Track( PCB_EDIT_FRAME* frame, wxDC* DC )
{ {
TRACK* newTrack; TRACK* newTrack;
other = GetTrace( other, segment->m_End, layerMask ); other = frame->GetBoard()->GetTrace( other, segment->m_End, layerMask );
if( other == NULL ) if( other == NULL )
break; break;
@ -980,7 +978,7 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
if( frame->DrawPanel->m_AbortRequest ) if( frame->DrawPanel->m_AbortRequest )
return; return;
pad = Locate_Pad_Connecte( frame->GetBoard(), segment, START ); pad = frame->GetBoard()->GetPad( segment, START );
if( pad ) if( pad )
{ {
@ -1004,7 +1002,7 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
} }
} }
pad = Locate_Pad_Connecte( frame->GetBoard(), segment, END ); pad = frame->GetBoard()->GetPad( segment, END );
if( pad ) if( pad )
{ {

View File

@ -562,28 +562,6 @@ static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* aPcb, LISTE_PAD* pt_liste,
} }
/**
* Function SortPadsByXCoord
* is used to Sort a pad list by x coordinate value.
*/
static int SortPadsByXCoord( const void* pt_ref, const void* pt_comp )
{
D_PAD* ref = *(LISTE_PAD*) pt_ref;
D_PAD* comp = *(LISTE_PAD*) pt_comp;
return ref->m_Pos.x - comp->m_Pos.x;
}
void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector )
{
aVector->insert( aVector->end(), aBoard->m_NetInfo->m_PadsFullList.begin(),
aBoard->m_NetInfo->m_PadsFullList.end() );
qsort( &(*aVector)[0], aBoard->GetPadsCount(), sizeof( D_PAD*), SortPadsByXCoord );
}
/* search connections between tracks and pads, and propagate pad net codes to the track segments /* search connections between tracks and pads, and propagate pad net codes to the track segments
* This is a 2 pass computation. * This is a 2 pass computation.
* First: * First:
@ -622,7 +600,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
/**************************************************************/ /**************************************************************/
/* Pass 1: search the connections between track ends and pads */ /* Pass 1: search the connections between track ends and pads */
/**************************************************************/ /**************************************************************/
CreateSortedPadListByXCoord( m_Pcb, &sortedPads ); m_Pcb->CreateSortedPadListByXCoord( &sortedPads );
/* Reset variables and flags used in computation */ /* Reset variables and flags used in computation */
pt_trace = m_Pcb->m_Track; pt_trace = m_Pcb->m_Track;

View File

@ -176,8 +176,8 @@ void PCB_EDIT_FRAME::Remove_One_Track( wxDC* DC, TRACK* pt_segm )
if( pt_segm == NULL ) if( pt_segm == NULL )
return; return;
TRACK* trackList = MarkTrace( GetBoard(), pt_segm, &segments_to_delete_count, TRACK* trackList = GetBoard()->MarkTrace( pt_segm, &segments_to_delete_count,
NULL, NULL, true ); NULL, NULL, true );
if( segments_to_delete_count == 0 ) if( segments_to_delete_count == 0 )
return; return;

View File

@ -411,7 +411,7 @@ void DRC::testPad2Pad()
{ {
std::vector<D_PAD*> sortedPads; std::vector<D_PAD*> sortedPads;
CreateSortedPadListByXCoord( m_pcb, &sortedPads ); m_pcb->CreateSortedPadListByXCoord( &sortedPads );
// find the max size of the pads (used to stop the test) // find the max size of the pads (used to stop the test)
int max_size = 0; int max_size = 0;
@ -420,7 +420,8 @@ void DRC::testPad2Pad()
{ {
D_PAD* pad = sortedPads[i]; D_PAD* pad = sortedPads[i];
if( pad->m_ShapeMaxRadius > max_size ) // m_ShapeMaxRadius is the radius value of the circle containing the pad // m_ShapeMaxRadius is the radius value of the circle containing the pad.
if( pad->m_ShapeMaxRadius > max_size )
max_size = pad->m_ShapeMaxRadius; max_size = pad->m_ShapeMaxRadius;
} }

View File

@ -1002,7 +1002,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
wxPoint pos = GetScreen()->GetCrossHairPosition(); wxPoint pos = GetScreen()->GetCrossHairPosition();
track->Draw( DrawPanel, &dc, GR_XOR ); track->Draw( DrawPanel, &dc, GR_XOR );
PICKED_ITEMS_LIST itemsListPicker; PICKED_ITEMS_LIST itemsListPicker;
TRACK* newtrack = CreateLockPoint( GetBoard(), pos, track, &itemsListPicker ); TRACK* newtrack = GetBoard()->CreateLockPoint( pos, track, &itemsListPicker );
SaveCopyInUndoList( itemsListPicker, UR_UNSPECIFIED ); SaveCopyInUndoList( itemsListPicker, UR_UNSPECIFIED );
track->Draw( DrawPanel, &dc, GR_XOR ); track->Draw( DrawPanel, &dc, GR_XOR );
newtrack->Draw( DrawPanel, &dc, GR_XOR ); newtrack->Draw( DrawPanel, &dc, GR_XOR );

View File

@ -166,7 +166,7 @@ void PCB_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment )
if( aTrackSegment == NULL ) if( aTrackSegment == NULL )
return; return;
pt_track = MarkTrace( GetBoard(), aTrackSegment, &nb_segm, NULL, NULL, true ); pt_track = GetBoard()->MarkTrace( aTrackSegment, &nb_segm, NULL, NULL, true );
PICKED_ITEMS_LIST itemsListPicker; PICKED_ITEMS_LIST itemsListPicker;
bool change = false; bool change = false;

View File

@ -33,7 +33,7 @@ void PCB_EDIT_FRAME::ExChange_Track_Layer( TRACK* pt_segm, wxDC* DC )
l1 = Route_Layer_TOP; l2 = Route_Layer_BOTTOM; l1 = Route_Layer_TOP; l2 = Route_Layer_BOTTOM;
pt_track = MarkTrace( GetBoard(), pt_segm, &nb_segm, NULL, NULL, true ); pt_track = GetBoard()->MarkTrace( pt_segm, &nb_segm, NULL, NULL, true );
if ( DC ) if ( DC )
DrawTraces( DrawPanel, DC, pt_track, nb_segm, GR_XOR ); DrawTraces( DrawPanel, DC, pt_track, nb_segm, GR_XOR );
@ -87,8 +87,8 @@ void PCB_EDIT_FRAME::ExChange_Track_Layer( TRACK* pt_segm, wxDC* DC )
for( ; ii < nb_segm; pt_segm = pt_segm->Next(), ii++ ) for( ; ii < nb_segm; pt_segm = pt_segm->Next(), ii++ )
{ {
pt_segm->start = Locate_Pad_Connecte( GetBoard(), pt_segm, START ); pt_segm->start = GetBoard()->GetPad( pt_segm, START );
pt_segm->end = Locate_Pad_Connecte( GetBoard(), pt_segm, END ); pt_segm->end = GetBoard()->GetPad( pt_segm, END );
} }
test_1_net_connexion( DC, pt_track->GetNet() ); test_1_net_connexion( DC, pt_track->GetNet() );
@ -113,7 +113,7 @@ bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC )
} }
/* Avoid more than one via on the current location: */ /* Avoid more than one via on the current location: */
if( Locate_Via( GetBoard(), g_CurrentTrackSegment->m_End, g_CurrentTrackSegment->GetLayer() ) ) if( GetBoard()->GetVia( g_CurrentTrackSegment->m_End, g_CurrentTrackSegment->GetLayer() ) )
return false; return false;
for( TRACK* segm = g_FirstTrackSegment; segm; segm = segm->Next() ) for( TRACK* segm = g_FirstTrackSegment; segm; segm = segm->Next() )
@ -277,7 +277,7 @@ void PCB_EDIT_FRAME::DisplayNetStatus( wxDC* DC )
int layerMask = (1 << getActiveLayer()); int layerMask = (1 << getActiveLayer());
wxPoint pos = GetScreen()->RefPos( true ); wxPoint pos = GetScreen()->RefPos( true );
pt_segm = GetTrace( GetBoard(), GetBoard()->m_Track, pos, layerMask ); pt_segm = GetBoard()->GetTrace( pos, layerMask );
if( pt_segm == NULL ) if( pt_segm == NULL )
GetBoard()->DisplayInfo( this ); GetBoard()->DisplayInfo( this );

View File

@ -104,7 +104,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* DC )
GetBoard()->SetHightLightNet(0); GetBoard()->SetHightLightNet(0);
// Search for a starting point of the new track, a track or pad // Search for a starting point of the new track, a track or pad
LockPoint = LocateLockPoint( GetBoard(), pos, layerMask ); LockPoint = GetBoard()->GetLockPoint( pos, layerMask );
if( LockPoint ) // An item (pad or track) is found if( LockPoint ) // An item (pad or track) is found
{ {
@ -120,7 +120,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* DC )
{ {
TrackOnStartPoint = (TRACK*) LockPoint; TrackOnStartPoint = (TRACK*) LockPoint;
GetBoard()->SetHightLightNet( TrackOnStartPoint->GetNet() ); GetBoard()->SetHightLightNet( TrackOnStartPoint->GetNet() );
CreateLockPoint( GetBoard(), pos, TrackOnStartPoint, &s_ItemsListPicker ); GetBoard()->CreateLockPoint( pos, TrackOnStartPoint, &s_ItemsListPicker );
} }
} }
else // no starting point, but a filled zone area can exist. This is else // no starting point, but a filled zone area can exist. This is
@ -247,7 +247,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* DC )
newTrack->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); newTrack->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
oneBeforeLatest->end = Locate_Pad_Connecte( GetBoard(), oneBeforeLatest, END ); oneBeforeLatest->end = GetBoard()->GetPad( oneBeforeLatest, END );
if( oneBeforeLatest->end ) if( oneBeforeLatest->end )
{ {
@ -451,7 +451,7 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* DC )
* This helps to reduce the computing time */ * This helps to reduce the computing time */
/* Attaching the end of the track. */ /* Attaching the end of the track. */
BOARD_ITEM* LockPoint = LocateLockPoint( GetBoard(), pos, layerMask ); BOARD_ITEM* LockPoint = GetBoard()->GetLockPoint( pos, layerMask );
if( LockPoint ) /* End of trace is on a pad. */ if( LockPoint ) /* End of trace is on a pad. */
{ {
@ -466,10 +466,9 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* DC )
GetBoard()->SetHightLightNet( adr_buf->GetNet() ); GetBoard()->SetHightLightNet( adr_buf->GetNet() );
/* Possible establishment of a hanging point. */ /* Possible establishment of a hanging point. */
LockPoint = CreateLockPoint( GetBoard(), LockPoint = GetBoard()->CreateLockPoint( g_CurrentTrackSegment->m_End,
g_CurrentTrackSegment->m_End, adr_buf,
adr_buf, &s_ItemsListPicker );
&s_ItemsListPicker );
} }
} }
@ -1050,7 +1049,7 @@ void DeleteNullTrackSegments( BOARD* pcb, DLIST<TRACK>& aTrackList )
while( track != NULL ) while( track != NULL )
{ {
TRACK* next_track = track->Next(); TRACK* next_track = track->Next();
LockPoint = Locate_Pad_Connecte( pcb, track, END ); LockPoint = pcb->GetPad( track, END );
if( LockPoint ) if( LockPoint )
{ {

View File

@ -555,7 +555,7 @@ void PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit
if( !itemCurrentlyEdited ) if( !itemCurrentlyEdited )
{ {
pos = screen->RefPos( true ); pos = screen->RefPos( true );
module = Locate_Prefered_Module( GetBoard(), pos, screen->m_Active_Layer, true ); module = GetBoard()->GetModule( pos, screen->m_Active_Layer, true );
} }
else if( GetCurItem()->Type() == TYPE_MODULE ) else if( GetCurItem()->Type() == TYPE_MODULE )
{ {
@ -641,7 +641,7 @@ bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC )
if( ItemFree ) if( ItemFree )
{ {
wxPoint pos = GetScreen()->RefPos( false ); wxPoint pos = GetScreen()->RefPos( false );
MODULE* module = Locate_Prefered_Module( GetBoard(), pos, ALL_LAYERS, false ); MODULE* module = GetBoard()->GetModule( pos, ALL_LAYERS, false );
if( module == NULL ) if( module == NULL )
return false; return false;
@ -659,14 +659,19 @@ bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC )
if( ItemFree ) if( ItemFree )
{ {
item = PcbGeneralLocateAndDisplay(); item = PcbGeneralLocateAndDisplay();
if( item == NULL ) if( item == NULL )
return false; return false;
if( (item->Type() == TYPE_MODULE) && !IsOK( this, _( "Delete module?" ) ) ) if( (item->Type() == TYPE_MODULE) && !IsOK( this, _( "Delete module?" ) ) )
return false; return false;
RemoveStruct( item, aDC ); RemoveStruct( item, aDC );
} }
else else
return false; {
return false;
}
} }
OnModify(); OnModify();

View File

@ -40,7 +40,7 @@ bool PCB_EDIT_FRAME::Clear_Pcb( bool aQuery )
// delete the old BOARD and create a new BOARD so that the default // delete the old BOARD and create a new BOARD so that the default
// layer names are put into the BOARD. // layer names are put into the BOARD.
SetBoard( new BOARD( NULL, this ) ); SetBoard( new BOARD( NULL ) );
SetCurItem( NULL ); SetCurItem( NULL );
/* clear filename, to avoid overwriting an old file */ /* clear filename, to avoid overwriting an old file */

View File

@ -13,246 +13,6 @@
/* Locates a via point pX, pY
* If layer < 0 will be located via whatever layer
* If layer = 0 .. 15 Via will be located according to its type:
* - Traverse: all layers
* - = Blind between layers useful
* - Blind idem
* Entry: coord point of reference, layer
* Output: NULL if not via
* (* TRACK) address via
*/
TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer )
{
TRACK* track;
for( track = Pcb->m_Track; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA )
continue;
if( track->m_Start != pos )
continue;
if( track->GetState( BUSY | IS_DELETED ) )
continue;
if( layer < 0 )
break;
if( track->IsOnLayer( layer ) )
break;
}
return track;
}
TRACK* Locate_Via_Area( TRACK* aStart, const wxPoint& pos, int layer )
{
TRACK* track;
for( track = aStart; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA )
continue;
if( !track->HitTest(pos) )
continue;
if( track->GetState( BUSY | IS_DELETED ) )
continue;
if( layer < 0 )
break;
if( track->IsOnLayer( layer ) )
break;
}
return track;
}
/* Locate the pad CONNECTED to a track
* input: ptr_trace: pointer to the segment of track
* Extr = flag = START -> beginning of the test segment
* END -> end of the segment to be tested
* Returns:
* A pointer to the description of the pad if found.
* NULL pointer if pad NOT FOUND
*/
D_PAD* Locate_Pad_Connecte( BOARD* Pcb, TRACK* ptr_trace, int extr )
{
D_PAD* ptr_pad = NULL;
wxPoint ref_pos;
int aLayerMask = g_TabOneLayerMask[ptr_trace->GetLayer()];
if( extr == START )
{
ref_pos = ptr_trace->m_Start;
}
else
{
ref_pos = ptr_trace->m_End;
}
for( MODULE* module = Pcb->m_Modules; module; module = module->Next() )
{
ptr_pad = Locate_Pads( module, ref_pos, aLayerMask );
if( ptr_pad != NULL )
break;
}
return ptr_pad;
}
/*
* Locate a pad pointed to by the coordinates ref_pos.x, ref_pos.y
* aLayerMask is allowed layers ( bitmap mask)
* Returns:
* Pointer to a pad if found or NULL
*/
D_PAD* Locate_Any_Pad( BOARD* Pcb, const wxPoint& ref_pos, int aLayerMask )
{
D_PAD* pad = NULL;
for( MODULE* module=Pcb->m_Modules; module && ( pad == NULL ); module = module->Next() )
{
if( aLayerMask )
pad = Locate_Pads( module, ref_pos, aLayerMask );
else
pad = Locate_Pads( module, ref_pos, ALL_LAYERS );
}
return pad;
}
/* Locate the pad pointed to by the coordinate ref_pos.x,, ref_pos.y
* Input:
* - the footprint to test
* - masque_layer layer(s) (bit_masque) which must be the pad
* Returns:
* A pointer to the pad if found or NULL
*/
D_PAD* Locate_Pads( MODULE* module, const wxPoint& ref_pos, int aLayerMask )
{
for( D_PAD* pt_pad = module->m_Pads; pt_pad; pt_pad = pt_pad->Next() )
{
/* ... and on the correct layer. */
if( ( pt_pad->m_layerMask & aLayerMask ) == 0 )
continue;
if( pt_pad->HitTest( ref_pos ) )
return pt_pad;
}
return NULL;
}
/**
* Function Locate_Prefered_Module
* locates a footprint by its bounding rectangle. If several footprints
* are possible, then the priority is: the closest on the active layer, then
* closest.
* The current mouse or cursor coordinates are grabbed from the active window
* to perform hit-testing.
* distance is calculated via manhattan distance from the center of the
* bounding rectangle to the cursor position.
*
* @param aPcb The BOARD to search within.
* @param aPosition Flag bits, tuning the search, see pcbnew.h
* @param aActiveLayer Layer to test.
* @param aVisibleOnly Search only the visible layers if true.
* @param aIgnoreLocked Ignore locked modules when true.
* @return MODULE* The best module or NULL if none.
*/
MODULE* Locate_Prefered_Module( BOARD* aPcb, const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked )
{
MODULE* pt_module;
MODULE* module = NULL;
MODULE* Altmodule = NULL;
int min_dim = 0x7FFFFFFF;
int alt_min_dim = 0x7FFFFFFF;
int layer;
pt_module = aPcb->m_Modules;
for( ; pt_module; pt_module = (MODULE*) pt_module->Next() )
{
// is the ref point within the module's bounds?
if( !pt_module->HitTest( aPosition ) )
continue;
// if caller wants to ignore locked modules, and this one is locked, skip it.
if( aIgnoreLocked && pt_module->IsLocked() )
continue;
/* Calculate priority: the priority is given to the layer of the
* module and the copper layer if the module layer is indelible,
* adhesive copper, a layer if cmp module layer is indelible,
* adhesive component.
*/
layer = pt_module->GetLayer();
if( layer==ADHESIVE_N_BACK || layer==SILKSCREEN_N_BACK )
layer = LAYER_N_BACK;
else if( layer==ADHESIVE_N_FRONT || layer==SILKSCREEN_N_FRONT )
layer = LAYER_N_FRONT;
/* Test of minimum size to choosing the best candidate. */
EDA_RECT bb = pt_module->GetFootPrintRect();
int offx = bb.GetX() + bb.GetWidth() / 2;
int offy = bb.GetY() + bb.GetHeight() / 2;
//off x & offy point to the middle of the box.
int dist = abs( aPosition.x - offx ) + abs( aPosition.y - offy );
//int dist = MIN(lx, ly); // to pick the smallest module (kinda
// screwy with same-sized modules -- this is bad!)
if( aActiveLayer == layer )
{
if( dist <= min_dim )
{
/* better footprint shown on the active layer */
module = pt_module;
min_dim = dist;
}
}
else if( aVisibleOnly && aPcb->IsModuleLayerVisible( layer ) )
{
if( dist <= alt_min_dim )
{
/* better footprint shown on other layers */
Altmodule = pt_module;
alt_min_dim = dist;
}
}
}
if( module )
{
return module;
}
if( Altmodule )
{
return Altmodule;
}
return NULL;
}
/* /*
* return true if the dist between p1 and p2 < max_dist * return true if the dist between p1 and p2 < max_dist
* Currently in test (currently rasnest algos work only if p1 == p2) * Currently in test (currently rasnest algos work only if p1 == p2)
@ -265,7 +25,9 @@ int dist;
dist = abs(p1.x - p2.x) + abs (p1.y - p2.y); dist = abs(p1.x - p2.x) + abs (p1.y - p2.y);
dist *= 7; dist *= 7;
dist /= 10; dist /= 10;
if ( dist < max_dist ) return true;
if ( dist < max_dist )
return true;
} }
#else #else
if ( p1 == p2 ) return true; if ( p1 == p2 ) return true;
@ -419,168 +181,3 @@ suite1:
return NULL; return NULL;
} }
/*
* 1 - Locate segment of track leading from the mouse.
* 2 - Locate segment of track point by point
* ref_pos.x, ref_pos.y.r
*
* The search begins to address start_adresse
*/
TRACK* GetTrace( BOARD* aPcb, TRACK* start_adresse, const wxPoint& ref_pos, int LayerMask )
{
for( TRACK* track = start_adresse; track; track = track->Next() )
{
int layer = track->GetLayer();
if( track->GetState( BUSY | IS_DELETED ) )
{
// D( printf( "track %p is BUSY | IS_DELETED. BUSY=%d IS_DELETED=%d\n",
// track, track->GetState( BUSY ),
// track->GetState( IS_DELETED ) );)
continue;
}
if( aPcb->GetBoardDesignSettings()->IsLayerVisible( layer ) == false )
continue;
if( track->Type() == TYPE_VIA ) /* VIA encountered. */
{
if( track->HitTest( ref_pos ) )
return track;
}
else
{
if( (g_TabOneLayerMask[layer] & LayerMask) == 0 )
continue; /* Segments on different layers. */
if( track->HitTest( ref_pos ) )
return track;
}
}
return NULL;
}
/*
* 1 - Locate zone area by the mouse.
* 2 - Locate zone area by point
* def_pos.x, ref_pos.y.r
*
* If layer == -1, tst layer is not
*
* The search begins to address start_adresse
*/
TRACK* Locate_Zone( TRACK* start_adresse, const wxPoint& ref_pos, int layer )
{
for( TRACK* Zone = start_adresse; Zone; Zone = Zone->Next() )
{
if( (layer != -1) && (Zone->GetLayer() != layer) )
continue;
if( Zone->HitTest( ref_pos ) )
return Zone;
}
return NULL;
}
/* Find the pad center px, py,
* The layer INDICATED BY aLayerMask (bitwise)
* (Runway end)
* The list of pads must already exist.
*
* Returns:
* NULL if no pad located.
* Pointer to the structure corresponding descr_pad if pad found
* (Good position and good layer).
*/
D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos, int aLayerMask )
{
for( unsigned i=0; i<Pcb->GetPadsCount(); ++i )
{
D_PAD* pad = Pcb->m_NetInfo->GetPad(i);
if( pad->m_Pos != ref_pos )
continue;
/* Pad found, it must be on the correct layer */
if( pad->m_layerMask & aLayerMask )
return pad;
}
return NULL;
}
/* Locate segment with one end that coincides with the point x, y
* Data on layers by masklayer
* Research is done to address start_adr has end_adr
* If end_adr = NULL, end search list
* The segments of track marks with the flag are not IS_DELETED or taken
* into account
*/
TRACK* GetTrace( TRACK* start_adr, TRACK* end_adr, const wxPoint& ref_pos, int MaskLayer )
{
TRACK* PtSegm;
if( start_adr == NULL )
return NULL;
for( PtSegm = start_adr; PtSegm != NULL; PtSegm = PtSegm->Next() )
{
if( PtSegm->GetState( IS_DELETED | BUSY ) == 0 )
{
if( ref_pos == PtSegm->m_Start )
{
if( MaskLayer & PtSegm->ReturnMaskLayer() )
return PtSegm;
}
if( ref_pos == PtSegm->m_End )
{
if( MaskLayer & PtSegm->ReturnMaskLayer() )
return PtSegm;
}
}
if( PtSegm == end_adr )
break;
}
return NULL;
}
/* Locates via through the point x, y, on layer data by masklayer.
* Search is done to address start_adr has end_adr.
* If end_adr = NULL, end search list
* Vias whose parameter has the State or IS_DELETED bit BUSY = 1 are ignored
*/
TRACK* Fast_Locate_Via( TRACK* start_adr, TRACK* end_adr, const wxPoint& pos, int MaskLayer )
{
TRACK* PtSegm;
for( PtSegm = start_adr; PtSegm != NULL; PtSegm = PtSegm->Next() )
{
if( PtSegm->Type() == TYPE_VIA )
{
if( pos == PtSegm->m_Start )
{
if( PtSegm->GetState( BUSY | IS_DELETED ) == 0 )
{
if( MaskLayer & PtSegm->ReturnMaskLayer() )
return PtSegm;
}
}
}
if( PtSegm == end_adr )
break;
}
return NULL;
}

View File

@ -153,7 +153,7 @@ bool Magnetize( BOARD* m_Pcb, PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize gr
if( doPad ) if( doPad )
{ {
int layer_mask = g_TabOneLayerMask[screen->m_Active_Layer]; int layer_mask = g_TabOneLayerMask[screen->m_Active_Layer];
D_PAD* pad = Locate_Any_Pad( m_Pcb, pos, layer_mask ); D_PAD* pad = m_Pcb->GetPad( pos, layer_mask );
if( pad ) if( pad )
{ {
@ -171,7 +171,7 @@ bool Magnetize( BOARD* m_Pcb, PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize gr
int layer = screen->m_Active_Layer; int layer = screen->m_Active_Layer;
for( TRACK* via = m_Pcb->m_Track; for( TRACK* via = m_Pcb->m_Track;
via && (via = Locate_Via_Area( via, *curpos, layer )) != NULL; via && (via = via->GetVia( *curpos, layer )) != NULL;
via = via->Next() ) via = via->Next() )
{ {
if( via != currTrack ) // a via cannot influence itself if( via != currTrack ) // a via cannot influence itself
@ -193,7 +193,7 @@ bool Magnetize( BOARD* m_Pcb, PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize gr
{ {
int layer_mask = g_TabOneLayerMask[layer]; int layer_mask = g_TabOneLayerMask[layer];
TRACK* track = GetTrace( m_Pcb, m_Pcb->m_Track, pos, layer_mask ); TRACK* track = m_Pcb->m_Track->GetTrace( pos, layer_mask );
if( !track || track->Type() != TYPE_TRACK ) if( !track || track->Type() != TYPE_TRACK )
{ {

View File

@ -127,10 +127,9 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( wxWindow* father,
UpdateTitle(); UpdateTitle();
if( g_ModuleEditor_Pcb == NULL ) if( g_ModuleEditor_Pcb == NULL )
g_ModuleEditor_Pcb = new BOARD( NULL, this ); g_ModuleEditor_Pcb = new BOARD( NULL );
SetBoard( g_ModuleEditor_Pcb ); SetBoard( g_ModuleEditor_Pcb );
GetBoard()->m_PcbFrame = this;
if( s_screenModule == NULL ) if( s_screenModule == NULL )
s_screenModule = new PCB_SCREEN(); s_screenModule = new PCB_SCREEN();

View File

@ -1019,14 +1019,15 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC )
* (only pad connection must be tested, track connection will be * (only pad connection must be tested, track connection will be
* tested by test_1_net_connexion() ) */ * tested by test_1_net_connexion() ) */
int layerMask = g_TabOneLayerMask[Track->GetLayer()]; int layerMask = g_TabOneLayerMask[Track->GetLayer()];
Track->start = Fast_Locate_Pad_Connecte( GetBoard(), Track->m_Start, layerMask ); Track->start = GetBoard()->GetPadFast( Track->m_Start, layerMask );
if( Track->start ) if( Track->start )
Track->SetState( BEGIN_ONPAD, ON ); Track->SetState( BEGIN_ONPAD, ON );
else else
Track->SetState( BEGIN_ONPAD, OFF ); Track->SetState( BEGIN_ONPAD, OFF );
Track->end = Fast_Locate_Pad_Connecte( GetBoard(), Track->m_End, layerMask ); Track->end = GetBoard()->GetPadFast( Track->m_End, layerMask );
if( Track->end ) if( Track->end )
Track->SetState( END_ONPAD, ON ); Track->SetState( END_ONPAD, ON );
else else
@ -1054,147 +1055,3 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC )
return true; return true;
} }
/* Find the point "attachment" of the end of a trace.
* This may be a TBP or another segment of the trace
* Returns:
* - Pointer to the PAD or:
* - Pointer to the segment or:
* - NULL
* Parameters:
* - position to test
* - mask layers to be tested
*/
BOARD_ITEM* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask )
{
for( MODULE* module = Pcb->m_Modules; module; module = module->Next() )
{
D_PAD* pad = Locate_Pads( module, pos, LayerMask );
if( pad )
return pad;
}
/* No pad has been located so check for a segment of the trace. */
TRACK* ptsegm = GetTrace( Pcb->m_Track, NULL, pos, LayerMask );
if( ptsegm == NULL )
ptsegm = GetTrace( Pcb, Pcb->m_Track, pos, LayerMask );
return ptsegm;
}
/* Create an intermediate point on a segment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( BOARD* aPcb,
wxPoint& aRefPoint,
TRACK* aSegm,
PICKED_ITEMS_LIST* aItemsListPicker )
{
if( aSegm->m_Start == aRefPoint || aSegm->m_End == aRefPoint )
return NULL;
/* A via is a good lock point */
if( aSegm->Type() == TYPE_VIA )
{
aRefPoint = aSegm->m_Start;
return aSegm;
}
/* Calculation coordinate of intermediate point relative to
* the start point of aSegm
*/
wxPoint delta = aSegm->m_End - aSegm->m_Start;
// Not yet in use:
#if 0
int ox, oy, fx, fy;
if( aRefSegm )
{
ox = aRefSegm->m_Start.x - aSegm->m_Start.x;
oy = aRefSegm->m_Start.y - aSegm->m_Start.y;
fx = aRefSegm->m_End.x - aSegm->m_Start.x;
fy = aRefSegm->m_End.y - aSegm->m_Start.y;
}
#endif
// calculate coordinates of aRefPoint relative to aSegm->m_Start
wxPoint newPoint = aRefPoint - aSegm->m_Start;
// newPoint must be on aSegm:
// Ensure newPoint.y/newPoint.y = delta.y/delta.x
if( delta.x == 0 )
newPoint.x = 0; /* horizontal segment*/
else
newPoint.y = wxRound(( (double)newPoint.x * delta.y ) / delta.x);
/* Create the intermediate point (that is to say creation of a new
* segment, beginning at the intermediate point.
*/
newPoint.x += aSegm->m_Start.x;
newPoint.y += aSegm->m_Start.y;
TRACK* newTrack = aSegm->Copy();
if( aItemsListPicker )
{
ITEM_PICKER picker( newTrack, UR_NEW );
aItemsListPicker->PushItem( picker );
}
DLIST<TRACK>* list = (DLIST<TRACK>*)aSegm->GetList();
wxASSERT( list );
list->Insert( newTrack, aSegm->Next() );
if( aItemsListPicker )
{
ITEM_PICKER picker( aSegm, UR_CHANGED );
picker.m_Link = aSegm->Copy();
aItemsListPicker->PushItem( picker );
}
/* Correct pointer at the end of the new segment. */
newTrack->end = aSegm->end;
newTrack->SetState( END_ONPAD, aSegm->GetState( END_ONPAD ) );
/* Set connections info relative to the new point
*/
/* Old segment now ends at new point. */
aSegm->m_End = newPoint;
aSegm->end = newTrack;
aSegm->SetState( END_ONPAD, OFF );
/* The new segment begins at the new point. */
newTrack->m_Start = newPoint;
newTrack->start = aSegm;
newTrack->SetState( BEGIN_ONPAD, OFF );
D_PAD * pad = Locate_Pad_Connecte( aPcb, newTrack, START );
if ( pad )
{
newTrack->start = pad;
newTrack->SetState( BEGIN_ONPAD, ON );
aSegm->end = pad;
aSegm->SetState( END_ONPAD, ON );
}
aRefPoint = newPoint;
return newTrack;
}

View File

@ -48,7 +48,8 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
{ {
if( item && item->m_Flags ) if( item && item->m_Flags )
{ {
AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ), KiBitmap( cancel_xpm ) ); AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ),
KiBitmap( cancel_xpm ) );
} }
else else
{ {
@ -166,7 +167,8 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
HK_MOVE_ITEM ); HK_MOVE_ITEM );
AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_DRAWING_REQUEST, AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_DRAWING_REQUEST,
msg, KiBitmap( move_xpm ) ); msg, KiBitmap( move_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DRAWING, _( "Edit Drawing" ), KiBitmap( edit_xpm ) ); AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DRAWING, _( "Edit Drawing" ),
KiBitmap( edit_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DRAWING, AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DRAWING,
_( "Delete Drawing" ), KiBitmap( delete_xpm ) ); _( "Delete Drawing" ), KiBitmap( delete_xpm ) );
@ -293,7 +295,8 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
case ID_TRACK_BUTT: case ID_TRACK_BUTT:
if ( ! locate_track ) // This menu is already added when a track is located if ( ! locate_track ) // This menu is already added when a track is located
AddMenuItem( aPopMenu, Append_Track_Width_List( GetBoard() ), AddMenuItem( aPopMenu, Append_Track_Width_List( GetBoard() ),
ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ), KiBitmap( width_track_xpm ) ); ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ),
KiBitmap( width_track_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_CU_LAYER, AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_CU_LAYER,
_( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) ); _( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
@ -375,7 +378,8 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
*/ */
void PCB_EDIT_FRAME::createPopUpBlockMenu( wxMenu* menu ) void PCB_EDIT_FRAME::createPopUpBlockMenu( wxMenu* menu )
{ {
AddMenuItem( menu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel Block" ), KiBitmap( cancel_xpm ) ); AddMenuItem( menu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel Block" ),
KiBitmap( cancel_xpm ) );
AddMenuItem( menu, ID_POPUP_ZOOM_BLOCK, _( "Zoom Block" ), KiBitmap( zoom_area_xpm ) ); AddMenuItem( menu, ID_POPUP_ZOOM_BLOCK, _( "Zoom Block" ), KiBitmap( zoom_area_xpm ) );
menu->AppendSeparator(); menu->AppendSeparator();
AddMenuItem( menu, ID_POPUP_PLACE_BLOCK, _( "Place Block" ), KiBitmap( apply_xpm ) ); AddMenuItem( menu, ID_POPUP_PLACE_BLOCK, _( "Place Block" ), KiBitmap( apply_xpm ) );
@ -404,7 +408,8 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
{ {
if( Track->Type() == TYPE_VIA ) if( Track->Type() == TYPE_VIA )
{ {
AddMenuItem( PopMenu, ID_POPUP_PCB_MOVE_TRACK_NODE, _( "Drag Via" ), KiBitmap( move_xpm ) ); AddMenuItem( PopMenu, ID_POPUP_PCB_MOVE_TRACK_NODE, _( "Drag Via" ),
KiBitmap( move_xpm ) );
} }
else else
{ {
@ -485,10 +490,10 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
// Delete control: // Delete control:
PopMenu->AppendSeparator(); PopMenu->AppendSeparator();
wxMenu* track_mnu = new wxMenu; wxMenu* track_mnu = new wxMenu;
AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_DELETE_TRACK_MNU, _( "Delete" ), KiBitmap( delete_xpm ) ); AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_DELETE_TRACK_MNU, _( "Delete" ),
KiBitmap( delete_xpm ) );
msg = AddHotkeyName( Track->Type()==TYPE_VIA ? msg = AddHotkeyName( Track->Type()==TYPE_VIA ? _( "Delete Via" ) : _( "Delete Segment" ),
_( "Delete Via" ) : _( "Delete Segment" ),
g_Board_Editor_Hokeys_Descr, HK_BACK_SPACE ); g_Board_Editor_Hokeys_Descr, HK_BACK_SPACE );
AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACKSEG, msg, KiBitmap( delete_line_xpm ) ); AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACKSEG, msg, KiBitmap( delete_line_xpm ) );
@ -497,7 +502,8 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
{ {
msg = AddHotkeyName( _( "Delete Track" ), g_Board_Editor_Hokeys_Descr, HK_DELETE ); msg = AddHotkeyName( _( "Delete Track" ), g_Board_Editor_Hokeys_Descr, HK_DELETE );
AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACK, msg, KiBitmap( delete_track_xpm ) ); AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACK, msg, KiBitmap( delete_track_xpm ) );
AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACKNET, _( "Delete Net" ), KiBitmap( delete_net_xpm ) ); AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACKNET, _( "Delete Net" ),
KiBitmap( delete_net_xpm ) );
} }
// Add global edition command // Add global edition command
@ -511,7 +517,8 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
// Add lock/unlock flags menu: // Add lock/unlock flags menu:
track_mnu = new wxMenu; track_mnu = new wxMenu;
AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_SETFLAGS_TRACK_MNU, _( "Set Flags" ), KiBitmap( flag_xpm ) ); AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_SETFLAGS_TRACK_MNU, _( "Set Flags" ),
KiBitmap( flag_xpm ) );
track_mnu->Append( ID_POPUP_PCB_LOCK_ON_TRACKSEG, _( "Locked: Yes" ), wxEmptyString, true ); track_mnu->Append( ID_POPUP_PCB_LOCK_ON_TRACKSEG, _( "Locked: Yes" ), wxEmptyString, true );
track_mnu->Append( ID_POPUP_PCB_LOCK_OFF_TRACKSEG, _( "Locked: No" ), wxEmptyString, true ); track_mnu->Append( ID_POPUP_PCB_LOCK_OFF_TRACKSEG, _( "Locked: No" ), wxEmptyString, true );
@ -557,14 +564,19 @@ void PCB_EDIT_FRAME::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu*
AddMenuItem( aPopMenu, zones_menu, -1, _( "Zones" ), KiBitmap( add_zone_xpm ) ); AddMenuItem( aPopMenu, zones_menu, -1, _( "Zones" ), KiBitmap( add_zone_xpm ) );
if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) ) // Use grid size because it is known
wxRealPoint grid = DrawPanel->GetGrid();
if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ),
wxRound( MIN( grid.x, grid.y ) ) ) )
{ {
AddMenuItem( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER, AddMenuItem( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER,
_( "Move Corner" ), KiBitmap( move_xpm ) ); _( "Move Corner" ), KiBitmap( move_xpm ) );
AddMenuItem( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER, AddMenuItem( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER,
_( "Delete Corner" ), KiBitmap( delete_xpm ) ); _( "Delete Corner" ), KiBitmap( delete_xpm ) );
} }
else if( edge_zone->HitTestForEdge( GetScreen()->RefPos( true ) ) ) else if( edge_zone->HitTestForEdge( GetScreen()->RefPos( true ),
wxRound( MIN( grid.x, grid.y ) ) ) )
{ {
AddMenuItem( zones_menu, ID_POPUP_PCB_ADD_ZONE_CORNER, AddMenuItem( zones_menu, ID_POPUP_PCB_ADD_ZONE_CORNER,
_( "Create Corner" ), KiBitmap( add_corner_xpm ) ); _( "Create Corner" ), KiBitmap( add_corner_xpm ) );
@ -582,7 +594,8 @@ void PCB_EDIT_FRAME::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu*
_( "Add Cutout Area" ), KiBitmap( add_zone_cutout_xpm ) ); _( "Add Cutout Area" ), KiBitmap( add_zone_cutout_xpm ) );
zones_menu->AppendSeparator(); zones_menu->AppendSeparator();
AddMenuItem( zones_menu, ID_POPUP_PCB_FILL_ZONE, _( "Fill Zone" ), KiBitmap( fill_zone_xpm ) ); AddMenuItem( zones_menu, ID_POPUP_PCB_FILL_ZONE, _( "Fill Zone" ),
KiBitmap( fill_zone_xpm ) );
if( edge_zone->m_FilledPolysList.size() > 0 ) if( edge_zone->m_FilledPolysList.size() > 0 )
{ {
@ -645,7 +658,8 @@ void PCB_EDIT_FRAME::createPopUpMenuForFootprints( MODULE* aModule, wxMenu* menu
if( !flags ) if( !flags )
{ {
msg = AddHotkeyName( _( "Edit" ), g_Board_Editor_Hokeys_Descr, HK_EDIT_ITEM ); msg = AddHotkeyName( _( "Edit" ), g_Board_Editor_Hokeys_Descr, HK_EDIT_ITEM );
AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_EDIT_MODULE, msg, KiBitmap( edit_module_xpm ) ); AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_EDIT_MODULE, msg,
KiBitmap( edit_module_xpm ) );
sub_menu_footprint->AppendSeparator(); sub_menu_footprint->AppendSeparator();
AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_DELETE_MODULE, AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_DELETE_MODULE,
_( "Delete Module" ), KiBitmap( delete_module_xpm ) ); _( "Delete Module" ), KiBitmap( delete_module_xpm ) );
@ -725,8 +739,10 @@ void PCB_EDIT_FRAME::createPopUpMenuForFpPads( D_PAD* Pad, wxMenu* menu )
sub_menu_Pad = new wxMenu; sub_menu_Pad = new wxMenu;
AddMenuItem( menu, sub_menu_Pad, -1, msg, KiBitmap( pad_xpm ) ); AddMenuItem( menu, sub_menu_Pad, -1, msg, KiBitmap( pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_MOVE_PAD_REQUEST, _( "Move" ), KiBitmap( move_pad_xpm ) ); AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_MOVE_PAD_REQUEST, _( "Move" ),
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_DRAG_PAD_REQUEST, _( "Drag" ), KiBitmap( drag_pad_xpm ) ); KiBitmap( move_pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_DRAG_PAD_REQUEST, _( "Drag" ),
KiBitmap( drag_pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_EDIT_PAD, _( "Edit" ), KiBitmap( options_pad_xpm ) ); AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_EDIT_PAD, _( "Edit" ), KiBitmap( options_pad_xpm ) );
sub_menu_Pad->AppendSeparator(); sub_menu_Pad->AppendSeparator();
@ -790,14 +806,17 @@ void PCB_EDIT_FRAME::createPopUpMenuForTexts( TEXTE_PCB* Text, wxMenu* menu )
_( "Reset Size" ), KiBitmap( reset_text_xpm ) ); _( "Reset Size" ), KiBitmap( reset_text_xpm ) );
sub_menu_Text->AppendSeparator(); sub_menu_Text->AppendSeparator();
AddMenuItem( sub_menu_Text, ID_POPUP_PCB_DELETE_TEXTEPCB, _( "Delete" ), KiBitmap( delete_text_xpm ) ); AddMenuItem( sub_menu_Text, ID_POPUP_PCB_DELETE_TEXTEPCB, _( "Delete" ),
KiBitmap( delete_text_xpm ) );
} }
void PCB_EDIT_FRAME::createPopUpMenuForMarkers( MARKER_PCB* aMarker, wxMenu* aPopMenu ) void PCB_EDIT_FRAME::createPopUpMenuForMarkers( MARKER_PCB* aMarker, wxMenu* aPopMenu )
{ {
AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_MARKER, _( "Delete Marker" ), KiBitmap( delete_xpm ) ); AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_MARKER, _( "Delete Marker" ),
AddMenuItem( aPopMenu, ID_POPUP_PCB_GETINFO_MARKER, _( "Marker Error Info" ), KiBitmap( info_xpm ) ); KiBitmap( delete_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_GETINFO_MARKER, _( "Marker Error Info" ),
KiBitmap( info_xpm ) );
} }

View File

@ -277,10 +277,11 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title,
m_HotkeysZoomAndGridList = g_Board_Editor_Hokeys_Descr; m_HotkeysZoomAndGridList = g_Board_Editor_Hokeys_Descr;
m_RecordingMacros = -1; m_RecordingMacros = -1;
for ( int i = 0; i < 10; i++ ) for ( int i = 0; i < 10; i++ )
m_Macros[i].m_Record.clear(); m_Macros[i].m_Record.clear();
SetBoard( new BOARD( NULL, this ) ); SetBoard( new BOARD( NULL ) );
// Create the PCB_LAYER_WIDGET *after* SetBoard(): // Create the PCB_LAYER_WIDGET *after* SetBoard():
@ -417,6 +418,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title,
PCB_EDIT_FRAME::~PCB_EDIT_FRAME() PCB_EDIT_FRAME::~PCB_EDIT_FRAME()
{ {
m_RecordingMacros = -1; m_RecordingMacros = -1;
for( int i = 0; i < 10; i++ ) for( int i = 0; i < 10; i++ )
m_Macros[i].m_Record.clear(); m_Macros[i].m_Record.clear();

View File

@ -1,16 +1,11 @@
/***********/ /**
/* protos.h */ * @file pcbnew/protos.h
/***********/ */
#ifndef PROTO_H #ifndef PROTO_H
#define PROTO_H #define PROTO_H
#include <vector>
class COMMAND;
/** /**
* Function SwapData * Function SwapData
* Used in undo / redo command: * Used in undo / redo command:
@ -22,24 +17,6 @@ class COMMAND;
void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage ); void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage );
/*******************/
/* PAD_CONNECT.CPP */
/*******************/
class D_PAD;
/**
* Function CreateSortedPadListByXCoord
* first empties then fills the vector with all pads and sorts them by
* increasing x coordinate. The vector only holds pointers to the pads and
* those pointers are only references to pads which are owned by the BOARD
* through other links.
* @param aBoard Which board to gather pads from.
* @param aVector Where to put the pad pointers.
*/
void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector );
/***************/ /***************/
/* TRPISTE.CPP */ /* TRPISTE.CPP */
/***************/ /***************/
@ -66,31 +43,6 @@ void DrawTraces( EDA_DRAW_PANEL* panel,
/* LOCATE.CPP : */ /* LOCATE.CPP : */
/****************/ /****************/
/* Find a pad by it's name om the module. */
TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer = -1 );
/**
* Function Locate_Via_Area
* finds the first SEGVIA which covers the given aPos with a matching layer.
* @param aStart The starting TRACK or SEGVIA in the BOARD's list.
* @param aPos The wxPoint to HitTest() against.
* @param aLayer The layer to match, pass -1 for a don't care.
* @return TRACK* - actually a SEGVIA* if found, else NULL.
*/
TRACK* Locate_Via_Area( TRACK* aStart, const wxPoint& aPos, int aLayer = ALL_LAYERS );
/* Locates the center through the point x, y, on layer data
* by masquelayer.
* Search is done to address start_adr has end_adr (not included)
*/
TRACK* Fast_Locate_Via( TRACK* start_adr, TRACK* end_adr, const wxPoint& pos, int masquelayer );
/* Locates the center through the point x, y, on layer data
* by masquelayer.
* Search is done to address start_adr has end_adr (not included)
*/
TRACK* GetTrace( TRACK* start_adr, TRACK* end_adr, const wxPoint& ref_pos, int masquelayer );
/* Search for segment connected to the segment edge by /* Search for segment connected to the segment edge by
* Ptr_piste: * Ptr_piste:
* If int = START, the point of beginning of the segment is used * If int = START, the point of beginning of the segment is used
@ -100,86 +52,6 @@ TRACK* GetTrace( TRACK* start_adr, TRACK* end_adr, const wxPoint& ref_pos, int m
*/ */
TRACK* GetConnectedTrace( TRACK* aTrace, TRACK* pt_base, TRACK* pt_lim, int extr ); TRACK* GetConnectedTrace( TRACK* aTrace, TRACK* pt_base, TRACK* pt_lim, int extr );
/*
* 1 - Locate segment of track leading from the mouse.
* 2 - Locate segment of track point by point.
* Ref_pX, ref_pY.
*
* If layer <0 the layer is not tested.
*
* The search begins to address start_adresse
*/
TRACK* GetTrace( BOARD* aPcb, TRACK* start_adresse, const wxPoint& ref_pos, int layer );
/* Locate pad connected to the beginning or end of a segment
* Input: pointer to the segment, and flag = START or END
* Returns:
* A pointer to the description of the patch if pad was found.
* NULL pointer if pad was not found.
*/
D_PAD* Locate_Pad_Connecte( BOARD* aPcb, TRACK* ptr_segment, int extr );
/*
* Locate pad pointed to by the coordinate ref_pX,, ref_pY or the current
* cursor position, search done on all tracks.
* Entry:
* - Mouse coord (Curseur_X and Curseur_Y)
* Or ref_pX, ref_pY
* Returns:
* Pointer to the pad if found
* NULL pointer if pad not found
*/
D_PAD* Locate_Any_Pad( BOARD* aPcb, const wxPoint& aPosition, int aLayerMask = ALL_LAYERS );
/* Locate pad pointed to by the coordinate ref_pX,, ref_pY or the cursor
* position of the current footprint.
* Input:
* - The module to search.
* - Layer to search or -1 to search all layers.
* Returns:
* A pointer to the pad if found otherwise NULL.
*/
D_PAD* Locate_Pads( MODULE* Module, const wxPoint& ref_pos, int layer );
/* Locate a footprint by its bounding rectangle. */
MODULE* Locate_Prefered_Module( BOARD* aPcb, const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked = false );
/* Locate a pad pointed to by the cursor on the footprint.
* Module.
* Input:
* - Module to search.
* Returns:
* A pointer to the pad if found otherwise NULL.
*/
D_PAD* Locate_Pads( MODULE* Module, int typeloc );
/* Locate a trace segment at the current cursor position.
* The search begins to address start_adresse.
*/
TRACK* GetTrace( TRACK* start_adresse, int typeloc );
DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int LayerSearch, int typeloc );
/* Locate pad containing the point px, py, layer on layer.
*
* The list of pads must already exist.
*
* Returns:
* Pointer to the pad if found, otherwise NULL.
*/
D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos, int layer );
/*
* 1 - Locate trace segment at the current cursor position.
* 2 - Locate trace segment at the given coordinates ref_pos.
*
* If layer == -1, check all layers.
*
* The search begins to address start_adresse
*/
TRACK* Locate_Zone( TRACK* start_adresse, const wxPoint& ref_pos, int layer );
/*************/ /*************/
/* MODULES.C */ /* MODULES.C */
@ -204,84 +76,9 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo
void CalculateSegmentEndPoint( const wxPoint& aPosition, int ox, int oy, int* fx, int* fy ); void CalculateSegmentEndPoint( const wxPoint& aPosition, int ox, int oy, int* fx, int* fy );
/*****************/
/* TRACK.CPP : */
/*****************/
/**
* Function MarkTrace
* marks a chain of track segments, connected to aTrackList.
* Each segment is marked by setting the BUSY bit into m_Flags. Electrical
* continuity is detected by walking each segment, and finally the segments
* are rearranged into a contiguous chain within the given list.
*
* @param aPcb = the board to analyze
* @param aStartSegm - The first interesting segment within a list of track
* segment of aPcb
* @param aSegmCount = a pointer to an integer where to return the number of
* interesting segments
* @param aTrackLen = a pointer to an integer where to return the lenght of the
* track
* @param aLengthDie = a pointer to an integer where to return the extra lengths inside
* integrated circuits from the pads connected to this track to the
* die (if any)
* @param aReorder = true for reorder the interesting segments (useful for
* track edition/deletion) in this case the flag BUSY is
* set (the user is responsible of flag clearing). False
* for no reorder : useful when we want just calculate the
* track length in this case, flags are reset
* @return TRACK* the first in the chain of interesting segments.
*/
TRACK* MarkTrace( BOARD* aPcb,
TRACK* aStartSegm,
int* aSegmCount,
int* aTrackLen,
int* aLengthDie,
bool aReorder );
/* Calculate end coordinate of a trace.
* Returns 1 if OK, 0 if trace looped back on itself.
* The coord are returned StartTrack-> ox, oy
* And EndTrack-> fx, fy if OK
* The segments are drawn consecutively.
*/
int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack );
/***************/ /***************/
/***************/ /***************/
/* Routine to find the point "attachment" at the end of a trace.
* This may be a PAD or another trace segment.
* Returns:
* - Pointer to the PAD or:
* - Pointer to the segment or:
* - NULL
* Parameters:
* - aPos - coordinate point test
* ALayerMask of mask layers to be tested
*/
BOARD_ITEM* LocateLockPoint( BOARD* aPcb, wxPoint aPos, int aLayerMask );
/* Create an intermediate point on a segment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( BOARD* aPcb,
wxPoint& aRefPoint,
TRACK* aSegm,
PICKED_ITEMS_LIST* aItemsListPicker );
/****************/ /****************/
/* CONTROLE.CPP */ /* CONTROLE.CPP */

View File

@ -1268,14 +1268,12 @@ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
g_CurrentTrackList.PushBack( newTrack ); g_CurrentTrackList.PushBack( newTrack );
} }
g_FirstTrackSegment->start = Locate_Pad_Connecte( pcbframe->GetBoard(), g_FirstTrackSegment->start = pcbframe->GetBoard()->GetPad( g_FirstTrackSegment, START );
g_FirstTrackSegment, START );
if( g_FirstTrackSegment->start ) if( g_FirstTrackSegment->start )
g_FirstTrackSegment->SetState( BEGIN_ONPAD, ON ); g_FirstTrackSegment->SetState( BEGIN_ONPAD, ON );
g_CurrentTrackSegment->end = Locate_Pad_Connecte( pcbframe->GetBoard(), g_CurrentTrackSegment->end = pcbframe->GetBoard()->GetPad( g_CurrentTrackSegment, END );
g_CurrentTrackSegment, END );
if( g_CurrentTrackSegment->end ) if( g_CurrentTrackSegment->end )
g_CurrentTrackSegment->SetState( END_ONPAD, ON ); g_CurrentTrackSegment->SetState( END_ONPAD, ON );

View File

@ -10,8 +10,6 @@
#include "protos.h" #include "protos.h"
static void ListSetState( EDA_ITEM* Start, int NbItem, int State, int onoff ); static void ListSetState( EDA_ITEM* Start, int NbItem, int State, int onoff );
extern int ReturnEndsTrack( TRACK* RefTrack, int NbSegm,
TRACK** StartTrack, TRACK** EndTrack );
/** /**
@ -54,7 +52,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
if( aNewTrack->Type() == TYPE_VIA && ( aNewTrackSegmentsCount > 1 ) ) if( aNewTrack->Type() == TYPE_VIA && ( aNewTrackSegmentsCount > 1 ) )
aNewTrack = aNewTrack->Next(); aNewTrack = aNewTrack->Next();
aNewTrack = MarkTrace( GetBoard(), aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true ); aNewTrack = GetBoard()->MarkTrace( aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
wxASSERT( aNewTrack ); wxASSERT( aNewTrack );
#if 0 && defined(DEBUG) #if 0 && defined(DEBUG)
@ -92,7 +90,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
break; break;
} }
if( ReturnEndsTrack( aNewTrack, aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 ) if( aNewTrack->GetEndSegments( aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 )
return 0; return 0;
if( ( StartTrack == NULL ) || ( EndTrack == NULL ) ) if( ( StartTrack == NULL ) || ( EndTrack == NULL ) )
@ -110,7 +108,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
endmasklayer = EndTrack->ReturnMaskLayer(); endmasklayer = EndTrack->ReturnMaskLayer();
/* There may be a via or a pad on the end points. */ /* There may be a via or a pad on the end points. */
pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, start, startmasklayer ); pt_segm = m_Pcb->m_Track->GetVia( NULL, start, startmasklayer );
if( pt_segm ) if( pt_segm )
startmasklayer |= pt_segm->ReturnMaskLayer(); startmasklayer |= pt_segm->ReturnMaskLayer();
@ -122,7 +120,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
startmasklayer |= pt_pad->m_layerMask; startmasklayer |= pt_pad->m_layerMask;
} }
pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, end, endmasklayer ); pt_segm = m_Pcb->m_Track->GetVia( NULL, end, endmasklayer );
if( pt_segm ) if( pt_segm )
endmasklayer |= pt_segm->ReturnMaskLayer(); endmasklayer |= pt_segm->ReturnMaskLayer();
@ -141,7 +139,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
/* A segment must be connected to the starting point, otherwise /* A segment must be connected to the starting point, otherwise
* it is unnecessary to analyze the other point * it is unnecessary to analyze the other point
*/ */
pt_segm = GetTrace( bufStart, bufEnd, start, startmasklayer ); pt_segm = GetTraceByEndPoint( bufStart, bufEnd, start, startmasklayer );
if( pt_segm == NULL ) /* Not connected to the track starting point. */ if( pt_segm == NULL ) /* Not connected to the track starting point. */
{ {
@ -156,7 +154,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
*/ */
for( pt_del = bufStart, nbconnect = 0; ; ) for( pt_del = bufStart, nbconnect = 0; ; )
{ {
pt_segm = GetTrace( pt_del, bufEnd, end, endmasklayer ); pt_segm = GetTraceByEndPoint( pt_del, bufEnd, end, endmasklayer );
if( pt_segm == NULL ) if( pt_segm == NULL )
break; break;
@ -211,7 +209,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
nbconnect--; nbconnect--;
pt_del->SetState( IS_LINKED, OFF ); pt_del->SetState( IS_LINKED, OFF );
pt_del = MarkTrace( GetBoard(), pt_del, &nb_segm, NULL, NULL, true ); pt_del = GetBoard()->MarkTrace( pt_del, &nb_segm, NULL, NULL, true );
/* Test if the marked track is redundant, i.e. if one of marked segments /* Test if the marked track is redundant, i.e. if one of marked segments
* is connected to the starting point of the new track. * is connected to the starting point of the new track.

View File

@ -1,541 +0,0 @@
/*****************
* track.cpp
*****************/
#include "fctsys.h"
#include "common.h"
#include "pcbnew.h"
#include "protos.h"
/* Functions to recognize a track.
* A track is a list of connected segments (or/and vias)
* from a starting to an ending point
* starting and ending points are a pad or a point with more than 2 segments
*connected
* (and obviously a dangling segment end)
*/
typedef std::vector<TRACK*> TRACK_PTRS; // buffer of item candidates when
// search for items on the same track
/* Local functions */
static void ChainMarkedSegments( BOARD* Pcb,
wxPoint ref_pos,
int masklayer,
TRACK_PTRS* aList );
TRACK* MarkTrace( BOARD* aPcb,
TRACK* aStartSegm,
int* aSegmCount,
int* aTrackLen,
int* aLengthDie,
bool aReorder )
{
int NbSegmBusy;
TRACK_PTRS trackList;
if( aSegmCount )
*aSegmCount = 0;
if( aTrackLen )
*aTrackLen = 0;
if( aStartSegm == NULL )
return NULL;
// Ensure the flag BUSY of all tracks of the board is cleared
// because we use it to mark segments of the track
for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
track->SetState( BUSY, OFF );
/* Set flags of the initial track segment */
aStartSegm->SetState( BUSY, ON );
int layerMask = aStartSegm->ReturnMaskLayer();
trackList.push_back( aStartSegm );
/* Examine the initial track segment : if it is really a segment, this is
* easy.
* If it is a via, one must search for connected segments.
* If <=2, this via connect 2 segments (or is connected to only one
* segment) and this via and these 2 segments are a part of a track.
* If > 2 only this via is flagged (the track has only this via)
*/
if( aStartSegm->Type() == TYPE_VIA )
{
TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL;
Segm1 = GetTrace( aPcb->m_Track, NULL, aStartSegm->m_Start, layerMask );
if( Segm1 )
{
Segm2 = GetTrace( Segm1->Next(), NULL, aStartSegm->m_Start, layerMask );
}
if( Segm2 )
{
Segm3 = GetTrace( Segm2->Next(), NULL, aStartSegm->m_Start, layerMask );
}
if( Segm3 ) // More than 2 segments are connected to this via. the track" is only this via
{
if( aSegmCount )
*aSegmCount = 1;
return aStartSegm;
}
if( Segm1 ) // search for others segments connected to the initial segment start point
{
layerMask = Segm1->ReturnMaskLayer();
ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList );
}
if( Segm2 ) // search for others segments connected to the initial segment end point
{
layerMask = Segm2->ReturnMaskLayer();
ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList );
}
}
else // mark the chain using both ends of the initial segment
{
ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList );
ChainMarkedSegments( aPcb, aStartSegm->m_End, layerMask, &trackList );
}
// Now examine selected vias and flag them if they are on the track
// If a via is connected to only one or 2 segments, it is flagged (is on
// the track)
// If a via is connected to more than 2 segments, it is a track end, and it
// is removed from the list
// go through the list backwards.
for( int i = trackList.size() - 1; i>=0; --i )
{
TRACK* via = trackList[i];
if( via->Type() != TYPE_VIA )
continue;
if( via == aStartSegm )
continue;
via->SetState( BUSY, ON ); // Try to flag it. the flag will be cleared later if needed
layerMask = via->ReturnMaskLayer();
TRACK* track = GetTrace( aPcb->m_Track, NULL, via->m_Start, layerMask );
// GetTrace does not consider tracks flagged BUSY.
// So if no connected track found, this via is on the current track
// only: keep it
if( track == NULL )
continue;
/* If a track is found, this via connects also others segments of an
* other track. This case happens when the vias ends the selected
* track but must we consider this via is on the selected track, or
* on an other track.
* (this is important when selecting a track for deletion: must this
* via be deleted or not?)
* We consider here this via on the track if others segment connected
* to this via remain connected when removing this via.
* We search for all others segment connected together:
* if there are on the same layer, the via is on the selected track
* if there are on different layers, the via is on an other track
*/
int layer = track->GetLayer();
while( ( track = GetTrace( track->Next(), NULL, via->m_Start, layerMask ) ) != NULL )
{
if( layer != track->GetLayer() )
{
// The via connects segments of an other track: it is removed
// from list because it is member of an other track
via->SetState( BUSY, OFF );
break;
}
}
}
/* Rearrange the track list in order to have flagged segments linked
* from firstTrack so the NbSegmBusy segments are consecutive segments
* in list, the first item in the full track list is firstTrack, and
* the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
* are the flagged segments
*/
NbSegmBusy = 0;
TRACK* firstTrack;
for( firstTrack = aPcb->m_Track; firstTrack; firstTrack = firstTrack->Next() )
{
// Search for the first flagged BUSY segments
if( firstTrack->GetState( BUSY ) )
{
NbSegmBusy = 1;
break;
}
}
if( firstTrack == NULL )
return NULL;
double full_len = 0;
double lenDie = 0;
if( aReorder )
{
DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
wxASSERT( list );
/* Rearrange the chain starting at firstTrack
* All others flagged items are moved from their position to the end
* of the flagged list
*/
TRACK* next;
for( TRACK* track = firstTrack->Next(); track; track = next )
{
next = track->Next();
if( track->GetState( BUSY ) ) // move it!
{
NbSegmBusy++;
track->UnLink();
list->Insert( track, firstTrack->Next() );
if( aTrackLen )
full_len += track->GetLength();
if( aLengthDie ) // Add now length die.
{
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
}
else if( aTrackLen )
{
NbSegmBusy = 0;
for( TRACK* track = firstTrack; track; track = track->Next() )
{
if( track->GetState( BUSY ) )
{
NbSegmBusy++;
track->SetState( BUSY, OFF );
full_len += track->GetLength();
// Add now length die.
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
if( aTrackLen )
*aTrackLen = wxRound( full_len );
if( aLengthDie )
*aLengthDie = wxRound( lenDie );
if( aSegmCount )
*aSegmCount = NbSegmBusy;
return firstTrack;
}
/**
* Function used by MarkTrace
* - Set the BUSY flag of connected segments, the first search point is
* ref_pos on layers allowed in masque_layer
* - Put segments fount in aList
* Vias are put in list but their flags BUSY is not set
* @param aPcb = the board
* @param aRef_pos = the reference coordinate of the starting search
* @param aLayerMask = the allowed layers for segments to search
* (1 layer when starting point is on a segment, but more than one when
* starting point is on a via)
* @param aList = the track list to fill with points of segments flagged
*/
static void ChainMarkedSegments( BOARD* aPcb,
wxPoint aRef_pos,
int aLayerMask,
TRACK_PTRS* aList )
{
TRACK* pt_segm, // The current segment being analyzed.
* pt_via, // The via identified, eventually destroy
* SegmentCandidate; // The end segment to destroy (or NULL =
// pt_segm
int NbSegm;
if( aPcb->m_Track == NULL )
return;
/* Set the BUSY flag of all connected segments, first search starting at
* aRef_pos
* Search ends when:
* - a pad is found (end of a track)
* - a segment end has more than one other segment end connected
* - and obviously when no connected item found
* Vias are a special case, because we must see others segment connected
* on others layers and they change the layer mask. They can be a track
* end or not
* They will be analyzer later, and vias on terminal points of the track
* will be considered as part of this track if they do not connect segments
* of an other track together and will be considered as part of an other
* track if when removing the via, the segments of that other track are
* disconnected
*/
for( ; ; )
{
if( Fast_Locate_Pad_Connecte( aPcb, aRef_pos, aLayerMask ) != NULL )
return;
/* Test for a via: a via changes the layer mask and can connect a lot
* of segments at location aRef_pos. When found, the via is just
* pushed in list. Vias will be examined later, when all connected
* segment are found and push in list. This is because when a via
* is found we do not know at this time the number of connected items
* and we do not know if this via is on the track or finish the track
*/
pt_via = Fast_Locate_Via( aPcb->m_Track, NULL, aRef_pos, aLayerMask );
if( pt_via )
{
aLayerMask = pt_via->ReturnMaskLayer();
aList->push_back( pt_via );
}
/* Now we search all segments connected to point aRef_pos
* if only 1 segment: this segment is candidate
* if > 1 segment:
* end of track (more than 2 segment connected at this location)
*/
pt_segm = aPcb->m_Track; SegmentCandidate = NULL;
NbSegm = 0;
while( ( pt_segm = GetTrace( pt_segm, NULL, aRef_pos, aLayerMask ) ) != NULL )
{
if( pt_segm->GetState( BUSY ) ) // already found and selected: skip it
{
pt_segm = pt_segm->Next();
continue;
}
if( pt_segm == pt_via ) // just previously found: skip it
{
pt_segm = pt_segm->Next();
continue;
}
NbSegm++;
if( NbSegm == 1 ) /* First time we found a connected item: pt_segm is candidate */
{
SegmentCandidate = pt_segm;
pt_segm = pt_segm->Next();
}
else /* More than 1 segment connected -> this location is an end of the track */
{
return;
}
}
if( SegmentCandidate ) // A candidate is found: flag it an push it in list
{
/* Initialize parameters to search items connected to this
* candidate:
* we must analyze connections to its other end
*/
aLayerMask = SegmentCandidate->ReturnMaskLayer();
if( aRef_pos == SegmentCandidate->m_Start )
{
aRef_pos = SegmentCandidate->m_End;
}
else
{
aRef_pos = SegmentCandidate->m_Start;
}
pt_segm = aPcb->m_Track; /* restart list of tracks to analyze */
/* flag this item an push it in list of selected items */
aList->push_back( SegmentCandidate );
SegmentCandidate->SetState( BUSY, ON );
}
else
{
return;
}
}
}
/* Calculate the end points coordinates of a track (a list of connected
* segments)
* RefTrack is a segment of the track
* return 1 if OK, 0 when a track is a closed loop
* and the beginning and the end of the track in *StartTrack and *EndTrack
* Modify *StartTrack en *EndTrack :
* (*StartTrack)->m_Start coordinate is the beginning of the track
* (*EndTrack)->m_End coordinate is the end of the track
* Segments connected must be consecutive in list
*/
int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack )
{
TRACK* Track, * via, * segm, * TrackListEnd;
int NbEnds, layerMask, ii, ok = 0;
if( NbSegm <= 1 )
{
*StartTrack = *EndTrack = RefTrack;
return 1;
}
/* Calculation of the limit analysis. */
*StartTrack = *EndTrack = NULL;
TrackListEnd = Track = RefTrack; ii = 0;
for( ; ( Track != NULL ) && ( ii < NbSegm ); ii++, Track = Track->Next() )
{
TrackListEnd = Track;
Track->m_Param = 0;
}
/* Calculate the extremes. */
NbEnds = 0; Track = RefTrack; ii = 0;
for( ; ( Track != NULL ) && ( ii < NbSegm ); ii++, Track = Track->Next() )
{
if( Track->Type() == TYPE_VIA )
continue;
layerMask = Track->ReturnMaskLayer();
via = Fast_Locate_Via( RefTrack, TrackListEnd, Track->m_Start, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTrace( RefTrack, TrackListEnd, Track->m_Start, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
*StartTrack = Track; NbEnds++;
break;
case 1:
int BeginPad, EndPad;
*EndTrack = Track;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
ok = 1;
return ok;
}
}
layerMask = Track->ReturnMaskLayer();
via = Fast_Locate_Via( RefTrack, TrackListEnd, Track->m_End, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTrace( RefTrack, TrackListEnd, Track->m_End, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
int BeginPad, EndPad;
*StartTrack = Track;
NbEnds++;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
break;
case 1:
*EndTrack = Track;
ok = 1;
return ok;
}
}
}
return ok;
}