KiCad PCB EDA Suite
export_gencad.cpp File Reference

Export GenCAD 1.4 format. More...

#include <fctsys.h>
#include <class_drawpanel.h>
#include <confirm.h>
#include <gestfich.h>
#include <pgm_base.h>
#include <wxPcbStruct.h>
#include <trigo.h>
#include <build_version.h>
#include <macros.h>
#include <pcbnew.h>
#include <dialogs/dialog_gencad_export_options.h>
#include <class_board.h>
#include <class_module.h>
#include <class_track.h>
#include <class_edge_mod.h>
#include <hash_eda.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, MODULE *module, 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 (MODULE *aModule)
 
static double MapXTo (int aX)
 
static double MapYTo (int aY)
 
static int PadListSortByShape (const void *aRefptr, const void *aObjptr)
 
static int ViaSort (const void *aRefptr, const void *aObjptr)
 
static size_t hashModule (const MODULE *aModule)
 Compute hashes for modules without taking into account their position, rotation or layer. More...
 
static int TrackListSortByNetcode (const void *refptr, const void *objptr)
 

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< MODULE *, 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

static void CreateArtworksSection ( FILE *  aFile)
static

Definition at line 400 of file export_gencad.cpp.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

401 {
402  /* The artworks section is empty */
403  fputs( "$ARTWORKS\n", aFile );
404  fputs( "$ENDARTWORKS\n\n", aFile );
405 }
static void CreateBoardSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1195 of file export_gencad.cpp.

References BOARD::Drawings(), Edge_Cuts, DRAWSEGMENT::GetEnd(), BOARD_ITEM::GetLayer(), DRAWSEGMENT::GetStart(), MapXTo(), MapYTo(), PCB_LINE_T, wxPoint::x, and wxPoint::y.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

1196 {
1197  fputs( "$BOARD\n", aFile );
1198 
1199  // Extract the board edges
1200  for( auto drawing : aPcb->Drawings() )
1201  {
1202  if( drawing->Type() == PCB_LINE_T )
1203  {
1204  DRAWSEGMENT* drawseg = static_cast<DRAWSEGMENT*>( drawing );
1205  if( drawseg->GetLayer() == Edge_Cuts )
1206  {
1207  // XXX GenCAD supports arc boundaries but I've seen nothing that reads them
1208  fprintf( aFile, "LINE %g %g %g %g\n",
1209  MapXTo( drawseg->GetStart().x ), MapYTo( drawseg->GetStart().y ),
1210  MapXTo( drawseg->GetEnd().x ), MapYTo( drawseg->GetEnd().y ) );
1211  }
1212  }
1213  }
1214 
1215  fputs( "$ENDBOARD\n\n", aFile );
1216 }
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
static double MapYTo(int aY)
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:251
static double MapXTo(int aX)
static void CreateComponentsSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 855 of file export_gencad.cpp.

References B_SilkS, escapeString(), F_SilkS, GenCADLayerName(), BOARD::GetCopperLayerCount(), TEXTE_MODULE::GetLength(), TEXTE_MODULE::GetPos0(), getShapeName(), EDA_TEXT::GetText(), EDA_TEXT::GetTextAngle(), EDA_TEXT::GetTextHeight(), EDA_TEXT::GetTextWidth(), BOARD::m_Modules, MapXTo(), MapYTo(), NEGATE_AND_NORMALIZE_ANGLE_POS(), MODULE::Next(), SCALE_FACTOR, TO_UTF8, wxPoint::x, and wxPoint::y.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

856 {
857  fputs( "$COMPONENTS\n", aFile );
858 
859  int cu_count = aPcb->GetCopperLayerCount();
860 
861  for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
862  {
863  const char* mirror;
864  const char* flip;
865  double fp_orient = module->GetOrientation();
866 
867  if( module->GetFlag() )
868  {
869  mirror = "MIRRORX";
870  flip = "FLIP";
871  NEGATE_AND_NORMALIZE_ANGLE_POS( fp_orient );
872  }
873  else
874  {
875  mirror = "0";
876  flip = "0";
877  }
878 
879  fprintf( aFile, "\nCOMPONENT \"%s\"\n",
880  TO_UTF8( escapeString( module->GetReference() ) ) );
881  fprintf( aFile, "DEVICE \"DEV_%s\"\n",
882  TO_UTF8( escapeString( getShapeName( module ) ) ) );
883  fprintf( aFile, "PLACE %g %g\n",
884  MapXTo( module->GetPosition().x ),
885  MapYTo( module->GetPosition().y ) );
886  fprintf( aFile, "LAYER %s\n",
887  module->GetFlag() ? "BOTTOM" : "TOP" );
888  fprintf( aFile, "ROTATION %g\n",
889  fp_orient / 10.0 );
890  fprintf( aFile, "SHAPE \"%s\" %s %s\n",
891  TO_UTF8( escapeString( getShapeName( module ) ) ),
892  mirror, flip );
893 
894  // Text on silk layer: RefDes and value (are they actually useful?)
895  TEXTE_MODULE *textmod = &module->Reference();
896 
897  for( int ii = 0; ii < 2; ii++ )
898  {
899  double txt_orient = textmod->GetTextAngle();
900  std::string layer = GenCADLayerName( cu_count, module->GetFlag() ? B_SilkS : F_SilkS );
901 
902  fprintf( aFile, "TEXT %g %g %g %g %s %s \"%s\"",
903  textmod->GetPos0().x / SCALE_FACTOR,
904  -textmod->GetPos0().y / SCALE_FACTOR,
905  textmod->GetTextWidth() / SCALE_FACTOR,
906  txt_orient / 10.0,
907  mirror,
908  layer.c_str(),
909  TO_UTF8( escapeString( textmod->GetText() ) ) );
910 
911  // Please note, the width is approx
912  fprintf( aFile, " 0 0 %g %g\n",
913  ( textmod->GetTextWidth() * textmod->GetLength() ) / SCALE_FACTOR,
914  textmod->GetTextHeight() / SCALE_FACTOR );
915 
916  textmod = &module->Value(); // Dirty trick for the second iteration
917  }
918 
919  // The SHEET is a 'generic description' for referencing the component
920  fprintf( aFile, "SHEET \"RefDes: %s, Value: %s\"\n",
921  TO_UTF8( module->GetReference() ),
922  TO_UTF8( module->GetValue() ) );
923  }
924 
925  fputs( "$ENDCOMPONENTS\n\n", aFile );
926 }
int GetLength() const
const wxPoint & GetPos0() const
int GetTextWidth() const
Definition: eda_text.h:218
MODULE * Next() const
Definition: class_module.h:120
int GetCopperLayerCount() const
Function GetCopperLayerCount.
static double MapYTo(int aY)
static wxString escapeString(const wxString &aString)
double GetTextAngle() const
Definition: eda_text.h:164
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
void NEGATE_AND_NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:284
DLIST< MODULE > m_Modules
Definition: class_board.h:245
static const double SCALE_FACTOR
int GetTextHeight() const
Definition: eda_text.h:221
static const wxString & getShapeName(MODULE *aModule)
static double MapXTo(int aX)
static void CreateDevicesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1157 of file export_gencad.cpp.

References componentShapes, escapeString(), LIB_ID::Format(), MODULE::GetAttributes(), MODULE::GetFPID(), MODULE::GetValue(), MOD_CMS, MOD_VIRTUAL, shapeNames, and TO_UTF8.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

1158 {
1159  std::set<wxString> emitted;
1160  fputs( "$DEVICES\n", aFile );
1161 
1162  for( const auto& componentShape : componentShapes )
1163  {
1164  const wxString& shapeName = shapeNames[componentShape.second];
1165  bool newDevice;
1166  std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1167 
1168  if( !newDevice ) // do not repeat device definitions
1169  continue;
1170 
1171  const MODULE* module = componentShape.first;
1172  fprintf( aFile, "\nDEVICE \"DEV_%s\"\n", TO_UTF8( escapeString( shapeName ) ) );
1173  fprintf( aFile, "PART \"%s\"\n", TO_UTF8( escapeString( module->GetValue() ) ) );
1174  fprintf( aFile, "PACKAGE \"%s\"\n", TO_UTF8( escapeString( module->GetFPID().Format() ) ) );
1175 
1176  // The TYPE attribute is almost freeform
1177  const char* ty = "TH";
1178 
1179  if( module->GetAttributes() & MOD_CMS )
1180  ty = "SMD";
1181 
1182  if( module->GetAttributes() & MOD_VIRTUAL )
1183  ty = "VIRTUAL";
1184 
1185  fprintf( aFile, "TYPE %s\n", ty );
1186  }
1187 
1188  fputs( "$ENDDEVICES\n\n", aFile );
1189 }
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:76
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:467
static wxString escapeString(const wxString &aString)
const LIB_ID & GetFPID() const
Definition: class_module.h:184
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
int GetAttributes() const
Definition: class_module.h:217
Virtual component: when created by copper shapes on board (Like edge card connectors, mounting hole...)
Definition: class_module.h:78
UTF8 Format() const
Definition: lib_id.cpp:263
static std::map< MODULE *, int > componentShapes
static std::map< int, wxString > shapeNames
static bool CreateHeaderInfoData ( FILE *  aFile,
PCB_EDIT_FRAME frame 
)
static

Definition at line 980 of file export_gencad.cpp.

References PCB_BASE_FRAME::GetBoard(), GetBuildVersion(), GetChars(), 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().

981 {
982  wxString msg;
983  BOARD *board = aFrame->GetBoard();
984 
985  fputs( "$HEADER\n", aFile );
986  fputs( "GENCAD 1.4\n", aFile );
987 
988  // Please note: GenCAD syntax requires quoted strings if they can contain spaces
989  msg.Printf( wxT( "USER \"%s %s\"\n" ),
990  GetChars( Pgm().App().GetAppName() ),
991  GetChars( GetBuildVersion() ) );
992  fputs( TO_UTF8( msg ), aFile );
993 
994  msg = wxT( "DRAWING \"" ) + board->GetFileName() + wxT( "\"\n" );
995  fputs( TO_UTF8( msg ), aFile );
996 
997  const TITLE_BLOCK& tb = aFrame->GetTitleBlock();
998 
999  msg = wxT( "REVISION \"" ) + tb.GetRevision() + wxT( " " ) + tb.GetDate() + wxT( "\"\n" );
1000 
1001  fputs( TO_UTF8( msg ), aFile );
1002  fputs( "UNITS INCH\n", aFile );
1003 
1004  // giving 0 as the argument to Map{X,Y}To returns the scaled origin point
1005  msg.Printf( wxT( "ORIGIN %g %g\n" ),
1006  storeOriginCoords ? MapXTo( 0 ) : 0,
1007  storeOriginCoords ? MapYTo( 0 ) : 0 );
1008  fputs( TO_UTF8( msg ), aFile );
1009 
1010  fputs( "INTERTRACK 0\n", aFile );
1011  fputs( "$ENDHEADER\n\n", aFile );
1012 
1013  return true;
1014 }
static double MapYTo(int aY)
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
const wxString & GetDate() const
Class TITLE_BLOCK holds the information shown in the lower right corner of a plot, printout, or editing view.
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
wxString GetBuildVersion()
Function GetBuildVersion Return the build version string.
const wxString & GetFileName() const
Definition: class_board.h:234
const wxString & GetRevision() const
static bool storeOriginCoords
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
static double MapXTo(int aX)
static void CreatePadsShapesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 410 of file export_gencad.cpp.

References D_PAD::BuildPadPolygon(), D_PAD::Compare(), SHAPE_LINE_CHAIN::CPoint(), DIM, flipBottomPads, fmt_mask(), gc_seq, GenCADLayerName(), GenCADLayerNameFlipped(), BOARD::GetCopperLayerCount(), D_PAD::GetCustomShapeAsPolygon(), BOARD::GetDesignSettings(), D_PAD::GetDrillSize(), VIA::GetDrillValue(), BOARD_DESIGN_SETTINGS::GetEnabledLayers(), GetFirstVia(), D_PAD::GetLayerSet(), VIA::GetLayerSet(), D_PAD::GetOffset(), BOARD::GetPadCount(), BOARD::GetPads(), D_PAD::GetRoundRectCornerRadius(), D_PAD::GetShape(), D_PAD::GetSize(), D_PAD::GetSubRatsnest(), TRACK::GetWidth(), BOARD::m_Track, min, next(), PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, PadListSortByShape(), SHAPE_LINE_CHAIN::PointCount(), SCALE_FACTOR, LSET::Seq(), D_PAD::SetSubRatsnest(), ViaSort(), wxPoint::x, VECTOR2< T >::x, wxPoint::y, and VECTOR2< T >::y.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

411 {
412  std::vector<D_PAD*> pads;
413  std::vector<D_PAD*> padstacks;
414  std::vector<VIA*> vias;
415  std::vector<VIA*> viastacks;
416 
417  padstacks.resize( 1 ); // We count pads from 1
418 
419  // The master layermask (i.e. the enabled layers) for padstack generation
420  LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
421  int cu_count = aPcb->GetCopperLayerCount();
422 
423  fputs( "$PADS\n", aFile );
424 
425  // Enumerate and sort the pads
426  if( aPcb->GetPadCount() > 0 )
427  {
428  pads = aPcb->GetPads();
429  qsort( &pads[0], aPcb->GetPadCount(), sizeof( D_PAD* ),
431  }
432 
433  // The same for vias
434  for( VIA* via = GetFirstVia( aPcb->m_Track ); via;
435  via = GetFirstVia( via->Next() ) )
436  {
437  vias.push_back( via );
438  }
439 
440  qsort( &vias[0], vias.size(), sizeof(VIA*), ViaSort );
441 
442  // Emit vias pads
443  TRACK* old_via = 0;
444 
445  for( unsigned i = 0; i < vias.size(); i++ )
446  {
447  VIA* via = vias[i];
448 
449  if( old_via && 0 == ViaSort( &old_via, &via ) )
450  continue;
451 
452  old_via = via;
453  viastacks.push_back( via );
454  fprintf( aFile, "PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
455  via->GetWidth(), via->GetDrillValue(),
456  fmt_mask( via->GetLayerSet() & master_layermask ).c_str(),
457  via->GetDrillValue() / SCALE_FACTOR,
458  via->GetWidth() / (SCALE_FACTOR * 2) );
459  }
460 
461  // Emit component pads
462  D_PAD* old_pad = 0;
463  int pad_name_number = 0;
464 
465  for( unsigned i = 0; i<pads.size(); ++i )
466  {
467  D_PAD* pad = pads[i];
468  const wxPoint& off = pad->GetOffset();
469 
470  pad->SetSubRatsnest( pad_name_number );
471 
472  if( old_pad && 0==D_PAD::Compare( old_pad, pad ) )
473  continue; // already created
474 
475  old_pad = pad;
476 
477  pad_name_number++;
478  pad->SetSubRatsnest( pad_name_number );
479 
480  fprintf( aFile, "PAD P%d", pad->GetSubRatsnest() );
481 
482  padstacks.push_back( pad ); // Will have its own padstack later
483  int dx = pad->GetSize().x / 2;
484  int dy = pad->GetSize().y / 2;
485 
486  switch( pad->GetShape() )
487  {
488  default:
489  wxASSERT_MSG( false, "Pad type not implemented" );
490  // fall-through
491 
492  case PAD_SHAPE_CIRCLE:
493  fprintf( aFile, " ROUND %g\n",
494  pad->GetDrillSize().x / SCALE_FACTOR );
495  /* Circle is center, radius */
496  fprintf( aFile, "CIRCLE %g %g %g\n",
497  off.x / SCALE_FACTOR,
498  -off.y / SCALE_FACTOR,
499  pad->GetSize().x / (SCALE_FACTOR * 2) );
500  break;
501 
502  case PAD_SHAPE_RECT:
503  fprintf( aFile, " RECTANGULAR %g\n",
504  pad->GetDrillSize().x / SCALE_FACTOR );
505 
506  // Rectangle is begin, size *not* begin, end!
507  fprintf( aFile, "RECTANGLE %g %g %g %g\n",
508  (-dx + off.x ) / SCALE_FACTOR,
509  (-dy - off.y ) / SCALE_FACTOR,
510  dx / (SCALE_FACTOR / 2), dy / (SCALE_FACTOR / 2) );
511  break;
512 
513  case PAD_SHAPE_ROUNDRECT:
514  case PAD_SHAPE_OVAL:
515  {
516  const wxSize& size = pad->GetSize();
517  int radius;
518 
519  if( pad->GetShape() == PAD_SHAPE_ROUNDRECT )
520  radius = pad->GetRoundRectCornerRadius();
521  else
522  radius = std::min( size.x, size.y ) / 2;
523 
524  int lineX = size.x / 2 - radius;
525  int lineY = size.y / 2 - radius;
526 
527  fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
528 
529  // bottom left arc
530  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
531  ( off.x - lineX - radius ) / SCALE_FACTOR,
532  ( -off.y - lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
533  ( -off.y - lineY - radius ) / SCALE_FACTOR,
534  ( off.x - lineX ) / SCALE_FACTOR, ( -off.y - lineY ) / SCALE_FACTOR );
535 
536  // bottom line
537  if( lineX > 0 )
538  {
539  fprintf( aFile, "LINE %g %g %g %g\n",
540  ( off.x - lineX ) / SCALE_FACTOR,
541  ( -off.y - lineY - radius ) / SCALE_FACTOR,
542  ( off.x + lineX ) / SCALE_FACTOR,
543  ( -off.y - lineY - radius ) / SCALE_FACTOR );
544  }
545 
546  // bottom right arc
547  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
548  ( off.x + lineX ) / SCALE_FACTOR,
549  ( -off.y - lineY - radius ) / SCALE_FACTOR,
550  ( off.x + lineX + radius ) / SCALE_FACTOR,
551  ( -off.y - lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
552  ( -off.y - lineY ) / SCALE_FACTOR );
553 
554  // right line
555  if( lineY > 0 )
556  {
557  fprintf( aFile, "LINE %g %g %g %g\n",
558  ( off.x + lineX + radius ) / SCALE_FACTOR,
559  ( -off.y + lineY ) / SCALE_FACTOR,
560  ( off.x + lineX + radius ) / SCALE_FACTOR,
561  ( -off.y - lineY ) / SCALE_FACTOR );
562  }
563 
564  // top right arc
565  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
566  ( off.x + lineX + radius ) / SCALE_FACTOR,
567  ( -off.y + lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
568  ( -off.y + lineY + radius ) / SCALE_FACTOR,
569  ( off.x + lineX ) / SCALE_FACTOR, ( -off.y + lineY ) / SCALE_FACTOR );
570 
571  // top line
572  if( lineX > 0 )
573  {
574  fprintf( aFile, "LINE %g %g %g %g\n"
575  , ( off.x - lineX ) / SCALE_FACTOR,
576  ( -off.y + lineY + radius ) / SCALE_FACTOR,
577  ( off.x + lineX ) / SCALE_FACTOR,
578  ( -off.y + lineY + radius ) / SCALE_FACTOR );
579  }
580 
581  // top left arc
582  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
583  ( off.x - lineX ) / SCALE_FACTOR,
584  ( -off.y + lineY + radius ) / SCALE_FACTOR,
585  ( off.x - lineX - radius ) / SCALE_FACTOR,
586  ( -off.y + lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
587  ( -off.y + lineY ) / SCALE_FACTOR );
588 
589  // left line
590  if( lineY > 0 )
591  {
592  fprintf( aFile, "LINE %g %g %g %g\n",
593  ( off.x - lineX - radius ) / SCALE_FACTOR,
594  ( -off.y - lineY ) / SCALE_FACTOR,
595  ( off.x - lineX - radius ) / SCALE_FACTOR,
596  ( -off.y + lineY ) / SCALE_FACTOR );
597  }
598  }
599  break;
600 
601  case PAD_SHAPE_TRAPEZOID:
602  {
603  fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
604 
605  wxPoint poly[4];
606  pad->BuildPadPolygon( poly, wxSize( 0, 0 ), 0 );
607 
608  for( int cur = 0; cur < 4; ++cur )
609  {
610  int next = ( cur + 1 ) % 4;
611  fprintf( aFile, "LINE %g %g %g %g\n",
612  ( off.x + poly[cur].x ) / SCALE_FACTOR,
613  ( -off.y - poly[cur].y ) / SCALE_FACTOR,
614  ( off.x + poly[next].x ) / SCALE_FACTOR,
615  ( -off.y - poly[next].y ) / SCALE_FACTOR );
616  }
617  }
618  break;
619 
620  case PAD_SHAPE_CUSTOM:
621  {
622  fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
623 
624  const SHAPE_POLY_SET& outline = pad->GetCustomShapeAsPolygon();
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  fputs( "\n$ENDPADS\n\n", aFile );
647 
648  // Now emit the padstacks definitions, using the combined layer masks
649  fputs( "$PADSTACKS\n", aFile );
650 
651  // Via padstacks
652  for( unsigned i = 0; i < viastacks.size(); i++ )
653  {
654  VIA* via = viastacks[i];
655 
656  LSET mask = via->GetLayerSet() & master_layermask;
657 
658  fprintf( aFile, "PADSTACK VIA%d.%d.%s %g\n",
659  via->GetWidth(), via->GetDrillValue(),
660  fmt_mask( mask ).c_str(),
661  via->GetDrillValue() / SCALE_FACTOR );
662 
663  for( LSEQ seq = mask.Seq( gc_seq, DIM( gc_seq ) ); seq; ++seq )
664  {
665  PCB_LAYER_ID layer = *seq;
666 
667  fprintf( aFile, "PAD V%d.%d.%s %s 0 0\n",
668  via->GetWidth(), via->GetDrillValue(),
669  fmt_mask( mask ).c_str(),
670  GenCADLayerName( cu_count, layer ).c_str()
671  );
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 noncompliant importer */
680  for( unsigned i = 1; i < padstacks.size(); i++ )
681  {
682  D_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, DIM( 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, GenCADLayerNameFlipped( cu_count, layer ).c_str() );
708  }
709  }
710  }
711 
712  fputs( "$ENDPADSTACKS\n\n", aFile );
713 }
CITER next(CITER it)
Definition: ptree.cpp:130
#define DIM(x)
of elements in an array
Definition: macros.h:98
static int PadListSortByShape(const void *aRefptr, const void *aObjptr)
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
static int ViaSort(const void *aRefptr, const void *aObjptr)
const SHAPE_POLY_SET & GetCustomShapeAsPolygon() const
Accessor to the custom shape as one polygon.
Definition: class_pad.h:341
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
int PointCount() const
Function PointCount()
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:511
int GetCopperLayerCount() const
Function GetCopperLayerCount.
void SetSubRatsnest(int aSubRatsnest)
Definition: class_pad.h:633
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
static bool flipBottomPads
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:337
static std::string GenCADLayerNameFlipped(int aCuCount, PCB_LAYER_ID aId)
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
Class SHAPE_POLY_SET.
int GetSubRatsnest() const
Function GetSubRatsnest.
Definition: class_pad.h:632
static int Compare(const D_PAD *padref, const D_PAD *padcmp)
Function Compare compares two pads and return 0 if they are equal.
Definition: class_pad.cpp:1063
static const PCB_LAYER_ID gc_seq[]
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:395
const wxSize & GetSize() const
Definition: class_pad.h:269
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
unsigned GetPadCount() const
Function GetPadCount.
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Class SHAPE_LINE_CHAIN.
int GetWidth() const
Definition: class_track.h:117
static const double SCALE_FACTOR
DLIST< TRACK > m_Track
Definition: class_board.h:246
static std::string fmt_mask(LSET aSet)
LSET GetEnabledLayers() const
Function GetEnabledLayers returns a bit-mask of all the layers that are enabled.
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
const wxPoint & GetOffset() const
Definition: class_pad.h:278
#define min(a, b)
Definition: auxiliary.h:85
VIA * GetFirstVia(TRACK *aTrk, const TRACK *aStopPoint=NULL)
Scan a track list for the first VIA o NULL if not found (or NULL passed)
Definition: class_track.h:496
static void CreateRoutesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1051 of file export_gencad.cpp.

References escapeString(), fmt_mask(), GenCADLayerName(), BOARD::GetCopperLayerCount(), BOARD::GetDesignSettings(), VIA::GetDrillValue(), BOARD_DESIGN_SETTINGS::GetEnabledLayers(), TRACK::GetEnd(), BOARD_ITEM::GetLayer(), VIA::GetLayerSet(), BOARD_CONNECTED_ITEM::GetNet(), BOARD_CONNECTED_ITEM::GetNetCode(), NETINFO_ITEM::GetNetname(), TRACK::GetStart(), TRACK::GetWidth(), BOARD::m_Track, BOARD::m_Zone, MapXTo(), MapYTo(), TRACK::Next(), PCB_TRACE_T, PCB_VIA_T, PCB_ZONE_T, SCALE_FACTOR, TO_UTF8, TrackListSortByNetcode(), EDA_ITEM::Type(), vset(), wxPoint::x, and wxPoint::y.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

1052 {
1053  TRACK* track, ** tracklist;
1054  int vianum = 1;
1055  int old_netcode, old_width, old_layer;
1056  int nbitems, ii;
1057  LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
1058 
1059  int cu_count = aPcb->GetCopperLayerCount();
1060 
1061  // Count items
1062  nbitems = 0;
1063 
1064  for( track = aPcb->m_Track; track; track = track->Next() )
1065  nbitems++;
1066 
1067  for( track = aPcb->m_Zone; track; track = track->Next() )
1068  {
1069  if( track->Type() == PCB_ZONE_T )
1070  nbitems++;
1071  }
1072 
1073  tracklist = (TRACK**) operator new( (nbitems + 1)* sizeof( TRACK* ) );
1074 
1075  nbitems = 0;
1076 
1077  for( track = aPcb->m_Track; track; track = track->Next() )
1078  tracklist[nbitems++] = track;
1079 
1080  for( track = aPcb->m_Zone; track; track = track->Next() )
1081  {
1082  if( track->Type() == PCB_ZONE_T )
1083  tracklist[nbitems++] = track;
1084  }
1085 
1086  tracklist[nbitems] = NULL;
1087 
1088  qsort( tracklist, nbitems, sizeof(TRACK*), TrackListSortByNetcode );
1089 
1090  fputs( "$ROUTES\n", aFile );
1091 
1092  old_netcode = -1; old_width = -1; old_layer = -1;
1093 
1094  for( ii = 0; ii < nbitems; ii++ )
1095  {
1096  track = tracklist[ii];
1097 
1098  if( old_netcode != track->GetNetCode() )
1099  {
1100  old_netcode = track->GetNetCode();
1101  NETINFO_ITEM* net = track->GetNet();
1102  wxString netname;
1103 
1104  if( net && (net->GetNetname() != wxEmptyString) )
1105  netname = net->GetNetname();
1106  else
1107  netname = wxT( "_noname_" );
1108 
1109  fprintf( aFile, "ROUTE \"%s\"\n", TO_UTF8( escapeString( netname ) ) );
1110  }
1111 
1112  if( old_width != track->GetWidth() )
1113  {
1114  old_width = track->GetWidth();
1115  fprintf( aFile, "TRACK TRACK%d\n", track->GetWidth() );
1116  }
1117 
1118  if( (track->Type() == PCB_TRACE_T) || (track->Type() == PCB_ZONE_T) )
1119  {
1120  if( old_layer != track->GetLayer() )
1121  {
1122  old_layer = track->GetLayer();
1123  fprintf( aFile, "LAYER %s\n",
1124  GenCADLayerName( cu_count, track->GetLayer() ).c_str()
1125  );
1126  }
1127 
1128  fprintf( aFile, "LINE %g %g %g %g\n",
1129  MapXTo( track->GetStart().x ), MapYTo( track->GetStart().y ),
1130  MapXTo( track->GetEnd().x ), MapYTo( track->GetEnd().y ) );
1131  }
1132 
1133  if( track->Type() == PCB_VIA_T )
1134  {
1135  const VIA* via = static_cast<const VIA*>(track);
1136 
1137  LSET vset = via->GetLayerSet() & master_layermask;
1138 
1139  fprintf( aFile, "VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
1140  via->GetWidth(), via->GetDrillValue(),
1141  fmt_mask( vset ).c_str(),
1142  MapXTo( via->GetStart().x ), MapYTo( via->GetStart().y ),
1143  via->GetDrillValue() / SCALE_FACTOR, vianum++ );
1144  }
1145  }
1146 
1147  fputs( "$ENDROUTES\n\n", aFile );
1148 
1149  delete tracklist;
1150 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
static double MapYTo(int aY)
DLIST< SEGZONE > m_Zone
Definition: class_board.h:247
static wxString escapeString(const wxString &aString)
const wxPoint & GetEnd() const
Definition: class_track.h:120
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)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
Class LSET is a set of PCB_LAYER_IDs.
const wxPoint & GetStart() const
Definition: class_track.h:123
static int TrackListSortByNetcode(const void *refptr, const void *objptr)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
class SEGZONE, a segment used to fill a zone area (segment on a copper layer)
Definition: typeinfo.h:97
int GetNetCode() const
Function GetNetCode.
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
Class NETINFO_ITEM handles the data for a net.
Definition: class_netinfo.h:69
TRACK * Next() const
Definition: class_track.h:100
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
int GetWidth() const
Definition: class_track.h:117
static const double SCALE_FACTOR
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:246
static std::string fmt_mask(LSET aSet)
const wxString & GetNetname() const
Function GetNetname.
LSET GetEnabledLayers() const
Function GetEnabledLayers returns a bit-mask of all the layers that are enabled.
NETINFO_ITEM * GetNet() const
Function GetNet Returns NET_INFO object for a given item.
static double MapXTo(int aX)
static void CreateShapesSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 737 of file export_gencad.cpp.

References componentShapes, escapeString(), UTF8::find(), flipBottomPads, FootprintWriteShape(), LIB_ID::Format(), Format(), MODULE::GetFlag(), MODULE::GetFPID(), D_PAD::GetName(), MODULE::GetOrientation(), D_PAD::GetOrientation(), D_PAD::GetPos0(), MODULE::GetReference(), D_PAD::GetSubRatsnest(), hashModule(), individualShapes, BOARD::m_Modules, MODULE::Next(), D_PAD::Next(), NORMALIZE_ANGLE_POS(), MODULE::PadsList(), SCALE_FACTOR, shapeNames, TO_UTF8, uniquePins, wxPoint::x, and wxPoint::y.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

738 {
739  MODULE* module;
740  D_PAD* pad;
741  const char* layer;
742  wxString pinname;
743  const char* mirror = "0";
744  std::map<wxString, size_t> shapes;
745 
746  fputs( "$SHAPES\n", aFile );
747 
748  for( module = aPcb->m_Modules; module; module = module->Next() )
749  {
750  if( !individualShapes )
751  {
752  // Check if such shape has been already generated, and if so - reuse it
753  // It is necessary to compute hash (i.e. check all children objects) as
754  // certain components instances might have been modified on the board.
755  // In such case the shape will be different despite the same LIB_ID.
756  wxString shapeName = module->GetFPID().Format();
757 
758  auto shapeIt = shapes.find( shapeName );
759  size_t modHash = hashModule( module );
760 
761  if( shapeIt != shapes.end() )
762  {
763  if( modHash != shapeIt->second )
764  {
765  // there is an entry for this footprint, but it has a modified shape,
766  // so we need to create a new entry
767  wxString newShapeName;
768  int suffix = 0;
769 
770  // find an unused name or matching entry
771  do
772  {
773  newShapeName = wxString::Format( "%s_%d", shapeName, suffix );
774  shapeIt = shapes.find( newShapeName );
775  ++suffix;
776  }
777  while( shapeIt != shapes.end() && shapeIt->second != modHash );
778 
779  shapeName = newShapeName;
780  }
781 
782  if( shapeIt != shapes.end() && modHash == shapeIt->second )
783  {
784  // shape found, so reuse it
785  componentShapes[module] = modHash;
786  continue;
787  }
788  }
789 
790  // new shape
791  componentShapes[module] = modHash;
792  shapeNames[modHash] = shapeName;
793  shapes[shapeName] = modHash;
794  FootprintWriteShape( aFile, module, shapeName );
795  }
796  else // individual shape for each component
797  {
798  FootprintWriteShape( aFile, module, module->GetReference() );
799  }
800 
801  // set of already emitted pins to check for duplicates
802  std::set<wxString> pins;
803 
804  for( pad = module->PadsList(); pad; pad = pad->Next() )
805  {
806  /* Padstacks are defined using the correct layers for the pads, therefore to
807  * all pads need to be marked as TOP to use the padstack information correctly.
808  */
809  layer = "TOP";
810  pinname = pad->GetName();
811 
812  if( pinname.IsEmpty() )
813  pinname = wxT( "none" );
814 
815  if( uniquePins )
816  {
817  int suffix = 0;
818  wxString origPinname( pinname );
819 
820  auto it = pins.find( pinname );
821 
822  while( it != pins.end() )
823  {
824  pinname = wxString::Format( "%s_%d", origPinname, suffix );
825  ++suffix;
826  it = pins.find( pinname );
827  }
828 
829  pins.insert( pinname );
830  }
831 
832  double orient = pad->GetOrientation() - module->GetOrientation();
833  NORMALIZE_ANGLE_POS( orient );
834 
835  // Bottom side modules use the flipped padstack
836  fprintf( aFile, ( flipBottomPads && module->GetFlag() ) ?
837  "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
838  "PIN \"%s\" PAD%d %g %g %s %g %s\n",
839  TO_UTF8( escapeString( pinname ) ), pad->GetSubRatsnest(),
840  pad->GetPos0().x / SCALE_FACTOR,
841  -pad->GetPos0().y / SCALE_FACTOR,
842  layer, orient / 10.0, mirror );
843  }
844  }
845 
846  fputs( "$ENDSHAPES\n\n", aFile );
847 }
int GetFlag() const
Definition: class_module.h:222
MODULE * Next() const
Definition: class_module.h:120
static bool uniquePins
const wxPoint & GetPos0() const
Definition: class_pad.h:263
static wxString escapeString(const wxString &aString)
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:241
static bool flipBottomPads
const LIB_ID & GetFPID() const
Definition: class_module.h:184
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
static bool individualShapes
double GetOrientation() const
Definition: class_module.h:180
int GetSubRatsnest() const
Function GetSubRatsnest.
Definition: class_pad.h:632
std::string::size_type find(char c) const
Definition: utf8.h:110
D_PAD * Next() const
Definition: class_pad.h:160
const wxString & GetName() const
Definition: class_pad.h:190
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
static size_t hashModule(const MODULE *aModule)
Compute hashes for modules without taking into account their position, rotation or layer...
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:439
static void FootprintWriteShape(FILE *File, MODULE *module, const wxString &aShapeName)
DLIST< MODULE > m_Modules
Definition: class_board.h:245
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:375
static const double SCALE_FACTOR
UTF8 Format() const
Definition: lib_id.cpp:263
DLIST< D_PAD > & PadsList()
Definition: class_module.h:154
static std::map< MODULE *, int > componentShapes
static std::map< int, wxString > shapeNames
static void CreateSignalsSection ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 931 of file export_gencad.cpp.

References escapeString(), BOARD::FindNet(), GetChars(), D_PAD::GetName(), NETINFO_ITEM::GetNet(), BOARD_CONNECTED_ITEM::GetNetCode(), BOARD::GetNetCount(), NETINFO_ITEM::GetNetname(), MODULE::GetReference(), BOARD::m_Modules, MODULE::Next(), D_PAD::Next(), MODULE::PadsList(), and TO_UTF8.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

932 {
933  wxString msg;
934  NETINFO_ITEM* net;
935  D_PAD* pad;
936  MODULE* module;
937  int NbNoConn = 1;
938 
939  fputs( "$SIGNALS\n", aFile );
940 
941  for( unsigned ii = 0; ii < aPcb->GetNetCount(); ii++ )
942  {
943  net = aPcb->FindNet( ii );
944 
945  if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection)
946  {
947  msg.Printf( "NoConnection%d", NbNoConn++ );
948  }
949 
950  if( net->GetNet() <= 0 ) // dummy netlist (no connection)
951  continue;
952 
953  msg = wxT( "SIGNAL \"" ) + escapeString( net->GetNetname() ) + "\"";
954 
955  fputs( TO_UTF8( msg ), aFile );
956  fputs( "\n", aFile );
957 
958  for( module = aPcb->m_Modules; module; module = module->Next() )
959  {
960  for( pad = module->PadsList(); pad; pad = pad->Next() )
961  {
962  if( pad->GetNetCode() != net->GetNet() )
963  continue;
964 
965  msg.Printf( wxT( "NODE \"%s\" \"%s\"" ),
966  GetChars( escapeString( module->GetReference() ) ),
967  GetChars( escapeString( pad->GetName() ) ) );
968 
969  fputs( TO_UTF8( msg ), aFile );
970  fputs( "\n", aFile );
971  }
972  }
973  }
974 
975  fputs( "$ENDSIGNALS\n\n", aFile );
976 }
MODULE * Next() const
Definition: class_module.h:120
static wxString escapeString(const wxString &aString)
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
D_PAD * Next() const
Definition: class_pad.h:160
const wxString & GetName() const
Definition: class_pad.h:190
int GetNet() const
Function GetNet.
int GetNetCode() const
Function GetNetCode.
Class NETINFO_ITEM handles the data for a net.
Definition: class_netinfo.h:69
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:439
DLIST< MODULE > m_Modules
Definition: class_board.h:245
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
DLIST< D_PAD > & PadsList()
Definition: class_module.h:154
const wxString & GetNetname() const
Function GetNetname.
unsigned GetNetCount() const
Function GetNetCount.
Definition: class_board.h:772
static void CreateTracksInfoData ( FILE *  aFile,
BOARD aPcb 
)
static

Definition at line 1229 of file export_gencad.cpp.

References TRACK::GetWidth(), BOARD::m_Track, BOARD::m_Zone, TRACK::Next(), and SCALE_FACTOR.

Referenced by PCB_EDIT_FRAME::ExportToGenCAD().

1230 {
1231  TRACK* track;
1232  int last_width = -1;
1233 
1234  // Find thickness used for traces
1235  // XXX could use the same sorting approach used for pads
1236 
1237  std::vector <int> trackinfo;
1238 
1239  unsigned ii;
1240 
1241  for( track = aPcb->m_Track; track; track = track->Next() )
1242  {
1243  if( last_width != track->GetWidth() ) // Find a thickness already used.
1244  {
1245  for( ii = 0; ii < trackinfo.size(); ii++ )
1246  {
1247  if( trackinfo[ii] == track->GetWidth() )
1248  break;
1249  }
1250 
1251  if( ii == trackinfo.size() ) // not found
1252  trackinfo.push_back( track->GetWidth() );
1253 
1254  last_width = track->GetWidth();
1255  }
1256  }
1257 
1258  for( track = aPcb->m_Zone; track; track = track->Next() )
1259  {
1260  if( last_width != track->GetWidth() ) // Find a thickness already used.
1261  {
1262  for( ii = 0; ii < trackinfo.size(); ii++ )
1263  {
1264  if( trackinfo[ii] == track->GetWidth() )
1265  break;
1266  }
1267 
1268  if( ii == trackinfo.size() ) // not found
1269  trackinfo.push_back( track->GetWidth() );
1270 
1271  last_width = track->GetWidth();
1272  }
1273  }
1274 
1275  // Write data
1276  fputs( "$TRACKS\n", aFile );
1277 
1278  for( ii = 0; ii < trackinfo.size(); ii++ )
1279  {
1280  fprintf( aFile, "TRACK TRACK%d %g\n", trackinfo[ii],
1281  trackinfo[ii] / SCALE_FACTOR );
1282  }
1283 
1284  fputs( "$ENDTRACKS\n\n", aFile );
1285 }
DLIST< SEGZONE > m_Zone
Definition: class_board.h:247
TRACK * Next() const
Definition: class_track.h:100
int GetWidth() const
Definition: class_track.h:117
static const double SCALE_FACTOR
DLIST< TRACK > m_Track
Definition: class_board.h:246
static wxString escapeString ( const wxString &  aString)
static

Definition at line 210 of file export_gencad.cpp.

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

211 {
212  wxString copy( aString );
213  copy.Replace( "\"", "\\\"" );
214  return copy;
215 }
static std::string fmt_mask ( LSET  aSet)
static

Definition at line 219 of file export_gencad.cpp.

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

Referenced by CreatePadsShapesSection(), and CreateRoutesSection().

220 {
221 #if 0
222  return aSet.FmtHex();
223 #else
224  return StrPrintf( "%08x", (unsigned) ( aSet & LSET::AllCuMask() ).to_ulong() );
225 #endif
226 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:646
std::string FmtHex() const
Function FmtHex returns a hex string showing contents of this LSEQ.
Definition: lset.cpp:253
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
static void FootprintWriteShape ( FILE *  File,
MODULE module,
const wxString &  aShapeName 
)
static

Definition at line 1293 of file export_gencad.cpp.

References B_SilkS, DisplayError(), escapeString(), F_SilkS, Format(), DRAWSEGMENT::GetAngle(), MODULE::GetAttributes(), EDGE_MODULE::GetEnd0(), BOARD_ITEM::GetLayer(), GetLineLength(), DRAWSEGMENT::GetShape(), EDGE_MODULE::GetStart0(), MODULE::GraphicalItemsList(), KiROUND(), MODULE::m_Attributs, EDGE_MODULE::m_End0, EDGE_MODULE::m_Start0, MOD_CMS, MOD_DEFAULT, MOD_VIRTUAL, EDA_ITEM::Next(), PCB_MODULE_EDGE_T, PCB_MODULE_TEXT_T, RotatePoint(), S_ARC, S_CIRCLE, S_POLYGON, S_SEGMENT, SCALE_FACTOR, TO_UTF8, EDA_ITEM::Type(), wxPoint::x, and wxPoint::y.

Referenced by CreateShapesSection().

1294 {
1295  EDGE_MODULE* PtEdge;
1296  EDA_ITEM* PtStruct;
1297 
1298  /* creates header: */
1299  fprintf( aFile, "\nSHAPE \"%s\"\n", TO_UTF8( escapeString( aShapeName ) ) );
1300 
1301  if( module->GetAttributes() & MOD_VIRTUAL )
1302  {
1303  fprintf( aFile, "INSERT SMD\n" );
1304  }
1305  else
1306  {
1307  if( module->GetAttributes() & MOD_CMS )
1308  {
1309  fprintf( aFile, "INSERT SMD\n" );
1310  }
1311  else
1312  {
1313  fprintf( aFile, "INSERT TH\n" );
1314  }
1315  }
1316 
1317 #if 0 /* ATTRIBUTE name and value is unspecified and the original exporter
1318  * got the syntax wrong, so CAM350 rejected the whole shape! */
1319 
1320  if( module->m_Attributs != MOD_DEFAULT )
1321  {
1322  fprintf( aFile, "ATTRIBUTE" );
1323 
1324  if( module->m_Attributs & MOD_CMS )
1325  fprintf( aFile, " PAD_SMD" );
1326 
1327  if( module->m_Attributs & MOD_VIRTUAL )
1328  fprintf( aFile, " VIRTUAL" );
1329 
1330  fprintf( aFile, "\n" );
1331  }
1332 #endif
1333 
1334  // Silk outline; wildly interpreted by various importers:
1335  // CAM350 read it right but only closed shapes
1336  // ProntoPlace double-flip it (at least the pads are correct)
1337  // GerberTool usually get it right...
1338  for( PtStruct = module->GraphicalItemsList(); PtStruct; PtStruct = PtStruct->Next() )
1339  {
1340  switch( PtStruct->Type() )
1341  {
1342  case PCB_MODULE_TEXT_T:
1343 
1344  // If we wanted to export text, this is not the correct section
1345  break;
1346 
1347  case PCB_MODULE_EDGE_T:
1348  PtEdge = (EDGE_MODULE*) PtStruct;
1349  if( PtEdge->GetLayer() == F_SilkS
1350  || PtEdge->GetLayer() == B_SilkS )
1351  {
1352  switch( PtEdge->GetShape() )
1353  {
1354  case S_SEGMENT:
1355  fprintf( aFile, "LINE %g %g %g %g\n",
1356  PtEdge->m_Start0.x / SCALE_FACTOR,
1357  -PtEdge->m_Start0.y / SCALE_FACTOR,
1358  PtEdge->m_End0.x / SCALE_FACTOR,
1359  -PtEdge->m_End0.y / SCALE_FACTOR );
1360  break;
1361 
1362  case S_CIRCLE:
1363  {
1364  int radius = KiROUND( GetLineLength( PtEdge->m_End0,
1365  PtEdge->m_Start0 ) );
1366  fprintf( aFile, "CIRCLE %g %g %g\n",
1367  PtEdge->m_Start0.x / SCALE_FACTOR,
1368  -PtEdge->m_Start0.y / SCALE_FACTOR,
1369  radius / SCALE_FACTOR );
1370  break;
1371  }
1372 
1373  case S_ARC:
1374  {
1375  int arcendx, arcendy;
1376  arcendx = PtEdge->m_End0.x - PtEdge->m_Start0.x;
1377  arcendy = PtEdge->m_End0.y - PtEdge->m_Start0.y;
1378  RotatePoint( &arcendx, &arcendy, -PtEdge->GetAngle() );
1379  arcendx += PtEdge->GetStart0().x;
1380  arcendy += PtEdge->GetStart0().y;
1381 
1382  fprintf( aFile, "ARC %g %g %g %g %g %g\n",
1383  PtEdge->m_End0.x / SCALE_FACTOR,
1384  -PtEdge->GetEnd0().y / SCALE_FACTOR,
1385  arcendx / SCALE_FACTOR,
1386  -arcendy / SCALE_FACTOR,
1387  PtEdge->GetStart0().x / SCALE_FACTOR,
1388  -PtEdge->GetStart0().y / SCALE_FACTOR );
1389  break;
1390  }
1391 
1392  case S_POLYGON:
1393  // Not exported (TODO)
1394  break;
1395 
1396  default:
1397  DisplayError( NULL, wxString::Format( "Type Edge Module %d invalid.", PtStruct->Type() ) );
1398  break;
1399  }
1400  }
1401  break;
1402 
1403  default:
1404  break;
1405  }
1406  }
1407 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB...
Definition: trigo.h:191
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:106
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
polygon (not yet used for tracks, but could be in microwave apps)
const wxPoint & GetEnd0() const
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:76
usual segment : line with rounded ends
EDA_ITEM * Next() const
Definition: base_struct.h:220
static wxString escapeString(const wxString &aString)
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
wxPoint m_End0
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
STROKE_T GetShape() const
Arcs (with rounded ends)
int GetAttributes() const
Definition: class_module.h:217
default
Definition: class_module.h:75
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
double GetAngle() const
const wxPoint & GetStart0() const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
Virtual component: when created by copper shapes on board (Like edge card connectors, mounting hole...)
Definition: class_module.h:78
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:165
static const double SCALE_FACTOR
DLIST< BOARD_ITEM > & GraphicalItemsList()
Definition: class_module.h:157
wxPoint m_Start0
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:73
int m_Attributs
Flag bits ( see Mod_Attribut )
Definition: class_module.h:700
static std::string GenCADLayerName ( int  aCuCount,
PCB_LAYER_ID  aId 
)
static

Definition at line 102 of file export_gencad.cpp.

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().

103 {
104  if( IsCopperLayer( aId ) )
105  {
106  if( aId == F_Cu )
107  return "TOP";
108  else if( aId == B_Cu )
109  return "BOTTOM";
110 
111  else if( aId <= 14 )
112  {
113  return StrPrintf( "INNER%d", aCuCount - aId - 1 );
114  }
115  else
116  {
117  return StrPrintf( "LAYER%d", aId );
118  }
119  }
120 
121  else
122  {
123  const char* txt;
124 
125  // using a switch to clearly show mapping & catch out of bounds index.
126  switch( aId )
127  {
128  // Technicals
129  case B_Adhes: txt = "B.Adhes"; break;
130  case F_Adhes: txt = "F.Adhes"; break;
131  case B_Paste: txt = "SOLDERPASTE_BOTTOM"; break;
132  case F_Paste: txt = "SOLDERPASTE_TOP"; break;
133  case B_SilkS: txt = "SILKSCREEN_BOTTOM"; break;
134  case F_SilkS: txt = "SILKSCREEN_TOP"; break;
135  case B_Mask: txt = "SOLDERMASK_BOTTOM"; break;
136  case F_Mask: txt = "SOLDERMASK_TOP"; break;
137 
138  // Users
139  case Dwgs_User: txt = "Dwgs.User"; break;
140  case Cmts_User: txt = "Cmts.User"; break;
141  case Eco1_User: txt = "Eco1.User"; break;
142  case Eco2_User: txt = "Eco2.User"; break;
143  case Edge_Cuts: txt = "Edge.Cuts"; break;
144  case Margin: txt = "Margin"; break;
145 
146  // Footprint
147  case F_CrtYd: txt = "F_CrtYd"; break;
148  case B_CrtYd: txt = "B_CrtYd"; break;
149  case F_Fab: txt = "F_Fab"; break;
150  case B_Fab: txt = "B_Fab"; break;
151 
152  default:
153  wxASSERT_MSG( 0, wxT( "aId UNEXPECTED" ) );
154  txt = "BAD-INDEX!"; break;
155  }
156 
157  return txt;
158  }
159 }
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
static std::string GenCADLayerNameFlipped ( int  aCuCount,
PCB_LAYER_ID  aId 
)
static

Definition at line 199 of file export_gencad.cpp.

References GenCADLayerName(), and StrPrintf().

Referenced by CreatePadsShapesSection().

200 {
201  if( 1<= aId && aId <= 14 )
202  {
203  return StrPrintf( "INNER%d", 14 - aId );
204  }
205 
206  return GenCADLayerName( aCuCount, aId );
207 }
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
static const wxString& getShapeName ( MODULE aModule)
static

Definition at line 241 of file export_gencad.cpp.

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

Referenced by CreateComponentsSection().

242 {
243  static const wxString invalid( "invalid" );
244 
245  if( individualShapes )
246  return aModule->GetReference();
247 
248  auto itShape = componentShapes.find( aModule );
249  wxCHECK( itShape != componentShapes.end(), invalid );
250 
251  auto itName = shapeNames.find( itShape->second );
252  wxCHECK( itName != shapeNames.end(), invalid );
253 
254  return itName->second;
255 }
static bool individualShapes
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:439
static std::map< MODULE *, int > componentShapes
static std::map< int, wxString > shapeNames
static size_t hashModule ( const MODULE aModule)
static

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

Definition at line 717 of file export_gencad.cpp.

References MODULE::GraphicalItemsList(), hash_eda(), LAYER, BOARD_ITEM::Next(), D_PAD::Next(), MODULE::PadsList(), POSITION, REL_COORD, and ROTATION.

Referenced by CreateShapesSection().

718 {
719  size_t ret = 0x11223344;
720  constexpr int flags = HASH_FLAGS::POSITION | HASH_FLAGS::REL_COORD
722 
723  for( const BOARD_ITEM* i = aModule->GraphicalItemsList(); i; i = i->Next() )
724  ret ^= hash_eda( i, flags );
725 
726  for( const D_PAD* i = aModule->PadsList(); i; i = i->Next() )
727  ret ^= hash_eda( i, flags );
728 
729  return ret;
730 }
use coordinates relative to the parent object
Definition: hash_eda.h:40
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
Definition: hash_eda.h:42
BOARD_ITEM * Next() const
D_PAD * Next() const
Definition: class_pad.h:160
DLIST< BOARD_ITEM > & GraphicalItemsList()
Definition: class_module.h:157
DLIST< D_PAD > & PadsList()
Definition: class_module.h:154
size_t hash_eda(const EDA_ITEM *aItem, int aFlags)
Definition: hash_eda.cpp:48
static double MapXTo ( int  aX)
static

Definition at line 263 of file export_gencad.cpp.

References GencadOffsetX, and SCALE_FACTOR.

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

264 {
265  return (aX - GencadOffsetX) / SCALE_FACTOR;
266 }
static const double SCALE_FACTOR
static int GencadOffsetX
static double MapYTo ( int  aY)
static

Definition at line 269 of file export_gencad.cpp.

References GencadOffsetY, and SCALE_FACTOR.

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

270 {
271  return (GencadOffsetY - aY) / SCALE_FACTOR;
272 }
static int GencadOffsetY
static const double SCALE_FACTOR
static int PadListSortByShape ( const void *  aRefptr,
const void *  aObjptr 
)
static

Definition at line 371 of file export_gencad.cpp.

References D_PAD::Compare().

Referenced by CreatePadsShapesSection().

372 {
373  const D_PAD* padref = *(D_PAD**) aRefptr;
374  const D_PAD* padcmp = *(D_PAD**) aObjptr;
375 
376  return D_PAD::Compare( padref, padcmp );
377 }
static int Compare(const D_PAD *padref, const D_PAD *padcmp)
Function Compare compares two pads and return 0 if they are equal.
Definition: class_pad.cpp:1063
static int TrackListSortByNetcode ( const void *  refptr,
const void *  objptr 
)
static

Definition at line 1021 of file export_gencad.cpp.

References p2t::cmp(), BOARD_ITEM::GetLayer(), BOARD_CONNECTED_ITEM::GetNetCode(), and TRACK::GetWidth().

Referenced by CreateRoutesSection().

1022 {
1023  const TRACK* ref, * cmp;
1024  int diff;
1025 
1026  ref = *( (TRACK**) refptr );
1027  cmp = *( (TRACK**) objptr );
1028 
1029  if( ( diff = ref->GetNetCode() - cmp->GetNetCode() ) )
1030  return diff;
1031 
1032  if( ( diff = ref->GetWidth() - cmp->GetWidth() ) )
1033  return diff;
1034 
1035  if( ( diff = ref->GetLayer() - cmp->GetLayer() ) )
1036  return diff;
1037 
1038  return 0;
1039 }
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetNetCode() const
Function GetNetCode.
int GetWidth() const
Definition: class_track.h:117
bool cmp(const Point *a, const Point *b)
Definition: shapes.h:227
static int ViaSort ( const void *  aRefptr,
const void *  aObjptr 
)
static

Definition at line 381 of file export_gencad.cpp.

References LSET::FmtBin(), VIA::GetDrillValue(), VIA::GetLayerSet(), and TRACK::GetWidth().

Referenced by CreatePadsShapesSection().

382 {
383  VIA* padref = *(VIA**) aRefptr;
384  VIA* padcmp = *(VIA**) aObjptr;
385 
386  if( padref->GetWidth() != padcmp->GetWidth() )
387  return padref->GetWidth() - padcmp->GetWidth();
388 
389  if( padref->GetDrillValue() != padcmp->GetDrillValue() )
390  return padref->GetDrillValue() - padcmp->GetDrillValue();
391 
392  if( padref->GetLayerSet() != padcmp->GetLayerSet() )
393  return padref->GetLayerSet().FmtBin().compare( padcmp->GetLayerSet().FmtBin() );
394 
395  return 0;
396 }
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
int GetWidth() const
Definition: class_track.h:117
std::string FmtBin() const
Function FmtBin returns a binary string showing contents of this LSEQ.
Definition: lset.cpp:229

Variable Documentation

std::map<MODULE*, int> componentShapes
static
bool flipBottomPads
static
const PCB_LAYER_ID gc_seq[]
static

Definition at line 162 of file export_gencad.cpp.

Referenced by CreatePadsShapesSection().

int GencadOffsetX
static

Definition at line 235 of file export_gencad.cpp.

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

int GencadOffsetY
static

Definition at line 235 of file export_gencad.cpp.

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

bool individualShapes
static
const double SCALE_FACTOR = 1000.0 * IU_PER_MILS
static
std::map<int, wxString> shapeNames
static
bool storeOriginCoords
static

Definition at line 232 of file export_gencad.cpp.

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

bool uniquePins
static

Definition at line 230 of file export_gencad.cpp.

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