KiCad PCB EDA Suite
export_gencad.cpp File Reference

Export GenCAD 1.4 format. More...

#include <build_version.h>
#include <board.h>
#include <board_design_settings.h>
#include <convert_basic_shapes_to_polygon.h>
#include <fp_shape.h>
#include <footprint.h>
#include <pad.h>
#include <pcb_track.h>
#include <confirm.h>
#include <core/arraydim.h>
#include <dialogs/dialog_gencad_export_options.h>
#include <locale_io.h>
#include <macros.h>
#include <hash_eda.h>
#include <pcb_edit_frame.h>
#include <pcbnew_settings.h>
#include <pgm_base.h>
#include <project/project_file.h>
#include <wx/app.h>
#include <wx/filedlg.h>

Go to the source code of this file.

Functions

static bool CreateHeaderInfoData (FILE *aFile, PCB_EDIT_FRAME *frame)
 
static void CreateArtworksSection (FILE *aFile)
 
static void CreateTracksInfoData (FILE *aFile, BOARD *aPcb)
 
static void CreateBoardSection (FILE *aFile, BOARD *aPcb)
 
static void CreateComponentsSection (FILE *aFile, BOARD *aPcb)
 
static void CreateDevicesSection (FILE *aFile, BOARD *aPcb)
 
static void CreateRoutesSection (FILE *aFile, BOARD *aPcb)
 
static void CreateSignalsSection (FILE *aFile, BOARD *aPcb)
 
static void CreateShapesSection (FILE *aFile, BOARD *aPcb)
 
static void CreatePadsShapesSection (FILE *aFile, BOARD *aPcb)
 
static void FootprintWriteShape (FILE *File, FOOTPRINT *aFootprint, const wxString &aShapeName)
 
static std::string GenCADLayerName (int aCuCount, PCB_LAYER_ID aId)
 
static std::string GenCADLayerNameFlipped (int aCuCount, PCB_LAYER_ID aId)
 
static wxString escapeString (const wxString &aString)
 
static std::string fmt_mask (LSET aSet)
 
static const wxString getShapeName (FOOTPRINT *aFootprint)
 
static double MapXTo (int aX)
 
static double MapYTo (int aY)
 
static bool ViaSort (const PCB_VIA *aPadref, const PCB_VIA *aPadcmp)
 
static size_t hashFootprint (const FOOTPRINT *aFootprint)
 Compute hashes for footprints without taking into account their position, rotation or layer. More...
 

Variables

static const PCB_LAYER_ID gc_seq []
 
static bool flipBottomPads
 
static bool uniquePins
 
static bool individualShapes
 
static bool storeOriginCoords
 
static int GencadOffsetX
 
static int GencadOffsetY
 
static std::map< FOOTPRINT *, int > componentShapes
 
static std::map< int, wxString > shapeNames
 
static const double SCALE_FACTOR = 1000.0 * IU_PER_MILS
 

Detailed Description

Export GenCAD 1.4 format.

Definition in file export_gencad.cpp.

Function Documentation

◆ CreateArtworksSection()

static void CreateArtworksSection ( FILE *  aFile)
static

Definition at line 357 of file export_gencad.cpp.

358{
359 /* The artworks section is empty */
360 fputs( "$ARTWORKS\n", aFile );
361 fputs( "$ENDARTWORKS\n\n", aFile );
362}

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateBoardSection()

static void CreateBoardSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1136 of file export_gencad.cpp.

1137{
1138 fputs( "$BOARD\n", aFile );
1139
1140 // Extract the board edges
1141 for( BOARD_ITEM* drawing : aPcb->Drawings() )
1142 {
1143 if( drawing->Type() == PCB_SHAPE_T )
1144 {
1145 PCB_SHAPE* drawseg = static_cast<PCB_SHAPE*>( drawing );
1146
1147 if( drawseg->GetLayer() == Edge_Cuts )
1148 {
1149 // XXX GenCAD supports arc boundaries but I've seen nothing that reads them
1150 fprintf( aFile, "LINE %g %g %g %g\n",
1151 MapXTo( drawseg->GetStart().x ), MapYTo( drawseg->GetStart().y ),
1152 MapXTo( drawseg->GetEnd().x ), MapYTo( drawseg->GetEnd().y ) );
1153 }
1154 }
1155 }
1156
1157 fputs( "$ENDBOARD\n\n", aFile );
1158}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:53
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:170
DRAWINGS & Drawings()
Definition: board.h:285
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:140
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:115
static double MapXTo(int aX)
static double MapYTo(int aY)
@ Edge_Cuts
Definition: layer_ids.h:113
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90

References BOARD::Drawings(), Edge_Cuts, EDA_SHAPE::GetEnd(), BOARD_ITEM::GetLayer(), EDA_SHAPE::GetStart(), MapXTo(), MapYTo(), PCB_SHAPE_T, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateComponentsSection()

static void CreateComponentsSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 854 of file export_gencad.cpp.

855{
856 fputs( "$COMPONENTS\n", aFile );
857
858 int cu_count = aPcb->GetCopperLayerCount();
859
860 for( FOOTPRINT* footprint : aPcb->Footprints() )
861 {
862 const char* mirror;
863 const char* flip;
864 EDA_ANGLE fp_orient = footprint->GetOrientation();
865
866 if( footprint->GetFlag() )
867 {
868 mirror = "MIRRORX";
869 flip = "FLIP";
870 fp_orient = fp_orient.Invert().Normalize();
871 }
872 else
873 {
874 mirror = "0";
875 flip = "0";
876 }
877
878 fprintf( aFile, "\nCOMPONENT \"%s\"\n",
879 TO_UTF8( escapeString( footprint->GetReference() ) ) );
880 fprintf( aFile, "DEVICE \"DEV_%s\"\n",
881 TO_UTF8( escapeString( getShapeName( footprint ) ) ) );
882 fprintf( aFile, "PLACE %g %g\n",
883 MapXTo( footprint->GetPosition().x ),
884 MapYTo( footprint->GetPosition().y ) );
885 fprintf( aFile, "LAYER %s\n",
886 footprint->GetFlag() ? "BOTTOM" : "TOP" );
887 fprintf( aFile, "ROTATION %g\n",
888 fp_orient.AsDegrees() );
889 fprintf( aFile, "SHAPE \"%s\" %s %s\n",
890 TO_UTF8( escapeString( getShapeName( footprint ) ) ),
891 mirror, flip );
892
893 // Text on silk layer: RefDes and value (are they actually useful?)
894 for( FP_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
895 {
896 std::string layer = GenCADLayerName( cu_count,
897 footprint->GetFlag() ? B_SilkS : F_SilkS );
898
899 fprintf( aFile, "TEXT %g %g %g %g %s %s \"%s\"",
900 textItem->GetPos0().x / SCALE_FACTOR,
901 -textItem->GetPos0().y / SCALE_FACTOR,
902 textItem->GetTextWidth() / SCALE_FACTOR,
903 textItem->GetTextAngle().AsDegrees(),
904 mirror,
905 layer.c_str(),
906 TO_UTF8( escapeString( textItem->GetText() ) ) );
907
908 // Please note, the width is approx
909 fprintf( aFile, " 0 0 %g %g\n",
910 ( textItem->GetTextWidth() * textItem->GetLength() ) / SCALE_FACTOR,
911 textItem->GetTextHeight() / SCALE_FACTOR );
912 }
913
914 // The SHEET is a 'generic description' for referencing the component
915 fprintf( aFile, "SHEET \"RefDes: %s, Value: %s\"\n",
916 TO_UTF8( footprint->GetReference() ),
917 TO_UTF8( footprint->GetValue() ) );
918 }
919
920 fputs( "$ENDCOMPONENTS\n\n", aFile );
921}
FOOTPRINTS & Footprints()
Definition: board.h:282
int GetCopperLayerCount() const
Definition: board.cpp:486
EDA_ANGLE Normalize()
Definition: eda_angle.h:260
double AsDegrees() const
Definition: eda_angle.h:149
EDA_ANGLE Invert() const
Definition: eda_angle.h:212
static const wxString getShapeName(FOOTPRINT *aFootprint)
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
static const double SCALE_FACTOR
static wxString escapeString(const wxString &aString)
@ F_SilkS
Definition: layer_ids.h:104
@ B_SilkS
Definition: layer_ids.h:103
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96

References EDA_ANGLE::AsDegrees(), B_SilkS, escapeString(), F_SilkS, BOARD::Footprints(), GenCADLayerName(), BOARD::GetCopperLayerCount(), getShapeName(), EDA_ANGLE::Invert(), MapXTo(), MapYTo(), EDA_ANGLE::Normalize(), SCALE_FACTOR, and TO_UTF8.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateDevicesSection()

static void CreateDevicesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1104 of file export_gencad.cpp.

1105{
1106 std::set<wxString> emitted;
1107 fputs( "$DEVICES\n", aFile );
1108
1109 for( const auto& componentShape : componentShapes )
1110 {
1111 const wxString& shapeName = shapeNames[componentShape.second];
1112 bool newDevice;
1113 std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1114
1115 if( !newDevice ) // do not repeat device definitions
1116 continue;
1117
1118 const FOOTPRINT* footprint = componentShape.first;
1119
1120 fprintf( aFile, "\nDEVICE \"DEV_%s\"\n", TO_UTF8( escapeString( shapeName ) ) );
1121
1122 fprintf( aFile, "PART \"%s\"\n",
1123 TO_UTF8( escapeString( footprint->GetValue() ) ) );
1124
1125 fprintf( aFile, "PACKAGE \"%s\"\n",
1126 TO_UTF8( escapeString( footprint->GetFPID().Format() ) ) );
1127 }
1128
1129 fputs( "$ENDDEVICES\n\n", aFile );
1130}
const LIB_ID & GetFPID() const
Definition: footprint.h:208
const wxString & GetValue() const
Definition: footprint.h:490
UTF8 Format() const
Definition: lib_id.cpp:116
static std::map< int, wxString > shapeNames
static std::map< FOOTPRINT *, int > componentShapes

References componentShapes, escapeString(), LIB_ID::Format(), FOOTPRINT::GetFPID(), FOOTPRINT::GetValue(), shapeNames, and TO_UTF8.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateHeaderInfoData()

static bool CreateHeaderInfoData ( FILE *  aFile,
PCB_EDIT_FRAME frame 
)
static

Definition at line 973 of file export_gencad.cpp.

974{
975 wxString msg;
976 BOARD* board = aFrame->GetBoard();
977
978 fputs( "$HEADER\n", aFile );
979 fputs( "GENCAD 1.4\n", aFile );
980
981 // Please note: GenCAD syntax requires quoted strings if they can contain spaces
982 msg.Printf( wxT( "USER \"%s %s\"\n" ),
983 Pgm().App().GetAppName(),
984 GetBuildVersion() );
985 fputs( TO_UTF8( msg ), aFile );
986
987 msg = wxT( "DRAWING \"" ) + board->GetFileName() + wxT( "\"\n" );
988 fputs( TO_UTF8( msg ), aFile );
989
990 wxString rev = ExpandTextVars( board->GetTitleBlock().GetRevision(), board->GetProject() );
991 wxString date = ExpandTextVars( board->GetTitleBlock().GetDate(), board->GetProject() );
992 msg = wxT( "REVISION \"" ) + rev + wxT( " " ) + date + wxT( "\"\n" );
993
994 fputs( TO_UTF8( msg ), aFile );
995 fputs( "UNITS INCH\n", aFile );
996
997 // giving 0 as the argument to Map{X,Y}To returns the scaled origin point
998 msg.Printf( wxT( "ORIGIN %g %g\n" ),
999 storeOriginCoords ? MapXTo( 0 ) : 0,
1000 storeOriginCoords ? MapYTo( 0 ) : 0 );
1001 fputs( TO_UTF8( msg ), aFile );
1002
1003 fputs( "INTERTRACK 0\n", aFile );
1004 fputs( "$ENDHEADER\n\n", aFile );
1005
1006 return true;
1007}
wxString GetBuildVersion()
Get the full KiCad version string.
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:37
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:240
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:599
const wxString & GetFileName() const
Definition: board.h:277
PROJECT * GetProject() const
Definition: board.h:415
const wxString & GetRevision() const
Definition: title_block.h:86
const wxString & GetDate() const
Definition: title_block.h:76
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:57
static bool storeOriginCoords
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111

References ExpandTextVars(), PCB_BASE_FRAME::GetBoard(), GetBuildVersion(), TITLE_BLOCK::GetDate(), BOARD::GetFileName(), BOARD::GetProject(), TITLE_BLOCK::GetRevision(), BOARD::GetTitleBlock(), MapXTo(), MapYTo(), Pgm(), storeOriginCoords, and TO_UTF8.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreatePadsShapesSection()

static void CreatePadsShapesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 367 of file export_gencad.cpp.

368{
369 std::vector<PAD*> padstacks;
370 std::vector<PCB_VIA*> vias;
371 std::vector<PCB_VIA*> viastacks;
372
373 padstacks.resize( 1 ); // We count pads from 1
374
375 // The master layermask (i.e. the enabled layers) for padstack generation
376 LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
377 int cu_count = aPcb->GetCopperLayerCount();
378
379 fputs( "$PADS\n", aFile );
380
381 // Enumerate and sort the pads
382
383 std::vector<PAD*> pads = aPcb->GetPads();
384 std::sort( pads.begin(), pads.end(), []( const PAD* a, const PAD* b )
385 {
386 return PAD::Compare( a, b ) < 0;
387 } );
388
389
390 // The same for vias
391 for( PCB_TRACK* track : aPcb->Tracks() )
392 {
393 if( PCB_VIA* via = dyn_cast<PCB_VIA*>( track ) )
394 vias.push_back( via );
395 }
396
397 std::sort( vias.begin(), vias.end(), ViaSort );
398 vias.erase( std::unique( vias.begin(), vias.end(), []( const PCB_VIA* a, const PCB_VIA* b )
399 {
400 return ViaSort( a, b ) == false;
401 } ),
402 vias.end() );
403
404 // Emit vias pads
405 for( PCB_VIA* via : vias )
406 {
407 viastacks.push_back( via );
408 fprintf( aFile, "PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
409 via->GetWidth(), via->GetDrillValue(),
410 fmt_mask( via->GetLayerSet() & master_layermask ).c_str(),
411 via->GetDrillValue() / SCALE_FACTOR,
412 via->GetWidth() / (SCALE_FACTOR * 2) );
413 }
414
415 // Emit component pads
416 PAD* old_pad = nullptr;
417 int pad_name_number = 0;
418
419 for( unsigned i = 0; i<pads.size(); ++i )
420 {
421 PAD* pad = pads[i];
422 const VECTOR2I& off = pad->GetOffset();
423
424 pad->SetSubRatsnest( pad_name_number );
425
426 // @warning: This code is not 100% correct. The #PAD::Compare function does not test
427 // custom pad primitives so there may be duplicate custom pads in the export.
428 if( old_pad && 0 == PAD::Compare( old_pad, pad ) )
429 continue;
430
431 old_pad = pad;
432
433 pad_name_number++;
434 pad->SetSubRatsnest( pad_name_number );
435
436 fprintf( aFile, "PAD P%d", pad->GetSubRatsnest() );
437
438 padstacks.push_back( pad ); // Will have its own padstack later
439 int dx = pad->GetSize().x / 2;
440 int dy = pad->GetSize().y / 2;
441
442 switch( pad->GetShape() )
443 {
444 default:
445 UNIMPLEMENTED_FOR( pad->ShowPadShape() );
447
449 fprintf( aFile, " ROUND %g\n",
450 pad->GetDrillSize().x / SCALE_FACTOR );
451
452 /* Circle is center, radius */
453 fprintf( aFile, "CIRCLE %g %g %g\n",
454 off.x / SCALE_FACTOR,
455 -off.y / SCALE_FACTOR,
456 pad->GetSize().x / (SCALE_FACTOR * 2) );
457 break;
458
459 case PAD_SHAPE::RECT:
460 fprintf( aFile, " RECTANGULAR %g\n",
461 pad->GetDrillSize().x / SCALE_FACTOR );
462
463 // Rectangle is begin, size *not* begin, end!
464 fprintf( aFile, "RECTANGLE %g %g %g %g\n",
465 (-dx + off.x ) / SCALE_FACTOR,
466 (-dy - off.y ) / SCALE_FACTOR,
467 dx / (SCALE_FACTOR / 2), dy / (SCALE_FACTOR / 2) );
468 break;
469
471 case PAD_SHAPE::OVAL:
472 {
473 const VECTOR2I& size = pad->GetSize();
474 int radius = std::min( size.x, size.y ) / 2;
475
476 if( pad->GetShape() == PAD_SHAPE::ROUNDRECT )
477 {
478 radius = pad->GetRoundRectCornerRadius();
479 }
480
481 int lineX = size.x / 2 - radius;
482 int lineY = size.y / 2 - radius;
483
484 fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
485
486 // bottom left arc
487 fprintf( aFile, "ARC %g %g %g %g %g %g\n",
488 ( off.x - lineX - radius ) / SCALE_FACTOR,
489 ( -off.y - lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
490 ( -off.y - lineY - radius ) / SCALE_FACTOR,
491 ( off.x - lineX ) / SCALE_FACTOR, ( -off.y - lineY ) / SCALE_FACTOR );
492
493 // bottom line
494 if( lineX > 0 )
495 {
496 fprintf( aFile, "LINE %g %g %g %g\n",
497 ( off.x - lineX ) / SCALE_FACTOR,
498 ( -off.y - lineY - radius ) / SCALE_FACTOR,
499 ( off.x + lineX ) / SCALE_FACTOR,
500 ( -off.y - lineY - radius ) / SCALE_FACTOR );
501 }
502
503 // bottom right arc
504 fprintf( aFile, "ARC %g %g %g %g %g %g\n",
505 ( off.x + lineX ) / SCALE_FACTOR,
506 ( -off.y - lineY - radius ) / SCALE_FACTOR,
507 ( off.x + lineX + radius ) / SCALE_FACTOR,
508 ( -off.y - lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
509 ( -off.y - lineY ) / SCALE_FACTOR );
510
511 // right line
512 if( lineY > 0 )
513 {
514 fprintf( aFile, "LINE %g %g %g %g\n",
515 ( off.x + lineX + radius ) / SCALE_FACTOR,
516 ( -off.y + lineY ) / SCALE_FACTOR,
517 ( off.x + lineX + radius ) / SCALE_FACTOR,
518 ( -off.y - lineY ) / SCALE_FACTOR );
519 }
520
521 // top right arc
522 fprintf( aFile, "ARC %g %g %g %g %g %g\n",
523 ( off.x + lineX + radius ) / SCALE_FACTOR,
524 ( -off.y + lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
525 ( -off.y + lineY + radius ) / SCALE_FACTOR,
526 ( off.x + lineX ) / SCALE_FACTOR, ( -off.y + lineY ) / SCALE_FACTOR );
527
528 // top line
529 if( lineX > 0 )
530 {
531 fprintf( aFile, "LINE %g %g %g %g\n"
532 , ( off.x - lineX ) / SCALE_FACTOR,
533 ( -off.y + lineY + radius ) / SCALE_FACTOR,
534 ( off.x + lineX ) / SCALE_FACTOR,
535 ( -off.y + lineY + radius ) / SCALE_FACTOR );
536 }
537
538 // top left arc
539 fprintf( aFile, "ARC %g %g %g %g %g %g\n",
540 ( off.x - lineX ) / SCALE_FACTOR,
541 ( -off.y + lineY + radius ) / SCALE_FACTOR,
542 ( off.x - lineX - radius ) / SCALE_FACTOR,
543 ( -off.y + lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
544 ( -off.y + lineY ) / SCALE_FACTOR );
545
546 // left line
547 if( lineY > 0 )
548 {
549 fprintf( aFile, "LINE %g %g %g %g\n",
550 ( off.x - lineX - radius ) / SCALE_FACTOR,
551 ( -off.y - lineY ) / SCALE_FACTOR,
552 ( off.x - lineX - radius ) / SCALE_FACTOR,
553 ( -off.y + lineY ) / SCALE_FACTOR );
554 }
555
556 break;
557 }
558
560 {
561 fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
562
563 int ddx = pad->GetDelta().x / 2;
564 int ddy = pad->GetDelta().y / 2;
565
566 VECTOR2I poly[4];
567 poly[0] = VECTOR2I( -dx + ddy, dy + ddx );
568 poly[1] = VECTOR2I( dx - ddy, dy - ddx );
569 poly[2] = VECTOR2I( dx + ddy, -dy + ddx );
570 poly[3] = VECTOR2I( -dx - ddy, -dy - ddx );
571
572 for( int cur = 0; cur < 4; ++cur )
573 {
574 int next = ( cur + 1 ) % 4;
575 fprintf( aFile, "LINE %g %g %g %g\n",
576 ( off.x + poly[cur].x ) / SCALE_FACTOR,
577 ( -off.y - poly[cur].y ) / SCALE_FACTOR,
578 ( off.x + poly[next].x ) / SCALE_FACTOR,
579 ( -off.y - poly[next].y ) / SCALE_FACTOR );
580 }
581
582 break;
583 }
584
586 {
587 fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
588
589 SHAPE_POLY_SET outline;
590 int maxError = aPcb->GetDesignSettings().m_MaxError;
591 VECTOR2I padOffset( 0, 0 );
592
593 TransformRoundChamferedRectToPolygon( outline, padOffset, pad->GetSize(),
594 pad->GetOrientation(),
595 pad->GetRoundRectCornerRadius(),
596 pad->GetChamferRectRatio(),
597 pad->GetChamferPositions(), 0, maxError,
598 ERROR_INSIDE );
599
600 for( int jj = 0; jj < outline.OutlineCount(); ++jj )
601 {
602 const SHAPE_LINE_CHAIN& poly = outline.COutline( jj );
603 int pointCount = poly.PointCount();
604
605 for( int ii = 0; ii < pointCount; ii++ )
606 {
607 int next = ( ii + 1 ) % pointCount;
608 fprintf( aFile, "LINE %g %g %g %g\n",
609 poly.CPoint( ii ).x / SCALE_FACTOR,
610 -poly.CPoint( ii ).y / SCALE_FACTOR,
611 poly.CPoint( next ).x / SCALE_FACTOR,
612 -poly.CPoint( next ).y / SCALE_FACTOR );
613 }
614 }
615
616 break;
617 }
618
620 {
621 fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
622
623 SHAPE_POLY_SET outline;
624 pad->MergePrimitivesAsPolygon( &outline );
625
626 for( int jj = 0; jj < outline.OutlineCount(); ++jj )
627 {
628 const SHAPE_LINE_CHAIN& poly = outline.COutline( jj );
629 int pointCount = poly.PointCount();
630
631 for( int ii = 0; ii < pointCount; ii++ )
632 {
633 int next = ( ii + 1 ) % pointCount;
634 fprintf( aFile, "LINE %g %g %g %g\n",
635 ( off.x + poly.CPoint( ii ).x ) / SCALE_FACTOR,
636 ( -off.y - poly.CPoint( ii ).y ) / SCALE_FACTOR,
637 ( off.x + poly.CPoint( next ).x ) / SCALE_FACTOR,
638 ( -off.y - poly.CPoint( next ).y ) / SCALE_FACTOR );
639 }
640 }
641
642 break;
643 }
644 }
645 }
646
647 fputs( "\n$ENDPADS\n\n", aFile );
648
649 // Now emit the padstacks definitions, using the combined layer masks
650 fputs( "$PADSTACKS\n", aFile );
651
652 // Via padstacks
653 for( unsigned i = 0; i < viastacks.size(); i++ )
654 {
655 PCB_VIA* via = viastacks[i];
656
657 LSET mask = via->GetLayerSet() & master_layermask;
658
659 fprintf( aFile, "PADSTACK VIA%d.%d.%s %g\n",
660 via->GetWidth(), via->GetDrillValue(),
661 fmt_mask( mask ).c_str(),
662 via->GetDrillValue() / SCALE_FACTOR );
663
664 for( LSEQ seq = mask.Seq( gc_seq, arrayDim( gc_seq ) ); seq; ++seq )
665 {
666 PCB_LAYER_ID layer = *seq;
667
668 fprintf( aFile, "PAD V%d.%d.%s %s 0 0\n",
669 via->GetWidth(), via->GetDrillValue(),
670 fmt_mask( mask ).c_str(),
671 GenCADLayerName( cu_count, layer ).c_str() );
672 }
673 }
674
675 /* Component padstacks
676 * Older versions of CAM350 don't apply correctly the FLIP semantics for
677 * padstacks, i.e. doesn't swap the top and bottom layers... so I need to
678 * define the shape as MIRRORX and define a separate 'flipped' padstack...
679 * until it appears yet another non-compliant importer */
680 for( unsigned i = 1; i < padstacks.size(); i++ )
681 {
682 PAD* pad = padstacks[i];
683
684 // Straight padstack
685 fprintf( aFile, "PADSTACK PAD%u %g\n", i, pad->GetDrillSize().x / SCALE_FACTOR );
686
687 LSET pad_set = pad->GetLayerSet() & master_layermask;
688
689 // the special gc_seq
690 for( LSEQ seq = pad_set.Seq( gc_seq, arrayDim( gc_seq ) ); seq; ++seq )
691 {
692 PCB_LAYER_ID layer = *seq;
693
694 fprintf( aFile, "PAD P%u %s 0 0\n", i, GenCADLayerName( cu_count, layer ).c_str() );
695 }
696
697 // Flipped padstack
698 if( flipBottomPads )
699 {
700 fprintf( aFile, "PADSTACK PAD%uF %g\n", i, pad->GetDrillSize().x / SCALE_FACTOR );
701
702 // the normal PCB_LAYER_ID sequence is inverted from gc_seq[]
703 for( LSEQ seq = pad_set.Seq(); seq; ++seq )
704 {
705 PCB_LAYER_ID layer = *seq;
706
707 fprintf( aFile, "PAD P%u %s 0 0\n", i,
708 GenCADLayerNameFlipped( cu_count, layer ).c_str() );
709 }
710 }
711 }
712
713 fputs( "$ENDPADSTACKS\n\n", aFile );
714}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
Definition: board.cpp:1954
TRACKS & Tracks()
Definition: board.h:279
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:615
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:490
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:529
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
Definition: pad.h:59
static int Compare(const PAD *aPadRef, const PAD *aPadCmp)
Compare two pads and return 0 if they are equal.
Definition: pad.cpp:1064
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
static bool ViaSort(const PCB_VIA *aPadref, const PCB_VIA *aPadcmp)
static const PCB_LAYER_ID gc_seq[]
static bool flipBottomPads
static std::string fmt_mask(LSET aSet)
static std::string GenCADLayerNameFlipped(int aCuCount, PCB_LAYER_ID aId)
@ ERROR_INSIDE
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:120
CITER next(CITER it)
Definition: ptree.cpp:126
VECTOR2< int > VECTOR2I
Definition: vector2d.h:607

References arrayDim(), CHAMFERED_RECT, CIRCLE, PAD::Compare(), SHAPE_POLY_SET::COutline(), SHAPE_LINE_CHAIN::CPoint(), CUSTOM, ERROR_INSIDE, flipBottomPads, fmt_mask(), gc_seq, GenCADLayerName(), GenCADLayerNameFlipped(), BOARD::GetCopperLayerCount(), BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetEnabledLayers(), BOARD::GetPads(), KI_FALLTHROUGH, BOARD_DESIGN_SETTINGS::m_MaxError, next(), SHAPE_POLY_SET::OutlineCount(), OVAL, pad, SHAPE_LINE_CHAIN::PointCount(), RECT, ROUNDRECT, SCALE_FACTOR, LSET::Seq(), BOARD::Tracks(), TransformRoundChamferedRectToPolygon(), TRAPEZOID, UNIMPLEMENTED_FOR, via, ViaSort(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateRoutesSection()

static void CreateRoutesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1019 of file export_gencad.cpp.

1020{
1021 int vianum = 1;
1022 int old_netcode, old_width, old_layer;
1023 LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
1024
1025 int cu_count = aPcb->GetCopperLayerCount();
1026
1027 TRACKS tracks( aPcb->Tracks() );
1028 std::sort( tracks.begin(), tracks.end(),
1029 []( const PCB_TRACK* a, const PCB_TRACK* b )
1030 {
1031 if( a->GetNetCode() == b->GetNetCode() )
1032 {
1033 if( a->GetWidth() == b->GetWidth() )
1034 return ( a->GetLayer() < b->GetLayer() );
1035
1036 return ( a->GetWidth() < b->GetWidth() );
1037 }
1038
1039 return ( a->GetNetCode() < b->GetNetCode() );
1040 } );
1041
1042 fputs( "$ROUTES\n", aFile );
1043
1044 old_netcode = -1; old_width = -1; old_layer = -1;
1045
1046 for( PCB_TRACK* track : tracks )
1047 {
1048 if( old_netcode != track->GetNetCode() )
1049 {
1050 old_netcode = track->GetNetCode();
1051 NETINFO_ITEM* net = track->GetNet();
1052 wxString netname;
1053
1054 if( net && (net->GetNetname() != wxEmptyString) )
1055 netname = net->GetNetname();
1056 else
1057 netname = wxT( "_noname_" );
1058
1059 fprintf( aFile, "ROUTE \"%s\"\n", TO_UTF8( escapeString( netname ) ) );
1060 }
1061
1062 if( old_width != track->GetWidth() )
1063 {
1064 old_width = track->GetWidth();
1065 fprintf( aFile, "TRACK TRACK%d\n", track->GetWidth() );
1066 }
1067
1068 if( track->Type() == PCB_TRACE_T )
1069 {
1070 if( old_layer != track->GetLayer() )
1071 {
1072 old_layer = track->GetLayer();
1073 fprintf( aFile, "LAYER %s\n",
1074 GenCADLayerName( cu_count, track->GetLayer() ).c_str() );
1075 }
1076
1077 fprintf( aFile, "LINE %g %g %g %g\n",
1078 MapXTo( track->GetStart().x ), MapYTo( track->GetStart().y ),
1079 MapXTo( track->GetEnd().x ), MapYTo( track->GetEnd().y ) );
1080 }
1081
1082 if( track->Type() == PCB_VIA_T )
1083 {
1084 const PCB_VIA* via = static_cast<const PCB_VIA*>(track);
1085
1086 LSET vset = via->GetLayerSet() & master_layermask;
1087
1088 fprintf( aFile, "VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
1089 via->GetWidth(), via->GetDrillValue(),
1090 fmt_mask( vset ).c_str(),
1091 MapXTo( via->GetStart().x ), MapYTo( via->GetStart().y ),
1092 via->GetDrillValue() / SCALE_FACTOR, vianum++ );
1093 }
1094 }
1095
1096 fputs( "$ENDROUTES\n\n", aFile );
1097}
Handle the data for a net.
Definition: netinfo.h:66
const wxString & GetNetname() const
Definition: netinfo.h:127
void vset(double *v, double x, double y, double z)
Definition: trackball.cpp:82
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:104
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:103

References BOARD::GetCopperLayerCount(), BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetEnabledLayers(), BOARD_CONNECTED_ITEM::GetNetCode(), and BOARD::Tracks().

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateShapesSection()

static void CreateShapesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 738 of file export_gencad.cpp.

739{
740 const char* layer;
741 wxString pinname;
742 const char* mirror = "0";
743 std::map<wxString, size_t> shapes;
744
745 fputs( "$SHAPES\n", aFile );
746
747 for( FOOTPRINT* footprint : aPcb->Footprints() )
748 {
749 if( !individualShapes )
750 {
751 // Check if such shape has been already generated, and if so - reuse it
752 // It is necessary to compute hash (i.e. check all children objects) as
753 // certain components instances might have been modified on the board.
754 // In such case the shape will be different despite the same LIB_ID.
755 wxString shapeName = footprint->GetFPID().Format();
756
757 auto shapeIt = shapes.find( shapeName );
758 size_t modHash = hashFootprint( footprint );
759
760 if( shapeIt != shapes.end() )
761 {
762 if( modHash != shapeIt->second )
763 {
764 // there is an entry for this footprint, but it has a modified shape,
765 // so we need to create a new entry
766 wxString newShapeName;
767 int suffix = 0;
768
769 // find an unused name or matching entry
770 do
771 {
772 newShapeName = wxString::Format( wxT( "%s_%d" ), shapeName, suffix );
773 shapeIt = shapes.find( newShapeName );
774 ++suffix;
775 }
776 while( shapeIt != shapes.end() && shapeIt->second != modHash );
777
778 shapeName = newShapeName;
779 }
780
781 if( shapeIt != shapes.end() && modHash == shapeIt->second )
782 {
783 // shape found, so reuse it
784 componentShapes[footprint] = modHash;
785 continue;
786 }
787 }
788
789 // new shape
790 componentShapes[footprint] = modHash;
791 shapeNames[modHash] = shapeName;
792 shapes[shapeName] = modHash;
793 FootprintWriteShape( aFile, footprint, shapeName );
794 }
795 else // individual shape for each component
796 {
797 FootprintWriteShape( aFile, footprint, footprint->GetReference() );
798 }
799
800 // set of already emitted pins to check for duplicates
801 std::set<wxString> pins;
802
803 for( PAD* pad : footprint->Pads() )
804 {
805 /* Padstacks are defined using the correct layers for the pads, therefore to
806 * all pads need to be marked as TOP to use the padstack information correctly.
807 */
808 layer = "TOP";
809 pinname = pad->GetNumber();
810
811 if( pinname.IsEmpty() )
812 pinname = wxT( "none" );
813
814 if( uniquePins )
815 {
816 int suffix = 0;
817 wxString origPinname( pinname );
818
819 auto it = pins.find( pinname );
820
821 while( it != pins.end() )
822 {
823 pinname = wxString::Format( wxT( "%s_%d" ), origPinname, suffix );
824 ++suffix;
825 it = pins.find( pinname );
826 }
827
828 pins.insert( pinname );
829 }
830
831 EDA_ANGLE orient = pad->GetOrientation() - footprint->GetOrientation();
832 orient.Normalize();
833
834 // Bottom side footprints use the flipped padstack
835 fprintf( aFile, ( flipBottomPads && footprint->GetFlag() ) ?
836 "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
837 "PIN \"%s\" PAD%d %g %g %s %g %s\n",
838 TO_UTF8( escapeString( pinname ) ), pad->GetSubRatsnest(),
839 pad->GetPos0().x / SCALE_FACTOR,
840 -pad->GetPos0().y / SCALE_FACTOR,
841 layer, orient.AsDegrees(), mirror );
842 }
843 }
844
845 fputs( "$ENDSHAPES\n\n", aFile );
846}
static bool uniquePins
static size_t hashFootprint(const FOOTPRINT *aFootprint)
Compute hashes for footprints without taking into account their position, rotation or layer.
static void FootprintWriteShape(FILE *File, FOOTPRINT *aFootprint, const wxString &aShapeName)
static bool individualShapes
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200

References EDA_ANGLE::AsDegrees(), componentShapes, escapeString(), flipBottomPads, BOARD::Footprints(), FootprintWriteShape(), Format(), hashFootprint(), individualShapes, EDA_ANGLE::Normalize(), pad, SCALE_FACTOR, shapeNames, TO_UTF8, and uniquePins.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateSignalsSection()

static void CreateSignalsSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 926 of file export_gencad.cpp.

927{
928 wxString msg;
929 NETINFO_ITEM* net;
930 int NbNoConn = 1;
931
932 fputs( "$SIGNALS\n", aFile );
933
934 for( unsigned ii = 0; ii < aPcb->GetNetCount(); ii++ )
935 {
936 net = aPcb->FindNet( ii );
937
938 if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection)
939 {
940 msg.Printf( wxT( "NoConnection%d" ), NbNoConn++ );
941 }
942
943 if( net->GetNetCode() <= 0 ) // dummy netlist (no connection)
944 continue;
945
946 msg = wxT( "SIGNAL \"" ) + escapeString( net->GetNetname() ) + wxT( "\"" );
947
948 fputs( TO_UTF8( msg ), aFile );
949 fputs( "\n", aFile );
950
951 for( FOOTPRINT* footprint : aPcb->Footprints() )
952 {
953 for( PAD* pad : footprint->Pads() )
954 {
955 if( pad->GetNetCode() != net->GetNetCode() )
956 continue;
957
958 msg.Printf( wxT( "NODE \"%s\" \"%s\"" ),
959 escapeString( footprint->GetReference() ),
960 escapeString( pad->GetNumber() ) );
961
962 fputs( TO_UTF8( msg ), aFile );
963 fputs( "\n", aFile );
964 }
965 }
966 }
967
968 fputs( "$ENDSIGNALS\n\n", aFile );
969}
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1432
unsigned GetNetCount() const
Definition: board.h:768
int GetNetCode() const
Definition: netinfo.h:121

References escapeString(), BOARD::FindNet(), BOARD::Footprints(), NETINFO_ITEM::GetNetCode(), BOARD::GetNetCount(), NETINFO_ITEM::GetNetname(), pad, and TO_UTF8.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateTracksInfoData()

static void CreateTracksInfoData ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1171 of file export_gencad.cpp.

1172{
1173 // Find thickness used for traces
1174
1175 std::set<int> trackinfo;
1176
1177 for( PCB_TRACK* track : aPcb->Tracks() )
1178 trackinfo.insert( track->GetWidth() );
1179
1180 // Write data
1181 fputs( "$TRACKS\n", aFile );
1182
1183 for( int size : trackinfo )
1184 fprintf( aFile, "TRACK TRACK%d %g\n", size, size / SCALE_FACTOR );
1185
1186 fputs( "$ENDTRACKS\n\n", aFile );
1187}

References SCALE_FACTOR, and BOARD::Tracks().

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ escapeString()

static wxString escapeString ( const wxString &  aString)
static

Definition at line 169 of file export_gencad.cpp.

170{
171 wxString copy( aString );
172 copy.Replace( wxT( "\"" ), wxT( "\\\"" ) );
173 return copy;
174}

References copy.

Referenced by CreateComponentsSection(), CreateDevicesSection(), CreateShapesSection(), CreateSignalsSection(), and FootprintWriteShape().

◆ fmt_mask()

static std::string fmt_mask ( LSET  aSet)
static

Definition at line 177 of file export_gencad.cpp.

178{
179 return StrPrintf( "%08x", (unsigned) ( aSet & LSET::AllCuMask() ).to_ulong() );
180}
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
Definition: richio.cpp:79

References LSET::AllCuMask(), and StrPrintf().

Referenced by CreatePadsShapesSection().

◆ FootprintWriteShape()

static void FootprintWriteShape ( FILE *  File,
FOOTPRINT aFootprint,
const wxString &  aShapeName 
)
static

Definition at line 1195 of file export_gencad.cpp.

1196{
1197 FP_SHAPE* shape;
1198
1199 /* creates header: */
1200 fprintf( aFile, "\nSHAPE \"%s\"\n", TO_UTF8( escapeString( aShapeName ) ) );
1201
1202 if( aFootprint->GetAttributes() & FP_THROUGH_HOLE )
1203 fprintf( aFile, "INSERT TH\n" );
1204 else
1205 fprintf( aFile, "INSERT SMD\n" );
1206
1207 // Silk outline; wildly interpreted by various importers:
1208 // CAM350 read it right but only closed shapes
1209 // ProntoPlace double-flip it (at least the pads are correct)
1210 // GerberTool usually get it right...
1211 for( BOARD_ITEM* PtStruct : aFootprint->GraphicalItems() )
1212 {
1213 switch( PtStruct->Type() )
1214 {
1215 case PCB_FP_TEXT_T:
1216 case PCB_FP_TEXTBOX_T:
1217
1218 // If we wanted to export text, this is not the correct section
1219 break;
1220
1221 case PCB_FP_SHAPE_T:
1222 shape = (FP_SHAPE*) PtStruct;
1223
1224 if( shape->GetLayer() == F_SilkS || shape->GetLayer() == B_SilkS )
1225 {
1226 switch( shape->GetShape() )
1227 {
1228 case SHAPE_T::SEGMENT:
1229 fprintf( aFile, "LINE %g %g %g %g\n",
1230 shape->GetStart0().x / SCALE_FACTOR,
1231 -shape->GetStart0().y / SCALE_FACTOR,
1232 shape->GetEnd0().x / SCALE_FACTOR,
1233 -shape->GetEnd0().y / SCALE_FACTOR );
1234 break;
1235
1236 case SHAPE_T::RECT:
1237 {
1238 fprintf( aFile, "LINE %g %g %g %g\n",
1239 shape->GetStart0().x / SCALE_FACTOR,
1240 -shape->GetStart0().y / SCALE_FACTOR,
1241 shape->GetEnd0().x / SCALE_FACTOR,
1242 -shape->GetStart0().y / SCALE_FACTOR );
1243 fprintf( aFile, "LINE %g %g %g %g\n",
1244 shape->GetEnd0().x / SCALE_FACTOR,
1245 -shape->GetStart0().y / SCALE_FACTOR,
1246 shape->GetEnd0().x / SCALE_FACTOR,
1247 -shape->GetEnd0().y / SCALE_FACTOR );
1248 fprintf( aFile, "LINE %g %g %g %g\n",
1249 shape->GetEnd0().x / SCALE_FACTOR,
1250 -shape->GetEnd0().y / SCALE_FACTOR,
1251 shape->GetStart0().x / SCALE_FACTOR,
1252 -shape->GetEnd0().y / SCALE_FACTOR );
1253 fprintf( aFile, "LINE %g %g %g %g\n",
1254 shape->GetStart0().x / SCALE_FACTOR,
1255 -shape->GetEnd0().y / SCALE_FACTOR,
1256 shape->GetStart0().x / SCALE_FACTOR,
1257 -shape->GetStart0().y / SCALE_FACTOR );
1258 }
1259 break;
1260
1261 case SHAPE_T::CIRCLE:
1262 {
1263 int radius = KiROUND( GetLineLength( shape->GetEnd0(), shape->GetStart0() ) );
1264
1265 fprintf( aFile, "CIRCLE %g %g %g\n",
1266 shape->GetStart0().x / SCALE_FACTOR,
1267 -shape->GetStart0().y / SCALE_FACTOR,
1268 radius / SCALE_FACTOR );
1269 break;
1270 }
1271
1272 case SHAPE_T::ARC:
1273 {
1274 VECTOR2I start = shape->GetStart0();
1275 VECTOR2I end = shape->GetEnd0();
1276
1277 if( shape->GetArcAngle() > ANGLE_0 )
1278 std::swap( start, end );
1279
1280 fprintf( aFile, "ARC %g %g %g %g %g %g\n",
1281 start.x / SCALE_FACTOR,
1282 -start.y / SCALE_FACTOR,
1283 end.x / SCALE_FACTOR,
1284 -end.y / SCALE_FACTOR,
1285 shape->GetCenter0().x / SCALE_FACTOR,
1286 -shape->GetCenter0().y / SCALE_FACTOR );
1287 }
1288 break;
1289
1290 case SHAPE_T::POLY:
1291 // Not exported (TODO)
1292 break;
1293
1294 default:
1295 wxFAIL_MSG( wxString::Format( wxT( "Type Edge Module %d invalid." ),
1296 PtStruct->Type() ) );
1297 break;
1298 }
1299 }
1300 break;
1301
1302 default:
1303 break;
1304 }
1305 }
1306}
EDA_ANGLE GetArcAngle() const
Definition: eda_shape.cpp:535
SHAPE_T GetShape() const
Definition: eda_shape.h:110
int GetAttributes() const
Definition: footprint.h:246
DRAWINGS & GraphicalItems()
Definition: footprint.h:178
const VECTOR2I & GetEnd0() const
Definition: fp_shape.h:114
VECTOR2I GetCenter0() const
Definition: fp_shape.cpp:144
const VECTOR2I & GetStart0() const
Definition: fp_shape.h:111
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:423
@ FP_THROUGH_HOLE
Definition: footprint.h:68
double GetLineLength(const VECTOR2I &aPointA, const VECTOR2I &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:188
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:96
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:95
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:94
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:80

References ANGLE_0, ARC, B_SilkS, CIRCLE, escapeString(), F_SilkS, Format(), FP_THROUGH_HOLE, EDA_SHAPE::GetArcAngle(), FOOTPRINT::GetAttributes(), FP_SHAPE::GetCenter0(), FP_SHAPE::GetEnd0(), BOARD_ITEM::GetLayer(), GetLineLength(), EDA_SHAPE::GetShape(), FP_SHAPE::GetStart0(), FOOTPRINT::GraphicalItems(), KiROUND(), PCB_FP_SHAPE_T, PCB_FP_TEXT_T, PCB_FP_TEXTBOX_T, POLY, RECT, SCALE_FACTOR, SEGMENT, TO_UTF8, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by CreateShapesSection().

◆ GenCADLayerName()

static std::string GenCADLayerName ( int  aCuCount,
PCB_LAYER_ID  aId 
)
static

Definition at line 68 of file export_gencad.cpp.

69{
70 if( IsCopperLayer( aId ) )
71 {
72 if( aId == F_Cu )
73 return "TOP";
74 else if( aId == B_Cu )
75 return "BOTTOM";
76 else if( aId <= 14 )
77 return StrPrintf( "INNER%d", aCuCount - aId - 1 );
78 else
79 return StrPrintf( "LAYER%d", aId );
80 }
81
82 else
83 {
84 const char* txt;
85
86 // using a switch to clearly show mapping & catch out of bounds index.
87 switch( aId )
88 {
89 // Technicals
90 case B_Adhes: txt = "B.Adhes"; break;
91 case F_Adhes: txt = "F.Adhes"; break;
92 case B_Paste: txt = "SOLDERPASTE_BOTTOM"; break;
93 case F_Paste: txt = "SOLDERPASTE_TOP"; break;
94 case B_SilkS: txt = "SILKSCREEN_BOTTOM"; break;
95 case F_SilkS: txt = "SILKSCREEN_TOP"; break;
96 case B_Mask: txt = "SOLDERMASK_BOTTOM"; break;
97 case F_Mask: txt = "SOLDERMASK_TOP"; break;
98
99 // Users
100 case Dwgs_User: txt = "Dwgs.User"; break;
101 case Cmts_User: txt = "Cmts.User"; break;
102 case Eco1_User: txt = "Eco1.User"; break;
103 case Eco2_User: txt = "Eco2.User"; break;
104 case Edge_Cuts: txt = "Edge.Cuts"; break;
105 case Margin: txt = "Margin"; break;
106
107 // Footprint
108 case F_CrtYd: txt = "F_CrtYd"; break;
109 case B_CrtYd: txt = "B_CrtYd"; break;
110 case F_Fab: txt = "F_Fab"; break;
111 case B_Fab: txt = "B_Fab"; break;
112
113 default:
114 wxASSERT_MSG( 0, wxT( "aId UNEXPECTED" ) );
115 txt = "BAD-INDEX!"; break;
116 }
117
118 return txt;
119 }
120}
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:822
@ F_CrtYd
Definition: layer_ids.h:117
@ B_Adhes
Definition: layer_ids.h:97
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ Cmts_User
Definition: layer_ids.h:110
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_Fab
Definition: layer_ids.h:120
@ Margin
Definition: layer_ids.h:114
@ B_CrtYd
Definition: layer_ids.h:116
@ Eco2_User
Definition: layer_ids.h:112
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:119

References B_Adhes, B_CrtYd, B_Cu, B_Fab, B_Mask, B_Paste, B_SilkS, Cmts_User, Dwgs_User, Eco1_User, Eco2_User, Edge_Cuts, F_Adhes, F_CrtYd, F_Cu, F_Fab, F_Mask, F_Paste, F_SilkS, IsCopperLayer(), Margin, and StrPrintf().

Referenced by CreateComponentsSection(), CreatePadsShapesSection(), and GenCADLayerNameFlipped().

◆ GenCADLayerNameFlipped()

static std::string GenCADLayerNameFlipped ( int  aCuCount,
PCB_LAYER_ID  aId 
)
static

Definition at line 160 of file export_gencad.cpp.

161{
162 if( 1<= aId && aId <= 14 )
163 return StrPrintf( "INNER%d", 14 - aId );
164
165 return GenCADLayerName( aCuCount, aId );
166}

References GenCADLayerName(), and StrPrintf().

Referenced by CreatePadsShapesSection().

◆ getShapeName()

static const wxString getShapeName ( FOOTPRINT aFootprint)
static

Definition at line 197 of file export_gencad.cpp.

198{
199 static const wxString invalid( "invalid" );
200
201 if( individualShapes )
202 return aFootprint->GetReference();
203
204 auto itShape = componentShapes.find( aFootprint );
205 wxCHECK( itShape != componentShapes.end(), invalid );
206
207 auto itName = shapeNames.find( itShape->second );
208 wxCHECK( itName != shapeNames.end(), invalid );
209
210 return itName->second;
211}
const wxString & GetReference() const
Definition: footprint.h:468

References componentShapes, FOOTPRINT::GetReference(), individualShapes, and shapeNames.

Referenced by CreateComponentsSection().

◆ hashFootprint()

static size_t hashFootprint ( const FOOTPRINT aFootprint)
static

Compute hashes for footprints without taking into account their position, rotation or layer.

Definition at line 718 of file export_gencad.cpp.

719{
720 size_t ret = 0x11223344;
721 constexpr int flags = HASH_FLAGS::HASH_POS | HASH_FLAGS::REL_COORD
723
724 for( BOARD_ITEM* i : aFootprint->GraphicalItems() )
725 ret += hash_fp_item( i, flags );
726
727 for( PAD* i : aFootprint->Pads() )
728 ret += hash_fp_item( i, flags );
729
730 return ret;
731}
PADS & Pads()
Definition: footprint.h:175
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
Definition: hash_eda.cpp:50
@ HASH_POS
use coordinates relative to the parent object
Definition: hash_eda.h:43
@ REL_COORD
Definition: hash_eda.h:46
@ HASH_LAYER
Definition: hash_eda.h:48
@ HASH_ROT
Definition: hash_eda.h:47

References FOOTPRINT::GraphicalItems(), hash_fp_item(), HASH_LAYER, HASH_POS, HASH_ROT, FOOTPRINT::Pads(), and REL_COORD.

Referenced by CreateShapesSection().

◆ MapXTo()

static double MapXTo ( int  aX)
static

Definition at line 221 of file export_gencad.cpp.

222{
223 return (aX - GencadOffsetX) / SCALE_FACTOR;
224}
static int GencadOffsetX

References GencadOffsetX, and SCALE_FACTOR.

Referenced by CreateBoardSection(), CreateComponentsSection(), and CreateHeaderInfoData().

◆ MapYTo()

static double MapYTo ( int  aY)
static

Definition at line 227 of file export_gencad.cpp.

228{
229 return (GencadOffsetY - aY) / SCALE_FACTOR;
230}
static int GencadOffsetY

References GencadOffsetY, and SCALE_FACTOR.

Referenced by CreateBoardSection(), CreateComponentsSection(), and CreateHeaderInfoData().

◆ ViaSort()

static bool ViaSort ( const PCB_VIA aPadref,
const PCB_VIA aPadcmp 
)
static

Definition at line 341 of file export_gencad.cpp.

342{
343 if( aPadref->GetWidth() != aPadcmp->GetWidth() )
344 return aPadref->GetWidth() < aPadcmp->GetWidth();
345
346 if( aPadref->GetDrillValue() != aPadcmp->GetDrillValue() )
347 return aPadref->GetDrillValue() < aPadcmp->GetDrillValue();
348
349 if( aPadref->GetLayerSet() != aPadcmp->GetLayerSet() )
350 return aPadref->GetLayerSet().FmtBin().compare( aPadcmp->GetLayerSet().FmtBin() ) < 0;
351
352 return false;
353}
std::string FmtBin() const
Return a binary string showing contents of this LSEQ.
Definition: lset.cpp:297
int GetWidth() const
Definition: pcb_track.h:103
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:184
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pcb_track.cpp:437

References LSET::FmtBin(), PCB_VIA::GetDrillValue(), PCB_VIA::GetLayerSet(), and PCB_TRACK::GetWidth().

Referenced by CreatePadsShapesSection().

Variable Documentation

◆ componentShapes

std::map<FOOTPRINT*, int> componentShapes
static

◆ flipBottomPads

bool flipBottomPads
static

◆ gc_seq

const PCB_LAYER_ID gc_seq[]
static

Definition at line 123 of file export_gencad.cpp.

Referenced by CreatePadsShapesSection().

◆ GencadOffsetX

int GencadOffsetX
static

Definition at line 190 of file export_gencad.cpp.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD(), and MapXTo().

◆ GencadOffsetY

int GencadOffsetY
static

Definition at line 190 of file export_gencad.cpp.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD(), and MapYTo().

◆ individualShapes

bool individualShapes
static

◆ SCALE_FACTOR

const double SCALE_FACTOR = 1000.0 * IU_PER_MILS
static

◆ shapeNames

◆ storeOriginCoords

bool storeOriginCoords
static

Definition at line 187 of file export_gencad.cpp.

Referenced by CreateHeaderInfoData(), and PCB_EDIT_FRAME::ExportToGenCAD().

◆ uniquePins

bool uniquePins
static

Definition at line 185 of file export_gencad.cpp.

Referenced by CreateShapesSection(), and PCB_EDIT_FRAME::ExportToGenCAD().