KiCad PCB EDA Suite
FABMASTER Class Reference

#include <import_fabmaster.h>

Classes

struct  CLASS
 
struct  COMPONENT
 
struct  FABMASTER_LAYER
 A!LAYER_SORT!LAYER_SUBCLASS!LAYER_ARTWORK!LAYER_USE!LAYER_CONDUCTOR!LAYER_DIELECTRIC_CONSTANT !LAYER_ELECTRICAL_CONDUCTIVITY!LAYER_MATERIAL!LAYER_SHIELD_LAYER!LAYER_THERMAL_CONDUCTIVITY!LAYER_THICKNESS! More...
 
struct  FABMASTER_PAD_SHAPE
 A!SUBCLASS!PAD_SHAPE_NAME!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1! GRAPHIC_DATA_2!GRAPHIC_DATA_3!GRAPHIC_DATA_4!GRAPHIC_DATA_5!GRAPHIC_DATA_6!GRAPHIC_DATA_7! GRAPHIC_DATA_8!GRAPHIC_DATA_9!PAD_STACK_NAME!REFDES!PIN_NUMBER! More...
 
struct  FM_PAD
 
struct  FM_VIA
 
struct  GEOM_GRAPHIC
 
struct  GRAPHIC_ARC
 
struct  GRAPHIC_DATA
 
struct  GRAPHIC_ITEM
 
struct  GRAPHIC_LINE
 
struct  GRAPHIC_RECTANGLE
 
struct  GRAPHIC_TEXT
 
struct  NETNAME
 
struct  PIN
 
struct  SYMBOL
 
struct  TRACE
 

Public Types

using single_row = std::vector< std::string >
 

Public Member Functions

 FABMASTER ()
 
bool Read (const std::string &aFile)
 
bool Process ()
 
bool LoadBoard (BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter)
 

Private Types

enum  section_type : int {
  UNKNOWN_EXTRACT, EXTRACT_PADSTACKS, EXTRACT_PAD_SHAPES, EXTRACT_FULL_LAYERS,
  EXTRACT_VIAS, FABMASTER_EXTRACT_PINS, EXTRACT_PINS, EXTRACT_TRACES,
  EXTRACT_GRAPHICS, EXTRACT_BASIC_LAYERS, EXTRACT_NETS, EXTRACT_REFDES
}
 
enum  COMPCLASS { COMPCLASS_NONE, COMPCLASS_IO, COMPCLASS_IC, COMPCLASS_DISCRETE }
 
enum  SYMTYPE {
  SYMTYPE_NONE, SYMTYPE_PACKAGE, SYMTYPE_MECH, SYMTYPE_FORMAT,
  SYMTYPE_DRAFTING
}
 
enum  GRAPHIC_SHAPE { GR_SHAPE_LINE, GR_SHAPE_TEXT, GR_SHAPE_RECTANGLE, GR_SHAPE_ARC }
 
enum  GRAPHIC_TYPE {
  GR_TYPE_NONE, GR_TYPE_CONNECT, GR_TYPE_NOTCONNECT, GR_TYPE_SHAPE,
  GR_TYPE_POLYGON, GR_TYPE_VOID
}
 
using graphic_element = std::set< std::unique_ptr< GRAPHIC_ITEM >, GRAPHIC_ITEM::SEQ_CMP >
 

Private Member Functions

section_type detectType (size_t aOffset)
 
void checkpoint ()
 
int execute_recordbuffer (int filetype)
 
int getColFromName (size_t aRow, const std::string &aStr)
 
SYMTYPE parseSymType (const std::string &aSymType)
 
COMPCLASS parseCompClass (const std::string &aCompClass)
 
double processScaleFactor (size_t aRow)
 Processes data from text vectors into internal database for further ordering. More...
 
size_t processPadStacks (size_t aRow)
 A!PADNAME!RECNUMBER!LAYER!FIXFLAG!VIAFLAG!PADSHAPE1!PADWIDTH!PADHGHT! PADXOFF!PADYOFF!PADFLASH!PADSHAPENAME!TRELSHAPE1!TRELWIDTH!TRELHGHT! TRELXOFF!TRELYOFF!TRELFLASH!TRELSHAPENAME!APADSHAPE1!APADWIDTH!APADHGHT! APADXOFF!APADYOFF!APADFLASH!APADSHAPENAME! More...
 
size_t processCustomPads (size_t aRow)
 A!SUBCLASS!PAD_SHAPE_NAME!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1! GRAPHIC_DATA_2!GRAPHIC_DATA_3!GRAPHIC_DATA_4!GRAPHIC_DATA_5!GRAPHIC_DATA_6!GRAPHIC_DATA_7! GRAPHIC_DATA_8!GRAPHIC_DATA_9!PAD_STACK_NAME!REFDES!PIN_NUMBER! More...
 
size_t processGeometry (size_t aRow)
 A!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2!GRAPHIC_DATA_3! GRAPHIC_DATA_4!GRAPHIC_DATA_5!GRAPHIC_DATA_6!GRAPHIC_DATA_7!GRAPHIC_DATA_8!GRAPHIC_DATA_9! SUBCLASS!SYM_NAME!REFDES! More...
 
size_t processVias (size_t aRow)
 A!VIA_X!VIA_Y!PAD_STACK_NAME!NET_NAME!TEST_POINT! More...
 
size_t processTraces (size_t aRow)
 A!CLASS!SUBCLASS!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2! GRAPHIC_DATA_3!GRAPHIC_DATA_4!GRAPHIC_DATA_5!GRAPHIC_DATA_6!GRAPHIC_DATA_7!GRAPHIC_DATA_8! GRAPHIC_DATA_9!NET_NAME! More...
 
size_t processFootprints (size_t aRow)
 A!REFDES!COMP_CLASS!COMP_PART_NUMBER!COMP_HEIGHT!COMP_DEVICE_LABEL!COMP_INSERTION_CODE!SYM_TYPE! SYM_NAME!SYM_MIRROR!SYM_ROTATE!SYM_X!SYM_Y!COMP_VALUE!COMP_TOL!COMP_VOLTAGE! More...
 
size_t processNets (size_t aRow)
 A!NET_NAME!REFDES!PIN_NUMBER!PIN_NAME!PIN_GROUND!PIN_POWER! More...
 
size_t processLayers (size_t aRow)
 A!LAYER_SORT!LAYER_SUBCLASS!LAYER_ARTWORK!LAYER_USE!LAYER_CONDUCTOR!LAYER_DIELECTRIC_CONSTANT! LAYER_ELECTRICAL_CONDUCTIVITY!LAYER_MATERIAL!LAYER_SHIELD_LAYER!LAYER_THERMAL_CONDUCTIVITY! LAYER_THICKNESS! More...
 
size_t processSimpleLayers (size_t aRow)
 
size_t processPadStackLayers (size_t aRow)
 
size_t processSymbols (size_t aRow)
 
size_t processPins (size_t aRow)
 A!SYM_NAME!SYM_MIRROR!PIN_NAME!PIN_NUMBER!PIN_X!PIN_Y!PAD_STACK_NAME!REFDES!PIN_ROTATION!TEST_POINT! More...
 
GRAPHIC_ITEMprocessGraphic (const GRAPHIC_DATA &aData, double aScale)
 Specialty functions for processing graphical data rows into the internal database. More...
 
GRAPHIC_ARCprocessArc (const GRAPHIC_DATA &aData, double aScale)
 
GRAPHIC_LINEprocessLine (const GRAPHIC_DATA &aData, double aScale)
 
GRAPHIC_TEXTprocessText (const GRAPHIC_DATA &aData, double aScale)
 
GRAPHIC_RECTANGLEprocessRectangle (const GRAPHIC_DATA &aData, double aScale)
 
PCB_LAYER_ID getLayer (const std::string &aLayerName)
 
bool assignLayers ()
 
double readDouble (const std::string &aStr) const
 Reads the double/integer value from a std string independent of the user locale. More...
 
int readInt (const std::string &aStr) const
 
bool orderZones (BOARD *aBoard)
 Sets zone priorities based on zone BB size. More...
 
bool loadZones (BOARD *aBoard)
 Loads sections of the database into the board. More...
 
bool loadOutline (BOARD *aBoard, const std::unique_ptr< TRACE > &aLine)
 
bool loadNets (BOARD *aBoard)
 
bool loadLayers (BOARD *aBoard)
 
bool loadGraphics (BOARD *aBoard)
 
bool loadVias (BOARD *aBoard)
 
bool loadEtch (BOARD *aBoard, const std::unique_ptr< TRACE > &aLine)
 
bool loadZone (BOARD *aBoard, const std::unique_ptr< FABMASTER::TRACE > &aLine)
 
bool loadPolygon (BOARD *aBoard, const std::unique_ptr< FABMASTER::TRACE > &aLine)
 
bool loadFootprints (BOARD *aBoard)
 
SHAPE_POLY_SET loadShapePolySet (const graphic_element &aLine)
 

Private Attributes

wxFileName m_filename
 
std::deque< single_rowrows
 
bool has_pads
 
bool has_comps
 
bool has_graphic
 
bool has_nets
 
bool has_pins
 
std::unordered_map< std::string, FM_PADpads
 
std::map< std::pair< std::string, std::string >, NETNAMEpin_nets
 
std::set< std::string > netnames
 
std::map< std::string, FABMASTER_LAYERlayers
 
std::unordered_map< std::string, FABMASTER_PAD_SHAPEpad_shapes
 
std::unordered_map< std::string, SYMBOLsymbols
 
std::vector< GEOM_GRAPHICboard_graphics
 
std::map< std::string, std::map< int, GEOM_GRAPHIC > > comp_graphics
 
std::vector< std::unique_ptr< FM_VIA > > vias
 
std::set< std::unique_ptr< TRACE >, TRACE::BY_IDtraces
 
std::set< std::unique_ptr< TRACE >, TRACE::BY_IDzones
 
std::set< std::unique_ptr< TRACE >, TRACE::BY_IDpolygons
 
std::set< std::unique_ptr< TRACE >, TRACE::BY_IDrefdes
 
std::map< std::string, std::vector< std::unique_ptr< COMPONENT > > > components
 
std::map< std::string, std::set< std::unique_ptr< PIN >, PIN::BY_NUM > > pins
 
std::map< std::string, PCB_LAYER_IDlayer_map
 
PROGRESS_REPORTERm_progressReporter
 optional; may be nullptr More...
 
unsigned m_doneCount
 
unsigned m_lastProgressCount
 
unsigned m_totalCount
 for progress reporting More...
 

Detailed Description

Definition at line 50 of file import_fabmaster.h.

Member Typedef Documentation

◆ graphic_element

using FABMASTER::graphic_element = std::set<std::unique_ptr<GRAPHIC_ITEM>, GRAPHIC_ITEM::SEQ_CMP>
private

Definition at line 278 of file import_fabmaster.h.

◆ single_row

using FABMASTER::single_row = std::vector<std::string>

Definition at line 54 of file import_fabmaster.h.

Member Enumeration Documentation

◆ COMPCLASS

enum FABMASTER::COMPCLASS
private
Enumerator
COMPCLASS_NONE 
COMPCLASS_IO 
COMPCLASS_IC 
COMPCLASS_DISCRETE 

Definition at line 140 of file import_fabmaster.h.

◆ GRAPHIC_SHAPE

Enumerator
GR_SHAPE_LINE 
GR_SHAPE_TEXT 
GR_SHAPE_RECTANGLE 
GR_SHAPE_ARC 

Definition at line 189 of file import_fabmaster.h.

◆ GRAPHIC_TYPE

Enumerator
GR_TYPE_NONE 
GR_TYPE_CONNECT 
GR_TYPE_NOTCONNECT 
GR_TYPE_SHAPE 
GR_TYPE_POLYGON 
GR_TYPE_VOID 

Definition at line 197 of file import_fabmaster.h.

◆ section_type

enum FABMASTER::section_type : int
private
Enumerator
UNKNOWN_EXTRACT 
EXTRACT_PADSTACKS 
EXTRACT_PAD_SHAPES 
EXTRACT_FULL_LAYERS 
EXTRACT_VIAS 
FABMASTER_EXTRACT_PINS 
EXTRACT_PINS 
EXTRACT_TRACES 
EXTRACT_GRAPHICS 
EXTRACT_BASIC_LAYERS 
EXTRACT_NETS 
EXTRACT_REFDES 

Definition at line 78 of file import_fabmaster.h.

◆ SYMTYPE

enum FABMASTER::SYMTYPE
private
Enumerator
SYMTYPE_NONE 
SYMTYPE_PACKAGE 
SYMTYPE_MECH 
SYMTYPE_FORMAT 
SYMTYPE_DRAFTING 

Definition at line 148 of file import_fabmaster.h.

Constructor & Destructor Documentation

◆ FABMASTER()

FABMASTER::FABMASTER ( )
inline

Definition at line 55 of file import_fabmaster.h.

55  :
56  has_pads( false ),
57  has_comps( false ),
58  has_graphic( false ),
59  has_nets( false ),
60  has_pins( false ),
61  m_progressReporter( nullptr ),
62  m_doneCount( 0 ),
64  m_totalCount( 0 )
65 
66  {}
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
unsigned m_doneCount
unsigned m_totalCount
for progress reporting
unsigned m_lastProgressCount

Member Function Documentation

◆ assignLayers()

bool FABMASTER::assignLayers ( )
private

Back copper has a special id number, so assign that to the last copper layer in the stackup

Definition at line 711 of file import_fabmaster.cpp.

712 {
713  bool has_l1 = false;
714  int max_layer = 0;
715  std::string max_layer_name;
716 
717  std::vector<std::pair<std::string, int>> extra_layers
718  {
719  { "ASSEMBLY_TOP", F_Fab },
720  { "ASSEMBLY_BOTTOM", B_Fab },
721  { "PLACE_BOUND_TOP", F_CrtYd },
722  { "PLACE_BOUND_BOTTOM", B_CrtYd },
723  };
724 
725  std::vector<FABMASTER_LAYER*> layer_order;
726 
727  for( auto& el : layers )
728  {
729  FABMASTER_LAYER& layer = el.second;
730  layer.layerid = UNSELECTED_LAYER;
731 
732  if( layer.conductive )
733  {
734  layer_order.push_back( &layer );
735  }
736  else if( layer.name.find( "SILK" ) != std::string::npos &&
737  layer.name.find( "AUTOSILK" ) == std::string::npos ) // Skip the autosilk layer
738  {
739  if( layer.name.find( "B" ) != std::string::npos )
740  layer.layerid = B_SilkS;
741  else
742  layer.layerid = F_SilkS;
743  }
744  else if( layer.name.find( "MASK" ) != std::string::npos ||
745  layer.name.find( "MSK" ) != std::string::npos )
746  {
747  if( layer.name.find( "B" ) != std::string::npos )
748  layer.layerid = B_Mask;
749  else
750  layer.layerid = F_Mask;
751  }
752  else if( layer.name.find( "PAST" ) != std::string::npos )
753  {
754  if( layer.name.find( "B" ) != std::string::npos )
755  layer.layerid = B_Paste;
756  else
757  layer.layerid = F_Paste;
758  }
759  else if( layer.name.find( "NCLEGEND" ) != std::string::npos )
760  layer.layerid = Dwgs_User;
761  else
762  layer.disable = true;
763  }
764 
765  std::sort( layer_order.begin(), layer_order.end(), FABMASTER_LAYER::BY_ID() );
766  int layernum = 0;
767 
768  for( auto layer : layer_order )
769  layer->layerid = layernum++;
770 
773  layer_order.back()->layerid = B_Cu;
774 
775  for( auto& new_pair : extra_layers )
776  {
777  FABMASTER_LAYER new_layer;
778 
779  new_layer.name = new_pair.first;
780  new_layer.layerid = new_pair.second;
781  new_layer.conductive = false;
782 
783  auto result = layers.emplace( new_pair.first, new_layer );
784 
785  if( !result.second )
786  {
787  result.first->second.layerid = new_pair.second;
788  result.first->second.disable = false;
789  }
790  }
791 
792  return true;
793 }
std::map< std::string, FABMASTER_LAYER > layers

References B_CrtYd, B_Cu, B_Fab, B_Mask, B_Paste, B_SilkS, FABMASTER::FABMASTER_LAYER::conductive, FABMASTER::FABMASTER_LAYER::disable, Dwgs_User, F_CrtYd, F_Fab, F_Mask, F_Paste, F_SilkS, FABMASTER::FABMASTER_LAYER::layerid, layers, FABMASTER::FABMASTER_LAYER::name, and UNSELECTED_LAYER.

Referenced by Process().

◆ checkpoint()

void FABMASTER::checkpoint ( )
private

Definition at line 61 of file import_fabmaster.cpp.

62 {
63  const unsigned PROGRESS_DELTA = 250;
64 
65  if( m_progressReporter )
66  {
67  if( ++m_doneCount > m_lastProgressCount + PROGRESS_DELTA )
68  {
70  / std::max( 1U, m_totalCount ) );
71 
73  THROW_IO_ERROR( ( "Open cancelled by user." ) );
74 
76  }
77  }
78 }
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
unsigned m_doneCount
unsigned m_totalCount
for progress reporting
unsigned m_lastProgressCount
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).

References PROGRESS_REPORTER::KeepRefreshing(), m_doneCount, m_lastProgressCount, m_progressReporter, m_totalCount, PROGRESS_REPORTER::SetCurrentProgress(), and THROW_IO_ERROR.

Referenced by LoadBoard(), loadFootprints(), loadGraphics(), loadLayers(), loadNets(), loadVias(), and loadZones().

◆ detectType()

FABMASTER::section_type FABMASTER::detectType ( size_t  aOffset)
private

We strip the underscores from all column names as some export variants use them and some do not

Definition at line 186 of file import_fabmaster.cpp.

187 {
188  single_row row;
189  try
190  {
191  row = rows.at( aOffset );
192  }
193  catch( std::out_of_range& )
194  {
195  return UNKNOWN_EXTRACT;
196  }
197 
198  if( row.size() < 3 )
199  return UNKNOWN_EXTRACT;
200 
201  if( row[0].back() != 'A' )
202  return UNKNOWN_EXTRACT;
203 
204  std::string row1 = row[1];
205  std::string row2 = row[2];
206  std::string row3{};
207 
209  alg::delete_if( row1, []( char c ){ return c == '_'; } );
210  alg::delete_if( row2, []( char c ){ return c == '_'; } );
211 
212  if( row.size() > 3 )
213  {
214  row3 = row[3];
215  alg::delete_if( row3, []( char c ){ return c == '_'; } );
216  }
217 
218  if( row1 == "REFDES" && row2 == "COMPCLASS" )
219  return EXTRACT_REFDES;
220 
221  if( row1 == "NETNAME" && row2 == "REFDES" )
222  return EXTRACT_NETS;
223 
224  if( row1 == "CLASS" && row2 == "SUBCLASS" && row3.empty() )
225  return EXTRACT_BASIC_LAYERS;
226 
227  if( row1 == "GRAPHICDATANAME" && row2 == "GRAPHICDATANUMBER" )
228  return EXTRACT_GRAPHICS;
229 
230  if( row1 == "CLASS" && row2 == "SUBCLASS" && row3 == "GRAPHICDATANAME" )
231  return EXTRACT_TRACES;
232 
233  if( row1 == "SYMNAME" && row2 == "PINNAME" )
234  return FABMASTER_EXTRACT_PINS;
235 
236  if( row1 == "SYMNAME" && row2 == "SYMMIRROR" && row3 == "PINNAME" )
237  return EXTRACT_PINS;
238 
239  if( row1 == "VIAX" && row2 == "VIAY" )
240  return EXTRACT_VIAS;
241 
242  if( row1 == "SUBCLASS" && row2 == "PADSHAPENAME" )
243  return EXTRACT_PAD_SHAPES;
244 
245  if( row1 == "PADNAME" )
246  return EXTRACT_PADSTACKS;
247 
248  if( row1 == "LAYERSORT" )
249  return EXTRACT_FULL_LAYERS;
250 
251  wxLogError( _( "Unknown FABMASTER section %s:%s at row %zu." ),
252  row1.c_str(),
253  row2.c_str(),
254  aOffset );
255  return UNKNOWN_EXTRACT;
256 
257 }
std::vector< std::string > single_row
#define _(s)
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
Definition: kicad_algo.h:173
std::deque< single_row > rows

References _, alg::delete_if(), EXTRACT_BASIC_LAYERS, EXTRACT_FULL_LAYERS, EXTRACT_GRAPHICS, EXTRACT_NETS, EXTRACT_PAD_SHAPES, EXTRACT_PADSTACKS, EXTRACT_PINS, EXTRACT_REFDES, EXTRACT_TRACES, EXTRACT_VIAS, FABMASTER_EXTRACT_PINS, rows, and UNKNOWN_EXTRACT.

Referenced by Process().

◆ execute_recordbuffer()

int FABMASTER::execute_recordbuffer ( int  filetype)
private

◆ getColFromName()

int FABMASTER::getColFromName ( size_t  aRow,
const std::string &  aStr 
)
private

Some Fabmaster headers include the underscores while others do not so we strip them uniformly before comparing

Definition at line 298 of file import_fabmaster.cpp.

299 {
300  if( aRow >= rows.size() )
301  return -1;
302 
303  std::vector<std::string> header = rows[aRow];
304 
305  for( size_t i = 0; i < header.size(); i++ )
306  {
309  alg::delete_if( header[i], []( const char c ) { return c == '_'; } );
310 
311  if( header[i] == aStr )
312  return i;
313  }
314 
315  THROW_IO_ERROR( wxString::Format( _( "Could not find column label %s." ), aStr.c_str() ) );
316  return -1;
317 }
#define _(s)
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
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
Definition: kicad_algo.h:173
std::deque< single_row > rows

References _, alg::delete_if(), Format(), rows, and THROW_IO_ERROR.

Referenced by processCustomPads(), processFootprints(), processGeometry(), processLayers(), processNets(), processPadStackLayers(), processPadStacks(), processPins(), processSimpleLayers(), processTraces(), and processVias().

◆ getLayer()

PCB_LAYER_ID FABMASTER::getLayer ( const std::string &  aLayerName)
private

Definition at line 320 of file import_fabmaster.cpp.

321 {
322  const auto& kicad_layer = layers.find( aLayerName);
323 
324  if( kicad_layer == layers.end() )
325  return UNDEFINED_LAYER;
326  else
327  return static_cast<PCB_LAYER_ID>( kicad_layer->second.layerid );
328 }
std::map< std::string, FABMASTER_LAYER > layers

References layers, and UNDEFINED_LAYER.

Referenced by loadEtch(), loadFootprints(), loadGraphics(), loadPolygon(), loadZone(), and loadZones().

◆ LoadBoard()

bool FABMASTER::LoadBoard ( BOARD aBoard,
PROGRESS_REPORTER aProgressReporter 
)

Definition at line 2972 of file import_fabmaster.cpp.

2973 {
2974  aBoard->SetFileName( m_filename.GetFullPath() );
2975  m_progressReporter = aProgressReporter;
2976 
2977  m_totalCount = netnames.size()
2978  + layers.size()
2979  + vias.size()
2980  + components.size()
2981  + zones.size()
2982  + board_graphics.size()
2983  + traces.size();
2984  m_doneCount = 0;
2985 
2986  loadNets( aBoard );
2987  loadLayers( aBoard );
2988  loadVias( aBoard );
2989  loadFootprints( aBoard );
2990  loadZones( aBoard );
2991  loadGraphics( aBoard );
2992 
2993  for( auto& track : traces )
2994  {
2995  checkpoint();
2996 
2997  if( track->lclass == "ETCH" )
2998  loadEtch( aBoard, track);
2999  else if( track->layer == "OUTLINE" )
3000  loadOutline( aBoard, track );
3001  }
3002 
3003  orderZones( aBoard );
3004 
3005  return true;
3006 }
std::map< std::string, std::vector< std::unique_ptr< COMPONENT > > > components
bool loadGraphics(BOARD *aBoard)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
bool loadEtch(BOARD *aBoard, const std::unique_ptr< TRACE > &aLine)
std::map< std::string, FABMASTER_LAYER > layers
std::vector< std::unique_ptr< FM_VIA > > vias
bool loadNets(BOARD *aBoard)
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > traces
std::vector< GEOM_GRAPHIC > board_graphics
bool loadFootprints(BOARD *aBoard)
bool loadVias(BOARD *aBoard)
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > zones
void SetFileName(const wxString &aFileName)
Definition: board.h:226
std::set< std::string > netnames
unsigned m_doneCount
unsigned m_totalCount
for progress reporting
wxFileName m_filename
bool orderZones(BOARD *aBoard)
Sets zone priorities based on zone BB size.
bool loadZones(BOARD *aBoard)
Loads sections of the database into the board.
bool loadLayers(BOARD *aBoard)
bool loadOutline(BOARD *aBoard, const std::unique_ptr< TRACE > &aLine)

References board_graphics, checkpoint(), components, layers, loadEtch(), loadFootprints(), loadGraphics(), loadLayers(), loadNets(), loadOutline(), loadVias(), loadZones(), m_doneCount, m_filename, m_progressReporter, m_totalCount, netnames, orderZones(), BOARD::SetFileName(), traces, vias, and zones.

Referenced by FABMASTER_PLUGIN::Load().

◆ loadEtch()

bool FABMASTER::loadEtch ( BOARD aBoard,
const std::unique_ptr< TRACE > &  aLine 
)
private

Definition at line 2505 of file import_fabmaster.cpp.

2506 {
2507  const NETNAMES_MAP& netinfo = aBoard->GetNetInfo().NetsByName();
2508  auto net_it = netinfo.find( aLine->netname );
2509 
2510  int last_subseq = 0;
2511  ZONE* new_zone = nullptr;
2512 
2513  for( const auto& seg : aLine->segment )
2514  {
2515  PCB_LAYER_ID layer = getLayer( seg->layer );
2516 
2517  if( IsCopperLayer( layer ) )
2518  {
2519  if( seg->shape == GR_SHAPE_LINE )
2520  {
2521  const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() );
2522 
2523  PCB_TRACK* trk = new PCB_TRACK( aBoard );
2524 
2525  trk->SetLayer( layer );
2526  trk->SetStart( wxPoint( src->start_x, src->start_y ) );
2527  trk->SetEnd( wxPoint( src->end_x, src->end_y ) );
2528  trk->SetWidth( src->width );
2529 
2530  if( net_it != netinfo.end() )
2531  trk->SetNet( net_it->second );
2532 
2533  aBoard->Add( trk, ADD_MODE::APPEND );
2534  }
2535  else if( seg->shape == GR_SHAPE_ARC )
2536  {
2537  const GRAPHIC_ARC* src = static_cast<const GRAPHIC_ARC*>( seg.get() );
2538 
2539  PCB_ARC* trk = new PCB_ARC( aBoard, &src->result );
2540  trk->SetLayer( layer );
2541  trk->SetWidth( src->width );
2542 
2543  if( net_it != netinfo.end() )
2544  trk->SetNet( net_it->second );
2545 
2546  aBoard->Add( trk, ADD_MODE::APPEND );
2547  }
2548  }
2549  else
2550  {
2551  wxLogError( _( "Expecting etch data to be on copper layer. Row found on layer '%s'" ),
2552  seg->layer.c_str() );
2553  }
2554  }
2555 
2556  return true;
2557 }
PCB_LAYER_ID getLayer(const std::string &aLayerName)
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:679
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:360
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
#define _(s)
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:796
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65

References _, BOARD::Add(), APPEND, FABMASTER::GRAPHIC_LINE::end_x, FABMASTER::GRAPHIC_LINE::end_y, getLayer(), BOARD::GetNetInfo(), GR_SHAPE_ARC, GR_SHAPE_LINE, IsCopperLayer(), NETINFO_LIST::NetsByName(), FABMASTER::GRAPHIC_ARC::result, FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, and FABMASTER::GRAPHIC_ITEM::width.

Referenced by LoadBoard().

◆ loadFootprints()

bool FABMASTER::loadFootprints ( BOARD aBoard)
private

Always set the module to the top and flip later if needed When flipping later, we get the full coordinate transform for free

TODO:Warning

Definition at line 1967 of file import_fabmaster.cpp.

1968 {
1969  const NETNAMES_MAP& netinfo = aBoard->GetNetInfo().NetsByName();
1970  const auto& ds = aBoard->GetDesignSettings();
1971 
1972  for( auto& mod : components )
1973  {
1974  checkpoint();
1975 
1976  bool has_multiple = mod.second.size() > 1;
1977 
1978  for( int i = 0; i < mod.second.size(); ++i )
1979  {
1980  auto& src = mod.second[i];
1981 
1982  FOOTPRINT* fp = new FOOTPRINT( aBoard );
1983 
1984  wxString mod_ref = src->name;
1985  wxString lib_ref = m_filename.GetName();
1986 
1987  if( has_multiple )
1988  mod_ref.Append( wxString::Format( "_%d", i ) );
1989 
1990  ReplaceIllegalFileNameChars( lib_ref, '_' );
1991  ReplaceIllegalFileNameChars( mod_ref, '_' );
1992 
1993  wxString key = !lib_ref.empty() ? lib_ref + ":" + mod_ref : mod_ref;
1994 
1995  LIB_ID fpID;
1996  fpID.Parse( key, true );
1997  fp->SetFPID( fpID );
1998 
1999  fp->SetPosition( wxPoint( src->x, src->y ) );
2000  fp->SetOrientationDegrees( -src->rotate );
2001 
2002  // KiCad netlisting requires parts to have non-digit + digit annotation.
2003  // If the reference begins with a number, we prepend 'UNK' (unknown) for the source designator
2004  wxString reference = src->refdes;
2005 
2006  if( !std::isalpha( src->refdes[0] ) )
2007  reference.Prepend( "UNK" );
2008 
2009  fp->SetReference( reference );
2010 
2011  fp->SetValue( src->value );
2012  fp->Value().SetLayer( F_Fab );
2013  fp->Value().SetVisible( false );
2014 
2015  for( auto& ref : refdes )
2016  {
2017  const GRAPHIC_TEXT *lsrc =
2018  static_cast<const GRAPHIC_TEXT*>( ( *( ref->segment.begin() ) ).get() );
2019 
2020  if( lsrc->text == src->refdes )
2021  {
2022  FP_TEXT* txt = nullptr;
2023  PCB_LAYER_ID layer = getLayer( ref->layer );
2024 
2025  if( !IsPcbLayer( layer ) )
2026  {
2027  printf("The layer %s is not mapped?\n", ref->layer.c_str() );
2028  continue;
2029  }
2030 
2031  if( layer == F_SilkS || layer == B_SilkS )
2032  txt = &( fp->Reference() );
2033  else
2034  txt = new FP_TEXT( fp );
2035 
2036  if( src->mirror )
2037  {
2038  txt->SetLayer( FlipLayer( layer ) );
2039  txt->SetTextPos( wxPoint( lsrc->start_x, 2 * src->y - ( lsrc->start_y - lsrc->height / 2 ) ) );
2040  }
2041  else
2042  {
2043  txt->SetLayer( layer );
2044  txt->SetTextPos( wxPoint( lsrc->start_x, lsrc->start_y - lsrc->height / 2 ) );
2045  }
2046 
2047  txt->SetText( lsrc->text );
2048  txt->SetItalic( lsrc->ital );
2049  txt->SetTextThickness( lsrc->thickness );
2050  txt->SetTextHeight( lsrc->height );
2051  txt->SetTextWidth( lsrc->width );
2052  txt->SetHorizJustify( lsrc->orient );
2053  txt->SetLocalCoord();
2054 
2055  if( txt != &fp->Reference() )
2056  fp->Add( txt, ADD_MODE::APPEND );
2057  }
2058  }
2059 
2062  fp->SetLayer( F_Cu );
2063 
2064  auto gr_it = comp_graphics.find( src->refdes );
2065 
2066  if( gr_it == comp_graphics.end() )
2067  {
2068  continue;
2069  //TODO: Error
2070  }
2071 
2072  for( auto& gr_ref : gr_it->second )
2073  {
2074  auto& graphic = gr_ref.second;
2075 
2076  for( auto& seg : *graphic.elements )
2077  {
2078  PCB_LAYER_ID layer = Dwgs_User;
2079 
2080  if( IsPcbLayer( getLayer( seg->layer ) ) )
2081  layer = getLayer( seg->layer );
2082 
2083  switch( seg->shape )
2084  {
2085 
2086  case GR_SHAPE_LINE:
2087  {
2088  const GRAPHIC_LINE* lsrc = static_cast<const GRAPHIC_LINE*>( seg.get() );
2089 
2090  FP_SHAPE* line = new FP_SHAPE( fp, SHAPE_T::SEGMENT );
2091 
2092  if( src->mirror )
2093  {
2094  line->SetLayer( FlipLayer( layer ) );
2095  line->SetStart( wxPoint( lsrc->start_x, 2 * src->y - lsrc->start_y ) );
2096  line->SetEnd( wxPoint( lsrc->end_x, 2 * src->y - lsrc->end_y ) );
2097  }
2098  else
2099  {
2100  line->SetLayer( layer );
2101  line->SetStart( wxPoint( lsrc->start_x, lsrc->start_y ) );
2102  line->SetEnd( wxPoint( lsrc->end_x, lsrc->end_y ) );
2103  }
2104 
2105  line->SetWidth( lsrc->width );
2106  line->SetLocalCoord();
2107 
2108  if( lsrc->width == 0 )
2109  line->SetWidth( ds.GetLineThickness( line->GetLayer() ) );
2110 
2111  fp->Add( line, ADD_MODE::APPEND );
2112  break;
2113  }
2114  case GR_SHAPE_ARC:
2115  {
2116  const GRAPHIC_ARC* lsrc = static_cast<const GRAPHIC_ARC*>( seg.get() );
2117 
2118  FP_SHAPE* arc = new FP_SHAPE( fp, SHAPE_T::ARC );
2119 
2120  if( src->mirror )
2121  {
2122  arc->SetLayer( FlipLayer( layer ) );
2123  arc->SetCenter( wxPoint( lsrc->center_x, 2 * src->y - lsrc->center_y ) );
2124  arc->SetStart( wxPoint( lsrc->end_x, 2 * src->y - lsrc->end_y ) );
2125  arc->SetArcAngleAndEnd0( lsrc->result.GetCentralAngle() * 10.0 );
2126  }
2127  else
2128  {
2129  arc->SetLayer( layer );
2130  arc->SetCenter( wxPoint( lsrc->center_x, lsrc->center_y ) );
2131  arc->SetStart( wxPoint( lsrc->end_x, lsrc->end_y ) );
2132  arc->SetArcAngleAndEnd0( -lsrc->result.GetCentralAngle() * 10.0 );
2133  }
2134 
2135  arc->SetWidth( lsrc->width );
2136  arc->SetLocalCoord();
2137 
2138  if( lsrc->width == 0 )
2139  arc->SetWidth( ds.GetLineThickness( arc->GetLayer() ) );
2140 
2141  fp->Add( arc, ADD_MODE::APPEND );
2142  break;
2143  }
2144  case GR_SHAPE_RECTANGLE:
2145  {
2146  const GRAPHIC_RECTANGLE *lsrc =
2147  static_cast<const GRAPHIC_RECTANGLE*>( seg.get() );
2148 
2149  FP_SHAPE* rect = new FP_SHAPE( fp, SHAPE_T::RECT );
2150 
2151  if( src->mirror )
2152  {
2153  rect->SetLayer( FlipLayer( layer ) );
2154  rect->SetStart( wxPoint( lsrc->start_x, 2 * src->y - lsrc->start_y ) );
2155  rect->SetEnd( wxPoint( lsrc->end_x, 2 * src->y - lsrc->end_y ) );
2156  }
2157  else
2158  {
2159  rect->SetLayer( layer );
2160  rect->SetStart( wxPoint( lsrc->start_x, lsrc->start_y ) );
2161  rect->SetEnd( wxPoint( lsrc->end_x, lsrc->end_y ) );
2162  }
2163 
2164  rect->SetWidth( ds.GetLineThickness( rect->GetLayer() ) );
2165  rect->SetLocalCoord();
2166 
2167  fp->Add( rect, ADD_MODE::APPEND );
2168  break;
2169  }
2170  case GR_SHAPE_TEXT:
2171  {
2172  const GRAPHIC_TEXT *lsrc =
2173  static_cast<const GRAPHIC_TEXT*>( seg.get() );
2174 
2175  FP_TEXT* txt = new FP_TEXT( fp );
2176 
2177  if( src->mirror )
2178  {
2179  txt->SetLayer( FlipLayer( layer ) );
2180  txt->SetTextPos( wxPoint( lsrc->start_x, 2 * src->y - ( lsrc->start_y - lsrc->height / 2 ) ) );
2181  }
2182  else
2183  {
2184  txt->SetLayer( layer );
2185  txt->SetTextPos( wxPoint( lsrc->start_x, lsrc->start_y - lsrc->height / 2 ) );
2186  }
2187 
2188  txt->SetText( lsrc->text );
2189  txt->SetItalic( lsrc->ital );
2190  txt->SetTextThickness( lsrc->thickness );
2191  txt->SetTextHeight( lsrc->height );
2192  txt->SetTextWidth( lsrc->width );
2193  txt->SetHorizJustify( lsrc->orient );
2194  txt->SetLocalCoord();
2195 
2196  // FABMASTER doesn't have visibility flags but layers that are not silk should be hidden
2197  // by default to prevent clutter.
2198  if( txt->GetLayer() != F_SilkS && txt->GetLayer() != B_SilkS )
2199  txt->SetVisible( false );
2200 
2201  fp->Add( txt, ADD_MODE::APPEND );
2202  break;
2203  }
2204  default:
2205  continue;
2206  }
2207  }
2208  }
2209 
2210  auto pin_it = pins.find( src->refdes );
2211 
2212  if( pin_it != pins.end() )
2213  {
2214  for( auto& pin : pin_it->second )
2215  {
2216  auto pin_net_it = pin_nets.find( std::make_pair( pin->refdes, pin->pin_number ) );
2217  auto padstack = pads.find( pin->padstack );
2218  std::string netname = "";
2219 
2220  if( pin_net_it != pin_nets.end() )
2221  netname = pin_net_it->second.name;
2222 
2223  auto net_it = netinfo.find( netname );
2224 
2225  PAD* newpad = new PAD( fp );
2226 
2227  if( net_it != netinfo.end() )
2228  newpad->SetNet( net_it->second );
2229  else
2230  newpad->SetNetCode( 0 );
2231 
2232  newpad->SetX( pin->pin_x );
2233 
2234  if( src->mirror )
2235  newpad->SetY( 2 * src->y - pin->pin_y );
2236  else
2237  newpad->SetY( pin->pin_y );
2238 
2239  newpad->SetNumber( pin->pin_number );
2240 
2241  if( padstack == pads.end() )
2242  {
2244  delete newpad;
2245  continue;
2246  }
2247  else
2248  {
2249  auto& pad = padstack->second;
2250 
2251  newpad->SetShape( pad.shape );
2252 
2253  if( pad.shape == PAD_SHAPE::CUSTOM )
2254  {
2255  // Choose the smaller dimension to ensure the base pad
2256  // is fully hidden by the custom pad
2257  int pad_size = std::min( pad.width, pad.height );
2258 
2259  newpad->SetSize( wxSize( pad_size / 2, pad_size / 2 ) );
2260 
2261  std::string custom_name = pad.custom_name + "_" + pin->refdes + "_" + pin->pin_number;
2262  auto custom_it = pad_shapes.find( custom_name );
2263 
2264  if( custom_it != pad_shapes.end() )
2265  {
2266 
2267  SHAPE_POLY_SET poly_outline;
2268  int last_subseq = 0;
2269  int hole_idx = -1;
2270 
2271  poly_outline.NewOutline();
2272 
2273  // Custom pad shapes have a group of elements
2274  // that are a list of graphical polygons
2275  for( const auto& el : (*custom_it).second.elements )
2276  {
2277  // For now, we are only processing the custom pad for the top layer
2278  // TODO: Use full padstacks when implementing in KiCad
2279  PCB_LAYER_ID primary_layer = src->mirror ? B_Cu : F_Cu;
2280 
2281  if( getLayer( ( *( el.second.begin() ) )->layer ) != primary_layer )
2282  continue;
2283 
2284  for( const auto& seg : el.second )
2285  {
2286  if( seg->subseq > 0 || seg->subseq != last_subseq )
2287  {
2288  poly_outline.Polygon(0).back().SetClosed( true );
2289  hole_idx = poly_outline.AddHole( SHAPE_LINE_CHAIN{} );
2290  }
2291 
2292  if( seg->shape == GR_SHAPE_LINE )
2293  {
2294  const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() );
2295 
2296  if( poly_outline.VertexCount( 0, hole_idx ) == 0 )
2297  poly_outline.Append( src->start_x, src->start_y, 0, hole_idx );
2298 
2299  poly_outline.Append( src->end_x, src->end_y, 0, hole_idx );
2300  }
2301  else if( seg->shape == GR_SHAPE_ARC )
2302  {
2303  const GRAPHIC_ARC* src = static_cast<const GRAPHIC_ARC*>( seg.get() );
2304  SHAPE_LINE_CHAIN& chain = poly_outline.Hole( 0, hole_idx );
2305 
2306  chain.Append( src->result );
2307  }
2308  }
2309  }
2310 
2311  if( poly_outline.OutlineCount() < 1
2312  || poly_outline.Outline( 0 ).PointCount() < 3 )
2313  {
2314  wxLogError( _( "Invalid custom pad '%s'. Replacing with "
2315  "circular pad." ),
2316  custom_name.c_str() );
2317  newpad->SetShape( PAD_SHAPE::CIRCLE );
2318  }
2319  else
2320  {
2321  poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
2322 
2323  poly_outline.Move( -newpad->GetPosition() );
2324 
2325  if( src->mirror )
2326  {
2327  poly_outline.Mirror( false, true, VECTOR2I( 0, ( pin->pin_y - src->y ) ) );
2328  poly_outline.Rotate( ( -src->rotate + pin->rotation ) * M_PI / 180.0 );
2329  }
2330  else
2331  {
2332  poly_outline.Rotate( ( src->rotate - pin->rotation ) * M_PI / 180.0 );
2333  }
2334 
2335  newpad->AddPrimitivePoly( poly_outline, 0, true );
2336  }
2337 
2338  SHAPE_POLY_SET mergedPolygon;
2339  newpad->MergePrimitivesAsPolygon( &mergedPolygon );
2340 
2341  if( mergedPolygon.OutlineCount() > 1 )
2342  {
2343  wxLogError( _( "Invalid custom pad '%s'. Replacing with "
2344  "circular pad." ),
2345  custom_name.c_str() );
2346  newpad->SetShape( PAD_SHAPE::CIRCLE );
2347  }
2348  }
2349  else
2350  {
2351  wxLogError( _( "Could not find custom pad '%s'." ),
2352  custom_name.c_str() );
2353  }
2354  }
2355  else
2356  newpad->SetSize( wxSize( pad.width, pad.height ) );
2357 
2358  if( pad.drill )
2359  {
2360  if( pad.plated )
2361  {
2362  newpad->SetAttribute( PAD_ATTRIB::PTH );
2363  newpad->SetLayerSet( PAD::PTHMask() );
2364  }
2365  else
2366  {
2367  newpad->SetAttribute( PAD_ATTRIB::NPTH );
2368  newpad->SetLayerSet( PAD::UnplatedHoleMask() );
2369  }
2370 
2371  if( pad.drill_size_x == pad.drill_size_y )
2373  else
2375 
2376  newpad->SetDrillSize( wxSize( pad.drill_size_x, pad.drill_size_y ) );
2377  }
2378  else
2379  {
2380  newpad->SetAttribute( PAD_ATTRIB::SMD );
2381 
2382  if( pad.top )
2383  newpad->SetLayerSet( PAD::SMDMask() );
2384  else if( pad.bottom )
2385  newpad->SetLayerSet( FlipLayerMask( PAD::SMDMask() ) );
2386  }
2387  }
2388 
2389  newpad->SetLocalCoord();
2390 
2391  if( src->mirror )
2392  newpad->SetOrientation( ( -src->rotate + pin->rotation ) * 10.0 );
2393  else
2394  newpad->SetOrientation( ( src->rotate - pin->rotation ) * 10.0 );
2395 
2396  fp->Add( newpad, ADD_MODE::APPEND );
2397  }
2398  }
2399 
2400  if( src->mirror )
2401  {
2402  fp->SetOrientationDegrees( 180.0 - src->rotate );
2403  fp->Flip( fp->GetPosition(), true );
2404  }
2405 
2406  aBoard->Add( fp, ADD_MODE::APPEND );
2407  }
2408  }
2409 
2410  return true;
2411 }
void SetReference(const wxString &aReference)
Definition: footprint.h:472
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:567
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:576
std::map< std::string, std::map< int, GEOM_GRAPHIC > > comp_graphics
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:161
std::map< std::string, std::vector< std::unique_ptr< COMPONENT > > > components
void SetItalic(bool isItalic)
Definition: eda_text.h:179
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:521
Smd pad, appears on the solder paste layer (default)
int VertexCount(int aOutline=-1, int aHole=-1) const
Returns the number of holes in a given outline.
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:246
PCB_LAYER_ID getLayer(const std::string &aLayerName)
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:679
void SetOrientationDegrees(double aOrientation)
Definition: footprint.h:189
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void SetSize(const wxSize &aSize)
Definition: pad.h:232
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
int PointCount() const
Return the number of points (vertices) in this line chain.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
bool IsPcbLayer(LAYER_NUM aLayer)
Test whether a layer is a valid layer for Pcbnew.
Definition: layer_ids.h:785
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both)
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Plated through hole pad.
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:499
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:360
FP_TEXT & Reference()
Definition: footprint.h:500
virtual void SetVisible(bool aVisible)
Definition: eda_text.h:185
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
like PAD_PTH, but not plated
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
std::map< std::pair< std::string, std::string >, NETNAME > pin_nets
void Move(const VECTOR2I &aVector) override
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
void SetLocalCoord()
< Set relative coordinates.
Definition: pad.cpp:561
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
void SetDrillSize(const wxSize &aSize)
Definition: pad.h:242
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: footprint.cpp:1472
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:166
#define _(s)
void SetValue(const wxString &aValue)
Definition: footprint.h:493
int NewOutline()
Creates a new hole in a given outline.
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Return the area of this poly set.
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:353
std::map< std::string, std::set< std::unique_ptr< PIN >, PIN::BY_NUM > > pins
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
void SetTextWidth(int aWidth)
Definition: eda_text.h:240
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:195
std::unordered_map< std::string, FM_PAD > pads
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:49
std::unordered_map< std::string, FABMASTER_PAD_SHAPE > pad_shapes
void SetLayerSet(LSET aLayers) override
Definition: pad.h:367
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
wxFileName m_filename
wxPoint GetPosition() const override
Definition: pad.h:178
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
Represent a polyline (an zero-thickness chain of connected line segments).
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:128
Definition: layer_ids.h:71
void AddPrimitivePoly(const SHAPE_POLY_SET &aPoly, int aThickness, bool aFilled)
Has meaning only for custom shape pads.
void SetY(int y)
Definition: pad.h:223
void SetTextHeight(int aHeight)
Definition: eda_text.h:243
void SetLocalCoord()
Definition: fp_text.cpp:209
wxPoint GetPosition() const override
Definition: footprint.h:186
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:161
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:159
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:187
POLYGON & Polygon(int aIndex)
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Removes an item from the container.
Definition: footprint.cpp:513
Definition: pad.h:57
void SetPosition(const wxPoint &aPos) override
Definition: footprint.cpp:1543
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:173
void SetOrientation(double aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:595
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > refdes
void SetX(int x)
Definition: pad.h:224
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...

References _, FOOTPRINT::Add(), BOARD::Add(), SHAPE_POLY_SET::AddHole(), PAD::AddPrimitivePoly(), APPEND, SHAPE_LINE_CHAIN::Append(), SHAPE_POLY_SET::Append(), ARC, B_Cu, B_SilkS, FABMASTER::GRAPHIC_ARC::center_x, FABMASTER::GRAPHIC_ARC::center_y, checkpoint(), CIRCLE, comp_graphics, components, CUSTOM, Dwgs_User, FABMASTER::GRAPHIC_LINE::end_x, FABMASTER::GRAPHIC_ARC::end_x, FABMASTER::GRAPHIC_RECTANGLE::end_x, FABMASTER::GRAPHIC_LINE::end_y, FABMASTER::GRAPHIC_ARC::end_y, FABMASTER::GRAPHIC_RECTANGLE::end_y, F_Cu, F_Fab, F_SilkS, FOOTPRINT::Flip(), FlipLayer(), FlipLayerMask(), Format(), SHAPE_POLY_SET::Fracture(), SHAPE_ARC::GetCentralAngle(), BOARD::GetDesignSettings(), getLayer(), BOARD::GetNetInfo(), PAD::GetPosition(), FOOTPRINT::GetPosition(), GR_SHAPE_ARC, GR_SHAPE_LINE, GR_SHAPE_RECTANGLE, GR_SHAPE_TEXT, FABMASTER::GRAPHIC_TEXT::height, SHAPE_POLY_SET::Hole(), IsPcbLayer(), FABMASTER::GRAPHIC_TEXT::ital, m_filename, PAD::MergePrimitivesAsPolygon(), SHAPE_POLY_SET::Mirror(), SHAPE_POLY_SET::Move(), NETINFO_LIST::NetsByName(), SHAPE_POLY_SET::NewOutline(), NPTH, FABMASTER::GRAPHIC_TEXT::orient, SHAPE_POLY_SET::Outline(), SHAPE_POLY_SET::OutlineCount(), PAD, pad, PAD_DRILL_SHAPE_CIRCLE, PAD_DRILL_SHAPE_OBLONG, pad_shapes, pads, LIB_ID::Parse(), pin, pin_nets, pins, SHAPE_LINE_CHAIN::PointCount(), SHAPE_POLY_SET::Polygon(), PTH, PAD::PTHMask(), RECT, refdes, FOOTPRINT::Reference(), ReplaceIllegalFileNameChars(), FABMASTER::GRAPHIC_ARC::result, SHAPE_POLY_SET::Rotate(), SEGMENT, PAD::SetAttribute(), PAD::SetDrillShape(), PAD::SetDrillSize(), FOOTPRINT::SetFPID(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetItalic(), BOARD_ITEM::SetLayer(), PAD::SetLayerSet(), FP_TEXT::SetLocalCoord(), PAD::SetLocalCoord(), BOARD_CONNECTED_ITEM::SetNet(), BOARD_CONNECTED_ITEM::SetNetCode(), PAD::SetNumber(), PAD::SetOrientation(), FOOTPRINT::SetOrientationDegrees(), FOOTPRINT::SetPosition(), FOOTPRINT::SetReference(), PAD::SetShape(), PAD::SetSize(), EDA_TEXT::SetText(), EDA_TEXT::SetTextHeight(), EDA_TEXT::SetTextPos(), EDA_TEXT::SetTextThickness(), EDA_TEXT::SetTextWidth(), FOOTPRINT::SetValue(), EDA_TEXT::SetVisible(), PAD::SetX(), PAD::SetY(), SMD, PAD::SMDMask(), FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, FABMASTER::GRAPHIC_TEXT::text, FABMASTER::GRAPHIC_TEXT::thickness, PAD::UnplatedHoleMask(), FOOTPRINT::Value(), SHAPE_POLY_SET::VertexCount(), and FABMASTER::GRAPHIC_ITEM::width.

Referenced by LoadBoard().

◆ loadGraphics()

bool FABMASTER::loadGraphics ( BOARD aBoard)
private

Zero-width segments/arcs are polygon outlines

Definition at line 2827 of file import_fabmaster.cpp.

2828 {
2829 
2830  for( auto& geom : board_graphics )
2831  {
2832  checkpoint();
2833 
2834  PCB_LAYER_ID layer;
2835 
2836  // The pin numbers are not useful for us outside of the footprints
2837  if( geom.subclass == "PIN_NUMBER" )
2838  continue;
2839 
2840  layer = getLayer( geom.subclass );
2841 
2842  if( !IsPcbLayer( layer ) )
2843  layer = Cmts_User;
2844 
2845  if( !geom.elements->empty() )
2846  {
2848  if( ( *( geom.elements->begin() ) )->width == 0 )
2849  {
2850  SHAPE_POLY_SET poly_outline = loadShapePolySet( *( geom.elements ) );
2851 
2852  if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
2853  continue;
2854 
2855  PCB_SHAPE* new_poly = new PCB_SHAPE( aBoard, SHAPE_T::POLY );
2856  new_poly->SetLayer( layer );
2857  new_poly->SetPolyShape( poly_outline );
2858  new_poly->SetWidth( 0 );
2859 
2860  if( layer == F_SilkS || layer == B_SilkS )
2861  new_poly->SetFilled( true );
2862 
2863  aBoard->Add( new_poly, ADD_MODE::APPEND );
2864  }
2865  }
2866 
2867  for( auto& seg : *geom.elements )
2868  {
2869  switch( seg->shape )
2870  {
2871 
2872  case GR_SHAPE_LINE:
2873  {
2874  const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() );
2875 
2876  PCB_SHAPE* line = new PCB_SHAPE( aBoard, SHAPE_T::SEGMENT );
2877  line->SetLayer( layer );
2878  line->SetStart( wxPoint( src->start_x, src->start_y ) );
2879  line->SetEnd( wxPoint( src->end_x, src->end_y ) );
2880  line->SetWidth( src->width );
2881 
2882  aBoard->Add( line, ADD_MODE::APPEND );
2883  break;
2884  }
2885  case GR_SHAPE_ARC:
2886  {
2887  const GRAPHIC_ARC* src = static_cast<const GRAPHIC_ARC*>( seg.get() );
2888 
2889  PCB_SHAPE* arc = new PCB_SHAPE( aBoard, SHAPE_T::ARC );
2890  arc->SetLayer( layer );
2891  arc->SetCenter( wxPoint( src->center_x, src->center_y ) );
2892  arc->SetStart( wxPoint( src->start_x, src->start_y ) );
2893  arc->SetArcAngleAndEnd( src->result.GetCentralAngle() * 10.0 );
2894  arc->SetWidth( src->width );
2895 
2896  aBoard->Add( arc, ADD_MODE::APPEND );
2897  break;
2898  }
2899  case GR_SHAPE_RECTANGLE:
2900  {
2901  const GRAPHIC_RECTANGLE *src =
2902  static_cast<const GRAPHIC_RECTANGLE*>( seg.get() );
2903 
2904  PCB_SHAPE* rect = new PCB_SHAPE( aBoard, SHAPE_T::RECT );
2905  rect->SetLayer( layer );
2906  rect->SetStart( wxPoint( src->start_x, src->start_y ) );
2907  rect->SetEnd( wxPoint( src->end_x, src->end_y ) );
2908  rect->SetWidth( 0 );
2909  aBoard->Add( rect, ADD_MODE::APPEND );
2910  break;
2911  }
2912  case GR_SHAPE_TEXT:
2913  {
2914  const GRAPHIC_TEXT *src =
2915  static_cast<const GRAPHIC_TEXT*>( seg.get() );
2916 
2917  PCB_TEXT* txt = new PCB_TEXT( aBoard );
2918  txt->SetLayer( layer );
2919  txt->SetTextPos( wxPoint( src->start_x, src->start_y - src->height / 2 ) );
2920  txt->SetText( src->text );
2921  txt->SetItalic( src->ital );
2922  txt->SetTextThickness( src->thickness );
2923  txt->SetTextHeight( src->height );
2924  txt->SetTextWidth( src->width );
2925  txt->SetHorizJustify( src->orient );
2926  aBoard->Add( txt, ADD_MODE::APPEND );
2927  break;
2928  }
2929  default:
2930  return false;
2931  }
2932  }
2933  }
2934 
2935  return true;
2936 
2937 }
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void SetFilled(bool aFlag)
Definition: eda_shape.h:83
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:161
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:215
PCB_LAYER_ID getLayer(const std::string &aLayerName)
int PointCount() const
Return the number of points (vertices) in this line chain.
bool IsPcbLayer(LAYER_NUM aLayer)
Test whether a layer is a valid layer for Pcbnew.
Definition: layer_ids.h:785
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
std::vector< GEOM_GRAPHIC > board_graphics
Represent a set of closed polygons.
void SetWidth(int aWidth)
Definition: eda_shape.h:88
SHAPE_POLY_SET loadShapePolySet(const graphic_element &aLine)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
const SHAPE_LINE_CHAIN & COutline(int aIndex) const

References BOARD::Add(), APPEND, ARC, B_SilkS, board_graphics, FABMASTER::GRAPHIC_ARC::center_x, FABMASTER::GRAPHIC_ARC::center_y, checkpoint(), Cmts_User, SHAPE_POLY_SET::COutline(), FABMASTER::GRAPHIC_LINE::end_x, FABMASTER::GRAPHIC_RECTANGLE::end_x, FABMASTER::GRAPHIC_LINE::end_y, FABMASTER::GRAPHIC_RECTANGLE::end_y, F_SilkS, SHAPE_ARC::GetCentralAngle(), getLayer(), GR_SHAPE_ARC, GR_SHAPE_LINE, GR_SHAPE_RECTANGLE, GR_SHAPE_TEXT, FABMASTER::GRAPHIC_TEXT::height, IsPcbLayer(), FABMASTER::GRAPHIC_TEXT::ital, loadShapePolySet(), FABMASTER::GRAPHIC_TEXT::orient, SHAPE_POLY_SET::OutlineCount(), SHAPE_LINE_CHAIN::PointCount(), POLY, RECT, FABMASTER::GRAPHIC_ARC::result, SEGMENT, EDA_SHAPE::SetFilled(), BOARD_ITEM::SetLayer(), EDA_SHAPE::SetPolyShape(), EDA_SHAPE::SetWidth(), FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, FABMASTER::GRAPHIC_TEXT::text, FABMASTER::GRAPHIC_TEXT::thickness, and FABMASTER::GRAPHIC_ITEM::width.

Referenced by LoadBoard().

◆ loadLayers()

bool FABMASTER::loadLayers ( BOARD aBoard)
private

The basic layers that get enabled for normal boards

Definition at line 2414 of file import_fabmaster.cpp.

2415 {
2416  LSET layer_set;
2417 
2419  layer_set |= LSET::AllTechMask() | LSET::UserMask();
2420 
2421  for( auto& layer : layers )
2422  {
2423  checkpoint();
2424 
2425  if( layer.second.layerid >= PCBNEW_LAYER_ID_START )
2426  layer_set.set( layer.second.layerid );
2427  }
2428 
2429  aBoard->SetEnabledLayers( layer_set );
2430 
2431  for( auto& layer : layers )
2432  {
2433  if( layer.second.conductive )
2434  {
2435  aBoard->SetLayerName( static_cast<PCB_LAYER_ID>( layer.second.layerid ),
2436  layer.second.name );
2437  }
2438  }
2439 
2440  return true;
2441 }
std::map< std::string, FABMASTER_LAYER > layers
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:820
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:504
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition: board.cpp:378
static LSET UserMask()
Definition: lset.cpp:834
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:487

References LSET::AllTechMask(), checkpoint(), layers, PCBNEW_LAYER_ID_START, BOARD::SetEnabledLayers(), BOARD::SetLayerName(), and LSET::UserMask().

Referenced by LoadBoard().

◆ loadNets()

bool FABMASTER::loadNets ( BOARD aBoard)
private

Definition at line 2491 of file import_fabmaster.cpp.

2492 {
2493  for( auto& net : netnames )
2494  {
2495  checkpoint();
2496 
2497  NETINFO_ITEM *newnet = new NETINFO_ITEM( aBoard, net );
2498  aBoard->Add( newnet, ADD_MODE::APPEND );
2499  }
2500 
2501  return true;
2502 }
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
std::set< std::string > netnames
Handle the data for a net.
Definition: netinfo.h:66

References BOARD::Add(), APPEND, checkpoint(), and netnames.

Referenced by LoadBoard().

◆ loadOutline()

bool FABMASTER::loadOutline ( BOARD aBoard,
const std::unique_ptr< TRACE > &  aLine 
)
private

Definition at line 2738 of file import_fabmaster.cpp.

2739 {
2740  PCB_LAYER_ID layer;
2741 
2742  if( aLine->lclass == "BOARD GEOMETRY" )
2743  layer = Edge_Cuts;
2744  else if( aLine->lclass == "DRAWING FORMAT" )
2745  layer = Dwgs_User;
2746  else
2747  layer = Cmts_User;
2748 
2749  for( auto& seg : aLine->segment )
2750  {
2751  switch( seg->shape )
2752  {
2753 
2754  case GR_SHAPE_LINE:
2755  {
2756  const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() );
2757 
2758  PCB_SHAPE* line = new PCB_SHAPE( aBoard, SHAPE_T::SEGMENT );
2759  line->SetLayer( layer );
2760  line->SetStart( wxPoint( src->start_x, src->start_y ) );
2761  line->SetEnd( wxPoint( src->end_x, src->end_y ) );
2762  line->SetWidth( src->width );
2763 
2764  if( line->GetWidth() == 0 )
2765  line->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
2766 
2767  aBoard->Add( line, ADD_MODE::APPEND );
2768  break;
2769  }
2770  case GR_SHAPE_ARC:
2771  {
2772  const GRAPHIC_ARC* src = static_cast<const GRAPHIC_ARC*>( seg.get() );
2773 
2774  PCB_SHAPE* arc = new PCB_SHAPE( aBoard, SHAPE_T::ARC );
2775  arc->SetLayer( layer );
2776  arc->SetCenter( wxPoint( src->center_x, src->center_y ) );
2777  arc->SetStart( wxPoint( src->start_x, src->start_y ) );
2778  arc->SetArcAngleAndEnd( src->result.GetCentralAngle() * 10.0 );
2779  arc->SetWidth( src->width );
2780 
2781  if( arc->GetWidth() == 0 )
2782  arc->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
2783 
2784  aBoard->Add( arc, ADD_MODE::APPEND );
2785  break;
2786  }
2787  case GR_SHAPE_RECTANGLE:
2788  {
2789  const GRAPHIC_RECTANGLE *src =
2790  static_cast<const GRAPHIC_RECTANGLE*>( seg.get() );
2791 
2792  PCB_SHAPE* rect = new PCB_SHAPE( aBoard, SHAPE_T::RECT );
2793  rect->SetLayer( layer );
2794  rect->SetStart( wxPoint( src->start_x, src->start_y ) );
2795  rect->SetEnd( wxPoint( src->end_x, src->end_y ) );
2796  rect->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
2797 
2798  aBoard->Add( rect, ADD_MODE::APPEND );
2799  break;
2800  }
2801  case GR_SHAPE_TEXT:
2802  {
2803  const GRAPHIC_TEXT *src = static_cast<const GRAPHIC_TEXT*>( seg.get() );
2804 
2805  PCB_TEXT* txt = new PCB_TEXT( aBoard );
2806  txt->SetLayer( layer );
2807  txt->SetTextPos( wxPoint( src->start_x, src->start_y - src->height / 2 ) );
2808  txt->SetText( src->text );
2809  txt->SetItalic( src->ital );
2810  txt->SetTextThickness( src->thickness );
2811  txt->SetTextHeight( src->height );
2812  txt->SetTextWidth( src->width );
2813  txt->SetHorizJustify( src->orient );
2814 
2815  aBoard->Add( txt, ADD_MODE::APPEND );
2816  break;
2817  }
2818  default:
2819  return false;
2820  }
2821  }
2822 
2823  return true;
2824 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65

References BOARD::Add(), APPEND, ARC, FABMASTER::GRAPHIC_ARC::center_x, FABMASTER::GRAPHIC_ARC::center_y, Cmts_User, Dwgs_User, Edge_Cuts, FABMASTER::GRAPHIC_LINE::end_x, FABMASTER::GRAPHIC_RECTANGLE::end_x, FABMASTER::GRAPHIC_LINE::end_y, FABMASTER::GRAPHIC_RECTANGLE::end_y, SHAPE_ARC::GetCentralAngle(), BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetLineThickness(), GR_SHAPE_ARC, GR_SHAPE_LINE, GR_SHAPE_RECTANGLE, GR_SHAPE_TEXT, FABMASTER::GRAPHIC_TEXT::height, FABMASTER::GRAPHIC_TEXT::ital, FABMASTER::GRAPHIC_TEXT::orient, RECT, FABMASTER::GRAPHIC_ARC::result, SEGMENT, FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, FABMASTER::GRAPHIC_TEXT::text, FABMASTER::GRAPHIC_TEXT::thickness, and FABMASTER::GRAPHIC_ITEM::width.

Referenced by LoadBoard(), and loadZones().

◆ loadPolygon()

bool FABMASTER::loadPolygon ( BOARD aBoard,
const std::unique_ptr< FABMASTER::TRACE > &  aLine 
)
private

Definition at line 2596 of file import_fabmaster.cpp.

2597 {
2598  if( aLine->segment.size() < 3 )
2599  return false;
2600 
2601  PCB_LAYER_ID layer = Cmts_User;
2602 
2603  auto new_layer = getLayer( aLine->layer );
2604 
2605  if( IsPcbLayer( new_layer ) )
2606  layer = new_layer;
2607 
2608  SHAPE_POLY_SET poly_outline = loadShapePolySet( aLine->segment );
2609 
2610  if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
2611  return false;
2612 
2613  PCB_SHAPE* new_poly = new PCB_SHAPE( aBoard );
2614 
2615  new_poly->SetShape( SHAPE_T::POLY );
2616  new_poly->SetLayer( layer );
2617 
2618  // Polygons on the silk layer are filled but other layers are not/fill doesn't make sense
2619  if( layer == F_SilkS || layer == B_SilkS )
2620  {
2621  new_poly->SetFilled( true );
2622  new_poly->SetWidth( 0 );
2623  }
2624  else
2625  {
2626  new_poly->SetWidth( ( *( aLine->segment.begin() ) )->width );
2627 
2628  if( new_poly->GetWidth() == 0 )
2629  new_poly->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
2630  }
2631 
2632  new_poly->SetPolyShape( poly_outline );
2633  aBoard->Add( new_poly, ADD_MODE::APPEND );
2634 
2635  return true;
2636 
2637 }
int GetWidth() const
Definition: eda_shape.h:89
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void SetFilled(bool aFlag)
Definition: eda_shape.h:83
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:161
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:215
PCB_LAYER_ID getLayer(const std::string &aLayerName)
int PointCount() const
Return the number of points (vertices) in this line chain.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
bool IsPcbLayer(LAYER_NUM aLayer)
Test whether a layer is a valid layer for Pcbnew.
Definition: layer_ids.h:785
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
Represent a set of closed polygons.
void SetWidth(int aWidth)
Definition: eda_shape.h:88
SHAPE_POLY_SET loadShapePolySet(const graphic_element &aLine)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:91

References BOARD::Add(), APPEND, B_SilkS, Cmts_User, SHAPE_POLY_SET::COutline(), F_SilkS, BOARD::GetDesignSettings(), getLayer(), BOARD_DESIGN_SETTINGS::GetLineThickness(), EDA_SHAPE::GetWidth(), IsPcbLayer(), loadShapePolySet(), SHAPE_POLY_SET::OutlineCount(), SHAPE_LINE_CHAIN::PointCount(), POLY, EDA_SHAPE::SetFilled(), BOARD_ITEM::SetLayer(), EDA_SHAPE::SetPolyShape(), EDA_SHAPE::SetShape(), and EDA_SHAPE::SetWidth().

Referenced by loadZones().

◆ loadShapePolySet()

SHAPE_POLY_SET FABMASTER::loadShapePolySet ( const graphic_element aLine)
private

Definition at line 2560 of file import_fabmaster.cpp.

2561 {
2562  SHAPE_POLY_SET poly_outline;
2563  int last_subseq = 0;
2564  int hole_idx = -1;
2565 
2566  poly_outline.NewOutline();
2567 
2568  for( const auto& seg : aElement )
2569  {
2570  if( seg->subseq > 0 || seg->subseq != last_subseq )
2571  hole_idx = poly_outline.AddHole( SHAPE_LINE_CHAIN{} );
2572 
2573  if( seg->shape == GR_SHAPE_LINE )
2574  {
2575  const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() );
2576 
2577  if( poly_outline.VertexCount( 0, hole_idx ) == 0 )
2578  poly_outline.Append( src->start_x, src->start_y, 0, hole_idx );
2579 
2580  poly_outline.Append( src->end_x, src->end_y, 0, hole_idx );
2581  }
2582  else if( seg->shape == GR_SHAPE_ARC )
2583  {
2584  const GRAPHIC_ARC* src = static_cast<const GRAPHIC_ARC*>( seg.get() );
2585  SHAPE_LINE_CHAIN& chain = poly_outline.Hole( 0, hole_idx );
2586 
2587  chain.Append( src->result );
2588  }
2589  }
2590 
2591  poly_outline.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
2592  return poly_outline;
2593 }
int VertexCount(int aOutline=-1, int aHole=-1) const
Returns the number of holes in a given outline.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
int NewOutline()
Creates a new hole in a given outline.
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Return the area of this poly set.
Represent a polyline (an zero-thickness chain of connected line segments).
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...

References SHAPE_POLY_SET::AddHole(), SHAPE_LINE_CHAIN::Append(), SHAPE_POLY_SET::Append(), FABMASTER::GRAPHIC_LINE::end_x, FABMASTER::GRAPHIC_LINE::end_y, SHAPE_POLY_SET::Fracture(), GR_SHAPE_ARC, GR_SHAPE_LINE, SHAPE_POLY_SET::Hole(), SHAPE_POLY_SET::NewOutline(), FABMASTER::GRAPHIC_ARC::result, FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, and SHAPE_POLY_SET::VertexCount().

Referenced by loadGraphics(), and loadPolygon().

◆ loadVias()

bool FABMASTER::loadVias ( BOARD aBoard)
private

Definition at line 2444 of file import_fabmaster.cpp.

2445 {
2446  const NETNAMES_MAP& netinfo = aBoard->GetNetInfo().NetsByName();
2447  const auto& ds = aBoard->GetDesignSettings();
2448 
2449  for( auto& via : vias )
2450  {
2451  checkpoint();
2452 
2453  auto net_it = netinfo.find( via->net );
2454  auto padstack = pads.find( via->padstack );
2455 
2456  PCB_VIA* new_via = new PCB_VIA( aBoard );
2457 
2458  new_via->SetPosition( wxPoint( via->x, via->y ) );
2459 
2460  if( net_it != netinfo.end() )
2461  new_via->SetNet( net_it->second );
2462 
2463  if( padstack == pads.end() )
2464  {
2465  new_via->SetDrillDefault();
2466 
2467  if( !ds.m_ViasDimensionsList.empty() )
2468  {
2469  new_via->SetWidth( ds.m_ViasDimensionsList[0].m_Diameter );
2470  new_via->SetDrill( ds.m_ViasDimensionsList[0].m_Drill );
2471  }
2472  else
2473  {
2474  new_via->SetDrillDefault();
2475  new_via->SetWidth( ds.m_ViasMinSize );
2476  }
2477  }
2478  else
2479  {
2480  new_via->SetDrill( padstack->second.drill_size_x );
2481  new_via->SetWidth( padstack->second.width );
2482  }
2483 
2484  aBoard->Add( new_via, ADD_MODE::APPEND );
2485  }
2486 
2487  return true;
2488 }
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: pcb_track.h:455
void SetPosition(const wxPoint &aPoint) override
Definition: pcb_track.h:393
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:679
std::vector< std::unique_ptr< FM_VIA > > vias
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:360
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
void SetDrillDefault()
Function SetDrillDefault sets the drill value for vias to the default value UNDEFINED_DRILL_DIAMETER.
Definition: pcb_track.h:476
std::unordered_map< std::string, FM_PAD > pads
void SetWidth(int aWidth)
Definition: pcb_track.h:101
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.

References BOARD::Add(), APPEND, checkpoint(), BOARD::GetDesignSettings(), BOARD::GetNetInfo(), NETINFO_LIST::NetsByName(), pads, PCB_VIA::SetDrill(), PCB_VIA::SetDrillDefault(), BOARD_CONNECTED_ITEM::SetNet(), PCB_VIA::SetPosition(), PCB_TRACK::SetWidth(), via, and vias.

Referenced by LoadBoard().

◆ loadZone()

bool FABMASTER::loadZone ( BOARD aBoard,
const std::unique_ptr< FABMASTER::TRACE > &  aLine 
)
private

Don't knock holes in the BOUNDARY systems. These are the outer layers for zone fills.

Definition at line 2640 of file import_fabmaster.cpp.

2641 {
2642  if( aLine->segment.size() < 3 )
2643  return false;
2644 
2645  int last_subseq = 0;
2646  int hole_idx = -1;
2647  SHAPE_POLY_SET* zone_outline = nullptr;
2648  ZONE* zone = nullptr;
2649 
2650  const NETNAMES_MAP& netinfo = aBoard->GetNetInfo().NetsByName();
2651  auto net_it = netinfo.find( aLine->netname );
2652  PCB_LAYER_ID layer = Cmts_User;
2653  auto new_layer = getLayer( aLine->layer );
2654 
2655  if( IsPcbLayer( new_layer ) )
2656  layer = new_layer;
2657 
2658  zone = new ZONE( aBoard );
2659  zone_outline = new SHAPE_POLY_SET;
2660 
2661  if( net_it != netinfo.end() )
2662  zone->SetNet( net_it->second );
2663 
2664  if( aLine->layer == "ALL" )
2665  zone->SetLayerSet( aBoard->GetLayerSet() & LSET::AllCuMask() );
2666  else
2667  zone->SetLayer( layer );
2668 
2669  zone->SetIsRuleArea( false );
2670  zone->SetDoNotAllowTracks( false );
2671  zone->SetDoNotAllowVias( false );
2672  zone->SetDoNotAllowPads( false );
2673  zone->SetDoNotAllowFootprints( false );
2674  zone->SetDoNotAllowCopperPour( false );
2675 
2676  if( aLine->lclass == "ROUTE KEEPOUT")
2677  {
2678  zone->SetIsRuleArea( true );
2679  zone->SetDoNotAllowTracks( true );
2680  }
2681  else if( aLine->lclass == "VIA KEEPOUT")
2682  {
2683  zone->SetIsRuleArea( true );
2684  zone->SetDoNotAllowVias( true );
2685  }
2686 
2687  zone->SetPriority( 50 );
2688  zone->SetLocalClearance( 0 );
2690 
2691  zone_outline->NewOutline();
2692 
2693 
2694  for( const auto& seg : aLine->segment )
2695  {
2696  if( seg->subseq > 0 && seg->subseq != last_subseq )
2697  {
2699  if( aLine->lclass == "BOUNDARY" )
2700  break;
2701 
2702  hole_idx = zone_outline->AddHole( SHAPE_LINE_CHAIN{} );
2703  last_subseq = seg->subseq;
2704  last_subseq = seg->subseq;
2705  }
2706 
2707  if( seg->shape == GR_SHAPE_LINE )
2708  {
2709  const GRAPHIC_LINE* src = static_cast<const GRAPHIC_LINE*>( seg.get() );
2710 
2711  if( zone_outline->VertexCount( 0, hole_idx ) == 0 )
2712  zone_outline->Append( src->start_x, src->start_y, 0, hole_idx );
2713 
2714  zone_outline->Append( src->end_x, src->end_y, 0, hole_idx );
2715  }
2716  else if( seg->shape == GR_SHAPE_ARC )
2717  {
2718  const GRAPHIC_ARC* src = static_cast<const GRAPHIC_ARC*>( seg.get() );
2719  zone_outline->Hole( 0, hole_idx ).Append( src->result );
2720  }
2721  }
2722 
2723  if( zone_outline->Outline( 0 ).PointCount() >= 3 )
2724  {
2725  zone->SetOutline( zone_outline );
2726  aBoard->Add( zone, ADD_MODE::APPEND );
2727  }
2728  else
2729  {
2730  delete( zone_outline );
2731  delete( zone );
2732  }
2733 
2734  return true;
2735 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
void SetDoNotAllowTracks(bool aEnable)
Definition: zone.h:745
void SetLayerSet(LSET aLayerSet) override
Definition: zone.cpp:250
int VertexCount(int aOutline=-1, int aHole=-1) const
Returns the number of holes in a given outline.
PCB_LAYER_ID getLayer(const std::string &aLayerName)
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:679
int PointCount() const
Return the number of points (vertices) in this line chain.
void SetPriority(unsigned aPriority)
Definition: zone.h:117
bool IsPcbLayer(LAYER_NUM aLayer)
Test whether a layer is a valid layer for Pcbnew.
Definition: layer_ids.h:785
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:360
void SetIsRuleArea(bool aEnable)
Definition: zone.h:742
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
pads are covered by copper
void SetDoNotAllowPads(bool aEnable)
Definition: zone.h:746
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition: zone.h:323
void SetDoNotAllowVias(bool aEnable)
Definition: zone.h:744
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
int NewOutline()
Creates a new hole in a given outline.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Return the area of this poly set.
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: zone.h:242
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
void SetDoNotAllowCopperPour(bool aEnable)
Definition: zone.h:743
Represent a polyline (an zero-thickness chain of connected line segments).
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:242
void SetLocalClearance(int aClearance)
Definition: zone.h:158
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:145
void SetDoNotAllowFootprints(bool aEnable)
Definition: zone.h:747
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...

References BOARD::Add(), SHAPE_POLY_SET::AddHole(), LSET::AllCuMask(), APPEND, SHAPE_LINE_CHAIN::Append(), SHAPE_POLY_SET::Append(), Cmts_User, FABMASTER::GRAPHIC_LINE::end_x, FABMASTER::GRAPHIC_LINE::end_y, FULL, getLayer(), BOARD_ITEM::GetLayerSet(), BOARD::GetNetInfo(), GR_SHAPE_ARC, GR_SHAPE_LINE, SHAPE_POLY_SET::Hole(), IsPcbLayer(), NETINFO_LIST::NetsByName(), SHAPE_POLY_SET::NewOutline(), SHAPE_POLY_SET::Outline(), SHAPE_LINE_CHAIN::PointCount(), FABMASTER::GRAPHIC_ARC::result, ZONE::SetDoNotAllowCopperPour(), ZONE::SetDoNotAllowFootprints(), ZONE::SetDoNotAllowPads(), ZONE::SetDoNotAllowTracks(), ZONE::SetDoNotAllowVias(), ZONE::SetIsRuleArea(), ZONE::SetLayer(), ZONE::SetLayerSet(), ZONE::SetLocalClearance(), BOARD_CONNECTED_ITEM::SetNet(), ZONE::SetOutline(), ZONE::SetPadConnection(), ZONE::SetPriority(), FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, and SHAPE_POLY_SET::VertexCount().

Referenced by loadZones().

◆ loadZones()

bool FABMASTER::loadZones ( BOARD aBoard)
private

Loads sections of the database into the board.

Parameters
aBoard
Returns
True if successful

Zones in FABMASTER come in two varieties:

  • Outlines with no net code attached
  • Filled areas with net code attached

In pcbnew, we want the outline with net code attached. To determine which outline should have which netcode, we look for overlapping areas. Each unnetted zone outline will be assigned the netcode that with the most hits on the edge of their outline.

Remove the filled areas in favor of the outlines

Zone1 will be the destination zone for the new net

We're looking for the netcode with the most overlaps to the un-netted zone

The overlap between outline1 and outline2 isn't perfect, so look for overlaps in both directions

Definition at line 1858 of file import_fabmaster.cpp.

1859 {
1860  for( auto& zone : zones )
1861  {
1862  checkpoint();
1863 
1864  if( IsCopperLayer( getLayer( zone->layer ) ) || zone->layer == "ALL" )
1865  {
1866  loadZone( aBoard, zone );
1867  }
1868  else
1869  {
1870  if( zone->layer == "OUTLINE" || zone->layer == "DESIGN_OUTLINE" )
1871  {
1872  loadOutline( aBoard, zone );
1873  }
1874  else
1875  {
1876  loadPolygon( aBoard, zone );
1877  }
1878  }
1879  }
1880 
1891  std::set<ZONE*> zones_to_delete;
1892 
1893  for( auto zone : aBoard->Zones() )
1894  {
1896  if( zone->GetNetCode() > 0 )
1897  {
1898  zones_to_delete.insert( zone );
1899  }
1900  }
1901 
1902  for( auto zone1 : aBoard->Zones() )
1903  {
1905  if( zone1->GetNetCode() > 0 )
1906  continue;
1907 
1908  SHAPE_LINE_CHAIN& outline1 = zone1->Outline()->Outline( 0 );
1909  std::vector<size_t> overlaps( aBoard->GetNetInfo().GetNetCount() + 1, 0 );
1910  std::vector<std::vector<ZONE*>> possible_deletions( overlaps.size() );
1911 
1912  for( auto zone2 : aBoard->Zones() )
1913  {
1914  if( zone2->GetNetCode() <= 0 )
1915  continue;
1916 
1917  SHAPE_LINE_CHAIN& outline2 = zone2->Outline()->Outline( 0 );
1918 
1919  if( zone1->GetLayer() != zone2->GetLayer() )
1920  continue;
1921 
1922  if( !outline1.BBox().Intersects( outline2.BBox() ) )
1923  continue;
1924 
1925  for( auto& pt1 : outline1.CPoints() )
1926  {
1928  if( outline2.PointOnEdge( pt1, 1 ) )
1929  overlaps[ zone2->GetNetCode() ]++;
1930  }
1931 
1932  for( auto& pt2 : outline2.CPoints() )
1933  {
1936  if( outline1.PointOnEdge( pt2, 1 ) )
1937  overlaps[ zone2->GetNetCode() ]++;
1938  }
1939  }
1940 
1941  size_t max_net = 0;
1942  size_t max_net_id = 0;
1943 
1944  for( size_t el = 1; el < overlaps.size(); ++el )
1945  {
1946  if( overlaps[el] > max_net )
1947  {
1948  max_net = overlaps[el];
1949  max_net_id = el;
1950  }
1951  }
1952 
1953  if( max_net > 0 )
1954  zone1->SetNetCode( max_net_id );
1955  }
1956 
1957  for( auto zone : zones_to_delete )
1958  {
1959  aBoard->Remove( zone );
1960  delete zone;
1961  }
1962 
1963  return true;
1964 }
ZONES & Zones()
Definition: board.h:239
PCB_LAYER_ID getLayer(const std::string &aLayerName)
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:679
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
bool loadZone(BOARD *aBoard, const std::unique_ptr< FABMASTER::TRACE > &aLine)
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:217
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
const std::vector< VECTOR2I > & CPoints() const
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > zones
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:796
Represent a polyline (an zero-thickness chain of connected line segments).
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:710
unsigned GetNetCount() const
Definition: netinfo.h:341
bool loadPolygon(BOARD *aBoard, const std::unique_ptr< FABMASTER::TRACE > &aLine)
bool loadOutline(BOARD *aBoard, const std::unique_ptr< TRACE > &aLine)

References SHAPE_LINE_CHAIN::BBox(), checkpoint(), SHAPE_LINE_CHAIN::CPoints(), getLayer(), NETINFO_LIST::GetNetCount(), BOARD::GetNetInfo(), BOX2< Vec >::Intersects(), IsCopperLayer(), loadOutline(), loadPolygon(), loadZone(), SHAPE_LINE_CHAIN_BASE::PointOnEdge(), BOARD::Remove(), BOARD::Zones(), and zones.

Referenced by LoadBoard().

◆ orderZones()

bool FABMASTER::orderZones ( BOARD aBoard)
private

Sets zone priorities based on zone BB size.

Larger bounding boxes get smaller priorities so smaller zones can knock out areas where they overlap.

Parameters
aBoard
Returns
True if successful

Definition at line 2940 of file import_fabmaster.cpp.

2941 {
2942  std::vector<ZONE*> zones = aBoard->Zones();
2943 
2944  std::sort( zones.begin(), zones.end(),
2945  [&]( const ZONE* a, const ZONE* b )
2946  {
2947  if( a->GetLayer() == b->GetLayer() )
2948  return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
2949 
2950  return a->GetLayer() < b->GetLayer();
2951  } );
2952 
2953  PCB_LAYER_ID layer = UNDEFINED_LAYER;
2954  unsigned int priority = 0;
2955 
2956  for( ZONE* zone : zones )
2957  {
2958  if( zone->GetLayer() != layer )
2959  {
2960  layer = zone->GetLayer();
2961  priority = 0;
2962  }
2963 
2964  zone->SetPriority( priority );
2965  priority += 10;
2966  }
2967 
2968  return true;
2969 }
ZONES & Zones()
Definition: board.h:239
const EDA_RECT GetBoundingBox() const override
Definition: zone.cpp:326
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: zone.cpp:222
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > zones
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
double GetArea() const
Return the area of the rectangle.
Definition: eda_rect.cpp:483
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65

References EDA_RECT::GetArea(), ZONE::GetBoundingBox(), ZONE::GetLayer(), UNDEFINED_LAYER, BOARD::Zones(), and zones.

Referenced by LoadBoard().

◆ parseCompClass()

FABMASTER::COMPCLASS FABMASTER::parseCompClass ( const std::string &  aCompClass)
private

Definition at line 1528 of file import_fabmaster.cpp.

1529 {
1530  if( aCmpClass == "IO" )
1531  return COMPCLASS_IO;
1532  else if( aCmpClass == "IC" )
1533  return COMPCLASS_IC;
1534  else if( aCmpClass == "DISCRETE" )
1535  return COMPCLASS_DISCRETE;
1536 
1537  return COMPCLASS_NONE;
1538 }

References COMPCLASS_DISCRETE, COMPCLASS_IC, COMPCLASS_IO, and COMPCLASS_NONE.

Referenced by processFootprints().

◆ parseSymType()

FABMASTER::SYMTYPE FABMASTER::parseSymType ( const std::string &  aSymType)
private

Definition at line 1513 of file import_fabmaster.cpp.

1514 {
1515  if( aSymType == "PACKAGE" )
1516  return SYMTYPE_PACKAGE;
1517  else if( aSymType == "DRAFTING")
1518  return SYMTYPE_DRAFTING;
1519  else if( aSymType == "MECHANICAL" )
1520  return SYMTYPE_MECH;
1521  else if( aSymType == "FORMAT" )
1522  return SYMTYPE_FORMAT;
1523 
1524  return SYMTYPE_NONE;
1525 }

References SYMTYPE_DRAFTING, SYMTYPE_FORMAT, SYMTYPE_MECH, SYMTYPE_NONE, and SYMTYPE_PACKAGE.

Referenced by processFootprints().

◆ Process()

bool FABMASTER::Process ( )

We extract the basic layers from the padstacks first as this is the only place the stackup is kept in the basic fabmaster export

Definition at line 1754 of file import_fabmaster.cpp.

1755 {
1756 
1757  for( size_t i = 0; i < rows.size(); )
1758  {
1759  auto type = detectType( i );
1760 
1761  switch( type )
1762  {
1763  case EXTRACT_PADSTACKS:
1764  {
1767  processPadStackLayers( i );
1768  assignLayers();
1769  int retval = processPadStacks( i );
1770 
1771  i += std::max( retval, 1 );
1772  break;
1773  }
1774 
1775  case EXTRACT_FULL_LAYERS:
1776  {
1777  int retval = processLayers( i );
1778 
1779  i += std::max( retval, 1 );
1780  break;
1781  }
1782 
1783  case EXTRACT_BASIC_LAYERS:
1784  {
1785  int retval = processSimpleLayers( i );
1786 
1787  i += std::max( retval, 1 );
1788  break;
1789  }
1790 
1791  case EXTRACT_VIAS:
1792  {
1793  int retval = processVias( i );
1794 
1795  i += std::max( retval, 1 );
1796  break;
1797  }
1798 
1799  case EXTRACT_TRACES:
1800  {
1801  int retval = processTraces( i );
1802 
1803  i += std::max( retval, 1 );
1804  break;
1805  }
1806 
1807  case EXTRACT_REFDES:
1808  {
1809  int retval = processFootprints( i );
1810 
1811  i += std::max( retval, 1 );
1812  break;
1813  }
1814 
1815  case EXTRACT_NETS:
1816  {
1817  int retval = processNets( i );
1818 
1819  i += std::max( retval, 1 );
1820  break;
1821  }
1822 
1823  case EXTRACT_GRAPHICS:
1824  {
1825  int retval = processGeometry( i );
1826 
1827  i += std::max( retval, 1 );
1828  break;
1829  }
1830 
1831  case EXTRACT_PINS:
1832  {
1833  int retval = processPins( i );
1834 
1835  i += std::max( retval, 1 );
1836  break;
1837  }
1838 
1839  case EXTRACT_PAD_SHAPES:
1840  {
1841  int retval = processCustomPads( i );
1842 
1843  i += std::max( retval, 1 );
1844  break;
1845  }
1846 
1847  default:
1848  ++i;
1849  break;
1850  }
1851 
1852  }
1853 
1854  return true;
1855 }
size_t processSimpleLayers(size_t aRow)
size_t processFootprints(size_t aRow)
A!REFDES!COMP_CLASS!COMP_PART_NUMBER!COMP_HEIGHT!COMP_DEVICE_LABEL!COMP_INSERTION_CODE!...
section_type detectType(size_t aOffset)
size_t processGeometry(size_t aRow)
A!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2!GRAPHIC_DATA_3!...
size_t processVias(size_t aRow)
A!VIA_X!VIA_Y!PAD_STACK_NAME!NET_NAME!TEST_POINT!
size_t processPadStacks(size_t aRow)
A!PADNAME!RECNUMBER!LAYER!FIXFLAG!VIAFLAG!PADSHAPE1!PADWIDTH!PADHGHT! PADXOFF!PADYOFF!...
size_t processPins(size_t aRow)
A!SYM_NAME!SYM_MIRROR!PIN_NAME!PIN_NUMBER!PIN_X!PIN_Y!PAD_STACK_NAME!REFDES!PIN_ROTATION!...
size_t processCustomPads(size_t aRow)
A!SUBCLASS!PAD_SHAPE_NAME!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!...
size_t processNets(size_t aRow)
A!NET_NAME!REFDES!PIN_NUMBER!PIN_NAME!PIN_GROUND!PIN_POWER!
size_t processLayers(size_t aRow)
A!LAYER_SORT!LAYER_SUBCLASS!LAYER_ARTWORK!LAYER_USE!LAYER_CONDUCTOR!LAYER_DIELECTRIC_CONSTANT!...
size_t processTraces(size_t aRow)
A!CLASS!SUBCLASS!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2!...
size_t processPadStackLayers(size_t aRow)
std::deque< single_row > rows

References assignLayers(), detectType(), EXTRACT_BASIC_LAYERS, EXTRACT_FULL_LAYERS, EXTRACT_GRAPHICS, EXTRACT_NETS, EXTRACT_PAD_SHAPES, EXTRACT_PADSTACKS, EXTRACT_PINS, EXTRACT_REFDES, EXTRACT_TRACES, EXTRACT_VIAS, processCustomPads(), processFootprints(), processGeometry(), processLayers(), processNets(), processPadStackLayers(), processPadStacks(), processPins(), processSimpleLayers(), processTraces(), processVias(), and rows.

Referenced by FABMASTER_PLUGIN::Load().

◆ processArc()

FABMASTER::GRAPHIC_ARC * FABMASTER::processArc ( const GRAPHIC_DATA aData,
double  aScale 
)
private

Definition at line 1038 of file import_fabmaster.cpp.

1039 {
1040  GRAPHIC_ARC* new_arc = new GRAPHIC_ARC ;
1041 
1042  new_arc->shape = GR_SHAPE_ARC;
1043  new_arc->start_x = KiROUND( readDouble( aData.graphic_data1 ) * aScale );
1044  new_arc->start_y = -KiROUND( readDouble( aData.graphic_data2 ) * aScale );
1045  new_arc->end_x = KiROUND( readDouble( aData.graphic_data3 ) * aScale );
1046  new_arc->end_y = -KiROUND( readDouble( aData.graphic_data4 ) * aScale );
1047  new_arc->center_x = KiROUND( readDouble( aData.graphic_data5 ) * aScale );
1048  new_arc->center_y = -KiROUND( readDouble( aData.graphic_data6 ) * aScale );
1049  new_arc->radius = KiROUND( readDouble( aData.graphic_data7 ) * aScale );
1050  new_arc->width = KiROUND( readDouble( aData.graphic_data8 ) * aScale );
1051 
1052  new_arc->clockwise = ( aData.graphic_data9 != "COUNTERCLOCKWISE" );
1053 
1054  double startangle = NormalizeAnglePos( RAD2DECIDEG(
1055  atan2( new_arc->start_y - new_arc->center_y,
1056  new_arc->start_x - new_arc->center_x ) ) );
1057  double endangle = NormalizeAnglePos( RAD2DECIDEG(
1058  atan2( new_arc->end_y - new_arc->center_y,
1059  new_arc->end_x - new_arc->center_x ) ) );
1060  double angle;
1061 
1062  VECTOR2I center( new_arc->center_x, new_arc->center_y );
1063  VECTOR2I start( new_arc->start_x, new_arc->start_y );
1064  VECTOR2I mid( new_arc->start_x, new_arc->start_y );
1065  VECTOR2I end( new_arc->end_x, new_arc->end_y );
1066 
1067  angle = endangle - startangle;
1068 
1069  if( new_arc->clockwise && angle < 0.0 )
1070  angle += 3600.0;
1071  if( !new_arc->clockwise && angle > 0.0 )
1072  angle -= 3600.0;
1073 
1074  if( start == end )
1075  angle = -3600.0;
1076 
1077  RotatePoint( mid, center, -angle / 2.0 );
1078 
1079  new_arc->result = SHAPE_ARC( start, mid, end, 0 );
1080 
1081  return new_arc;
1082 }
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
double RAD2DECIDEG(double rad)
Definition: trigo.h:234
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
T NormalizeAnglePos(T Angle)
Normalize angle to be in the 0.0 .. 360.0 range: angle is in 1/10 degrees.
Definition: trigo.h:281
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
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:73

References PNS::angle(), FABMASTER::GRAPHIC_ARC::center_x, FABMASTER::GRAPHIC_ARC::center_y, FABMASTER::GRAPHIC_ARC::clockwise, FABMASTER::GRAPHIC_ARC::end_x, FABMASTER::GRAPHIC_ARC::end_y, GR_SHAPE_ARC, FABMASTER::GRAPHIC_DATA::graphic_data1, FABMASTER::GRAPHIC_DATA::graphic_data2, FABMASTER::GRAPHIC_DATA::graphic_data3, FABMASTER::GRAPHIC_DATA::graphic_data4, FABMASTER::GRAPHIC_DATA::graphic_data5, FABMASTER::GRAPHIC_DATA::graphic_data6, FABMASTER::GRAPHIC_DATA::graphic_data7, FABMASTER::GRAPHIC_DATA::graphic_data8, FABMASTER::GRAPHIC_DATA::graphic_data9, KiROUND(), NormalizeAnglePos(), RAD2DECIDEG(), FABMASTER::GRAPHIC_ARC::radius, readDouble(), FABMASTER::GRAPHIC_ARC::result, RotatePoint(), FABMASTER::GRAPHIC_ITEM::shape, FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, and FABMASTER::GRAPHIC_ITEM::width.

Referenced by processGraphic().

◆ processCustomPads()

size_t FABMASTER::processCustomPads ( size_t  aRow)
private

A!SUBCLASS!PAD_SHAPE_NAME!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1! GRAPHIC_DATA_2!GRAPHIC_DATA_3!GRAPHIC_DATA_4!GRAPHIC_DATA_5!GRAPHIC_DATA_6!GRAPHIC_DATA_7! GRAPHIC_DATA_8!GRAPHIC_DATA_9!PAD_STACK_NAME!REFDES!PIN_NUMBER!

emplace may fail here, in which case, it returns the correct position to use for the existing map

Definition at line 876 of file import_fabmaster.cpp.

877 {
878  size_t rownum = aRow + 2;
879 
880  if( rownum >= rows.size() )
881  return -1;
882 
883  auto header = rows[aRow];
884  double scale_factor = processScaleFactor( aRow + 1 );
885 
886  if( scale_factor <= 0.0 )
887  return -1;
888 
889  int pad_subclass_col = getColFromName( aRow, "SUBCLASS" );
890  int pad_shape_name_col = getColFromName( aRow, "PADSHAPENAME" );
891  int pad_grdata_name_col = getColFromName( aRow, "GRAPHICDATANAME" );
892  int pad_grdata_num_col = getColFromName( aRow, "GRAPHICDATANUMBER" );
893  int pad_record_tag_col = getColFromName( aRow, "RECORDTAG" );
894  int pad_grdata1_col = getColFromName( aRow, "GRAPHICDATA1" );
895  int pad_grdata2_col = getColFromName( aRow, "GRAPHICDATA2" );
896  int pad_grdata3_col = getColFromName( aRow, "GRAPHICDATA3" );
897  int pad_grdata4_col = getColFromName( aRow, "GRAPHICDATA4" );
898  int pad_grdata5_col = getColFromName( aRow, "GRAPHICDATA5" );
899  int pad_grdata6_col = getColFromName( aRow, "GRAPHICDATA6" );
900  int pad_grdata7_col = getColFromName( aRow, "GRAPHICDATA7" );
901  int pad_grdata8_col = getColFromName( aRow, "GRAPHICDATA8" );
902  int pad_grdata9_col = getColFromName( aRow, "GRAPHICDATA9" );
903  int pad_stack_name_col = getColFromName( aRow, "PADSTACKNAME" );
904  int pad_refdes_col = getColFromName( aRow, "REFDES" );
905  int pad_pin_num_col = getColFromName( aRow, "PINNUMBER" );
906 
907  if( pad_subclass_col < 0 || pad_shape_name_col < 0 || pad_grdata1_col < 0 || pad_grdata2_col < 0
908  || pad_grdata3_col < 0 || pad_grdata4_col < 0 || pad_grdata5_col < 0
909  || pad_grdata6_col < 0 || pad_grdata7_col < 0 || pad_grdata8_col < 0
910  || pad_grdata9_col < 0 || pad_stack_name_col < 0 || pad_refdes_col < 0
911  || pad_pin_num_col < 0 )
912  return -1;
913 
914  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
915  {
916  const single_row& row = rows[rownum];
917 
918  if( row.size() != header.size() )
919  {
920  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
921  rownum,
922  header.size(),
923  row.size() );
924 
925  continue;
926  }
927 
928  auto pad_layer = row[pad_subclass_col];
929  auto pad_shape_name = row[pad_shape_name_col];
930  auto pad_record_tag = row[pad_record_tag_col];
931 
932  GRAPHIC_DATA gr_data;
933  gr_data.graphic_dataname = row[pad_grdata_name_col];
934  gr_data.graphic_datanum = row[pad_grdata_num_col];
935  gr_data.graphic_data1 = row[pad_grdata1_col];
936  gr_data.graphic_data2 = row[pad_grdata2_col];
937  gr_data.graphic_data3 = row[pad_grdata3_col];
938  gr_data.graphic_data4 = row[pad_grdata4_col];
939  gr_data.graphic_data5 = row[pad_grdata5_col];
940  gr_data.graphic_data6 = row[pad_grdata6_col];
941  gr_data.graphic_data7 = row[pad_grdata7_col];
942  gr_data.graphic_data8 = row[pad_grdata8_col];
943  gr_data.graphic_data9 = row[pad_grdata9_col];
944 
945  auto pad_stack_name = row[pad_stack_name_col];
946  auto pad_refdes = row[pad_refdes_col];
947  auto pad_pin_num = row[pad_pin_num_col];
948 
949  // N.B. We get the FIGSHAPE records as "FIG_SHAPE name". We only want "name"
950  // and we don't process other pad shape records
951  std::string prefix( "FIG_SHAPE " );
952 
953  if( pad_shape_name.length() <= prefix.length()
954  || !std::equal( prefix.begin(), prefix.end(), pad_shape_name.begin() ) )
955  {
956  continue;
957  }
958 
959  // Custom pads are a series of records with the same record ID but incrementing
960  // Sequence numbers.
961  int id = -1;
962  int seq = -1;
963 
964  if( std::sscanf( pad_record_tag.c_str(), "%d %d", &id, &seq ) != 2 )
965  {
966  wxLogError( _( "Invalid format for id string '%s' in custom pad row %zu." ),
967  pad_record_tag.c_str(),
968  rownum );
969  continue;
970  }
971 
972  auto name = pad_shape_name.substr( prefix.length() );
973  name += "_" + pad_refdes + "_" + pad_pin_num;
974  auto ret = pad_shapes.emplace( name, FABMASTER_PAD_SHAPE{} );
975 
976  auto& custom_pad = ret.first->second;
977 
978  // If we were able to insert the pad name, then we need to initialize the
979  // record
980  if( ret.second )
981  {
982  custom_pad.name = name;
983  custom_pad.padstack = pad_stack_name;
984  custom_pad.pinnum = pad_pin_num;
985  custom_pad.refdes = pad_refdes;
986  }
987 
988  // At this point we extract the individual graphical elements for processing the complex pad. The
989  // coordinates are in board origin format, so we'll need to fix the offset later when we assign them
990  // to the modules.
991 
992  auto gr_item = std::unique_ptr<GRAPHIC_ITEM>( processGraphic( gr_data, scale_factor ) );
993 
994  if( gr_item )
995  {
996  gr_item->layer = pad_layer;
997  gr_item->refdes = pad_refdes;
998  gr_item->seq = seq;
999  gr_item->subseq = 0;
1000 
1002  auto pad_it = custom_pad.elements.emplace( id, graphic_element{} );
1003  auto retval = pad_it.first->second.insert( std::move(gr_item ) );
1004 
1005  if( !retval.second )
1006  {
1007  wxLogError( _( "Could not insert graphical item %d into padstack '%s'." ),
1008  seq,
1009  pad_stack_name.c_str() );
1010  }
1011  }
1012  else
1013  {
1014  wxLogError( _( "Unrecognized pad shape primitive '%s' in row %zu." ),
1015  gr_data.graphic_dataname,
1016  rownum );
1017  }
1018  }
1019 
1020  return rownum - aRow;
1021 }
std::vector< std::string > single_row
GRAPHIC_ITEM * processGraphic(const GRAPHIC_DATA &aData, double aScale)
Specialty functions for processing graphical data rows into the internal database.
std::set< std::unique_ptr< GRAPHIC_ITEM >, GRAPHIC_ITEM::SEQ_CMP > graphic_element
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
std::unordered_map< std::string, FABMASTER_PAD_SHAPE > pad_shapes
const char * name
Definition: DXF_plotter.cpp:56
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, getColFromName(), FABMASTER::GRAPHIC_DATA::graphic_data1, FABMASTER::GRAPHIC_DATA::graphic_data2, FABMASTER::GRAPHIC_DATA::graphic_data3, FABMASTER::GRAPHIC_DATA::graphic_data4, FABMASTER::GRAPHIC_DATA::graphic_data5, FABMASTER::GRAPHIC_DATA::graphic_data6, FABMASTER::GRAPHIC_DATA::graphic_data7, FABMASTER::GRAPHIC_DATA::graphic_data8, FABMASTER::GRAPHIC_DATA::graphic_data9, FABMASTER::GRAPHIC_DATA::graphic_dataname, FABMASTER::GRAPHIC_DATA::graphic_datanum, name, pad_shapes, processGraphic(), processScaleFactor(), and rows.

Referenced by Process().

◆ processFootprints()

size_t FABMASTER::processFootprints ( size_t  aRow)
private

A!REFDES!COMP_CLASS!COMP_PART_NUMBER!COMP_HEIGHT!COMP_DEVICE_LABEL!COMP_INSERTION_CODE!SYM_TYPE! SYM_NAME!SYM_MIRROR!SYM_ROTATE!SYM_X!SYM_Y!COMP_VALUE!COMP_TOL!COMP_VOLTAGE!

Definition at line 1544 of file import_fabmaster.cpp.

1545 {
1546  size_t rownum = aRow + 2;
1547 
1548  if( rownum >= rows.size() )
1549  return -1;
1550 
1551  const single_row& header = rows[aRow];
1552  double scale_factor = processScaleFactor( aRow + 1 );
1553 
1554  if( scale_factor <= 0.0 )
1555  return -1;
1556 
1557  int refdes_col = getColFromName( aRow, "REFDES" );
1558  int compclass_col = getColFromName( aRow, "COMPCLASS" );
1559  int comppartnum_col = getColFromName( aRow, "COMPPARTNUMBER" );
1560  int compheight_col = getColFromName( aRow, "COMPHEIGHT" );
1561  int compdevlabelcol = getColFromName( aRow, "COMPDEVICELABEL" );
1562  int compinscode_col = getColFromName( aRow, "COMPINSERTIONCODE" );
1563  int symtype_col = getColFromName( aRow, "SYMTYPE" );
1564  int symname_col = getColFromName( aRow, "SYMNAME" );
1565  int symmirror_col = getColFromName( aRow, "SYMMIRROR" );
1566  int symrotate_col = getColFromName( aRow, "SYMROTATE" );
1567  int symx_col = getColFromName( aRow, "SYMX" );
1568  int symy_col = getColFromName( aRow, "SYMY" );
1569  int compvalue_col = getColFromName( aRow, "COMPVALUE" );
1570  int comptol_col = getColFromName( aRow, "COMPTOL" );
1571  int compvolt_col = getColFromName( aRow, "COMPVOLTAGE" );
1572 
1573  if( refdes_col < 0 || compclass_col < 0 || comppartnum_col < 0 || compheight_col < 0
1574  || compdevlabelcol < 0 || compinscode_col < 0 || symtype_col < 0 || symname_col < 0
1575  || symmirror_col < 0 || symrotate_col < 0 || symx_col < 0 || symy_col < 0
1576  || compvalue_col < 0 || comptol_col < 0 || compvolt_col < 0 )
1577  return -1;
1578 
1579  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
1580  {
1581  const single_row& row = rows[rownum];
1582 
1583  if( row.size() != header.size() )
1584  {
1585  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1586  rownum,
1587  header.size(),
1588  row.size() );
1589  continue;
1590  }
1591 
1592  auto cmp = std::make_unique<COMPONENT>();
1593 
1594  cmp->refdes = row[refdes_col];
1595  cmp->cclass = parseCompClass( row[compclass_col] );
1596  cmp->pn = row[comppartnum_col];
1597  cmp->height = row[compheight_col];
1598  cmp->dev_label = row[compdevlabelcol];
1599  cmp->insert_code = row[compinscode_col];
1600  cmp->type = parseSymType( row[symtype_col] );
1601  cmp->name = row[symname_col];
1602  cmp->mirror = ( row[symmirror_col] == "YES" );
1603  cmp->rotate = readDouble( row[symrotate_col] );
1604  cmp->x = KiROUND( readDouble( row[symx_col] ) * scale_factor );
1605  cmp->y = -KiROUND( readDouble( row[symy_col] ) * scale_factor );
1606  cmp->value = row[compvalue_col];
1607  cmp->tol = row[comptol_col];
1608  cmp->voltage = row[compvolt_col];
1609 
1610  auto vec = components.find( cmp->refdes );
1611 
1612  if( vec == components.end() )
1613  {
1614  auto retval = components.insert( std::make_pair( cmp->refdes, std::vector<std::unique_ptr<COMPONENT>>{} ) );
1615 
1616  vec = retval.first;
1617  }
1618 
1619  vec->second.push_back( std::move( cmp ) );
1620  }
1621 
1622  return rownum - aRow;
1623 }
std::vector< std::string > single_row
std::map< std::string, std::vector< std::unique_ptr< COMPONENT > > > components
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
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:73
COMPCLASS parseCompClass(const std::string &aCompClass)
SYMTYPE parseSymType(const std::string &aSymType)
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, components, getColFromName(), KiROUND(), parseCompClass(), parseSymType(), processScaleFactor(), readDouble(), and rows.

Referenced by Process().

◆ processGeometry()

size_t FABMASTER::processGeometry ( size_t  aRow)
private

A!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2!GRAPHIC_DATA_3! GRAPHIC_DATA_4!GRAPHIC_DATA_5!GRAPHIC_DATA_6!GRAPHIC_DATA_7!GRAPHIC_DATA_8!GRAPHIC_DATA_9! SUBCLASS!SYM_NAME!REFDES!

Definition at line 1182 of file import_fabmaster.cpp.

1183 {
1184  size_t rownum = aRow + 2;
1185 
1186  if( rownum >= rows.size() )
1187  return -1;
1188 
1189  const single_row& header = rows[aRow];
1190  double scale_factor = processScaleFactor( aRow + 1 );
1191 
1192  if( scale_factor <= 0.0 )
1193  return -1;
1194 
1195  int geo_name_col = getColFromName( aRow, "GRAPHICDATANAME" );
1196  int geo_num_col = getColFromName( aRow, "GRAPHICDATANUMBER" );
1197  int geo_tag_col = getColFromName( aRow, "RECORDTAG" );
1198  int geo_grdata1_col = getColFromName( aRow, "GRAPHICDATA1" );
1199  int geo_grdata2_col = getColFromName( aRow, "GRAPHICDATA2" );
1200  int geo_grdata3_col = getColFromName( aRow, "GRAPHICDATA3" );
1201  int geo_grdata4_col = getColFromName( aRow, "GRAPHICDATA4" );
1202  int geo_grdata5_col = getColFromName( aRow, "GRAPHICDATA5" );
1203  int geo_grdata6_col = getColFromName( aRow, "GRAPHICDATA6" );
1204  int geo_grdata7_col = getColFromName( aRow, "GRAPHICDATA7" );
1205  int geo_grdata8_col = getColFromName( aRow, "GRAPHICDATA8" );
1206  int geo_grdata9_col = getColFromName( aRow, "GRAPHICDATA9" );
1207  int geo_subclass_col = getColFromName( aRow, "SUBCLASS" );
1208  int geo_sym_name_col = getColFromName( aRow, "SYMNAME" );
1209  int geo_refdes_col = getColFromName( aRow, "REFDES" );
1210 
1211  if( geo_name_col < 0 || geo_num_col < 0 || geo_grdata1_col < 0 || geo_grdata2_col < 0
1212  || geo_grdata3_col < 0 || geo_grdata4_col < 0 || geo_grdata5_col < 0
1213  || geo_grdata6_col < 0 || geo_grdata7_col < 0 || geo_grdata8_col < 0
1214  || geo_grdata9_col < 0 || geo_subclass_col < 0 || geo_sym_name_col < 0
1215  || geo_refdes_col < 0 )
1216  return -1;
1217 
1218  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
1219  {
1220  const single_row& row = rows[rownum];
1221 
1222  if( row.size() != header.size() )
1223  {
1224  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1225  rownum,
1226  header.size(),
1227  row.size() );
1228  continue;
1229  }
1230 
1231  auto geo_tag = row[geo_tag_col];
1232 
1233  GRAPHIC_DATA gr_data;
1234  gr_data.graphic_dataname = row[geo_name_col];
1235  gr_data.graphic_datanum = row[geo_num_col];
1236  gr_data.graphic_data1 = row[geo_grdata1_col];
1237  gr_data.graphic_data2 = row[geo_grdata2_col];
1238  gr_data.graphic_data3 = row[geo_grdata3_col];
1239  gr_data.graphic_data4 = row[geo_grdata4_col];
1240  gr_data.graphic_data5 = row[geo_grdata5_col];
1241  gr_data.graphic_data6 = row[geo_grdata6_col];
1242  gr_data.graphic_data7 = row[geo_grdata7_col];
1243  gr_data.graphic_data8 = row[geo_grdata8_col];
1244  gr_data.graphic_data9 = row[geo_grdata9_col];
1245 
1246  auto geo_refdes = row[geo_refdes_col];
1247 
1248  // Grouped graphics are a series of records with the same record ID but incrementing
1249  // Sequence numbers.
1250  int id = -1;
1251  int seq = -1;
1252  int subseq = 0;
1253 
1254  if( std::sscanf( geo_tag.c_str(), "%d %d %d", &id, &seq, &subseq ) < 2 )
1255  {
1256  wxLogError( _( "Invalid format for record_tag string '%s' in row %zu." ),
1257  geo_tag.c_str(),
1258  rownum );
1259  continue;
1260  }
1261 
1262  auto gr_item = std::unique_ptr<GRAPHIC_ITEM>( processGraphic( gr_data, scale_factor ) );
1263 
1264  if( !gr_item )
1265  {
1266  wxLogDebug( "Unhandled graphic item '%s' in row %zu.",
1267  gr_data.graphic_dataname.c_str(),
1268  geo_tag.c_str(),
1269  rownum );
1270  continue;
1271  }
1272 
1273  gr_item->layer = row[geo_subclass_col];
1274  gr_item->seq = seq;
1275  gr_item->subseq = subseq;
1276 
1277  if( geo_refdes.empty() )
1278  {
1279  if( board_graphics.empty() || board_graphics.back().id != id )
1280  {
1281  GEOM_GRAPHIC new_gr;
1282  new_gr.subclass = row[geo_subclass_col];
1283  new_gr.refdes = row[geo_refdes_col];
1284  new_gr.name = row[geo_sym_name_col];
1285  new_gr.id = id;
1286  new_gr.elements = std::make_unique<graphic_element>();
1287  board_graphics.push_back( std::move( new_gr ) );
1288  }
1289 
1290  GEOM_GRAPHIC& graphic = board_graphics.back();
1291  graphic.elements->emplace( std::move( gr_item ) );
1292  }
1293  else
1294  {
1295  auto sym_gr_it = comp_graphics.emplace( geo_refdes,
1296  std::map<int, GEOM_GRAPHIC>{} );
1297  auto map_it = sym_gr_it.first->second.emplace( id, GEOM_GRAPHIC{} );
1298  auto& gr = map_it.first;
1299 
1300  if( map_it.second )
1301  {
1302  gr->second.subclass = row[geo_subclass_col];
1303  gr->second.refdes = row[geo_refdes_col];
1304  gr->second.name = row[geo_sym_name_col];
1305  gr->second.id = id;
1306  gr->second.elements = std::make_unique<graphic_element>();
1307  }
1308 
1309  auto result = gr->second.elements->emplace( std::move( gr_item ) );
1310  }
1311  }
1312 
1313  return rownum - aRow;
1314 }
std::vector< std::string > single_row
std::map< std::string, std::map< int, GEOM_GRAPHIC > > comp_graphics
std::vector< GEOM_GRAPHIC > board_graphics
GRAPHIC_ITEM * processGraphic(const GRAPHIC_DATA &aData, double aScale)
Specialty functions for processing graphical data rows into the internal database.
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, board_graphics, comp_graphics, FABMASTER::GEOM_GRAPHIC::elements, getColFromName(), FABMASTER::GRAPHIC_DATA::graphic_data1, FABMASTER::GRAPHIC_DATA::graphic_data2, FABMASTER::GRAPHIC_DATA::graphic_data3, FABMASTER::GRAPHIC_DATA::graphic_data4, FABMASTER::GRAPHIC_DATA::graphic_data5, FABMASTER::GRAPHIC_DATA::graphic_data6, FABMASTER::GRAPHIC_DATA::graphic_data7, FABMASTER::GRAPHIC_DATA::graphic_data8, FABMASTER::GRAPHIC_DATA::graphic_data9, FABMASTER::GRAPHIC_DATA::graphic_dataname, FABMASTER::GRAPHIC_DATA::graphic_datanum, FABMASTER::GEOM_GRAPHIC::id, FABMASTER::GEOM_GRAPHIC::name, processGraphic(), processScaleFactor(), FABMASTER::GEOM_GRAPHIC::refdes, rows, and FABMASTER::GEOM_GRAPHIC::subclass.

Referenced by Process().

◆ processGraphic()

FABMASTER::GRAPHIC_ITEM * FABMASTER::processGraphic ( const GRAPHIC_DATA aData,
double  aScale 
)
private

Specialty functions for processing graphical data rows into the internal database.

Parameters
aDataLoaded data vector
aScalePrior loaded scale factor
Returns
Pointer to newly allocated graphical item or nullptr on failure

Definition at line 1144 of file import_fabmaster.cpp.

1145 {
1146  GRAPHIC_ITEM* retval = nullptr;
1147 
1148  if( aData.graphic_dataname == "LINE" )
1149  retval = processLine( aData, aScale );
1150  else if( aData.graphic_dataname == "ARC" )
1151  retval = processArc( aData, aScale );
1152  else if( aData.graphic_dataname == "RECTANGLE" )
1153  retval = processRectangle( aData, aScale );
1154  else if( aData.graphic_dataname == "TEXT" )
1155  retval = processText( aData, aScale );
1156 
1157  if( retval && !aData.graphic_data10.empty() )
1158  {
1159  if( aData.graphic_data10 == "CONNECT" )
1160  retval->type = GR_TYPE_CONNECT;
1161  else if( aData.graphic_data10 == "NOTCONNECT" )
1162  retval->type = GR_TYPE_NOTCONNECT;
1163  else if( aData.graphic_data10 == "SHAPE" )
1164  retval->type = GR_TYPE_NOTCONNECT;
1165  else if( aData.graphic_data10 == "VOID" )
1166  retval->type = GR_TYPE_NOTCONNECT;
1167  else if( aData.graphic_data10 == "POLYGON" )
1168  retval->type = GR_TYPE_NOTCONNECT;
1169  else
1170  retval->type = GR_TYPE_NONE;
1171  }
1172 
1173  return retval;
1174 }
GRAPHIC_LINE * processLine(const GRAPHIC_DATA &aData, double aScale)
GRAPHIC_RECTANGLE * processRectangle(const GRAPHIC_DATA &aData, double aScale)
GRAPHIC_ARC * processArc(const GRAPHIC_DATA &aData, double aScale)
GRAPHIC_TEXT * processText(const GRAPHIC_DATA &aData, double aScale)

References GR_TYPE_CONNECT, GR_TYPE_NONE, GR_TYPE_NOTCONNECT, FABMASTER::GRAPHIC_DATA::graphic_data10, FABMASTER::GRAPHIC_DATA::graphic_dataname, processArc(), processLine(), processRectangle(), processText(), and FABMASTER::GRAPHIC_ITEM::type.

Referenced by processCustomPads(), processGeometry(), and processTraces().

◆ processLayers()

size_t FABMASTER::processLayers ( size_t  aRow)
private

A!LAYER_SORT!LAYER_SUBCLASS!LAYER_ARTWORK!LAYER_USE!LAYER_CONDUCTOR!LAYER_DIELECTRIC_CONSTANT! LAYER_ELECTRICAL_CONDUCTIVITY!LAYER_MATERIAL!LAYER_SHIELD_LAYER!LAYER_THERMAL_CONDUCTIVITY! LAYER_THICKNESS!

Definition at line 801 of file import_fabmaster.cpp.

802 {
803  size_t rownum = aRow + 2;
804 
805  if( rownum >= rows.size() )
806  return -1;
807 
808  auto header = rows[aRow];
809  double scale_factor = processScaleFactor( aRow + 1 );
810 
811  if( scale_factor <= 0.0 )
812  return -1;
813 
814  int layer_sort_col = getColFromName( aRow, "LAYERSORT" );
815  int layer_subclass_col = getColFromName( aRow, "LAYERSUBCLASS" );
816  int layer_art_col = getColFromName( aRow, "LAYERARTWORK" );
817  int layer_use_col = getColFromName( aRow, "LAYERUSE" );
818  int layer_cond_col = getColFromName( aRow, "LAYERCONDUCTOR" );
819  int layer_er_col = getColFromName( aRow, "LAYERDIELECTRICCONSTANT" );
820  int layer_rho_col = getColFromName( aRow, "LAYERELECTRICALCONDUCTIVITY" );
821  int layer_mat_col = getColFromName( aRow, "LAYERMATERIAL" );
822 
823  if( layer_sort_col < 0 || layer_subclass_col < 0 || layer_art_col < 0 || layer_use_col < 0
824  || layer_cond_col < 0 || layer_er_col < 0 || layer_rho_col < 0 || layer_mat_col < 0 )
825  return -1;
826 
827  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
828  {
829  const single_row& row = rows[rownum];
830 
831  if( row.size() != header.size() )
832  {
833  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
834  rownum,
835  header.size(),
836  row.size() );
837  continue;
838  }
839 
840  auto layer_sort = row[layer_sort_col];
841  auto layer_subclass = row[layer_subclass_col];
842  auto layer_art = row[layer_art_col];
843  auto layer_use = row[layer_use_col];
844  auto layer_cond = row[layer_cond_col];
845  auto layer_er = row[layer_er_col];
846  auto layer_rho = row[layer_rho_col];
847  auto layer_mat = row[layer_mat_col];
848 
849  if( layer_mat == "AIR" )
850  continue;
851 
852  FABMASTER_LAYER layer;
853 
854  if( layer_subclass.empty() )
855  {
856  if( layer_cond != "NO" )
857  layer.name = "In.Cu" + layer_sort;
858  else
859  layer.name = "Dielectric" + layer_sort;
860  }
861 
862  layer.positive = ( layer_art != "NEGATIVE" );
863 
864  layers.emplace( layer.name, layer );
865  }
866 
867  return rownum - aRow;
868 }
std::vector< std::string > single_row
std::map< std::string, FABMASTER_LAYER > layers
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, getColFromName(), layers, FABMASTER::FABMASTER_LAYER::name, FABMASTER::FABMASTER_LAYER::positive, processScaleFactor(), and rows.

Referenced by Process().

◆ processLine()

FABMASTER::GRAPHIC_LINE * FABMASTER::processLine ( const GRAPHIC_DATA aData,
double  aScale 
)
private

Definition at line 1024 of file import_fabmaster.cpp.

1025 {
1026  GRAPHIC_LINE* new_line = new GRAPHIC_LINE ;
1027 
1028  new_line->shape = GR_SHAPE_LINE;
1029  new_line->start_x = KiROUND( readDouble( aData.graphic_data1 ) * aScale );
1030  new_line->start_y = -KiROUND( readDouble( aData.graphic_data2 ) * aScale );
1031  new_line->end_x = KiROUND( readDouble( aData.graphic_data3 ) * aScale );
1032  new_line->end_y = -KiROUND( readDouble( aData.graphic_data4 ) * aScale );
1033  new_line->width = KiROUND( readDouble( aData.graphic_data5 ) * aScale );
1034 
1035  return new_line;
1036 }
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
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:73

References FABMASTER::GRAPHIC_LINE::end_x, FABMASTER::GRAPHIC_LINE::end_y, GR_SHAPE_LINE, FABMASTER::GRAPHIC_DATA::graphic_data1, FABMASTER::GRAPHIC_DATA::graphic_data2, FABMASTER::GRAPHIC_DATA::graphic_data3, FABMASTER::GRAPHIC_DATA::graphic_data4, FABMASTER::GRAPHIC_DATA::graphic_data5, KiROUND(), readDouble(), FABMASTER::GRAPHIC_ITEM::shape, FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, and FABMASTER::GRAPHIC_ITEM::width.

Referenced by processGraphic().

◆ processNets()

size_t FABMASTER::processNets ( size_t  aRow)
private

A!NET_NAME!REFDES!PIN_NUMBER!PIN_NAME!PIN_GROUND!PIN_POWER!

Definition at line 1701 of file import_fabmaster.cpp.

1702 {
1703  size_t rownum = aRow + 2;
1704 
1705  if( rownum >= rows.size() )
1706  return -1;
1707 
1708  const single_row& header = rows[aRow];
1709  double scale_factor = processScaleFactor( aRow + 1 );
1710 
1711  if( scale_factor <= 0.0 )
1712  return -1;
1713 
1714  int netname_col = getColFromName( aRow, "NETNAME" );
1715  int refdes_col = getColFromName( aRow, "REFDES" );
1716  int pinnum_col = getColFromName( aRow, "PINNUMBER" );
1717  int pinname_col = getColFromName( aRow, "PINNAME" );
1718  int pingnd_col = getColFromName( aRow, "PINGROUND" );
1719  int pinpwr_col = getColFromName( aRow, "PINPOWER" );
1720 
1721  if( netname_col < 0 || refdes_col < 0 || pinnum_col < 0 || pinname_col < 0 || pingnd_col < 0
1722  || pinpwr_col < 0 )
1723  return -1;
1724 
1725  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
1726  {
1727  const single_row& row = rows[rownum];
1728 
1729  if( row.size() != header.size() )
1730  {
1731  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1732  rownum,
1733  header.size(),
1734  row.size() );
1735  continue;
1736  }
1737 
1738  NETNAME new_net;
1739  new_net.name = row[netname_col];
1740  new_net.refdes = row[refdes_col];
1741  new_net.pin_num = row[pinnum_col];
1742  new_net.pin_name = row[pinname_col];
1743  new_net.pin_gnd = ( row[pingnd_col] == "YES" );
1744  new_net.pin_pwr = ( row[pinpwr_col] == "YES" );
1745 
1746  pin_nets.emplace( std::make_pair( new_net.refdes, new_net.pin_num ), new_net );
1747  netnames.insert( row[netname_col] );
1748  }
1749 
1750  return rownum - aRow;
1751 }
std::vector< std::string > single_row
std::map< std::pair< std::string, std::string >, NETNAME > pin_nets
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
std::set< std::string > netnames
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, getColFromName(), FABMASTER::NETNAME::name, netnames, FABMASTER::NETNAME::pin_gnd, FABMASTER::NETNAME::pin_name, pin_nets, FABMASTER::NETNAME::pin_num, FABMASTER::NETNAME::pin_pwr, processScaleFactor(), FABMASTER::NETNAME::refdes, and rows.

Referenced by Process().

◆ processPadStackLayers()

size_t FABMASTER::processPadStackLayers ( size_t  aRow)
private

If the layer ids have not yet been assigned

Definition at line 331 of file import_fabmaster.cpp.

332 {
333  size_t rownum = aRow + 2;
334 
335  if( rownum >= rows.size() )
336  return -1;
337 
338  const single_row& header = rows[aRow];
339 
340  int pad_name_col = getColFromName( aRow, "PADNAME" );
341  int pad_num_col = getColFromName( aRow, "RECNUMBER" );
342  int pad_lay_col = getColFromName( aRow, "LAYER" );
343  int pad_fix_col = getColFromName( aRow, "FIXFLAG" );
344  int pad_via_col = getColFromName( aRow, "VIAFLAG" );
345  int pad_shape_col = getColFromName( aRow, "PADSHAPE1" );
346  int pad_width_col = getColFromName( aRow, "PADWIDTH" );
347  int pad_height_col = getColFromName( aRow, "PADHGHT" );
348  int pad_xoff_col = getColFromName( aRow, "PADXOFF" );
349  int pad_yoff_col = getColFromName( aRow, "PADYOFF" );
350  int pad_flash_col = getColFromName( aRow, "PADFLASH" );
351  int pad_shape_name_col = getColFromName( aRow, "PADSHAPENAME" );
352 
353  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
354  {
355  const single_row& row = rows[rownum];
356 
357  if( row.size() != header.size() )
358  {
359  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
360  rownum,
361  header.size(),
362  row.size() );
363  continue;
364  }
365 
366  auto pad_name = row[pad_name_col];
367  auto pad_num = row[pad_num_col];
368  auto pad_layer = row[pad_lay_col];
369  auto pad_is_fixed = row[pad_fix_col];
370  auto pad_is_via = row[pad_via_col];
371  auto pad_shape = row[pad_shape_col];
372  auto pad_width = row[pad_width_col];
373  auto pad_height = row[pad_height_col];
374  auto pad_xoff = row[pad_xoff_col];
375  auto pad_yoff = row[pad_yoff_col];
376  auto pad_flash = row[pad_flash_col];
377  auto pad_shapename = row[pad_shape_name_col];
378 
379  // This layer setting seems to be unused
380  if( pad_layer == "INTERNAL_PAD_DEF" || pad_layer == "internal_pad_def" )
381  continue;
382 
383  // Skip the technical layers
384  if( pad_layer[0] == '~' )
385  break;
386 
387  auto result = layers.emplace( pad_layer, FABMASTER_LAYER{} );
388  FABMASTER_LAYER& layer = result.first->second;
389 
391  if( layer.id == 0 )
392  {
393  layer.name = pad_layer;
394  layer.id = readInt( pad_num );
395  layer.conductive = true;
396  }
397  }
398 
399  return 0;
400 }
std::vector< std::string > single_row
std::map< std::string, FABMASTER_LAYER > layers
int readInt(const std::string &aStr) const
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
std::deque< single_row > rows

References _, FABMASTER::FABMASTER_LAYER::conductive, getColFromName(), FABMASTER::FABMASTER_LAYER::id, layers, FABMASTER::FABMASTER_LAYER::name, readInt(), and rows.

Referenced by Process().

◆ processPadStacks()

size_t FABMASTER::processPadStacks ( size_t  aRow)
private

A!PADNAME!RECNUMBER!LAYER!FIXFLAG!VIAFLAG!PADSHAPE1!PADWIDTH!PADHGHT! PADXOFF!PADYOFF!PADFLASH!PADSHAPENAME!TRELSHAPE1!TRELWIDTH!TRELHGHT! TRELXOFF!TRELYOFF!TRELFLASH!TRELSHAPENAME!APADSHAPE1!APADWIDTH!APADHGHT! APADXOFF!APADYOFF!APADFLASH!APADSHAPENAME!

Handle the drill layer

This is to account for broken fabmaster outputs where circle drill hits don't actually get the drill hit value.

All remaining technical layers are not handled

Definition at line 409 of file import_fabmaster.cpp.

410 {
411  size_t rownum = aRow + 2;
412 
413  if( rownum >= rows.size() )
414  return -1;
415 
416  const single_row& header = rows[aRow];
417  double scale_factor = processScaleFactor( aRow + 1 );
418 
419  if( scale_factor <= 0.0 )
420  return -1;
421 
422  int pad_name_col = getColFromName( aRow, "PADNAME" );
423  int pad_num_col = getColFromName( aRow, "RECNUMBER" );
424  int pad_lay_col = getColFromName( aRow, "LAYER" );
425  int pad_fix_col = getColFromName( aRow, "FIXFLAG" );
426  int pad_via_col = getColFromName( aRow, "VIAFLAG" );
427  int pad_shape_col = getColFromName( aRow, "PADSHAPE1" );
428  int pad_width_col = getColFromName( aRow, "PADWIDTH" );
429  int pad_height_col = getColFromName( aRow, "PADHGHT" );
430  int pad_xoff_col = getColFromName( aRow, "PADXOFF" );
431  int pad_yoff_col = getColFromName( aRow, "PADYOFF" );
432  int pad_flash_col = getColFromName( aRow, "PADFLASH" );
433  int pad_shape_name_col = getColFromName( aRow, "PADSHAPENAME" );
434 
435  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
436  {
437  const single_row& row = rows[rownum];
438  FM_PAD* pad;
439 
440  if( row.size() != header.size() )
441  {
442  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
443  rownum,
444  header.size(),
445  row.size() );
446  continue;
447  }
448 
449  auto pad_name = row[pad_name_col];
450  auto pad_num = row[pad_num_col];
451  auto pad_layer = row[pad_lay_col];
452  auto pad_is_fixed = row[pad_fix_col];
453  auto pad_is_via = row[pad_via_col];
454  auto pad_shape = row[pad_shape_col];
455  auto pad_width = row[pad_width_col];
456  auto pad_height = row[pad_height_col];
457  auto pad_xoff = row[pad_xoff_col];
458  auto pad_yoff = row[pad_yoff_col];
459  auto pad_flash = row[pad_flash_col];
460  auto pad_shapename = row[pad_shape_name_col];
461 
462  // This layer setting seems to be unused
463  if( pad_layer == "INTERNAL_PAD_DEF" || pad_layer == "internal_pad_def" )
464  continue;
465 
466  int recnum = KiROUND( readDouble( pad_num ) );
467 
468  auto new_pad = pads.find( pad_name );
469 
470  if( new_pad != pads.end() )
471  pad = &new_pad->second;
472  else
473  {
474  pads[pad_name] = FM_PAD();
475  pad = &pads[pad_name];
476  pad->name = pad_name;
477  }
478 
480  if( pad_layer == "~DRILL" )
481  {
482  int drill_hit;
483  int drill_x;
484  int drill_y;
485 
486  try
487  {
488  drill_hit = KiROUND( std::fabs( readDouble( pad_shape ) * scale_factor ) );
489  drill_x = KiROUND( std::fabs( readDouble( pad_width ) * scale_factor ) );
490  drill_y = KiROUND( std::fabs( readDouble( pad_height ) * scale_factor ) );
491  }
492  catch( ... )
493  {
494  wxLogError( _( "Expecting drill size value but found %s!%s!%s in row %zu." ),
495  pad_shape.c_str(),
496  pad_width.c_str(),
497  pad_height.c_str(),
498  rownum );
499  continue;
500  }
501 
502  if( drill_hit == 0 )
503  {
504  pad->drill = false;
505  continue;
506  }
507 
508  pad->drill = true;
509 
512  if( drill_x == drill_y )
513  {
514  pad->drill_size_x = drill_hit;
515  pad->drill_size_y = drill_hit;
516  }
517  else
518  {
519  pad->drill_size_x = drill_x;
520  pad->drill_size_y = drill_y;
521  }
522 
523  if( !pad_shapename.empty() && pad_shapename[0] == 'P' )
524  pad->plated = true;
525 
526  continue;
527  }
528 
529  if( pad_shape.empty() )
530  continue;
531 
532  double w;
533  double h;
534 
535  try
536  {
537  w = readDouble( pad_width ) * scale_factor;
538  h = readDouble( pad_height ) * scale_factor;
539  }
540  catch( ... )
541  {
542  wxLogError( _( "Expecting pad size values but found %s : %s in row %zu." ),
543  pad_width.c_str(),
544  pad_height.c_str(),
545  rownum );
546  continue;
547  }
548 
549  if( w <= 0.0 )
550  continue;
551 
552  auto layer = layers.find( pad_layer );
553 
554  if( layer != layers.end() )
555  {
556  if( layer->second.layerid == F_Cu )
557  pad->top = true;
558  else if( layer->second.layerid == B_Cu )
559  pad->bottom = true;
560  }
561 
562  if( w > std::numeric_limits<int>::max() || h > std::numeric_limits<int>::max() )
563  {
564  wxLogError( _( "Invalid pad size in row %zu." ), rownum );
565  continue;
566  }
567 
568  if( pad_layer == "~TSM" || pad_layer == "~BSM" )
569  {
570  if( w > 0.0 && h > 0.0 )
571  {
572  pad->mask_width = KiROUND( w );
573  pad->mask_height = KiROUND( h );
574  }
575  continue;
576  }
577 
578  if( pad_layer == "~TSP" || pad_layer == "~BSP" )
579  {
580  if( w > 0.0 && h > 0.0 )
581  {
582  pad->paste_width = KiROUND( w );
583  pad->paste_height = KiROUND( h );
584  }
585  continue;
586  }
587 
589  if( pad_layer[0] == '~' )
590  continue;
591 
592  try
593  {
594  pad->x_offset = KiROUND( readDouble( pad_xoff ) * scale_factor );
595  pad->y_offset = -KiROUND( readDouble( pad_yoff ) * scale_factor );
596  }
597  catch( ... )
598  {
599  wxLogError( _( "Expecting pad offset values but found %s:%s in row %zu." ),
600  pad_xoff.c_str(),
601  pad_yoff.c_str(),
602  rownum );
603  continue;
604  }
605 
606  if( w > 0.0 && h > 0.0 && recnum == 1 )
607  {
608  pad->width = KiROUND( w );
609  pad->height = KiROUND( h );
610  pad->via = ( std::toupper( pad_is_via[0] ) != 'V' );
611 
612  if( pad_shape == "CIRCLE" )
613  {
614  pad->height = pad->width;
615  pad->shape = PAD_SHAPE::CIRCLE;
616  }
617  else if( pad_shape == "RECTANGLE" )
618  {
619  pad->shape = PAD_SHAPE::RECT;
620  }
621  else if( pad_shape == "ROUNDED_RECT" )
622  {
623  pad->shape = PAD_SHAPE::ROUNDRECT;
624  }
625  else if( pad_shape == "SQUARE" )
626  {
627  pad->shape = PAD_SHAPE::RECT;
628  pad->height = pad->width;
629  }
630  else if( pad_shape == "OBLONG" || pad_shape == "OBLONG_X" || pad_shape == "OBLONG_Y" )
631  pad->shape = PAD_SHAPE::OVAL;
632  else if( pad_shape == "OCTAGON" )
633  {
634  pad->shape = PAD_SHAPE::RECT;
635  pad->is_octogon = true;
636  }
637  else if( pad_shape == "SHAPE" )
638  {
639  pad->shape = PAD_SHAPE::CUSTOM;
640  pad->custom_name = pad_shapename;
641  }
642  else
643  {
644  wxLogError( _( "Unknown pad shape name '%s' on layer '%s' in row %zu." ),
645  pad_shape.c_str(),
646  pad_layer.c_str(),
647  rownum );
648  continue;
649  }
650  }
651  }
652 
653  return rownum - aRow;
654 }
std::vector< std::string > single_row
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
std::map< std::string, FABMASTER_LAYER > layers
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
std::unordered_map< std::string, FM_PAD > pads
Definition: layer_ids.h:71
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:73
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, B_Cu, CIRCLE, CUSTOM, F_Cu, getColFromName(), KiROUND(), layers, OVAL, pad, pads, processScaleFactor(), readDouble(), RECT, ROUNDRECT, and rows.

Referenced by Process().

◆ processPins()

size_t FABMASTER::processPins ( size_t  aRow)
private

A!SYM_NAME!SYM_MIRROR!PIN_NAME!PIN_NUMBER!PIN_X!PIN_Y!PAD_STACK_NAME!REFDES!PIN_ROTATION!TEST_POINT!

Definition at line 1629 of file import_fabmaster.cpp.

1630 {
1631  size_t rownum = aRow + 2;
1632 
1633  if( rownum >= rows.size() )
1634  return -1;
1635 
1636  const single_row& header = rows[aRow];
1637  double scale_factor = processScaleFactor( aRow + 1 );
1638 
1639  if( scale_factor <= 0.0 )
1640  return -1;
1641 
1642  int symname_col = getColFromName( aRow, "SYMNAME" );
1643  int symmirror_col = getColFromName( aRow, "SYMMIRROR" );
1644  int pinname_col = getColFromName( aRow, "PINNAME" );
1645  int pinnum_col = getColFromName( aRow, "PINNUMBER" );
1646  int pinx_col = getColFromName( aRow, "PINX" );
1647  int piny_col = getColFromName( aRow, "PINY" );
1648  int padstack_col = getColFromName( aRow, "PADSTACKNAME" );
1649  int refdes_col = getColFromName( aRow, "REFDES" );
1650  int pinrot_col = getColFromName( aRow, "PINROTATION" );
1651  int testpoint_col = getColFromName( aRow, "TESTPOINT" );
1652 
1653  if( symname_col < 0 ||symmirror_col < 0 || pinname_col < 0 || pinnum_col < 0 || pinx_col < 0
1654  || piny_col < 0 || padstack_col < 0 || refdes_col < 0 || pinrot_col < 0
1655  || testpoint_col < 0 )
1656  return -1;
1657 
1658  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
1659  {
1660  const single_row& row = rows[rownum];
1661 
1662  if( row.size() != header.size() )
1663  {
1664  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1665  rownum,
1666  header.size(),
1667  row.size() );
1668  continue;
1669  }
1670 
1671  auto pin = std::make_unique<PIN>();
1672 
1673  pin->name = row[symname_col];
1674  pin->mirror = ( row[symmirror_col] == "YES" );
1675  pin->pin_name = row[pinname_col];
1676  pin->pin_number = row[pinnum_col];
1677  pin->pin_x = KiROUND( readDouble( row[pinx_col] ) * scale_factor );
1678  pin->pin_y = -KiROUND( readDouble( row[piny_col] ) * scale_factor );
1679  pin->padstack = row[padstack_col];
1680  pin->refdes = row[refdes_col];
1681  pin->rotation = readDouble( row[pinrot_col] );
1682 
1683  auto map_it = pins.find( pin->refdes );
1684 
1685  if( map_it == pins.end() )
1686  {
1687  auto retval = pins.insert( std::make_pair( pin->refdes, std::set<std::unique_ptr<PIN>, PIN::BY_NUM>{} ) );
1688  map_it = retval.first;
1689  }
1690 
1691  map_it->second.insert( std::move( pin ) );
1692  }
1693 
1694  return rownum - aRow;
1695 }
std::vector< std::string > single_row
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
std::map< std::string, std::set< std::unique_ptr< PIN >, PIN::BY_NUM > > pins
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:73
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, getColFromName(), KiROUND(), pin, pins, processScaleFactor(), readDouble(), and rows.

Referenced by Process().

◆ processRectangle()

FABMASTER::GRAPHIC_RECTANGLE * FABMASTER::processRectangle ( const GRAPHIC_DATA aData,
double  aScale 
)
private

Definition at line 1084 of file import_fabmaster.cpp.

1085 {
1086  GRAPHIC_RECTANGLE* new_rect = new GRAPHIC_RECTANGLE;
1087 
1088  new_rect->shape = GR_SHAPE_RECTANGLE;
1089  new_rect->start_x = KiROUND( readDouble( aData.graphic_data1 ) * aScale );
1090  new_rect->start_y = -KiROUND( readDouble( aData.graphic_data2 ) * aScale );
1091  new_rect->end_x = KiROUND( readDouble( aData.graphic_data3 ) * aScale );
1092  new_rect->end_y = -KiROUND( readDouble( aData.graphic_data4 ) * aScale );
1093  new_rect->fill = aData.graphic_data5 == "1";
1094  new_rect->width = 0;
1095 
1096  return new_rect;
1097 }
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
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:73

References FABMASTER::GRAPHIC_RECTANGLE::end_x, FABMASTER::GRAPHIC_RECTANGLE::end_y, FABMASTER::GRAPHIC_RECTANGLE::fill, GR_SHAPE_RECTANGLE, FABMASTER::GRAPHIC_DATA::graphic_data1, FABMASTER::GRAPHIC_DATA::graphic_data2, FABMASTER::GRAPHIC_DATA::graphic_data3, FABMASTER::GRAPHIC_DATA::graphic_data4, FABMASTER::GRAPHIC_DATA::graphic_data5, KiROUND(), readDouble(), FABMASTER::GRAPHIC_ITEM::shape, FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, and FABMASTER::GRAPHIC_ITEM::width.

Referenced by processGraphic().

◆ processScaleFactor()

double FABMASTER::processScaleFactor ( size_t  aRow)
private

Processes data from text vectors into internal database for further ordering.

Parameters
aRowvector offset being processed
Returns
Count of the number of rows processed, return -1 on error

Definition at line 259 of file import_fabmaster.cpp.

260 {
261  double retval = 0.0;
262 
263  if( aRow >= rows.size() )
264  return -1.0;
265 
266  if( rows[aRow].size() < 11 )
267  {
268  wxLogError( _( "Invalid row size in J row %zu. Expecting 11 elements but found %zu." ),
269  aRow,
270  rows[aRow].size() );
271  return -1.0;
272  }
273 
274  for( int i = 7; i < 10 && retval < 1.0; ++i )
275  {
276  auto units = rows[aRow][i];
277  std::transform(units.begin(), units.end(),units.begin(), ::toupper);
278 
279  if( units == "MILS" )
280  retval = IU_PER_MILS;
281  else if( units == "MILLIMETERS" )
282  retval = IU_PER_MM;
283  else if( units == "MICRONS" )
284  retval = IU_PER_MM * 10.0;
285  else if( units == "INCHES" )
286  retval = IU_PER_MILS * 1000.0;
287  }
288 
289  if( retval < 1.0 )
290  {
291  wxLogError( _( "Could not find units value, defaulting to mils." ) );
292  retval = IU_PER_MILS;
293  }
294 
295  return retval;
296 }
static constexpr double IU_PER_MM
Mock up a conversion function.
#define _(s)
#define IU_PER_MILS
Definition: plotter.cpp:136
std::deque< single_row > rows

References _, IU_PER_MILS, IU_PER_MM, and rows.

Referenced by processCustomPads(), processFootprints(), processGeometry(), processLayers(), processNets(), processPadStacks(), processPins(), processSimpleLayers(), processTraces(), and processVias().

◆ processSimpleLayers()

size_t FABMASTER::processSimpleLayers ( size_t  aRow)
private

Definition at line 657 of file import_fabmaster.cpp.

658 {
659  size_t rownum = aRow + 2;
660 
661  if( rownum >= rows.size() )
662  return -1;
663 
664  auto header = rows[aRow];
665  double scale_factor = processScaleFactor( aRow + 1 );
666 
667  if( scale_factor <= 0.0 )
668  return -1;
669 
670  int layer_class_col = getColFromName( aRow, "CLASS" );
671  int layer_subclass_col = getColFromName( aRow, "SUBCLASS" );
672 
673  if( layer_class_col < 0 || layer_subclass_col < 0 )
674  return -1;
675 
676  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
677  {
678  const single_row& row = rows[rownum];
679 
680  if( row.size() != header.size() )
681  {
682  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
683  rownum,
684  header.size(),
685  row.size() );
686  continue;
687  }
688 
689  auto result = layers.emplace( row[layer_subclass_col], FABMASTER_LAYER{} );
690  FABMASTER_LAYER& layer = result.first->second;
691 
692  layer.name = row[layer_subclass_col];
693  layer.positive = true;
694  layer.conductive = false;
695 
696  if( row[layer_class_col] == "ANTI ETCH" )
697  {
698  layer.positive = false;
699  layer.conductive = true;
700  }
701  else if( row[layer_class_col] == "ETCH" )
702  {
703  layer.conductive = true;
704  }
705  }
706 
707  return rownum - aRow;
708 }
std::vector< std::string > single_row
std::map< std::string, FABMASTER_LAYER > layers
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, FABMASTER::FABMASTER_LAYER::conductive, getColFromName(), layers, FABMASTER::FABMASTER_LAYER::name, FABMASTER::FABMASTER_LAYER::positive, processScaleFactor(), and rows.

Referenced by Process().

◆ processSymbols()

size_t FABMASTER::processSymbols ( size_t  aRow)
private

◆ processText()

FABMASTER::GRAPHIC_TEXT * FABMASTER::processText ( const GRAPHIC_DATA aData,
double  aScale 
)
private

Definition at line 1099 of file import_fabmaster.cpp.

1100 {
1101  GRAPHIC_TEXT* new_text = new GRAPHIC_TEXT;
1102 
1103  new_text->shape = GR_SHAPE_TEXT;
1104  new_text->start_x = KiROUND( readDouble( aData.graphic_data1 ) * aScale );
1105  new_text->start_y = -KiROUND( readDouble( aData.graphic_data2 ) * aScale );
1106  new_text->rotation = KiROUND( readDouble( aData.graphic_data3 ) );
1107  new_text->mirror = ( aData.graphic_data4 == "YES" );
1108 
1109  if( aData.graphic_data5 == "RIGHT" )
1110  new_text->orient = GR_TEXT_HJUSTIFY_RIGHT;
1111  else if( aData.graphic_data5 == "CENTER" )
1112  new_text->orient = GR_TEXT_HJUSTIFY_CENTER;
1113  else
1114  new_text->orient = GR_TEXT_HJUSTIFY_LEFT;
1115 
1116  std::vector<std::string> toks = split( aData.graphic_data6, " \t" );
1117 
1118  if( toks.size() < 8 )
1119  {
1120  // We log the error here but continue in the case of too few tokens
1121  wxLogError( _( "Invalid token count. Expected 8 but found %zu." ), toks.size() );
1122  new_text->height = 0;
1123  new_text->width = 0;
1124  new_text->ital = false;
1125  new_text->thickness = 0;
1126  }
1127  else
1128  {
1129  // 0 = size
1130  // 1 = font
1131  new_text->height = KiROUND( readDouble( toks[2] ) * aScale );
1132  new_text->width = KiROUND( readDouble( toks[3] ) * aScale );
1133  new_text->ital = readDouble( toks[4] ) != 0.0;
1134  // 5 = character spacing
1135  // 6 = line spacing
1136  new_text->thickness = KiROUND( readDouble( toks[7] ) * aScale );
1137  }
1138 
1139  new_text->text = aData.graphic_data7;
1140  return new_text;
1141 }
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
#define _(s)
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:73
static std::vector< std::string > split(const std::string &aStr, const std::string &aDelim)
Split the input string into a vector of output strings.
Definition: string_utils.h:293

References _, GR_SHAPE_TEXT, GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, FABMASTER::GRAPHIC_DATA::graphic_data1, FABMASTER::GRAPHIC_DATA::graphic_data2, FABMASTER::GRAPHIC_DATA::graphic_data3, FABMASTER::GRAPHIC_DATA::graphic_data4, FABMASTER::GRAPHIC_DATA::graphic_data5, FABMASTER::GRAPHIC_DATA::graphic_data6, FABMASTER::GRAPHIC_DATA::graphic_data7, FABMASTER::GRAPHIC_TEXT::height, FABMASTER::GRAPHIC_TEXT::ital, KiROUND(), FABMASTER::GRAPHIC_TEXT::mirror, FABMASTER::GRAPHIC_TEXT::orient, readDouble(), FABMASTER::GRAPHIC_TEXT::rotation, FABMASTER::GRAPHIC_ITEM::shape, split(), FABMASTER::GRAPHIC_ITEM::start_x, FABMASTER::GRAPHIC_ITEM::start_y, FABMASTER::GRAPHIC_TEXT::text, FABMASTER::GRAPHIC_TEXT::thickness, and FABMASTER::GRAPHIC_ITEM::width.

Referenced by processGraphic().

◆ processTraces()

size_t FABMASTER::processTraces ( size_t  aRow)
private

A!CLASS!SUBCLASS!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2! GRAPHIC_DATA_3!GRAPHIC_DATA_4!GRAPHIC_DATA_5!GRAPHIC_DATA_6!GRAPHIC_DATA_7!GRAPHIC_DATA_8! GRAPHIC_DATA_9!NET_NAME!

Definition at line 1375 of file import_fabmaster.cpp.

1376 {
1377  size_t rownum = aRow + 2;
1378 
1379  if( rownum >= rows.size() )
1380  return -1;
1381 
1382  const single_row& header = rows[aRow];
1383  double scale_factor = processScaleFactor( aRow + 1 );
1384 
1385  if( scale_factor <= 0.0 )
1386  return -1;
1387 
1388  int class_col = getColFromName( aRow, "CLASS" );
1389  int layer_col = getColFromName( aRow, "SUBCLASS" );
1390  int grdata_name_col = getColFromName( aRow, "GRAPHICDATANAME" );
1391  int grdata_num_col = getColFromName( aRow, "GRAPHICDATANUMBER" );
1392  int tag_col = getColFromName( aRow, "RECORDTAG" );
1393  int grdata1_col = getColFromName( aRow, "GRAPHICDATA1" );
1394  int grdata2_col = getColFromName( aRow, "GRAPHICDATA2" );
1395  int grdata3_col = getColFromName( aRow, "GRAPHICDATA3" );
1396  int grdata4_col = getColFromName( aRow, "GRAPHICDATA4" );
1397  int grdata5_col = getColFromName( aRow, "GRAPHICDATA5" );
1398  int grdata6_col = getColFromName( aRow, "GRAPHICDATA6" );
1399  int grdata7_col = getColFromName( aRow, "GRAPHICDATA7" );
1400  int grdata8_col = getColFromName( aRow, "GRAPHICDATA8" );
1401  int grdata9_col = getColFromName( aRow, "GRAPHICDATA9" );
1402  int netname_col = getColFromName( aRow, "NETNAME" );
1403 
1404  if( class_col < 0 || layer_col < 0 || grdata_name_col < 0 || grdata_num_col < 0
1405  || tag_col < 0 || grdata1_col < 0 || grdata2_col < 0 || grdata3_col < 0
1406  || grdata4_col < 0 || grdata5_col < 0 || grdata6_col < 0 || grdata7_col < 0
1407  || grdata8_col < 0 || grdata9_col < 0 || netname_col < 0 )
1408  return -1;
1409 
1410  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
1411  {
1412  const single_row& row = rows[rownum];
1413 
1414  if( row.size() != header.size() )
1415  {
1416  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1417  rownum,
1418  header.size(),
1419  row.size() );
1420  continue;
1421  }
1422 
1423  GRAPHIC_DATA gr_data;
1424  gr_data.graphic_dataname = row[grdata_name_col];
1425  gr_data.graphic_datanum = row[grdata_num_col];
1426  gr_data.graphic_data1 = row[grdata1_col];
1427  gr_data.graphic_data2 = row[grdata2_col];
1428  gr_data.graphic_data3 = row[grdata3_col];
1429  gr_data.graphic_data4 = row[grdata4_col];
1430  gr_data.graphic_data5 = row[grdata5_col];
1431  gr_data.graphic_data6 = row[grdata6_col];
1432  gr_data.graphic_data7 = row[grdata7_col];
1433  gr_data.graphic_data8 = row[grdata8_col];
1434  gr_data.graphic_data9 = row[grdata9_col];
1435 
1436  const std::string& geo_tag = row[tag_col];
1437  // Grouped graphics are a series of records with the same record ID but incrementing
1438  // Sequence numbers.
1439  int id = -1;
1440  int seq = -1;
1441  int subseq = 0;
1442 
1443  if( std::sscanf( geo_tag.c_str(), "%d %d %d", &id, &seq, &subseq ) < 2 )
1444  {
1445  wxLogError( _( "Invalid format for record_tag string '%s' in row %zu." ),
1446  geo_tag.c_str(),
1447  rownum );
1448  continue;
1449  }
1450 
1451  auto gr_item = std::unique_ptr<GRAPHIC_ITEM>( processGraphic( gr_data, scale_factor ) );
1452 
1453  if( !gr_item )
1454  {
1455  wxLogDebug( _( "Unhandled graphic item '%s' in row %zu." ),
1456  gr_data.graphic_dataname.c_str(),
1457  rownum );
1458  continue;
1459  }
1460 
1461  auto new_trace = std::make_unique<TRACE>();
1462  new_trace->id = id;
1463  new_trace->layer = row[layer_col];
1464  new_trace->netname = row[netname_col];
1465  new_trace->lclass = row[class_col];
1466 
1467  gr_item->layer = row[layer_col];
1468  gr_item->seq = seq;
1469  gr_item->subseq = subseq;
1470 
1471  // Collect the reference designator positions for the footprints later
1472  if( new_trace->lclass == "REF DES" )
1473  {
1474  auto result = refdes.emplace( std::move( new_trace ) );
1475  auto& ref = *result.first;
1476  ref->segment.emplace( std::move( gr_item ) );
1477  }
1478  else if( gr_item->width == 0 )
1479  {
1480  auto result = zones.emplace( std::move( new_trace ) );
1481  auto& zone = *result.first;
1482  auto gr_result = zone->segment.emplace( std::move( gr_item ) );
1483 
1484  if( !gr_result.second )
1485  {
1486  wxLogError( _( "Duplicate item for ID %d and sequence %d in row %zu." ),
1487  id,
1488  seq,
1489  rownum );
1490  }
1491 
1492  }
1493  else
1494  {
1495  auto result = traces.emplace( std::move( new_trace ) );
1496  auto& trace = *result.first;
1497  auto gr_result = trace->segment.emplace( std::move( gr_item ) );
1498 
1499  if( !gr_result.second )
1500  {
1501  wxLogError( _( "Duplicate item for ID %d and sequence %d in row %zu." ),
1502  id,
1503  seq,
1504  rownum );
1505  }
1506  }
1507  }
1508 
1509  return rownum - aRow;
1510 }
std::vector< std::string > single_row
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > traces
GRAPHIC_ITEM * processGraphic(const GRAPHIC_DATA &aData, double aScale)
Specialty functions for processing graphical data rows into the internal database.
#define _(s)
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > zones
int getColFromName(size_t aRow, const std::string &aStr)
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > refdes
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, getColFromName(), FABMASTER::GRAPHIC_DATA::graphic_data1, FABMASTER::GRAPHIC_DATA::graphic_data2, FABMASTER::GRAPHIC_DATA::graphic_data3, FABMASTER::GRAPHIC_DATA::graphic_data4, FABMASTER::GRAPHIC_DATA::graphic_data5, FABMASTER::GRAPHIC_DATA::graphic_data6, FABMASTER::GRAPHIC_DATA::graphic_data7, FABMASTER::GRAPHIC_DATA::graphic_data8, FABMASTER::GRAPHIC_DATA::graphic_data9, FABMASTER::GRAPHIC_DATA::graphic_dataname, FABMASTER::GRAPHIC_DATA::graphic_datanum, processGraphic(), processScaleFactor(), refdes, rows, traces, and zones.

Referenced by Process().

◆ processVias()

size_t FABMASTER::processVias ( size_t  aRow)
private

A!VIA_X!VIA_Y!PAD_STACK_NAME!NET_NAME!TEST_POINT!

Definition at line 1320 of file import_fabmaster.cpp.

1321 {
1322  size_t rownum = aRow + 2;
1323 
1324  if( rownum >= rows.size() )
1325  return -1;
1326 
1327  const single_row& header = rows[aRow];
1328  double scale_factor = processScaleFactor( aRow + 1 );
1329 
1330  if( scale_factor <= 0.0 )
1331  return -1;
1332 
1333  int viax_col = getColFromName( aRow, "VIAX" );
1334  int viay_col = getColFromName( aRow, "VIAY" );
1335  int padstack_name_col = getColFromName( aRow, "PADSTACKNAME" );
1336  int net_name_col = getColFromName( aRow, "NETNAME" );
1337  int test_point_col = getColFromName( aRow, "TESTPOINT" );
1338 
1339  if( viax_col < 0 || viay_col < 0 || padstack_name_col < 0 || net_name_col < 0
1340  || test_point_col < 0 )
1341  return -1;
1342 
1343  for( ; rownum < rows.size() && rows[rownum].size() > 0 && rows[rownum][0] == "S"; ++rownum )
1344  {
1345  const single_row& row = rows[rownum];
1346 
1347  if( row.size() != header.size() )
1348  {
1349  wxLogError( _( "Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1350  rownum,
1351  header.size(),
1352  row.size() );
1353  continue;
1354  }
1355 
1356  vias.emplace_back( std::make_unique<FM_VIA>() );
1357  auto& via = vias.back();
1358 
1359  via->x = KiROUND( readDouble( row[viax_col] ) * scale_factor );
1360  via->y = -KiROUND( readDouble( row[viay_col] ) * scale_factor );
1361  via->padstack = row[padstack_name_col];
1362  via->net = row[net_name_col];
1363  via->test_point = ( row[test_point_col] == "YES" );
1364  }
1365 
1366  return rownum - aRow;
1367 }
std::vector< std::string > single_row
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
std::vector< std::unique_ptr< FM_VIA > > vias
#define _(s)
int getColFromName(size_t aRow, const std::string &aStr)
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:73
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
std::deque< single_row > rows

References _, getColFromName(), KiROUND(), processScaleFactor(), readDouble(), rows, via, and vias.

Referenced by Process().

◆ Read()

bool FABMASTER::Read ( const std::string &  aFile)

Rows end with "!" and we don't want to keep the empty cell

Definition at line 103 of file import_fabmaster.cpp.

104 {
105 
106  std::ifstream ifs( aFile, std::ios::in | std::ios::binary );
107 
108  if( !ifs.is_open() )
109  return false;
110 
111  m_filename = aFile;
112 
113  // Read/ignore all bytes in the file to find the size and then go back to the beginning
114  ifs.ignore( std::numeric_limits<std::streamsize>::max() );
115  std::streamsize length = ifs.gcount();
116  ifs.clear();
117  ifs.seekg( 0, std::ios_base::beg );
118 
119  std::string buffer( std::istreambuf_iterator<char>{ ifs }, {} );
120 
121  std::vector < std::string > row;
122 
123  // Reserve an estimate of the number of rows to prevent continual re-allocation
124  // crashing (Looking at you MSVC)
125  row.reserve( length / 100 );
126  std::string cell;
127  cell.reserve( 100 );
128 
129  bool quoted = false;
130 
131  for( auto ch : buffer )
132  {
133  switch( ch )
134  {
135  case '"':
136 
137  if( cell.empty() || cell[0] == '"' )
138  quoted = !quoted;
139 
140  cell += ch;
141  break;
142 
143  case '!':
144  if( !quoted )
145  {
146  row.push_back( cell );
147  cell.clear();
148  }
149  else
150  cell += ch;
151 
152  break;
153 
154  case '\n':
155 
157  if( !cell.empty() )
158  row.push_back( cell );
159 
160  cell.clear();
161  rows.push_back( row );
162  row.clear();
163  quoted = false;
164  break;
165 
166  case '\r':
167  break;
168 
169  default:
170  cell += std::toupper( ch );
171  }
172  }
173 
174  // Handle last line without linebreak
175  if( !cell.empty() || !row.empty() )
176  {
177  row.push_back( cell );
178  cell.clear();
179  rows.push_back( row );
180  row.clear();
181  }
182 
183  return true;
184 }
wxFileName m_filename
std::deque< single_row > rows

References m_filename, and rows.

Referenced by FABMASTER_PLUGIN::Load().

◆ readDouble()

double FABMASTER::readDouble ( const std::string &  aStr) const
private

Reads the double/integer value from a std string independent of the user locale.

Parameters
aStrstring to generate value from
Returns
0 if value cannot be created

Definition at line 81 of file import_fabmaster.cpp.

82 {
83  std::istringstream istr( aStr );
84  istr.imbue( std::locale::classic() );
85 
86  double doubleValue;
87  istr >> doubleValue;
88  return doubleValue;
89 }

Referenced by processArc(), processFootprints(), processLine(), processPadStacks(), processPins(), processRectangle(), processText(), and processVias().

◆ readInt()

int FABMASTER::readInt ( const std::string &  aStr) const
private

Definition at line 92 of file import_fabmaster.cpp.

93 {
94  std::istringstream istr( aStr );
95  istr.imbue( std::locale::classic() );
96 
97  int intValue;
98  istr >> intValue;
99  return intValue;
100 }

Referenced by processPadStackLayers().

Member Data Documentation

◆ board_graphics

std::vector<GEOM_GRAPHIC> FABMASTER::board_graphics
private

Definition at line 399 of file import_fabmaster.h.

Referenced by LoadBoard(), loadGraphics(), and processGeometry().

◆ comp_graphics

std::map<std::string, std::map<int, GEOM_GRAPHIC> > FABMASTER::comp_graphics
private

Definition at line 400 of file import_fabmaster.h.

Referenced by loadFootprints(), and processGeometry().

◆ components

std::map<std::string, std::vector<std::unique_ptr<COMPONENT> > > FABMASTER::components
private

Definition at line 476 of file import_fabmaster.h.

Referenced by LoadBoard(), loadFootprints(), and processFootprints().

◆ has_comps

bool FABMASTER::has_comps
private

Definition at line 97 of file import_fabmaster.h.

◆ has_graphic

bool FABMASTER::has_graphic
private

Definition at line 98 of file import_fabmaster.h.

◆ has_nets

bool FABMASTER::has_nets
private

Definition at line 99 of file import_fabmaster.h.

◆ has_pads

bool FABMASTER::has_pads
private

Definition at line 96 of file import_fabmaster.h.

◆ has_pins

bool FABMASTER::has_pins
private

Definition at line 100 of file import_fabmaster.h.

◆ layer_map

std::map<std::string, PCB_LAYER_ID> FABMASTER::layer_map
private

Definition at line 505 of file import_fabmaster.h.

◆ layers

std::map<std::string, FABMASTER_LAYER> FABMASTER::layers
private

◆ m_doneCount

unsigned FABMASTER::m_doneCount
private

Definition at line 587 of file import_fabmaster.h.

Referenced by checkpoint(), and LoadBoard().

◆ m_filename

wxFileName FABMASTER::m_filename
private

Definition at line 76 of file import_fabmaster.h.

Referenced by LoadBoard(), loadFootprints(), and Read().

◆ m_lastProgressCount

unsigned FABMASTER::m_lastProgressCount
private

Definition at line 588 of file import_fabmaster.h.

Referenced by checkpoint().

◆ m_progressReporter

PROGRESS_REPORTER* FABMASTER::m_progressReporter
private

optional; may be nullptr

Definition at line 586 of file import_fabmaster.h.

Referenced by checkpoint(), and LoadBoard().

◆ m_totalCount

unsigned FABMASTER::m_totalCount
private

for progress reporting

Definition at line 589 of file import_fabmaster.h.

Referenced by checkpoint(), and LoadBoard().

◆ netnames

std::set<std::string> FABMASTER::netnames
private

Definition at line 180 of file import_fabmaster.h.

Referenced by LoadBoard(), loadNets(), and processNets().

◆ pad_shapes

std::unordered_map<std::string, FABMASTER_PAD_SHAPE> FABMASTER::pad_shapes
private

Definition at line 331 of file import_fabmaster.h.

Referenced by loadFootprints(), and processCustomPads().

◆ pads

std::unordered_map<std::string, FM_PAD> FABMASTER::pads
private

Definition at line 138 of file import_fabmaster.h.

Referenced by loadFootprints(), loadVias(), and processPadStacks().

◆ pin_nets

std::map<std::pair<std::string, std::string>, NETNAME> FABMASTER::pin_nets
private

Definition at line 179 of file import_fabmaster.h.

Referenced by loadFootprints(), and processNets().

◆ pins

std::map<std::string, std::set<std::unique_ptr<PIN>, PIN::BY_NUM> > FABMASTER::pins
private

Definition at line 503 of file import_fabmaster.h.

Referenced by loadFootprints(), and processPins().

◆ polygons

std::set<std::unique_ptr<TRACE>, TRACE::BY_ID> FABMASTER::polygons
private

Definition at line 441 of file import_fabmaster.h.

◆ refdes

std::set<std::unique_ptr<TRACE>, TRACE::BY_ID> FABMASTER::refdes
private

Definition at line 443 of file import_fabmaster.h.

Referenced by loadFootprints(), and processTraces().

◆ rows

◆ symbols

std::unordered_map<std::string, SYMBOL> FABMASTER::symbols
private

Definition at line 374 of file import_fabmaster.h.

◆ traces

std::set<std::unique_ptr<TRACE>, TRACE::BY_ID> FABMASTER::traces
private

Definition at line 437 of file import_fabmaster.h.

Referenced by LoadBoard(), and processTraces().

◆ vias

std::vector<std::unique_ptr<FM_VIA> > FABMASTER::vias
private

Definition at line 414 of file import_fabmaster.h.

Referenced by LoadBoard(), loadVias(), and processVias().

◆ zones

std::set<std::unique_ptr<TRACE>, TRACE::BY_ID> FABMASTER::zones
private

Definition at line 439 of file import_fabmaster.h.

Referenced by LoadBoard(), loadZones(), orderZones(), and processTraces().


The documentation for this class was generated from the following files: