KiCad PCB EDA Suite
export_gencad.cpp File Reference

Export GenCAD 1.4 format. More...

#include <build_version.h>
#include <board.h>
#include <fp_shape.h>
#include <footprint.h>
#include <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>

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 VIA *aPadref, const 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 349 of file export_gencad.cpp.

350 {
351  /* The artworks section is empty */
352  fputs( "$ARTWORKS\n", aFile );
353  fputs( "$ENDARTWORKS\n\n", aFile );
354 }

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateBoardSection()

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

Definition at line 1089 of file export_gencad.cpp.

1090 {
1091  fputs( "$BOARD\n", aFile );
1092 
1093  // Extract the board edges
1094  for( BOARD_ITEM* drawing : aPcb->Drawings() )
1095  {
1096  if( drawing->Type() == PCB_SHAPE_T )
1097  {
1098  PCB_SHAPE* drawseg = static_cast<PCB_SHAPE*>( drawing );
1099 
1100  if( drawseg->GetLayer() == Edge_Cuts )
1101  {
1102  // XXX GenCAD supports arc boundaries but I've seen nothing that reads them
1103  fprintf( aFile, "LINE %g %g %g %g\n",
1104  MapXTo( drawseg->GetStart().x ), MapYTo( drawseg->GetStart().y ),
1105  MapXTo( drawseg->GetEnd().x ), MapYTo( drawseg->GetEnd().y ) );
1106  }
1107  }
1108  }
1109 
1110  fputs( "$ENDBOARD\n\n", aFile );
1111 }
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Definition: pcb_shape.h:156
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
static double MapYTo(int aY)
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Definition: pcb_shape.h:145
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173
DRAWINGS & Drawings()
Definition: board.h:308
static double MapXTo(int aX)

References BOARD::Drawings(), Edge_Cuts, PCB_SHAPE::GetEnd(), BOARD_ITEM::GetLayer(), PCB_SHAPE::GetStart(), MapXTo(), MapYTo(), and PCB_SHAPE_T.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateComponentsSection()

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

Definition at line 807 of file export_gencad.cpp.

808 {
809  fputs( "$COMPONENTS\n", aFile );
810 
811  int cu_count = aPcb->GetCopperLayerCount();
812 
813  for( FOOTPRINT* footprint : aPcb->Footprints() )
814  {
815  const char* mirror;
816  const char* flip;
817  double fp_orient = footprint->GetOrientation();
818 
819  if( footprint->GetFlag() )
820  {
821  mirror = "MIRRORX";
822  flip = "FLIP";
823  NEGATE_AND_NORMALIZE_ANGLE_POS( fp_orient );
824  }
825  else
826  {
827  mirror = "0";
828  flip = "0";
829  }
830 
831  fprintf( aFile, "\nCOMPONENT \"%s\"\n",
832  TO_UTF8( escapeString( footprint->GetReference() ) ) );
833  fprintf( aFile, "DEVICE \"DEV_%s\"\n",
834  TO_UTF8( escapeString( getShapeName( footprint ) ) ) );
835  fprintf( aFile, "PLACE %g %g\n",
836  MapXTo( footprint->GetPosition().x ),
837  MapYTo( footprint->GetPosition().y ) );
838  fprintf( aFile, "LAYER %s\n",
839  footprint->GetFlag() ? "BOTTOM" : "TOP" );
840  fprintf( aFile, "ROTATION %g\n",
841  fp_orient / 10.0 );
842  fprintf( aFile, "SHAPE \"%s\" %s %s\n",
843  TO_UTF8( escapeString( getShapeName( footprint ) ) ),
844  mirror, flip );
845 
846  // Text on silk layer: RefDes and value (are they actually useful?)
847  for( FP_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
848  {
849  double txt_orient = textItem->GetTextAngle();
850  std::string layer = GenCADLayerName( cu_count, footprint->GetFlag() ? B_SilkS : F_SilkS );
851 
852  fprintf( aFile, "TEXT %g %g %g %g %s %s \"%s\"",
853  textItem->GetPos0().x / SCALE_FACTOR,
854  -textItem->GetPos0().y / SCALE_FACTOR,
855  textItem->GetTextWidth() / SCALE_FACTOR,
856  txt_orient / 10.0,
857  mirror,
858  layer.c_str(),
859  TO_UTF8( escapeString( textItem->GetText() ) ) );
860 
861  // Please note, the width is approx
862  fprintf( aFile, " 0 0 %g %g\n",
863  ( textItem->GetTextWidth() * textItem->GetLength() ) / SCALE_FACTOR,
864  textItem->GetTextHeight() / SCALE_FACTOR );
865  }
866 
867  // The SHEET is a 'generic description' for referencing the component
868  fprintf( aFile, "SHEET \"RefDes: %s, Value: %s\"\n",
869  TO_UTF8( footprint->GetReference() ),
870  TO_UTF8( footprint->GetValue() ) );
871  }
872 
873  fputs( "$ENDCOMPONENTS\n\n", aFile );
874 }
static const wxString getShapeName(FOOTPRINT *aFootprint)
static double MapYTo(int aY)
static wxString escapeString(const wxString &aString)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
FOOTPRINTS & Footprints()
Definition: board.h:305
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
void NEGATE_AND_NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:353
int GetCopperLayerCount() const
Definition: board.cpp:435
static const double SCALE_FACTOR
static double MapXTo(int aX)

References B_SilkS, escapeString(), F_SilkS, BOARD::Footprints(), GenCADLayerName(), BOARD::GetCopperLayerCount(), getShapeName(), MapXTo(), MapYTo(), NEGATE_AND_NORMALIZE_ANGLE_POS(), SCALE_FACTOR, and TO_UTF8.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateDevicesSection()

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

Definition at line 1057 of file export_gencad.cpp.

1058 {
1059  std::set<wxString> emitted;
1060  fputs( "$DEVICES\n", aFile );
1061 
1062  for( const auto& componentShape : componentShapes )
1063  {
1064  const wxString& shapeName = shapeNames[componentShape.second];
1065  bool newDevice;
1066  std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1067 
1068  if( !newDevice ) // do not repeat device definitions
1069  continue;
1070 
1071  const FOOTPRINT* footprint = componentShape.first;
1072 
1073  fprintf( aFile, "\nDEVICE \"DEV_%s\"\n", TO_UTF8( escapeString( shapeName ) ) );
1074 
1075  fprintf( aFile, "PART \"%s\"\n",
1076  TO_UTF8( escapeString( footprint->GetValue() ) ) );
1077 
1078  fprintf( aFile, "PACKAGE \"%s\"\n",
1079  TO_UTF8( escapeString( footprint->GetFPID().Format() ) ) );
1080  }
1081 
1082  fputs( "$ENDDEVICES\n\n", aFile );
1083 }
const wxString & GetValue() const
Definition: footprint.h:454
static std::map< FOOTPRINT *, int > componentShapes
static wxString escapeString(const wxString &aString)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
const LIB_ID & GetFPID() const
Definition: footprint.h:190
UTF8 Format() const
Definition: lib_id.cpp:233
static std::map< int, wxString > shapeNames

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 926 of file export_gencad.cpp.

927 {
928  wxString msg;
929  BOARD* board = aFrame->GetBoard();
930 
931  fputs( "$HEADER\n", aFile );
932  fputs( "GENCAD 1.4\n", aFile );
933 
934  // Please note: GenCAD syntax requires quoted strings if they can contain spaces
935  msg.Printf( wxT( "USER \"%s %s\"\n" ),
936  Pgm().App().GetAppName(),
937  GetBuildVersion() );
938  fputs( TO_UTF8( msg ), aFile );
939 
940  msg = wxT( "DRAWING \"" ) + board->GetFileName() + wxT( "\"\n" );
941  fputs( TO_UTF8( msg ), aFile );
942 
943  const TITLE_BLOCK& tb = aFrame->GetTitleBlock();
944 
945  msg = wxT( "REVISION \"" ) + tb.GetRevision() + wxT( " " ) + tb.GetDate() + wxT( "\"\n" );
946 
947  fputs( TO_UTF8( msg ), aFile );
948  fputs( "UNITS INCH\n", aFile );
949 
950  // giving 0 as the argument to Map{X,Y}To returns the scaled origin point
951  msg.Printf( wxT( "ORIGIN %g %g\n" ),
952  storeOriginCoords ? MapXTo( 0 ) : 0,
953  storeOriginCoords ? MapYTo( 0 ) : 0 );
954  fputs( TO_UTF8( msg ), aFile );
955 
956  fputs( "INTERTRACK 0\n", aFile );
957  fputs( "$ENDHEADER\n\n", aFile );
958 
959  return true;
960 }
static double MapYTo(int aY)
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
const wxString & GetFileName() const
Definition: board.h:300
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:40
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
wxString GetBuildVersion()
Get the full KiCad version string.
const wxString & GetRevision() const
Definition: title_block.h:86
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
static bool storeOriginCoords
const wxString & GetDate() const
Definition: title_block.h:76
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
static double MapXTo(int aX)

References PCB_BASE_FRAME::GetBoard(), GetBuildVersion(), TITLE_BLOCK::GetDate(), BOARD::GetFileName(), TITLE_BLOCK::GetRevision(), PCB_BASE_FRAME::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 359 of file export_gencad.cpp.

360 {
361  std::vector<PAD*> padstacks;
362  std::vector<VIA*> vias;
363  std::vector<VIA*> viastacks;
364 
365  padstacks.resize( 1 ); // We count pads from 1
366 
367  // The master layermask (i.e. the enabled layers) for padstack generation
368  LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
369  int cu_count = aPcb->GetCopperLayerCount();
370 
371  fputs( "$PADS\n", aFile );
372 
373  // Enumerate and sort the pads
374 
375  std::vector<PAD*> pads = aPcb->GetPads();
376  std::sort( pads.begin(), pads.end(), []( const PAD* a, const PAD* b )
377  {
378  return PAD::Compare( a, b ) < 0;
379  } );
380 
381 
382  // The same for vias
383  for( TRACK* track : aPcb->Tracks() )
384  {
385  if( VIA* via = dyn_cast<VIA*>( track ) )
386  vias.push_back( via );
387  }
388 
389  std::sort( vias.begin(), vias.end(), ViaSort );
390  vias.erase( std::unique( vias.begin(), vias.end(), []( const VIA* a, const VIA* b )
391  {
392  return ViaSort( a, b ) == false;
393  } ),
394  vias.end() );
395 
396  // Emit vias pads
397 
398  for( VIA* via : vias )
399  {
400  viastacks.push_back( via );
401  fprintf( aFile, "PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
402  via->GetWidth(), via->GetDrillValue(),
403  fmt_mask( via->GetLayerSet() & master_layermask ).c_str(),
404  via->GetDrillValue() / SCALE_FACTOR,
405  via->GetWidth() / (SCALE_FACTOR * 2) );
406  }
407 
408  // Emit component pads
409  PAD* old_pad = 0;
410  int pad_name_number = 0;
411 
412  for( unsigned i = 0; i<pads.size(); ++i )
413  {
414  PAD* pad = pads[i];
415  const wxPoint& off = pad->GetOffset();
416 
417  pad->SetSubRatsnest( pad_name_number );
418 
419  if( old_pad && 0 == PAD::Compare( old_pad, pad ) )
420  continue; // already created
421 
422  old_pad = pad;
423 
424  pad_name_number++;
425  pad->SetSubRatsnest( pad_name_number );
426 
427  fprintf( aFile, "PAD P%d", pad->GetSubRatsnest() );
428 
429  padstacks.push_back( pad ); // Will have its own padstack later
430  int dx = pad->GetSize().x / 2;
431  int dy = pad->GetSize().y / 2;
432 
433  switch( pad->GetShape() )
434  {
435  default:
436  wxASSERT_MSG( false, "Pad type not implemented" );
438 
439  case PAD_SHAPE_CIRCLE:
440  fprintf( aFile, " ROUND %g\n",
441  pad->GetDrillSize().x / SCALE_FACTOR );
442  /* Circle is center, radius */
443  fprintf( aFile, "CIRCLE %g %g %g\n",
444  off.x / SCALE_FACTOR,
445  -off.y / SCALE_FACTOR,
446  pad->GetSize().x / (SCALE_FACTOR * 2) );
447  break;
448 
449  case PAD_SHAPE_RECT:
450  fprintf( aFile, " RECTANGULAR %g\n",
451  pad->GetDrillSize().x / SCALE_FACTOR );
452 
453  // Rectangle is begin, size *not* begin, end!
454  fprintf( aFile, "RECTANGLE %g %g %g %g\n",
455  (-dx + off.x ) / SCALE_FACTOR,
456  (-dy - off.y ) / SCALE_FACTOR,
457  dx / (SCALE_FACTOR / 2), dy / (SCALE_FACTOR / 2) );
458  break;
459 
460  case PAD_SHAPE_ROUNDRECT:
461  case PAD_SHAPE_OVAL:
462  {
463  const wxSize& size = pad->GetSize();
464  int radius;
465 
466  if( pad->GetShape() == PAD_SHAPE_ROUNDRECT )
467  radius = pad->GetRoundRectCornerRadius();
468  else
469  radius = std::min( size.x, size.y ) / 2;
470 
471  int lineX = size.x / 2 - radius;
472  int lineY = size.y / 2 - radius;
473 
474  fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
475 
476  // bottom left arc
477  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
478  ( off.x - lineX - radius ) / SCALE_FACTOR,
479  ( -off.y - lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
480  ( -off.y - lineY - radius ) / SCALE_FACTOR,
481  ( off.x - lineX ) / SCALE_FACTOR, ( -off.y - lineY ) / SCALE_FACTOR );
482 
483  // bottom line
484  if( lineX > 0 )
485  {
486  fprintf( aFile, "LINE %g %g %g %g\n",
487  ( off.x - lineX ) / SCALE_FACTOR,
488  ( -off.y - lineY - radius ) / SCALE_FACTOR,
489  ( off.x + lineX ) / SCALE_FACTOR,
490  ( -off.y - lineY - radius ) / SCALE_FACTOR );
491  }
492 
493  // bottom right arc
494  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
495  ( off.x + lineX ) / SCALE_FACTOR,
496  ( -off.y - lineY - radius ) / SCALE_FACTOR,
497  ( off.x + lineX + radius ) / SCALE_FACTOR,
498  ( -off.y - lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
499  ( -off.y - lineY ) / SCALE_FACTOR );
500 
501  // right line
502  if( lineY > 0 )
503  {
504  fprintf( aFile, "LINE %g %g %g %g\n",
505  ( off.x + lineX + radius ) / SCALE_FACTOR,
506  ( -off.y + lineY ) / SCALE_FACTOR,
507  ( off.x + lineX + radius ) / SCALE_FACTOR,
508  ( -off.y - lineY ) / SCALE_FACTOR );
509  }
510 
511  // top right arc
512  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
513  ( off.x + lineX + radius ) / SCALE_FACTOR,
514  ( -off.y + lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
515  ( -off.y + lineY + radius ) / SCALE_FACTOR,
516  ( off.x + lineX ) / SCALE_FACTOR, ( -off.y + lineY ) / SCALE_FACTOR );
517 
518  // top line
519  if( lineX > 0 )
520  {
521  fprintf( aFile, "LINE %g %g %g %g\n"
522  , ( off.x - lineX ) / SCALE_FACTOR,
523  ( -off.y + lineY + radius ) / SCALE_FACTOR,
524  ( off.x + lineX ) / SCALE_FACTOR,
525  ( -off.y + lineY + radius ) / SCALE_FACTOR );
526  }
527 
528  // top left arc
529  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
530  ( off.x - lineX ) / SCALE_FACTOR,
531  ( -off.y + lineY + radius ) / SCALE_FACTOR,
532  ( off.x - lineX - radius ) / SCALE_FACTOR,
533  ( -off.y + lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
534  ( -off.y + lineY ) / SCALE_FACTOR );
535 
536  // left line
537  if( lineY > 0 )
538  {
539  fprintf( aFile, "LINE %g %g %g %g\n",
540  ( off.x - lineX - radius ) / SCALE_FACTOR,
541  ( -off.y - lineY ) / SCALE_FACTOR,
542  ( off.x - lineX - radius ) / SCALE_FACTOR,
543  ( -off.y + lineY ) / SCALE_FACTOR );
544  }
545  }
546  break;
547 
548  case PAD_SHAPE_TRAPEZOID:
549  {
550  fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
551 
552  int ddx = pad->GetDelta().x / 2;
553  int ddy = pad->GetDelta().y / 2;
554 
555  wxPoint poly[4];
556  poly[0] = wxPoint( -dx + ddy, dy + ddx );
557  poly[1] = wxPoint( dx - ddy, dy - ddx );
558  poly[2] = wxPoint( dx + ddy, -dy + ddx );
559  poly[3] = wxPoint( -dx - ddy, -dy - ddx );
560 
561  for( int cur = 0; cur < 4; ++cur )
562  {
563  int next = ( cur + 1 ) % 4;
564  fprintf( aFile, "LINE %g %g %g %g\n",
565  ( off.x + poly[cur].x ) / SCALE_FACTOR,
566  ( -off.y - poly[cur].y ) / SCALE_FACTOR,
567  ( off.x + poly[next].x ) / SCALE_FACTOR,
568  ( -off.y - poly[next].y ) / SCALE_FACTOR );
569  }
570  }
571  break;
572 
573  case PAD_SHAPE_CUSTOM:
574  {
575  fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
576 
577  SHAPE_POLY_SET outline;
578  pad->MergePrimitivesAsPolygon( &outline, UNDEFINED_LAYER );
579 
580  for( int jj = 0; jj < outline.OutlineCount(); ++jj )
581  {
582  const SHAPE_LINE_CHAIN& poly = outline.COutline( jj );
583  int pointCount = poly.PointCount();
584 
585  for( int ii = 0; ii < pointCount; ii++ )
586  {
587  int next = ( ii + 1 ) % pointCount;
588  fprintf( aFile, "LINE %g %g %g %g\n",
589  ( off.x + poly.CPoint( ii ).x ) / SCALE_FACTOR,
590  ( -off.y - poly.CPoint( ii ).y ) / SCALE_FACTOR,
591  ( off.x + poly.CPoint( next ).x ) / SCALE_FACTOR,
592  ( -off.y - poly.CPoint( next ).y ) / SCALE_FACTOR );
593  }
594  }
595  }
596  break;
597  }
598  }
599 
600  fputs( "\n$ENDPADS\n\n", aFile );
601 
602  // Now emit the padstacks definitions, using the combined layer masks
603  fputs( "$PADSTACKS\n", aFile );
604 
605  // Via padstacks
606  for( unsigned i = 0; i < viastacks.size(); i++ )
607  {
608  VIA* via = viastacks[i];
609 
610  LSET mask = via->GetLayerSet() & master_layermask;
611 
612  fprintf( aFile, "PADSTACK VIA%d.%d.%s %g\n",
613  via->GetWidth(), via->GetDrillValue(),
614  fmt_mask( mask ).c_str(),
615  via->GetDrillValue() / SCALE_FACTOR );
616 
617  for( LSEQ seq = mask.Seq( gc_seq, arrayDim( gc_seq ) ); seq; ++seq )
618  {
619  PCB_LAYER_ID layer = *seq;
620 
621  fprintf( aFile, "PAD V%d.%d.%s %s 0 0\n",
622  via->GetWidth(), via->GetDrillValue(),
623  fmt_mask( mask ).c_str(),
624  GenCADLayerName( cu_count, layer ).c_str()
625  );
626  }
627  }
628 
629  /* Component padstacks
630  * Older versions of CAM350 don't apply correctly the FLIP semantics for
631  * padstacks, i.e. doesn't swap the top and bottom layers... so I need to
632  * define the shape as MIRRORX and define a separate 'flipped' padstack...
633  * until it appears yet another noncompliant importer */
634  for( unsigned i = 1; i < padstacks.size(); i++ )
635  {
636  PAD* pad = padstacks[i];
637 
638  // Straight padstack
639  fprintf( aFile, "PADSTACK PAD%u %g\n", i, pad->GetDrillSize().x / SCALE_FACTOR );
640 
641  LSET pad_set = pad->GetLayerSet() & master_layermask;
642 
643  // the special gc_seq
644  for( LSEQ seq = pad_set.Seq( gc_seq, arrayDim( gc_seq ) ); seq; ++seq )
645  {
646  PCB_LAYER_ID layer = *seq;
647 
648  fprintf( aFile, "PAD P%u %s 0 0\n", i, GenCADLayerName( cu_count, layer ).c_str() );
649  }
650 
651  // Flipped padstack
652  if( flipBottomPads )
653  {
654  fprintf( aFile, "PADSTACK PAD%uF %g\n", i, pad->GetDrillSize().x / SCALE_FACTOR );
655 
656  // the normal PCB_LAYER_ID sequence is inverted from gc_seq[]
657  for( LSEQ seq = pad_set.Seq(); seq; ++seq )
658  {
659  PCB_LAYER_ID layer = *seq;
660 
661  fprintf( aFile, "PAD P%u %s 0 0\n", i, GenCADLayerNameFlipped( cu_count, layer ).c_str() );
662  }
663  }
664  }
665 
666  fputs( "$ENDPADSTACKS\n\n", aFile );
667 }
CITER next(CITER it)
Definition: ptree.cpp:126
Definition: track.h:343
static int Compare(const PAD *padref, const PAD *padcmp)
Compare two pads and return 0 if they are equal.
Definition: pad.cpp:1002
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:593
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
static bool flipBottomPads
int PointCount() const
Function PointCount()
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
const VECTOR2I & CPoint(int aIndex) const
Function Point()
static std::string GenCADLayerNameFlipped(int aCuCount, PCB_LAYER_ID aId)
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
Represent a set of closed polygons.
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
Definition: board.cpp:1909
static const PCB_LAYER_ID gc_seq[]
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
static bool ViaSort(const VIA *aPadref, const VIA *aPadcmp)
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
SHAPE_LINE_CHAIN.
int GetCopperLayerCount() const
Definition: board.cpp:435
static const double SCALE_FACTOR
static std::string fmt_mask(LSET aSet)
Definition: pad.h:60
TRACKS & Tracks()
Definition: board.h:302
Definition: track.h:83

References arrayDim(), PAD::Compare(), SHAPE_LINE_CHAIN::CPoint(), flipBottomPads, fmt_mask(), gc_seq, GenCADLayerName(), GenCADLayerNameFlipped(), BOARD::GetCopperLayerCount(), BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetEnabledLayers(), BOARD::GetPads(), KI_FALLTHROUGH, next(), pad, PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, SHAPE_LINE_CHAIN::PointCount(), SCALE_FACTOR, LSET::Seq(), BOARD::Tracks(), UNDEFINED_LAYER, 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 972 of file export_gencad.cpp.

973 {
974  int vianum = 1;
975  int old_netcode, old_width, old_layer;
976  LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
977 
978  int cu_count = aPcb->GetCopperLayerCount();
979 
980  TRACKS tracks( aPcb->Tracks() );
981  std::sort( tracks.begin(), tracks.end(),
982  []( const TRACK* a, const TRACK* b )
983  {
984  if( a->GetNetCode() == b->GetNetCode() )
985  {
986  if( a->GetWidth() == b->GetWidth() )
987  return ( a->GetLayer() < b->GetLayer() );
988 
989  return ( a->GetWidth() < b->GetWidth() );
990  }
991 
992  return ( a->GetNetCode() < b->GetNetCode() );
993  } );
994 
995  fputs( "$ROUTES\n", aFile );
996 
997  old_netcode = -1; old_width = -1; old_layer = -1;
998 
999  for( TRACK* track : tracks )
1000  {
1001  if( old_netcode != track->GetNetCode() )
1002  {
1003  old_netcode = track->GetNetCode();
1004  NETINFO_ITEM* net = track->GetNet();
1005  wxString netname;
1006 
1007  if( net && (net->GetNetname() != wxEmptyString) )
1008  netname = net->GetNetname();
1009  else
1010  netname = wxT( "_noname_" );
1011 
1012  fprintf( aFile, "ROUTE \"%s\"\n", TO_UTF8( escapeString( netname ) ) );
1013  }
1014 
1015  if( old_width != track->GetWidth() )
1016  {
1017  old_width = track->GetWidth();
1018  fprintf( aFile, "TRACK TRACK%d\n", track->GetWidth() );
1019  }
1020 
1021  if( track->Type() == PCB_TRACE_T )
1022  {
1023  if( old_layer != track->GetLayer() )
1024  {
1025  old_layer = track->GetLayer();
1026  fprintf( aFile, "LAYER %s\n",
1027  GenCADLayerName( cu_count, track->GetLayer() ).c_str() );
1028  }
1029 
1030  fprintf( aFile, "LINE %g %g %g %g\n",
1031  MapXTo( track->GetStart().x ), MapYTo( track->GetStart().y ),
1032  MapXTo( track->GetEnd().x ), MapYTo( track->GetEnd().y ) );
1033  }
1034 
1035  if( track->Type() == PCB_VIA_T )
1036  {
1037  const VIA* via = static_cast<const VIA*>(track);
1038 
1039  LSET vset = via->GetLayerSet() & master_layermask;
1040 
1041  fprintf( aFile, "VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
1042  via->GetWidth(), via->GetDrillValue(),
1043  fmt_mask( vset ).c_str(),
1044  MapXTo( via->GetStart().x ), MapYTo( via->GetStart().y ),
1045  via->GetDrillValue() / SCALE_FACTOR, vianum++ );
1046  }
1047  }
1048 
1049  fputs( "$ENDROUTES\n\n", aFile );
1050 }
Definition: track.h:343
static double MapYTo(int aY)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:593
static wxString escapeString(const wxString &aString)
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
void vset(double *v, double x, double y, double z)
Definition: trackball.cpp:82
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
LSET is a set of PCB_LAYER_IDs.
const wxString & GetNetname() const
Definition: netinfo.h:119
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
Handle the data for a net.
Definition: netinfo.h:64
int GetWidth() const
Definition: track.h:110
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
int GetCopperLayerCount() const
Definition: board.cpp:435
static const double SCALE_FACTOR
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
static std::string fmt_mask(LSET aSet)
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173
TRACKS & Tracks()
Definition: board.h:302
Definition: track.h:83
static double MapXTo(int aX)

References escapeString(), fmt_mask(), GenCADLayerName(), BOARD::GetCopperLayerCount(), BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetEnabledLayers(), BOARD_ITEM::GetLayer(), BOARD_CONNECTED_ITEM::GetNetCode(), NETINFO_ITEM::GetNetname(), TRACK::GetWidth(), MapXTo(), MapYTo(), PCB_TRACE_T, PCB_VIA_T, SCALE_FACTOR, TO_UTF8, BOARD::Tracks(), via, and vset().

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ CreateShapesSection()

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

Definition at line 691 of file export_gencad.cpp.

692 {
693  const char* layer;
694  wxString pinname;
695  const char* mirror = "0";
696  std::map<wxString, size_t> shapes;
697 
698  fputs( "$SHAPES\n", aFile );
699 
700  for( FOOTPRINT* footprint : aPcb->Footprints() )
701  {
702  if( !individualShapes )
703  {
704  // Check if such shape has been already generated, and if so - reuse it
705  // It is necessary to compute hash (i.e. check all children objects) as
706  // certain components instances might have been modified on the board.
707  // In such case the shape will be different despite the same LIB_ID.
708  wxString shapeName = footprint->GetFPID().Format();
709 
710  auto shapeIt = shapes.find( shapeName );
711  size_t modHash = hashFootprint( footprint );
712 
713  if( shapeIt != shapes.end() )
714  {
715  if( modHash != shapeIt->second )
716  {
717  // there is an entry for this footprint, but it has a modified shape,
718  // so we need to create a new entry
719  wxString newShapeName;
720  int suffix = 0;
721 
722  // find an unused name or matching entry
723  do
724  {
725  newShapeName = wxString::Format( "%s_%d", shapeName, suffix );
726  shapeIt = shapes.find( newShapeName );
727  ++suffix;
728  }
729  while( shapeIt != shapes.end() && shapeIt->second != modHash );
730 
731  shapeName = newShapeName;
732  }
733 
734  if( shapeIt != shapes.end() && modHash == shapeIt->second )
735  {
736  // shape found, so reuse it
737  componentShapes[footprint] = modHash;
738  continue;
739  }
740  }
741 
742  // new shape
743  componentShapes[footprint] = modHash;
744  shapeNames[modHash] = shapeName;
745  shapes[shapeName] = modHash;
746  FootprintWriteShape( aFile, footprint, shapeName );
747  }
748  else // individual shape for each component
749  {
750  FootprintWriteShape( aFile, footprint, footprint->GetReference() );
751  }
752 
753  // set of already emitted pins to check for duplicates
754  std::set<wxString> pins;
755 
756  for( PAD* pad : footprint->Pads() )
757  {
758  /* Padstacks are defined using the correct layers for the pads, therefore to
759  * all pads need to be marked as TOP to use the padstack information correctly.
760  */
761  layer = "TOP";
762  pinname = pad->GetName();
763 
764  if( pinname.IsEmpty() )
765  pinname = wxT( "none" );
766 
767  if( uniquePins )
768  {
769  int suffix = 0;
770  wxString origPinname( pinname );
771 
772  auto it = pins.find( pinname );
773 
774  while( it != pins.end() )
775  {
776  pinname = wxString::Format( "%s_%d", origPinname, suffix );
777  ++suffix;
778  it = pins.find( pinname );
779  }
780 
781  pins.insert( pinname );
782  }
783 
784  double orient = pad->GetOrientation() - footprint->GetOrientation();
785  NORMALIZE_ANGLE_POS( orient );
786 
787  // Bottom side footprints use the flipped padstack
788  fprintf( aFile, ( flipBottomPads && footprint->GetFlag() ) ?
789  "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
790  "PIN \"%s\" PAD%d %g %g %s %g %s\n",
791  TO_UTF8( escapeString( pinname ) ), pad->GetSubRatsnest(),
792  pad->GetPos0().x / SCALE_FACTOR,
793  -pad->GetPos0().y / SCALE_FACTOR,
794  layer, orient / 10.0, mirror );
795  }
796  }
797 
798  fputs( "$ENDSHAPES\n\n", aFile );
799 }
static std::map< FOOTPRINT *, int > componentShapes
static bool uniquePins
static wxString escapeString(const wxString &aString)
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:288
static bool flipBottomPads
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
static size_t hashFootprint(const FOOTPRINT *aFootprint)
Compute hashes for footprints without taking into account their position, rotation or layer.
static bool individualShapes
FOOTPRINTS & Footprints()
Definition: board.h:305
static void FootprintWriteShape(FILE *File, FOOTPRINT *aFootprint, const wxString &aShapeName)
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
static const double SCALE_FACTOR
Definition: pad.h:60
static std::map< int, wxString > shapeNames

References componentShapes, escapeString(), flipBottomPads, BOARD::Footprints(), FootprintWriteShape(), Format(), hashFootprint(), individualShapes, NORMALIZE_ANGLE_POS(), 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 879 of file export_gencad.cpp.

880 {
881  wxString msg;
882  NETINFO_ITEM* net;
883  int NbNoConn = 1;
884 
885  fputs( "$SIGNALS\n", aFile );
886 
887  for( unsigned ii = 0; ii < aPcb->GetNetCount(); ii++ )
888  {
889  net = aPcb->FindNet( ii );
890 
891  if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection)
892  {
893  msg.Printf( "NoConnection%d", NbNoConn++ );
894  }
895 
896  if( net->GetNetCode() <= 0 ) // dummy netlist (no connection)
897  continue;
898 
899  msg = wxT( "SIGNAL \"" ) + escapeString( net->GetNetname() ) + "\"";
900 
901  fputs( TO_UTF8( msg ), aFile );
902  fputs( "\n", aFile );
903 
904  for( FOOTPRINT* footprint : aPcb->Footprints() )
905  {
906  for( PAD* pad : footprint->Pads() )
907  {
908  if( pad->GetNetCode() != net->GetNetCode() )
909  continue;
910 
911  msg.Printf( wxT( "NODE \"%s\" \"%s\"" ),
912  escapeString( footprint->GetReference() ),
913  escapeString( pad->GetName() ) );
914 
915  fputs( TO_UTF8( msg ), aFile );
916  fputs( "\n", aFile );
917  }
918  }
919  }
920 
921  fputs( "$ENDSIGNALS\n\n", aFile );
922 }
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1268
static wxString escapeString(const wxString &aString)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
unsigned GetNetCount() const
Definition: board.h:785
FOOTPRINTS & Footprints()
Definition: board.h:305
const wxString & GetNetname() const
Definition: netinfo.h:119
Handle the data for a net.
Definition: netinfo.h:64
Definition: pad.h:60
int GetNetCode() const
Definition: netinfo.h:113

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 1124 of file export_gencad.cpp.

1125 {
1126  // Find thickness used for traces
1127 
1128  std::set<int> trackinfo;
1129 
1130  for( TRACK* track : aPcb->Tracks() )
1131  trackinfo.insert( track->GetWidth() );
1132 
1133  // Write data
1134  fputs( "$TRACKS\n", aFile );
1135 
1136  for( int size : trackinfo )
1137  fprintf( aFile, "TRACK TRACK%d %g\n", size, size / SCALE_FACTOR );
1138 
1139  fputs( "$ENDTRACKS\n\n", aFile );
1140 }
static const double SCALE_FACTOR
TRACKS & Tracks()
Definition: board.h:302
Definition: track.h:83

References SCALE_FACTOR, and BOARD::Tracks().

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

◆ escapeString()

static wxString escapeString ( const wxString &  aString)
static

Definition at line 165 of file export_gencad.cpp.

166 {
167  wxString copy( aString );
168  copy.Replace( "\"", "\\\"" );
169  return copy;
170 }

References copy.

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

◆ fmt_mask()

static std::string fmt_mask ( LSET  aSet)
static

Definition at line 173 of file export_gencad.cpp.

174 {
175  return StrPrintf( "%08x", (unsigned) ( aSet & LSET::AllCuMask() ).to_ulong() );
176 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
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:78

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

Referenced by CreatePadsShapesSection(), and CreateRoutesSection().

◆ FootprintWriteShape()

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

Definition at line 1148 of file export_gencad.cpp.

1149 {
1150  FP_SHAPE* shape;
1151 
1152  /* creates header: */
1153  fprintf( aFile, "\nSHAPE \"%s\"\n", TO_UTF8( escapeString( aShapeName ) ) );
1154 
1155  if( aFootprint->GetAttributes() & FP_THROUGH_HOLE )
1156  fprintf( aFile, "INSERT TH\n" );
1157  else
1158  fprintf( aFile, "INSERT SMD\n" );
1159 
1160  // Silk outline; wildly interpreted by various importers:
1161  // CAM350 read it right but only closed shapes
1162  // ProntoPlace double-flip it (at least the pads are correct)
1163  // GerberTool usually get it right...
1164  for( BOARD_ITEM* PtStruct : aFootprint->GraphicalItems() )
1165  {
1166  switch( PtStruct->Type() )
1167  {
1168  case PCB_FP_TEXT_T:
1169 
1170  // If we wanted to export text, this is not the correct section
1171  break;
1172 
1173  case PCB_FP_SHAPE_T:
1174  shape = (FP_SHAPE*) PtStruct;
1175  if( shape->GetLayer() == F_SilkS || shape->GetLayer() == B_SilkS )
1176  {
1177  switch( shape->GetShape() )
1178  {
1179  case S_SEGMENT:
1180  fprintf( aFile, "LINE %g %g %g %g\n",
1181  shape->m_Start0.x / SCALE_FACTOR,
1182  -shape->m_Start0.y / SCALE_FACTOR,
1183  shape->m_End0.x / SCALE_FACTOR,
1184  -shape->m_End0.y / SCALE_FACTOR );
1185  break;
1186 
1187  case S_RECT:
1188  {
1189  fprintf( aFile, "LINE %g %g %g %g\n",
1190  shape->m_Start0.x / SCALE_FACTOR,
1191  -shape->m_Start0.y / SCALE_FACTOR,
1192  shape->m_End0.x / SCALE_FACTOR,
1193  -shape->m_Start0.y / SCALE_FACTOR );
1194  fprintf( aFile, "LINE %g %g %g %g\n",
1195  shape->m_End0.x / SCALE_FACTOR,
1196  -shape->m_Start0.y / SCALE_FACTOR,
1197  shape->m_End0.x / SCALE_FACTOR,
1198  -shape->m_End0.y / SCALE_FACTOR );
1199  fprintf( aFile, "LINE %g %g %g %g\n",
1200  shape->m_End0.x / SCALE_FACTOR,
1201  -shape->m_End0.y / SCALE_FACTOR,
1202  shape->m_Start0.x / SCALE_FACTOR,
1203  -shape->m_End0.y / SCALE_FACTOR );
1204  fprintf( aFile, "LINE %g %g %g %g\n",
1205  shape->m_Start0.x / SCALE_FACTOR,
1206  -shape->m_End0.y / SCALE_FACTOR,
1207  shape->m_Start0.x / SCALE_FACTOR,
1208  -shape->m_Start0.y / SCALE_FACTOR );
1209  }
1210  break;
1211 
1212  case S_CIRCLE:
1213  {
1214  int radius = KiROUND( GetLineLength( shape->m_End0, shape->m_Start0 ) );
1215  fprintf( aFile, "CIRCLE %g %g %g\n",
1216  shape->m_Start0.x / SCALE_FACTOR,
1217  -shape->m_Start0.y / SCALE_FACTOR,
1218  radius / SCALE_FACTOR );
1219  break;
1220  }
1221 
1222  case S_ARC:
1223  {
1224  int arcendx, arcendy;
1225  arcendx = shape->m_End0.x - shape->m_Start0.x;
1226  arcendy = shape->m_End0.y - shape->m_Start0.y;
1227  RotatePoint( &arcendx, &arcendy, -shape->GetAngle() );
1228  arcendx += shape->GetStart0().x;
1229  arcendy += shape->GetStart0().y;
1230 
1231  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
1232  shape->m_End0.x / SCALE_FACTOR,
1233  -shape->GetEnd0().y / SCALE_FACTOR,
1234  arcendx / SCALE_FACTOR,
1235  -arcendy / SCALE_FACTOR,
1236  shape->GetStart0().x / SCALE_FACTOR,
1237  -shape->GetStart0().y / SCALE_FACTOR );
1238  break;
1239  }
1240 
1241  case S_POLYGON:
1242  // Not exported (TODO)
1243  break;
1244 
1245  default:
1246  wxFAIL_MSG( wxString::Format( "Type Edge Module %d invalid.",
1247  PtStruct->Type() ) );
1248  break;
1249  }
1250  }
1251  break;
1252 
1253  default:
1254  break;
1255  }
1256  }
1257 }
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:223
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
polygon (not yet used for tracks, but could be in microwave apps)
Definition: board_item.h:54
const wxPoint & GetStart0() const
Definition: fp_shape.h:112
usual segment : line with rounded ends
Definition: board_item.h:50
Arcs (with rounded ends)
Definition: board_item.h:52
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
static wxString escapeString(const wxString &aString)
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:228
segment with non rounded ends
Definition: board_item.h:51
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
wxPoint m_End0
End point, relative to footprint origin, orient 0.
Definition: fp_shape.h:161
wxPoint m_Start0
Start point or center, relative to footprint origin, orient 0.
Definition: fp_shape.h:160
DRAWINGS & GraphicalItems()
Definition: footprint.h:167
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
int GetAttributes() const
Definition: footprint.h:231
double GetAngle() const
Definition: pcb_shape.h:127
const wxPoint & GetEnd0() const
Definition: fp_shape.h:115
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:68
static const double SCALE_FACTOR
ring
Definition: board_item.h:53
PCB_SHAPE_TYPE_T GetShape() const
Definition: pcb_shape.h:130
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173

References B_SilkS, escapeString(), F_SilkS, Format(), FP_THROUGH_HOLE, PCB_SHAPE::GetAngle(), FOOTPRINT::GetAttributes(), FP_SHAPE::GetEnd0(), BOARD_ITEM::GetLayer(), GetLineLength(), PCB_SHAPE::GetShape(), FP_SHAPE::GetStart0(), FOOTPRINT::GraphicalItems(), KiROUND(), FP_SHAPE::m_End0, FP_SHAPE::m_Start0, PCB_FP_SHAPE_T, PCB_FP_TEXT_T, RotatePoint(), S_ARC, S_CIRCLE, S_POLYGON, S_RECT, S_SEGMENT, SCALE_FACTOR, and TO_UTF8.

Referenced by CreateShapesSection().

◆ GenCADLayerName()

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

Definition at line 64 of file export_gencad.cpp.

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

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(), CreateRoutesSection(), and GenCADLayerNameFlipped().

◆ GenCADLayerNameFlipped()

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

Definition at line 156 of file export_gencad.cpp.

157 {
158  if( 1<= aId && aId <= 14 )
159  return StrPrintf( "INNER%d", 14 - aId );
160 
161  return GenCADLayerName( aCuCount, aId );
162 }
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:78
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)

References GenCADLayerName(), and StrPrintf().

Referenced by CreatePadsShapesSection().

◆ getShapeName()

static const wxString getShapeName ( FOOTPRINT aFootprint)
static

Definition at line 191 of file export_gencad.cpp.

192 {
193  static const wxString invalid( "invalid" );
194 
195  if( individualShapes )
196  return aFootprint->GetReference();
197 
198  auto itShape = componentShapes.find( aFootprint );
199  wxCHECK( itShape != componentShapes.end(), invalid );
200 
201  auto itName = shapeNames.find( itShape->second );
202  wxCHECK( itName != shapeNames.end(), invalid );
203 
204  return itName->second;
205 }
static std::map< FOOTPRINT *, int > componentShapes
static bool individualShapes
const wxString & GetReference() const
Definition: footprint.h:432
static std::map< int, wxString > shapeNames

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 671 of file export_gencad.cpp.

672 {
673  size_t ret = 0x11223344;
674  constexpr int flags = HASH_FLAGS::HASH_POS | HASH_FLAGS::REL_COORD
676 
677  for( BOARD_ITEM* i : aFootprint->GraphicalItems() )
678  ret += hash_fp_item( i, flags );
679 
680  for( PAD* i : aFootprint->Pads() )
681  ret += hash_fp_item( i, flags );
682 
683  return ret;
684 }
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
use coordinates relative to the parent object
Definition: hash_eda.h:43
PADS & Pads()
Definition: footprint.h:164
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
Definition: hash_eda.cpp:49
DRAWINGS & GraphicalItems()
Definition: footprint.h:167
Definition: pad.h:60

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 213 of file export_gencad.cpp.

214 {
215  return (aX - GencadOffsetX) / SCALE_FACTOR;
216 }
static const double SCALE_FACTOR
static int GencadOffsetX

References GencadOffsetX, and SCALE_FACTOR.

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

◆ MapYTo()

static double MapYTo ( int  aY)
static

Definition at line 219 of file export_gencad.cpp.

220 {
221  return (GencadOffsetY - aY) / SCALE_FACTOR;
222 }
static int GencadOffsetY
static const double SCALE_FACTOR

References GencadOffsetY, and SCALE_FACTOR.

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

◆ ViaSort()

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

Definition at line 333 of file export_gencad.cpp.

334 {
335  if( aPadref->GetWidth() != aPadcmp->GetWidth() )
336  return aPadref->GetWidth() < aPadcmp->GetWidth();
337 
338  if( aPadref->GetDrillValue() != aPadcmp->GetDrillValue() )
339  return aPadref->GetDrillValue() < aPadcmp->GetDrillValue();
340 
341  if( aPadref->GetLayerSet() != aPadcmp->GetLayerSet() )
342  return aPadref->GetLayerSet().FmtBin().compare( aPadcmp->GetLayerSet().FmtBin() ) < 0;
343 
344  return false;
345 }
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: track.cpp:376
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: track.cpp:173
int GetWidth() const
Definition: track.h:110
std::string FmtBin() const
Return a binary string showing contents of this LSEQ.
Definition: lset.cpp:297

References LSET::FmtBin(), VIA::GetDrillValue(), VIA::GetLayerSet(), and 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 119 of file export_gencad.cpp.

Referenced by CreatePadsShapesSection().

◆ GencadOffsetX

int GencadOffsetX
static

Definition at line 185 of file export_gencad.cpp.

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

◆ GencadOffsetY

int GencadOffsetY
static

Definition at line 185 of file export_gencad.cpp.

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

◆ individualShapes

bool individualShapes
static

◆ SCALE_FACTOR

◆ shapeNames

◆ storeOriginCoords

bool storeOriginCoords
static

Definition at line 182 of file export_gencad.cpp.

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

◆ uniquePins

bool uniquePins
static

Definition at line 180 of file export_gencad.cpp.

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