KiCad PCB EDA Suite
eagle_plugin.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2012-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 /*
27 
28 Pcbnew PLUGIN for Eagle 6.x XML *.brd and footprint format.
29 
30 XML parsing and converting:
31 Getting line numbers and byte offsets from the source XML file is not
32 possible using currently available XML libraries within KiCad project:
33 wxXmlDocument and boost::property_tree.
34 
35 property_tree will give line numbers but no byte offsets, and only during
36 document loading. This means that if we have a problem after the document is
37 successfully loaded, there is no way to correlate back to line number and byte
38 offset of the problem. So a different approach is taken, one which relies on the
39 XML elements themselves using an XPATH type of reporting mechanism. The path to
40 the problem is reported in the error messages. This means keeping track of that
41 path as we traverse the XML document for the sole purpose of accurate error
42 reporting.
43 
44 User can load the source XML file into firefox or other xml browser and follow
45 our error message.
46 
47 Load() TODO's
48 
49 *) verify zone fill clearances are correct
50 
51 */
52 
53 #include <cerrno>
54 
55 #include <wx/string.h>
56 #include <wx/xml/xml.h>
57 
58 #include <common.h>
60 #include <fctsys.h>
62 #include <kicad_string.h>
63 #include <macros.h>
64 #include <properties.h>
65 #include <trigo.h>
66 #include <wx/filename.h>
67 #include <math/util.h> // for KiROUND
68 
69 #include <class_board.h>
70 #include <class_module.h>
71 #include <class_track.h>
72 #include <class_edge_mod.h>
73 #include <class_zone.h>
74 #include <class_pcb_text.h>
75 #include <class_dimension.h>
76 
77 #include <eagle_plugin.h>
78 
79 using namespace std;
80 
81 
82 typedef MODULE_MAP::iterator MODULE_ITER;
83 typedef MODULE_MAP::const_iterator MODULE_CITER;
84 
85 
88 static int parseEagle( const wxString& aDistance )
89 {
90  ECOORD::EAGLE_UNIT unit = ( aDistance.npos != aDistance.find( "mil" ) )
91  ? ECOORD::EAGLE_UNIT::EU_MIL : ECOORD::EAGLE_UNIT::EU_MM;
92 
93  ECOORD coord( aDistance, unit );
94 
95  return coord.ToPcbUnits();
96 }
97 
98 
99 // In Eagle one can specify DRC rules where min value > max value,
100 // in such case the max value has the priority
101 template<typename T>
102 static T eagleClamp( T aMin, T aValue, T aMax )
103 {
104  T ret = std::max( aMin, aValue );
105  return std::min( aMax, ret );
106 }
107 
108 
111 static wxString makeKey( const wxString& aFirst, const wxString& aSecond )
112 {
113  wxString key = aFirst + '\x02' + aSecond;
114  return key;
115 }
116 
117 
118 static void setKeepoutSettingsToZone( ZONE_CONTAINER* aZone, LAYER_NUM aLayer )
119 {
120  if( aLayer == EAGLE_LAYER::TRESTRICT || aLayer == EAGLE_LAYER::BRESTRICT )
121  {
122  aZone->SetIsKeepout( true );
123  aZone->SetDoNotAllowVias( true );
124  aZone->SetDoNotAllowTracks( true );
125  aZone->SetDoNotAllowCopperPour( true );
126  aZone->SetDoNotAllowPads( true );
127  aZone->SetDoNotAllowFootprints( false );
128 
129  if( aLayer == EAGLE_LAYER::TRESTRICT ) // front layer keepout
130  aZone->SetLayer( F_Cu );
131  else // bottom layer keepout
132  aZone->SetLayer( B_Cu );
133  }
134  else if( aLayer == EAGLE_LAYER::VRESTRICT )
135  {
136  aZone->SetIsKeepout( true );
137  aZone->SetDoNotAllowVias( true );
138  aZone->SetDoNotAllowTracks( false );
139  aZone->SetDoNotAllowCopperPour( false );
140  aZone->SetDoNotAllowPads( false );
141  aZone->SetDoNotAllowFootprints( false );
142 
143  aZone->SetLayerSet( LSET::AllCuMask() );
144  }
145 }
146 
147 
148 void ERULES::parse( wxXmlNode* aRules )
149 {
150  wxXmlNode* child = aRules->GetChildren();
151 
152  while( child )
153  {
154  if( child->GetName() == "param" )
155  {
156  const wxString& name = child->GetAttribute( "name" );
157  const wxString& value = child->GetAttribute( "value" );
158 
159  if( name == "psElongationLong" )
160  psElongationLong = wxAtoi( value );
161  else if( name == "psElongationOffset" )
162  psElongationOffset = wxAtoi( value );
163 
164  else if( name == "mvStopFrame" )
165  value.ToDouble( &mvStopFrame );
166  else if( name == "mvCreamFrame" )
167  value.ToDouble( &mvCreamFrame );
168  else if( name == "mlMinStopFrame" )
169  mlMinStopFrame = parseEagle( value );
170  else if( name == "mlMaxStopFrame" )
171  mlMaxStopFrame = parseEagle( value );
172  else if( name == "mlMinCreamFrame" )
173  mlMinCreamFrame = parseEagle( value );
174  else if( name == "mlMaxCreamFrame" )
175  mlMaxCreamFrame = parseEagle( value );
176 
177  else if( name == "srRoundness" )
178  value.ToDouble( &srRoundness );
179  else if( name == "srMinRoundness" )
180  srMinRoundness = parseEagle( value );
181  else if( name == "srMaxRoundness" )
182  srMaxRoundness = parseEagle( value );
183 
184  else if( name == "psTop" )
185  psTop = wxAtoi( value );
186  else if( name == "psBottom" )
187  psBottom = wxAtoi( value );
188  else if( name == "psFirst" )
189  psFirst = wxAtoi( value );
190 
191  else if( name == "rvPadTop" )
192  value.ToDouble( &rvPadTop );
193  else if( name == "rlMinPadTop" )
194  rlMinPadTop = parseEagle( value );
195  else if( name == "rlMaxPadTop" )
196  rlMaxPadTop = parseEagle( value );
197 
198  else if( name == "rvViaOuter" )
199  value.ToDouble( &rvViaOuter );
200  else if( name == "rlMinViaOuter" )
201  rlMinViaOuter = parseEagle( value );
202  else if( name == "rlMaxViaOuter" )
203  rlMaxViaOuter = parseEagle( value );
204  else if( name == "mdWireWire" )
205  mdWireWire = parseEagle( value );
206  }
207 
208  child = child->GetNext();
209  }
210 }
211 
212 
214  m_rules( new ERULES() ),
215  m_xpath( new XPATH() ),
216  m_mod_time( wxDateTime::Now() )
217 {
218  init( NULL );
219  clear_cu_map();
220 }
221 
222 
224 {
225  deleteTemplates();
226  delete m_rules;
227  delete m_xpath;
228 }
229 
230 
231 const wxString EAGLE_PLUGIN::PluginName() const
232 {
233  return wxT( "Eagle" );
234 }
235 
236 
237 const wxString EAGLE_PLUGIN::GetFileExtension() const
238 {
239  return wxT( "brd" );
240 }
241 
242 
243 wxSize inline EAGLE_PLUGIN::kicad_fontz( const ECOORD& d, int aTextThickness ) const
244 {
245  // Eagle includes stroke thickness in the text size, KiCAD does not
246  int kz = d.ToPcbUnits();
247  return wxSize( kz - aTextThickness, kz - aTextThickness );
248 }
249 
250 
251 BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties )
252 {
253  LOCALE_IO toggle; // toggles on, then off, the C locale.
254  wxXmlNode* doc;
255 
256  init( aProperties );
257 
258  m_board = aAppendToMe ? aAppendToMe : new BOARD();
259 
260  // Give the filename to the board if it's new
261  if( !aAppendToMe )
262  m_board->SetFileName( aFileName );
263 
264  // delete on exception, if I own m_board, according to aAppendToMe
265  unique_ptr<BOARD> deleter( aAppendToMe ? NULL : m_board );
266 
267  try
268  {
269  // Load the document
270  wxXmlDocument xmlDocument;
271  wxFileName fn = aFileName;
272 
273  if( !xmlDocument.Load( fn.GetFullPath() ) )
274  THROW_IO_ERROR( wxString::Format( _( "Unable to read file \"%s\"" ),
275  fn.GetFullPath() ) );
276 
277  doc = xmlDocument.GetRoot();
278 
279  m_min_trace = INT_MAX;
280  m_min_hole = INT_MAX;
281  m_min_via = INT_MAX;
282  m_min_annulus = INT_MAX;
283 
284  loadAllSections( doc );
285 
286  BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
287 
288  if( m_min_trace < designSettings.m_TrackMinWidth )
289  designSettings.m_TrackMinWidth = m_min_trace;
290 
291  if( m_min_via < designSettings.m_ViasMinSize )
292  designSettings.m_ViasMinSize = m_min_via;
293 
294  if( m_min_hole < designSettings.m_MinThroughDrill )
295  designSettings.m_MinThroughDrill = m_min_hole;
296 
297  if( m_min_annulus < designSettings.m_ViasMinAnnulus )
298  designSettings.m_ViasMinAnnulus = m_min_annulus;
299 
300  if( m_rules->mdWireWire )
301  {
302  NETCLASS* defaultNetclass = designSettings.GetDefault();
303  int clearance = KiROUND( m_rules->mdWireWire );
304 
305  if( clearance < defaultNetclass->GetClearance() )
306  defaultNetclass->SetClearance( clearance );
307  }
308 
309  // should be empty, else missing m_xpath->pop()
310  wxASSERT( m_xpath->Contents().size() == 0 );
311  }
312  // Catch all exceptions thrown from the parser.
313  catch( const XML_PARSER_ERROR &exc )
314  {
315  wxString errmsg = exc.what();
316 
317  errmsg += "\n@ ";
318  errmsg += m_xpath->Contents();
319 
320  THROW_IO_ERROR( errmsg );
321  }
322 
323  // IO_ERROR exceptions are left uncaught, they pass upwards from here.
324 
325  // Ensure the copper layers count is a multiple of 2
326  // Pcbnew does not like boards with odd layers count
327  // (these boards cannot exist. they actually have a even layers count)
328  int lyrcnt = m_board->GetCopperLayerCount();
329 
330  if( (lyrcnt % 2) != 0 )
331  {
332  lyrcnt++;
333  m_board->SetCopperLayerCount( lyrcnt );
334  }
335 
336  centerBoard();
337 
338  deleter.release();
339  return m_board;
340 }
341 
342 
343 void EAGLE_PLUGIN::init( const PROPERTIES* aProperties )
344 {
345  m_hole_count = 0;
346  m_min_trace = 0;
347  m_min_hole = 0;
348  m_min_via = 0;
349  m_min_annulus = 0;
350  m_xpath->clear();
351  m_pads_to_nets.clear();
352 
353  m_board = NULL;
354  m_props = aProperties;
355 
356 
357  delete m_rules;
358  m_rules = new ERULES();
359 }
360 
361 
363 {
364  // All cu layers are invalid until we see them in the <layers> section while
365  // loading either a board or library. See loadLayerDefs().
366  for( unsigned i = 0; i < arrayDim(m_cu_map); ++i )
367  m_cu_map[i] = -1;
368 }
369 
370 
371 void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
372 {
373  wxXmlNode* drawing = MapChildren( aDoc )["drawing"];
374  NODE_MAP drawingChildren = MapChildren( drawing );
375 
376  wxXmlNode* board = drawingChildren["board"];
377  NODE_MAP boardChildren = MapChildren( board );
378 
379  m_xpath->push( "eagle.drawing" );
380 
381  {
382  m_xpath->push( "board" );
383 
384  wxXmlNode* designrules = boardChildren["designrules"];
385  loadDesignRules( designrules );
386 
387  m_xpath->pop();
388  }
389 
390  {
391  m_xpath->push( "layers" );
392 
393  wxXmlNode* layers = drawingChildren["layers"];
394  loadLayerDefs( layers );
395 
396  m_xpath->pop();
397  }
398 
399  {
400  m_xpath->push( "board" );
401 
402  wxXmlNode* plain = boardChildren["plain"];
403  loadPlain( plain );
404 
405  wxXmlNode* signals = boardChildren["signals"];
406  loadSignals( signals );
407 
408  wxXmlNode* libs = boardChildren["libraries"];
409  loadLibraries( libs );
410 
411  wxXmlNode* elems = boardChildren["elements"];
412  loadElements( elems );
413 
414  m_xpath->pop(); // "board"
415  }
416 
417  m_xpath->pop(); // "eagle.drawing"
418 }
419 
420 
421 void EAGLE_PLUGIN::loadDesignRules( wxXmlNode* aDesignRules )
422 {
423  if( aDesignRules )
424  {
425  m_xpath->push( "designrules" );
426  m_rules->parse( aDesignRules );
427  m_xpath->pop(); // "designrules"
428  }
429 }
430 
431 
432 void EAGLE_PLUGIN::loadLayerDefs( wxXmlNode* aLayers )
433 {
434  if( !aLayers )
435  return;
436 
437  ELAYERS cu; // copper layers
438 
439  // Get the first layer and iterate
440  wxXmlNode* layerNode = aLayers->GetChildren();
441 
442  m_eagleLayers.clear();
443 
444  while( layerNode )
445  {
446  ELAYER elayer( layerNode );
447  m_eagleLayers.insert( std::make_pair( elayer.number, elayer ) );
448 
449  // find the subset of layers that are copper and active
450  if( elayer.number >= 1 && elayer.number <= 16 && ( !elayer.active || *elayer.active ) )
451  {
452  cu.push_back( elayer );
453  }
454 
455  layerNode = layerNode->GetNext();
456  }
457 
458  // establish cu layer map:
459  int ki_layer_count = 0;
460 
461  for( EITER it = cu.begin(); it != cu.end(); ++it, ++ki_layer_count )
462  {
463  if( ki_layer_count == 0 )
464  m_cu_map[it->number] = F_Cu;
465  else if( ki_layer_count == int( cu.size()-1 ) )
466  m_cu_map[it->number] = B_Cu;
467  else
468  {
469  // some eagle boards do not have contiguous layer number sequences.
470 
471 #if 0 // pre PCB_LAYER_ID & LSET:
472  m_cu_map[it->number] = cu.size() - 1 - ki_layer_count;
473 #else
474  m_cu_map[it->number] = ki_layer_count;
475 #endif
476  }
477  }
478 
479 #if 0 && defined(DEBUG)
480  printf( "m_cu_map:\n" );
481  for( unsigned i=0; i<arrayDim(m_cu_map); ++i )
482  {
483  printf( "\t[%d]:%d\n", i, m_cu_map[i] );
484  }
485 #endif
486 
487  // Set the layer names and cu count if we're loading a board.
488  if( m_board )
489  {
490  m_board->SetCopperLayerCount( cu.size() );
491 
492  for( EITER it = cu.begin(); it != cu.end(); ++it )
493  {
494  PCB_LAYER_ID layer = kicad_layer( it->number );
495 
496  // these function provide their own protection against UNDEFINED_LAYER:
497  m_board->SetLayerName( layer, FROM_UTF8( it->name.c_str() ) );
498  m_board->SetLayerType( layer, LT_SIGNAL );
499 
500  // could map the colors here
501  }
502  }
503 }
504 
505 
506 #define DIMENSION_PRECISION 1 // 0.001 mm
507 
508 void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
509 {
510  if( !aGraphics )
511  return;
512 
513  m_xpath->push( "plain" );
514 
515  // Get the first graphic and iterate
516  wxXmlNode* gr = aGraphics->GetChildren();
517 
518  // (polygon | wire | text | circle | rectangle | frame | hole)*
519  while( gr )
520  {
521  wxString grName = gr->GetName();
522 
523  if( grName == "wire" )
524  {
525  m_xpath->push( "wire" );
526 
527  EWIRE w( gr );
528  PCB_LAYER_ID layer = kicad_layer( w.layer );
529 
530  wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
531  wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
532 
533  if( layer != UNDEFINED_LAYER )
534  {
535  DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board );
536  int width = w.width.ToPcbUnits();
537 
538  // KiCad cannot handle zero or negative line widths
539  if( width <= 0 )
540  width = m_board->GetDesignSettings().GetLineThickness( layer );
541 
542  m_board->Add( dseg, ADD_MODE::APPEND );
543 
544  if( !w.curve )
545  {
546  dseg->SetStart( start );
547  dseg->SetEnd( end );
548  }
549  else
550  {
551  wxPoint center = ConvertArcCenter( start, end, *w.curve );
552 
553  dseg->SetShape( S_ARC );
554  dseg->SetStart( center );
555  dseg->SetEnd( start );
556  dseg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
557  }
558 
559  dseg->SetLayer( layer );
560  dseg->SetWidth( width );
561  }
562 
563  m_xpath->pop();
564  }
565  else if( grName == "text" )
566  {
567  m_xpath->push( "text" );
568 
569  ETEXT t( gr );
570  PCB_LAYER_ID layer = kicad_layer( t.layer );
571 
572  if( layer != UNDEFINED_LAYER )
573  {
574  TEXTE_PCB* pcbtxt = new TEXTE_PCB( m_board );
575  m_board->Add( pcbtxt, ADD_MODE::APPEND );
576 
577  pcbtxt->SetLayer( layer );
578  pcbtxt->SetText( FROM_UTF8( t.text.c_str() ) );
579  pcbtxt->SetTextPos( wxPoint( kicad_x( t.x ), kicad_y( t.y ) ) );
580 
581  double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default
582  int textThickness = KiROUND( t.size.ToPcbUnits() * ratio / 100 );
583  pcbtxt->SetTextThickness( textThickness );
584  pcbtxt->SetTextSize( kicad_fontz( t.size, textThickness ) );
585 
586  int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT;
587 
588  if( t.rot )
589  {
590  int sign = t.rot->mirror ? -1 : 1;
591  pcbtxt->SetMirrored( t.rot->mirror );
592 
593  double degrees = t.rot->degrees;
594 
595  if( degrees == 90 || t.rot->spin )
596  pcbtxt->SetTextAngle( sign * t.rot->degrees * 10 );
597  else if( degrees == 180 )
598  align = ETEXT::TOP_RIGHT;
599  else if( degrees == 270 )
600  {
601  pcbtxt->SetTextAngle( sign * 90 * 10 );
602  align = ETEXT::TOP_RIGHT;
603  }
604  else // Ok so text is not at 90,180 or 270 so do some funny stuff to get placement right
605  {
606  if( ( degrees > 0 ) && ( degrees < 90 ) )
607  pcbtxt->SetTextAngle( sign * t.rot->degrees * 10 );
608  else if( ( degrees > 90 ) && ( degrees < 180 ) )
609  {
610  pcbtxt->SetTextAngle( sign * ( t.rot->degrees + 180 ) * 10 );
611  align = ETEXT::TOP_RIGHT;
612  }
613  else if( ( degrees > 180 ) && ( degrees < 270 ) )
614  {
615  pcbtxt->SetTextAngle( sign * ( t.rot->degrees - 180 ) * 10 );
616  align = ETEXT::TOP_RIGHT;
617  }
618  else if( ( degrees > 270 ) && ( degrees < 360 ) )
619  {
620  pcbtxt->SetTextAngle( sign * t.rot->degrees * 10 );
621  align = ETEXT::BOTTOM_LEFT;
622  }
623  }
624  }
625 
626  switch( align )
627  {
628  case ETEXT::CENTER:
629  // this was the default in pcbtxt's constructor
630  break;
631 
632  case ETEXT::CENTER_LEFT:
634  break;
635 
636  case ETEXT::CENTER_RIGHT:
638  break;
639 
640  case ETEXT::TOP_CENTER:
642  break;
643 
644  case ETEXT::TOP_LEFT:
647  break;
648 
649  case ETEXT::TOP_RIGHT:
652  break;
653 
656  break;
657 
658  case ETEXT::BOTTOM_LEFT:
661  break;
662 
663  case ETEXT::BOTTOM_RIGHT:
666  break;
667  }
668  }
669  m_xpath->pop();
670  }
671  else if( grName == "circle" )
672  {
673  m_xpath->push( "circle" );
674 
675  ECIRCLE c( gr );
676 
677  int width = c.width.ToPcbUnits();
678  int radius = c.radius.ToPcbUnits();
679 
681  || c.layer == EAGLE_LAYER::VRESTRICT )
682  {
683  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
684  m_board->Add( zone, ADD_MODE::APPEND );
685 
686  setKeepoutSettingsToZone( zone, c.layer );
687 
688  // approximate circle as polygon with a edge every 10 degree
689  wxPoint center( kicad_x( c.x ), kicad_y( c.y ) );
690  int outlineRadius = radius + ( width / 2 );
691  for( int angle = 0; angle < 360; angle += 10 )
692  {
693  wxPoint rotatedPoint( outlineRadius, 0 );
694  RotatePoint( &rotatedPoint, angle * 10. );
695  zone->AppendCorner( center + rotatedPoint, -1 );
696  }
697 
698  if( width > 0 )
699  {
700  zone->NewHole();
701  int innerRadius = radius - ( width / 2 );
702  for( int angle = 0; angle < 360; angle += 10 )
703  {
704  wxPoint rotatedPoint( innerRadius, 0 );
705  RotatePoint( &rotatedPoint, angle * 10. );
706  zone->AppendCorner( center + rotatedPoint, 0 );
707  }
708  }
709 
712  }
713  else
714  {
715  PCB_LAYER_ID layer = kicad_layer( c.layer );
716 
717  if( layer != UNDEFINED_LAYER ) // unsupported layer
718  {
719  DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board );
720  m_board->Add( dseg, ADD_MODE::APPEND );
721 
722  // with == 0 means filled circle
723  if( width <= 0 )
724  {
725  width = radius;
726  radius = radius / 2;
727  }
728 
729  dseg->SetShape( S_CIRCLE );
730  dseg->SetLayer( layer );
731  dseg->SetStart( wxPoint( kicad_x( c.x ), kicad_y( c.y ) ) );
732  dseg->SetEnd( wxPoint( kicad_x( c.x ) + radius, kicad_y( c.y ) ) );
733  dseg->SetWidth( width );
734  }
735  }
736  m_xpath->pop();
737  }
738  else if( grName == "rectangle" )
739  {
740  // This seems to be a simplified rectangular [copper] zone, cannot find any
741  // net related info on it from the DTD.
742  m_xpath->push( "rectangle" );
743 
744  ERECT r( gr );
745  PCB_LAYER_ID layer = kicad_layer( r.layer );
746 
747  if( IsCopperLayer( layer ) )
748  {
749  // use a "netcode = 0" type ZONE:
750  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
751  m_board->Add( zone, ADD_MODE::APPEND );
752 
753  zone->SetLayer( layer );
755 
757 
758  const int outlineIdx = -1; // this is the id of the copper zone main outline
759  zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ), outlineIdx );
760  zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ), outlineIdx );
761  zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ), outlineIdx );
762  zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ), outlineIdx );
763 
764  if( r.rot )
765  {
766  zone->Rotate( zone->GetPosition(), r.rot->degrees * 10 );
767  }
768  // this is not my fault:
769  zone->SetHatch( outline_hatch, ZONE_CONTAINER::GetDefaultHatchPitch(), true );
770  }
771 
772  m_xpath->pop();
773  }
774  else if( grName == "hole" )
775  {
776  m_xpath->push( "hole" );
777 
778  // Fabricate a MODULE with a single PAD_ATTRIB_HOLE_NOT_PLATED pad.
779  // Use m_hole_count to gen up a unique name.
780 
781  MODULE* module = new MODULE( m_board );
782  m_board->Add( module, ADD_MODE::APPEND );
783  module->SetReference( wxString::Format( "@HOLE%d", m_hole_count++ ) );
784  module->Reference().SetVisible( false );
785 
786  packageHole( module, gr, true );
787 
788  m_xpath->pop();
789  }
790  else if( grName == "frame" )
791  {
792  // picture this
793  }
794  else if( grName == "polygon" )
795  {
796  m_xpath->push( "polygon" );
797  loadPolygon( gr );
798  m_xpath->pop(); // "polygon"
799  }
800  else if( grName == "dimension" )
801  {
802  EDIMENSION d( gr );
803  PCB_LAYER_ID layer = kicad_layer( d.layer );
804 
805  if( layer != UNDEFINED_LAYER )
806  {
807  const BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
808  DIMENSION* dimension = new DIMENSION( m_board );
809  m_board->Add( dimension, ADD_MODE::APPEND );
810 
811  if( d.dimensionType )
812  {
813  // Eagle dimension graphic arms may have different lengths, but they look
814  // incorrect in KiCad (the graphic is tilted). Make them even length in such case.
815  if( *d.dimensionType == "horizontal" )
816  {
817  int newY = ( d.y1.ToPcbUnits() + d.y2.ToPcbUnits() ) / 2;
818  d.y1 = ECOORD( newY, ECOORD::EAGLE_UNIT::EU_NM );
819  d.y2 = ECOORD( newY, ECOORD::EAGLE_UNIT::EU_NM );
820  }
821  else if( *d.dimensionType == "vertical" )
822  {
823  int newX = ( d.x1.ToPcbUnits() + d.x2.ToPcbUnits() ) / 2;
824  d.x1 = ECOORD( newX, ECOORD::EAGLE_UNIT::EU_NM );
825  d.x2 = ECOORD( newX, ECOORD::EAGLE_UNIT::EU_NM );
826  }
827  }
828 
829  dimension->SetLayer( layer );
830  // The origin and end are assumed to always be in this order from eagle
831  dimension->SetOrigin( wxPoint( kicad_x( d.x1 ), kicad_y( d.y1 ) ),
833  dimension->SetEnd( wxPoint( kicad_x( d.x2 ), kicad_y( d.y2 ) ),
835  dimension->Text().SetTextSize( designSettings.GetTextSize( layer ) );
836  dimension->Text().SetTextThickness( designSettings.GetTextThickness( layer ));
837  dimension->SetWidth( designSettings.GetLineThickness( layer ) );
838  dimension->SetUnits( EDA_UNITS::MILLIMETRES, false );
839 
840  // check which axis the dimension runs in
841  // because the "height" of the dimension is perpendicular to that axis
842  // Note the check is just if two axes are close enough to each other
843  // Eagle appears to have some rounding errors
844  if( abs( ( d.x1 - d.x2 ).ToPcbUnits() ) < 50000 ) // 50000 nm = 0.05 mm
845  dimension->SetHeight( kicad_x( d.x3 - d.x1 ), DIMENSION_PRECISION );
846  else
847  dimension->SetHeight( kicad_y( d.y3 - d.y1 ), DIMENSION_PRECISION );
848 
850  }
851  }
852 
853  // Get next graphic
854  gr = gr->GetNext();
855  }
856  m_xpath->pop();
857 }
858 
859 
860 void EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLib, const wxString* aLibName )
861 {
862  if( !aLib )
863  return;
864 
865  // library will have <xmlattr> node, skip that and get the single packages node
866  wxXmlNode* packages = MapChildren( aLib )["packages"];
867 
868  if( !packages )
869  return;
870 
871  m_xpath->push( "packages" );
872 
873  // Create a MODULE for all the eagle packages, for use later via a copy constructor
874  // to instantiate needed MODULES in our BOARD. Save the MODULE templates in
875  // a MODULE_MAP using a single lookup key consisting of libname+pkgname.
876 
877  // Get the first package and iterate
878  wxXmlNode* package = packages->GetChildren();
879 
880  while( package )
881  {
882  m_xpath->push( "package", "name" );
883 
884  wxString pack_ref = package->GetAttribute( "name" );
885  ReplaceIllegalFileNameChars( pack_ref, '_' );
886 
887  m_xpath->Value( pack_ref.ToUTF8() );
888 
889  wxString key = aLibName ? makeKey( *aLibName, pack_ref ) : pack_ref;
890 
891  MODULE* m = makeModule( package, pack_ref );
892 
893  // add the templating MODULE to the MODULE template factory "m_templates"
894  std::pair<MODULE_ITER, bool> r = m_templates.insert( {key, m} );
895 
896  if( !r.second
897  // && !( m_props && m_props->Value( "ignore_duplicates" ) )
898  )
899  {
900  wxString lib = aLibName ? *aLibName : m_lib_path;
901  const wxString& pkg = pack_ref;
902 
903  wxString emsg = wxString::Format(
904  _( "<package> name: \"%s\" duplicated in eagle <library>: \"%s\"" ),
905  GetChars( pkg ),
906  GetChars( lib )
907  );
908  THROW_IO_ERROR( emsg );
909  }
910 
911  m_xpath->pop();
912 
913  package = package->GetNext();
914  }
915 
916  m_xpath->pop(); // "packages"
917 }
918 
919 
920 void EAGLE_PLUGIN::loadLibraries( wxXmlNode* aLibs )
921 {
922  if( !aLibs )
923  return;
924 
925  m_xpath->push( "libraries.library", "name" );
926 
927  // Get the first library and iterate
928  wxXmlNode* library = aLibs->GetChildren();
929 
930  while( library )
931  {
932  const wxString& lib_name = library->GetAttribute( "name" );
933 
934  m_xpath->Value( lib_name.c_str() );
935  loadLibrary( library, &lib_name );
936  library = library->GetNext();
937  }
938 
939  m_xpath->pop();
940 }
941 
942 
943 void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
944 {
945  if( !aElements )
946  return;
947 
948  m_xpath->push( "elements.element", "name" );
949 
950  EATTR name;
951  EATTR value;
952  bool refanceNamePresetInPackageLayout;
953  bool valueNamePresetInPackageLayout;
954 
955  // Get the first element and iterate
956  wxXmlNode* element = aElements->GetChildren();
957 
958  while( element )
959  {
960  if( element->GetName() != "element" )
961  {
962  wxLogDebug( "expected: <element> read <%s>. Skip it", element->GetName() );
963  // Get next item
964  element = element->GetNext();
965  continue;
966  }
967 
968  EELEMENT e( element );
969 
970  // use "NULL-ness" as an indication of presence of the attribute:
971  EATTR* nameAttr = nullptr;
972  EATTR* valueAttr = nullptr;
973 
974  m_xpath->Value( e.name.c_str() );
975 
976  wxString pkg_key = makeKey( e.library, e.package );
977 
978  MODULE_CITER mi = m_templates.find( pkg_key );
979 
980  if( mi == m_templates.end() )
981  {
982  wxString emsg = wxString::Format( _( "No \"%s\" package in library \"%s\"" ),
983  GetChars( FROM_UTF8( e.package.c_str() ) ),
984  GetChars( FROM_UTF8( e.library.c_str() ) ) );
985  THROW_IO_ERROR( emsg );
986  }
987 
988  // copy constructor to clone the template
989  MODULE* m = new MODULE( *mi->second );
991 
992  // update the nets within the pads of the clone
993  for( auto pad : m->Pads() )
994  {
995  wxString pn_key = makeKey( e.name, pad->GetName() );
996 
997  NET_MAP_CITER ni = m_pads_to_nets.find( pn_key );
998  if( ni != m_pads_to_nets.end() )
999  {
1000  const ENET* enet = &ni->second;
1001  pad->SetNetCode( enet->netcode );
1002  }
1003  }
1004 
1005  refanceNamePresetInPackageLayout = true;
1006  valueNamePresetInPackageLayout = true;
1007  m->SetPosition( wxPoint( kicad_x( e.x ), kicad_y( e.y ) ) );
1008 
1009  // Is >NAME field set in package layout ?
1010  if( m->GetReference().size() == 0 )
1011  {
1012  m->Reference().SetVisible( false ); // No so no show
1013  refanceNamePresetInPackageLayout = false;
1014  }
1015 
1016  // Is >VALUE field set in package layout
1017  if( m->GetValue().size() == 0 )
1018  {
1019  m->Value().SetVisible( false ); // No so no show
1020  valueNamePresetInPackageLayout = false;
1021  }
1022 
1023  m->SetReference( FROM_UTF8( e.name.c_str() ) );
1024  m->SetValue( FROM_UTF8( e.value.c_str() ) );
1025 
1026  if( !e.smashed )
1027  { // Not smashed so show NAME & VALUE
1028  if( valueNamePresetInPackageLayout )
1029  m->Value().SetVisible( true ); // Only if place holder in package layout
1030 
1031  if( refanceNamePresetInPackageLayout )
1032  m->Reference().SetVisible( true ); // Only if place holder in package layout
1033  }
1034  else if( *e.smashed == true )
1035  { // Smashed so set default to no show for NAME and VALUE
1036  m->Value().SetVisible( false );
1037  m->Reference().SetVisible( false );
1038 
1039  // initialize these to default values in case the <attribute> elements are not present.
1040  m_xpath->push( "attribute", "name" );
1041 
1042  // VALUE and NAME can have something like our text "effects" overrides
1043  // in SWEET and new schematic. Eagle calls these XML elements "attribute".
1044  // There can be one for NAME and/or VALUE both. Features present in the
1045  // EATTR override the ones established in the package only if they are
1046  // present here (except for rot, which if not present means angle zero).
1047  // So the logic is a bit different than in packageText() and in plain text.
1048 
1049  // Get the first attribute and iterate
1050  wxXmlNode* attribute = element->GetChildren();
1051 
1052  while( attribute )
1053  {
1054  if( attribute->GetName() != "attribute" )
1055  {
1056  wxLogDebug( "expected: <attribute> read <%s>. Skip it", attribute->GetName() );
1057  attribute = attribute->GetNext();
1058  continue;
1059  }
1060 
1061  EATTR a( attribute );
1062 
1063  if( a.name == "NAME" )
1064  {
1065  name = a;
1066  nameAttr = &name;
1067 
1068  // do we have a display attribute ?
1069  if( a.display )
1070  {
1071  // Yes!
1072  switch( *a.display )
1073  {
1074  case EATTR::VALUE :
1075  {
1076  wxString reference = e.name;
1077 
1078  // EAGLE allows references to be single digits. This breaks KiCad netlisting, which requires
1079  // parts to have non-digit + digit annotation. If the reference begins with a number,
1080  // we prepend 'UNK' (unknown) for the symbol designator
1081  if( reference.find_first_not_of( "0123456789" ) == wxString::npos )
1082  reference.Prepend( "UNK" );
1083 
1084  nameAttr->name = reference;
1085  m->SetReference( reference );
1086  if( refanceNamePresetInPackageLayout )
1087  m->Reference().SetVisible( true );
1088  break;
1089  }
1090  case EATTR::NAME :
1091  if( refanceNamePresetInPackageLayout )
1092  {
1093  m->SetReference( "NAME" );
1094  m->Reference().SetVisible( true );
1095  }
1096  break;
1097 
1098  case EATTR::BOTH :
1099  if( refanceNamePresetInPackageLayout )
1100  m->Reference().SetVisible( true );
1101  nameAttr->name = nameAttr->name + " = " + e.name;
1102  m->SetReference( "NAME = " + e.name );
1103  break;
1104 
1105  case EATTR::Off :
1106  m->Reference().SetVisible( false );
1107  break;
1108 
1109  default:
1110  nameAttr->name = e.name;
1111  if( refanceNamePresetInPackageLayout )
1112  m->Reference().SetVisible( true );
1113  }
1114  }
1115  else
1116  // No display, so default is visible, and show value of NAME
1117  m->Reference().SetVisible( true );
1118  }
1119  else if( a.name == "VALUE" )
1120  {
1121  value = a;
1122  valueAttr = &value;
1123 
1124  if( a.display )
1125  {
1126  // Yes!
1127  switch( *a.display )
1128  {
1129  case EATTR::VALUE :
1130  valueAttr->value = opt_wxString( e.value );
1131  m->SetValue( e.value );
1132  if( valueNamePresetInPackageLayout )
1133  m->Value().SetVisible( true );
1134  break;
1135 
1136  case EATTR::NAME :
1137  if( valueNamePresetInPackageLayout )
1138  m->Value().SetVisible( true );
1139  m->SetValue( "VALUE" );
1140  break;
1141 
1142  case EATTR::BOTH :
1143  if( valueNamePresetInPackageLayout )
1144  m->Value().SetVisible( true );
1145  valueAttr->value = opt_wxString( "VALUE = " + e.value );
1146  m->SetValue( "VALUE = " + e.value );
1147  break;
1148 
1149  case EATTR::Off :
1150  m->Value().SetVisible( false );
1151  break;
1152 
1153  default:
1154  valueAttr->value = opt_wxString( e.value );
1155  if( valueNamePresetInPackageLayout )
1156  m->Value().SetVisible( true );
1157  }
1158  }
1159  else
1160  // No display, so default is visible, and show value of NAME
1161  m->Value().SetVisible( true );
1162 
1163  }
1164 
1165  attribute = attribute->GetNext();
1166  }
1167 
1168  m_xpath->pop(); // "attribute"
1169  }
1170 
1171  orientModuleAndText( m, e, nameAttr, valueAttr );
1172 
1173  // Set the local coordinates for the footprint text items
1174  m->Reference().SetLocalCoord();
1175  m->Value().SetLocalCoord();
1176 
1177  // Get next element
1178  element = element->GetNext();
1179  }
1180 
1181  m_xpath->pop(); // "elements.element"
1182 }
1183 
1184 
1186 {
1187  EPOLYGON p( aPolyNode );
1188  PCB_LAYER_ID layer = kicad_layer( p.layer );
1189  ZONE_CONTAINER* zone = nullptr;
1190  bool keepout = ( p.layer == EAGLE_LAYER::TRESTRICT || p.layer == EAGLE_LAYER::BRESTRICT
1191  || p.layer == EAGLE_LAYER::VRESTRICT );
1192 
1193  if( !IsCopperLayer( layer ) && !keepout )
1194  return nullptr;
1195 
1196  // use a "netcode = 0" type ZONE:
1197  zone = new ZONE_CONTAINER( m_board );
1198  m_board->Add( zone, ADD_MODE::APPEND );
1199 
1200  if( !keepout )
1201  zone->SetLayer( layer );
1202  else
1203  setKeepoutSettingsToZone( zone, p.layer );
1204 
1205  // Get the first vertex and iterate
1206  wxXmlNode* vertex = aPolyNode->GetChildren();
1207  std::vector<EVERTEX> vertices;
1208 
1209  // Create a circular vector of vertices
1210  // The "curve" parameter indicates a curve from the current
1211  // to the next vertex, so we keep the first at the end as well
1212  // to allow the curve to link back
1213  while( vertex )
1214  {
1215  if( vertex->GetName() == "vertex" )
1216  vertices.emplace_back( vertex );
1217 
1218  vertex = vertex->GetNext();
1219  }
1220 
1221  vertices.push_back( vertices[0] );
1222 
1223  SHAPE_POLY_SET polygon;
1224  polygon.NewOutline();
1225 
1226  for( size_t i = 0; i < vertices.size() - 1; i++ )
1227  {
1228  EVERTEX v1 = vertices[i];
1229 
1230  // Append the corner
1231  polygon.Append( kicad_x( v1.x ), kicad_y( v1.y ) );
1232 
1233  if( v1.curve )
1234  {
1235  EVERTEX v2 = vertices[i + 1];
1236  wxPoint center = ConvertArcCenter(
1237  wxPoint( kicad_x( v1.x ), kicad_y( v1.y ) ),
1238  wxPoint( kicad_x( v2.x ), kicad_y( v2.y ) ), *v1.curve );
1239  double angle = DEG2RAD( *v1.curve );
1240  double end_angle = atan2( kicad_y( v2.y ) - center.y,
1241  kicad_x( v2.x ) - center.x );
1242  double radius = sqrt( pow( center.x - kicad_x( v1.x ), 2 )
1243  + pow( center.y - kicad_y( v1.y ), 2 ) );
1244 
1245  // If we are curving, we need at least 2 segments otherwise
1246  // delta_angle == angle
1247  double delta_angle = angle / std::max(
1248  2, GetArcToSegmentCount( KiROUND( radius ),
1249  ARC_HIGH_DEF, *v1.curve ) - 1 );
1250 
1251  for( double a = end_angle + angle;
1252  fabs( a - end_angle ) > fabs( delta_angle );
1253  a -= delta_angle )
1254  {
1255  polygon.Append( KiROUND( radius * cos( a ) ) + center.x,
1256  KiROUND( radius * sin( a ) ) + center.y );
1257  }
1258  }
1259  }
1260 
1261  // Eagle traces the zone such that half of the pen width is outside the polygon.
1262  // We trace the zone such that the copper is completely inside.
1263  if( p.width.ToPcbUnits() > 0 )
1264  {
1267  }
1268 
1269  zone->AddPolygon( polygon.COutline( 0 ) );
1270 
1271  // If the pour is a cutout it needs to be set to a keepout
1272  if( p.pour == EPOLYGON::CUTOUT )
1273  {
1274  zone->SetIsKeepout( true );
1275  zone->SetDoNotAllowVias( false );
1276  zone->SetDoNotAllowTracks( false );
1277  zone->SetDoNotAllowPads( false );
1278  zone->SetDoNotAllowFootprints( false );
1279  zone->SetDoNotAllowCopperPour( true );
1281  }
1282  else if( p.pour == EPOLYGON::HATCH )
1283  {
1284  int spacing = p.spacing ? p.spacing->ToPcbUnits() : 50 * IU_PER_MILS;
1285 
1288  zone->SetHatchFillTypeGap( spacing - p.width.ToPcbUnits() );
1289  zone->SetHatchFillTypeOrientation( 0 );
1290  }
1291 
1292  // We divide the thickness by half because we are tracing _inside_ the zone outline
1293  // This means the radius of curvature will be twice the size for an equivalent EAGLE zone
1294  zone->SetMinThickness(
1295  std::max<int>( ZONE_THICKNESS_MIN_VALUE_MIL * IU_PER_MILS, p.width.ToPcbUnits() / 2 ) );
1296 
1297  if( p.isolate )
1298  zone->SetZoneClearance( p.isolate->ToPcbUnits() );
1299  else
1300  zone->SetZoneClearance( 1 ); // @todo: set minimum clearance value based on board settings
1301 
1302  // missing == yes per DTD.
1303  bool thermals = !p.thermals || *p.thermals;
1305 
1306  if( thermals )
1307  {
1308  // FIXME: eagle calculates dimensions for thermal spokes
1309  // based on what the zone is connecting to.
1310  // (i.e. width of spoke is half of the smaller side of an smd pad)
1311  // This is a basic workaround
1312  zone->SetThermalReliefGap( p.width.ToPcbUnits() + 50000 ); // 50000nm == 0.05mm
1313  zone->SetThermalReliefCopperBridge( p.width.ToPcbUnits() + 50000 );
1314  }
1315 
1316  int rank = p.rank ? (p.max_priority - *p.rank) : p.max_priority;
1317  zone->SetPriority( rank );
1318 
1319  return zone;
1320 }
1321 
1322 
1323 void EAGLE_PLUGIN::orientModuleAndText( MODULE* m, const EELEMENT& e, const EATTR* nameAttr,
1324  const EATTR* valueAttr )
1325 {
1326  if( e.rot )
1327  {
1328  if( e.rot->mirror )
1329  {
1330  double orientation = e.rot->degrees + 180.0;
1331  m->SetOrientation( orientation * 10 );
1332  m->Flip( m->GetPosition(), false );
1333  }
1334  else
1335  m->SetOrientation( e.rot->degrees * 10 );
1336  }
1337 
1338  orientModuleText( m, e, &m->Reference(), nameAttr );
1339  orientModuleText( m, e, &m->Value(), valueAttr );
1340 }
1341 
1342 
1344  TEXTE_MODULE* txt, const EATTR* aAttr )
1345 {
1346  // Smashed part ?
1347  if( aAttr )
1348  { // Yes
1349  const EATTR& a = *aAttr;
1350 
1351  if( a.value )
1352  {
1353  txt->SetText( FROM_UTF8( a.value->c_str() ) );
1354  }
1355 
1356  if( a.x && a.y ) // OPT
1357  {
1358  wxPoint pos( kicad_x( *a.x ), kicad_y( *a.y ) );
1359  txt->SetTextPos( pos );
1360  }
1361 
1362  // Even though size and ratio are both optional, I am not seeing
1363  // a case where ratio is present but size is not.
1364  double ratio = 8;
1365  wxSize fontz = txt->GetTextSize();
1366  int textThickness = KiROUND( fontz.y * ratio / 100 );
1367 
1368  txt->SetTextThickness( textThickness );
1369  if( a.size )
1370  {
1371  fontz = kicad_fontz( *a.size, textThickness );
1372  txt->SetTextSize( fontz );
1373 
1374  if( a.ratio )
1375  ratio = *a.ratio;
1376  }
1377 
1378 
1379 
1380  int align = ETEXT::BOTTOM_LEFT; // bottom-left is eagle default
1381 
1382  if( a.align )
1383  align = a.align;
1384 
1385  // The "rot" in a EATTR seems to be assumed to be zero if it is not
1386  // present, and this zero rotation becomes an override to the
1387  // package's text field. If they did not want zero, they specify
1388  // what they want explicitly.
1389  double degrees = a.rot ? a.rot->degrees : 0;
1390  double orient; // relative to parent
1391 
1392  int sign = 1;
1393  bool spin = false;
1394 
1395  if( a.rot )
1396  {
1397  spin = a.rot->spin;
1398  sign = a.rot->mirror ? -1 : 1;
1399  txt->SetMirrored( a.rot->mirror );
1400  }
1401 
1402  if( degrees == 90 || degrees == 0 || spin )
1403  {
1404  orient = degrees - m->GetOrientation() / 10;
1405  txt->SetTextAngle( sign * orient * 10 );
1406  }
1407  else if( degrees == 180 )
1408  {
1409  orient = 0 - m->GetOrientation() / 10;
1410  txt->SetTextAngle( sign * orient * 10 );
1411  align = -align;
1412  }
1413  else if( degrees == 270 )
1414  {
1415  orient = 90 - m->GetOrientation() / 10;
1416  align = -align;
1417  txt->SetTextAngle( sign * orient * 10 );
1418  }
1419  else
1420  {
1421  orient = 90 - degrees - m->GetOrientation() / 10;
1422  txt->SetTextAngle( sign * orient * 10 );
1423  }
1424 
1425  switch( align )
1426  {
1427  case ETEXT::TOP_RIGHT:
1430  break;
1431 
1432  case ETEXT::BOTTOM_LEFT:
1435  break;
1436 
1437  case ETEXT::TOP_LEFT:
1440  break;
1441 
1442  case ETEXT::BOTTOM_RIGHT:
1445  break;
1446 
1447  case ETEXT::TOP_CENTER:
1450  break;
1451 
1452  case ETEXT::BOTTOM_CENTER:
1455  break;
1456 
1457  default:
1458  ;
1459  }
1460  }
1461  else // Part is not smash so use Lib default for NAME/VALUE // the text is per the original package, sans <attribute>
1462  {
1463  double degrees = ( txt->GetTextAngle() + m->GetOrientation() ) / 10;
1464 
1465  // @todo there are a few more cases than these to contend with:
1466  if( (!txt->IsMirrored() && ( abs( degrees ) == 180 || abs( degrees ) == 270 ))
1467  || ( txt->IsMirrored() && ( degrees == 360 ) ) )
1468  {
1469  // ETEXT::TOP_RIGHT:
1472  }
1473  }
1474 }
1475 
1476 
1477 MODULE* EAGLE_PLUGIN::makeModule( wxXmlNode* aPackage, const wxString& aPkgName )
1478 {
1479  std::unique_ptr<MODULE> m( new MODULE( m_board ) );
1480 
1481  LIB_ID fpID;
1482  fpID.Parse( aPkgName, LIB_ID::ID_PCB, true );
1483  m->SetFPID( fpID );
1484 
1485  // Get the first package item and iterate
1486  wxXmlNode* packageItem = aPackage->GetChildren();
1487 
1488  while( packageItem )
1489  {
1490  const wxString& itemName = packageItem->GetName();
1491 
1492  if( itemName == "description" )
1493  m->SetDescription( FROM_UTF8( packageItem->GetNodeContent().c_str() ) );
1494 
1495  else if( itemName == "wire" )
1496  packageWire( m.get(), packageItem );
1497 
1498  else if( itemName == "pad" )
1499  packagePad( m.get(), packageItem );
1500 
1501  else if( itemName == "text" )
1502  packageText( m.get(), packageItem );
1503 
1504  else if( itemName == "rectangle" )
1505  packageRectangle( m.get(), packageItem );
1506 
1507  else if( itemName == "polygon" )
1508  packagePolygon( m.get(), packageItem );
1509 
1510  else if( itemName == "circle" )
1511  packageCircle( m.get(), packageItem );
1512 
1513  else if( itemName == "hole" )
1514  packageHole( m.get(), packageItem, false );
1515 
1516  else if( itemName == "smd" )
1517  packageSMD( m.get(), packageItem );
1518 
1519  packageItem = packageItem->GetNext();
1520  }
1521 
1522  return m.release();
1523 }
1524 
1525 
1526 void EAGLE_PLUGIN::packageWire( MODULE* aModule, wxXmlNode* aTree ) const
1527 {
1528  EWIRE w( aTree );
1529  PCB_LAYER_ID layer = kicad_layer( w.layer );
1530  wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
1531  wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
1532  int width = w.width.ToPcbUnits();
1533 
1534  // KiCad cannot handle zero or negative line widths which apparently have meaning in Eagle.
1535  if( width <= 0 )
1536  {
1537  BOARD* board = aModule->GetBoard();
1538 
1539  if( board )
1540  {
1541  width = board->GetDesignSettings().GetLineThickness( layer );
1542  }
1543  else
1544  {
1545  // When loading footprint libraries, there is no board so use the default KiCad
1546  // line widths.
1547  switch( layer )
1548  {
1549  case Edge_Cuts:
1550  width = Millimeter2iu( DEFAULT_EDGE_WIDTH );
1551  break;
1552  case F_SilkS:
1553  case B_SilkS:
1554  width = Millimeter2iu( DEFAULT_SILK_LINE_WIDTH );
1555  break;
1556  case F_CrtYd:
1557  case B_CrtYd:
1558  width = Millimeter2iu( DEFAULT_COURTYARD_WIDTH );
1559  break;
1560  default:
1561  width = Millimeter2iu( DEFAULT_LINE_WIDTH );
1562  }
1563  }
1564  }
1565 
1566  // FIXME: the cap attribute is ignored because KiCad can't create lines
1567  // with flat ends.
1568  EDGE_MODULE* dwg;
1569 
1570  if( !w.curve )
1571  {
1572  dwg = new EDGE_MODULE( aModule, S_SEGMENT );
1573 
1574  dwg->SetStart0( start );
1575  dwg->SetEnd0( end );
1576  }
1577  else
1578  {
1579  dwg = new EDGE_MODULE( aModule, S_ARC );
1580  wxPoint center = ConvertArcCenter( start, end, *w.curve );
1581 
1582  dwg->SetStart0( center );
1583  dwg->SetEnd0( start );
1584  dwg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
1585  }
1586 
1587  dwg->SetLayer( layer );
1588  dwg->SetWidth( width );
1589  dwg->SetDrawCoord();
1590 
1591  aModule->Add( dwg );
1592 }
1593 
1594 
1595 void EAGLE_PLUGIN::packagePad( MODULE* aModule, wxXmlNode* aTree )
1596 {
1597  // this is thru hole technology here, no SMDs
1598  EPAD e( aTree );
1599  int shape = EPAD::UNDEF;
1600  int eagleDrillz = e.drill.ToPcbUnits();
1601 
1602  D_PAD* pad = new D_PAD( aModule );
1603  aModule->Add( pad );
1604  transferPad( e, pad );
1605 
1606  if( e.first && *e.first && m_rules->psFirst != EPAD::UNDEF )
1607  shape = m_rules->psFirst;
1608  else if( aModule->GetLayer() == F_Cu && m_rules->psTop != EPAD::UNDEF )
1609  shape = m_rules->psTop;
1610  else if( aModule->GetLayer() == B_Cu && m_rules->psBottom != EPAD::UNDEF )
1611  shape = m_rules->psBottom;
1612 
1613  pad->SetDrillSize( wxSize( eagleDrillz, eagleDrillz ) );
1614  pad->SetLayerSet( LSET::AllCuMask() );
1615 
1616  if( eagleDrillz < m_min_hole )
1617  m_min_hole = eagleDrillz;
1618 
1619  // Solder mask
1620  if( !e.stop || *e.stop == true ) // enabled by default
1621  pad->SetLayerSet( pad->GetLayerSet().set( B_Mask ).set( F_Mask ) );
1622 
1623  if( shape == EPAD::ROUND || shape == EPAD::SQUARE || shape == EPAD::OCTAGON )
1624  e.shape = shape;
1625 
1626  if( e.shape )
1627  {
1628  switch( *e.shape )
1629  {
1630  case EPAD::ROUND:
1631  pad->SetShape( PAD_SHAPE_CIRCLE );
1632  break;
1633 
1634  case EPAD::OCTAGON:
1635  // no KiCad octagonal pad shape, use PAD_CIRCLE for now.
1636  // pad->SetShape( PAD_OCTAGON );
1637  wxASSERT( pad->GetShape() == PAD_SHAPE_CIRCLE ); // verify set in D_PAD constructor
1640  pad->SetChamferRectRatio( 0.25 );
1641  break;
1642 
1643  case EPAD::LONG:
1644  pad->SetShape( PAD_SHAPE_OVAL );
1645  break;
1646 
1647  case EPAD::SQUARE:
1648  pad->SetShape( PAD_SHAPE_RECT );
1649  break;
1650 
1651  case EPAD::OFFSET:
1652  pad->SetShape( PAD_SHAPE_OVAL );
1653  break;
1654  }
1655  }
1656  else
1657  {
1658  // if shape is not present, our default is circle and that matches their default "round"
1659  }
1660 
1661  if( e.diameter )
1662  {
1663  int diameter = e.diameter->ToPcbUnits();
1664  pad->SetSize( wxSize( diameter, diameter ) );
1665  }
1666  else
1667  {
1668  double drillz = pad->GetDrillSize().x;
1669  double annulus = drillz * m_rules->rvPadTop; // copper annulus, eagle "restring"
1670  annulus = eagleClamp( m_rules->rlMinPadTop, annulus, m_rules->rlMaxPadTop );
1671  int diameter = KiROUND( drillz + 2 * annulus );
1672  pad->SetSize( wxSize( KiROUND( diameter ), KiROUND( diameter ) ) );
1673  }
1674 
1675  if( pad->GetShape() == PAD_SHAPE_OVAL )
1676  {
1677  // The Eagle "long" pad is wider than it is tall,
1678  // m_elongation is percent elongation
1679  wxSize sz = pad->GetSize();
1680  sz.x = ( sz.x * ( 100 + m_rules->psElongationLong ) ) / 100;
1681  pad->SetSize( sz );
1682 
1683  if( e.shape && *e.shape == EPAD::OFFSET )
1684  {
1685  int offset = KiROUND( ( sz.x - sz.y ) / 2.0 );
1686  pad->SetOffset( wxPoint( offset, 0 ) );
1687  }
1688  }
1689 
1690  if( e.rot )
1691  {
1692  pad->SetOrientation( e.rot->degrees * 10 );
1693  }
1694 }
1695 
1696 
1697 void EAGLE_PLUGIN::packageText( MODULE* aModule, wxXmlNode* aTree ) const
1698 {
1699  ETEXT t( aTree );
1700  PCB_LAYER_ID layer = kicad_layer( t.layer );
1701 
1702  if( layer == UNDEFINED_LAYER )
1703  layer = Cmts_User;
1704 
1705  TEXTE_MODULE* txt;
1706 
1707  if( t.text == ">NAME" || t.text == ">name" )
1708  txt = &aModule->Reference();
1709  else if( t.text == ">VALUE" || t.text == ">value" )
1710  txt = &aModule->Value();
1711  else
1712  {
1713  // FIXME: graphical text items are rotated for some reason.
1714  txt = new TEXTE_MODULE( aModule );
1715  aModule->Add( txt );
1716  }
1717 
1718  txt->SetText( FROM_UTF8( t.text.c_str() ) );
1719 
1720  wxPoint pos( kicad_x( t.x ), kicad_y( t.y ) );
1721 
1722  txt->SetTextPos( pos );
1723  txt->SetPos0( pos - aModule->GetPosition() );
1724 
1725  txt->SetLayer( layer );
1726 
1727 
1728  double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default
1729  int textThickness = KiROUND( t.size.ToPcbUnits() * ratio / 100 );
1730 
1731  txt->SetTextThickness( textThickness );
1732  txt->SetTextSize( kicad_fontz( t.size, textThickness ) );
1733 
1734  int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT; // bottom-left is eagle default
1735 
1736  // An eagle package is never rotated, the DTD does not allow it.
1737  // angle -= aModule->GetOrienation();
1738 
1739  if( t.rot )
1740  {
1741  int sign = t.rot->mirror ? -1 : 1;
1742  txt->SetMirrored( t.rot->mirror );
1743 
1744  double degrees = t.rot->degrees;
1745 
1746  if( degrees == 90 || t.rot->spin )
1747  txt->SetTextAngle( sign * degrees * 10 );
1748  else if( degrees == 180 )
1749  align = ETEXT::TOP_RIGHT;
1750  else if( degrees == 270 )
1751  {
1752  align = ETEXT::TOP_RIGHT;
1753  txt->SetTextAngle( sign * 90 * 10 );
1754  }
1755  }
1756 
1757  switch( align )
1758  {
1759  case ETEXT::CENTER:
1760  // this was the default in pcbtxt's constructor
1761  break;
1762 
1763  case ETEXT::CENTER_LEFT:
1765  break;
1766 
1767  case ETEXT::CENTER_RIGHT:
1769  break;
1770 
1771  case ETEXT::TOP_CENTER:
1773  break;
1774 
1775  case ETEXT::TOP_LEFT:
1778  break;
1779 
1780  case ETEXT::TOP_RIGHT:
1783  break;
1784 
1785  case ETEXT::BOTTOM_CENTER:
1787  break;
1788 
1789  case ETEXT::BOTTOM_LEFT:
1792  break;
1793 
1794  case ETEXT::BOTTOM_RIGHT:
1797  break;
1798  }
1799 }
1800 
1801 
1802 void EAGLE_PLUGIN::packageRectangle( MODULE* aModule, wxXmlNode* aTree ) const
1803 {
1804  ERECT r( aTree );
1805 
1807  || r.layer == EAGLE_LAYER::VRESTRICT )
1808  {
1809  MODULE_ZONE_CONTAINER* zone = new MODULE_ZONE_CONTAINER( aModule );
1810  aModule->Add( zone, ADD_MODE::APPEND );
1811 
1812  setKeepoutSettingsToZone( zone, r.layer );
1813 
1814  const int outlineIdx = -1; // this is the id of the copper zone main outline
1815  zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ), outlineIdx );
1816  zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ), outlineIdx );
1817  zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ), outlineIdx );
1818  zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ), outlineIdx );
1819 
1820  if( r.rot )
1821  {
1822  wxPoint center( ( kicad_x( r.x1 ) + kicad_x( r.x2 ) ) / 2,
1823  ( kicad_y( r.y1 ) + kicad_y( r.y2 ) ) / 2 );
1824  zone->Rotate( center, r.rot->degrees * 10 );
1825  }
1826 
1827  zone->SetHatch(
1829  }
1830  else
1831  {
1832  PCB_LAYER_ID layer = kicad_layer( r.layer );
1833 
1834  EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
1835 
1836  aModule->Add( dwg );
1837 
1838  dwg->SetLayer( layer );
1839  dwg->SetWidth( 0 );
1840 
1841  std::vector<wxPoint> pts;
1842 
1843  wxPoint start( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ) );
1844  wxPoint end( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) );
1845 
1846  pts.push_back( start );
1847  pts.emplace_back( kicad_x( r.x2 ), kicad_y( r.y1 ) );
1848  pts.emplace_back( kicad_x( r.x2 ), kicad_y( r.y2 ) );
1849  pts.push_back( end );
1850 
1851  dwg->SetPolyPoints( pts );
1852 
1853  dwg->SetStart0( start );
1854  dwg->SetEnd0( end );
1855 
1856  if( r.rot )
1857  dwg->Rotate( dwg->GetCenter(), r.rot->degrees * 10 );
1858  }
1859 }
1860 
1861 
1862 void EAGLE_PLUGIN::packagePolygon( MODULE* aModule, wxXmlNode* aTree ) const
1863 {
1864  EPOLYGON p( aTree );
1865 
1866  std::vector<wxPoint> pts;
1867 
1868  // Get the first vertex and iterate
1869  wxXmlNode* vertex = aTree->GetChildren();
1870  std::vector<EVERTEX> vertices;
1871 
1872  // Create a circular vector of vertices
1873  // The "curve" parameter indicates a curve from the current
1874  // to the next vertex, so we keep the first at the end as well
1875  // to allow the curve to link back
1876  while( vertex )
1877  {
1878  if( vertex->GetName() == "vertex" )
1879  vertices.emplace_back( vertex );
1880 
1881  vertex = vertex->GetNext();
1882  }
1883 
1884  vertices.push_back( vertices[0] );
1885 
1886  for( size_t i = 0; i < vertices.size() - 1; i++ )
1887  {
1888  EVERTEX v1 = vertices[i];
1889 
1890  // Append the corner
1891  pts.emplace_back( kicad_x( v1.x ), kicad_y( v1.y ) );
1892 
1893  if( v1.curve )
1894  {
1895  EVERTEX v2 = vertices[i + 1];
1896  wxPoint center = ConvertArcCenter(
1897  wxPoint( kicad_x( v1.x ), kicad_y( v1.y ) ),
1898  wxPoint( kicad_x( v2.x ), kicad_y( v2.y ) ), *v1.curve );
1899  double angle = DEG2RAD( *v1.curve );
1900  double end_angle = atan2( kicad_y( v2.y ) - center.y,
1901  kicad_x( v2.x ) - center.x );
1902  double radius = sqrt( pow( center.x - kicad_x( v1.x ), 2 )
1903  + pow( center.y - kicad_y( v1.y ), 2 ) );
1904 
1905  // Don't allow a zero-radius curve
1906  if( KiROUND( radius ) == 0 )
1907  radius = 1.0;
1908 
1909  int segCount = GetArcToSegmentCount( KiROUND( radius ), ARC_HIGH_DEF, *v1.curve ) - 1;
1910 
1911  // If we are curving, we need at least 2 segments otherwise delta == angle
1912  if( segCount < 2 )
1913  segCount = 2;
1914 
1915  double delta = angle / segCount;
1916 
1917  for( double a = end_angle + angle; fabs( a - end_angle ) > fabs( delta ); a -= delta )
1918  {
1919  pts.push_back(
1920  wxPoint( KiROUND( radius * cos( a ) ),
1921  KiROUND( radius * sin( a ) ) ) + center );
1922  }
1923  }
1924  }
1925 
1927  || p.layer == EAGLE_LAYER::VRESTRICT )
1928  {
1929  MODULE_ZONE_CONTAINER* zone = new MODULE_ZONE_CONTAINER( aModule );
1930  aModule->Add( zone, ADD_MODE::APPEND );
1931 
1932  setKeepoutSettingsToZone( zone, p.layer );
1933 
1934  SHAPE_LINE_CHAIN outline( pts );
1935  outline.SetClosed( true );
1936  zone->Outline()->AddOutline( outline );
1937 
1938  zone->SetHatch(
1940  }
1941  else
1942  {
1943  PCB_LAYER_ID layer = kicad_layer( p.layer );
1944  EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
1945 
1946  aModule->Add( dwg );
1947 
1948  dwg->SetWidth( 0 ); // it's filled, no need for boundary width
1949  dwg->SetLayer( layer );
1950 
1951  dwg->SetPolyPoints( pts );
1952  dwg->SetStart0( *pts.begin() );
1953  dwg->SetEnd0( pts.back() );
1954  dwg->SetDrawCoord();
1955  dwg->GetPolyShape().Inflate(
1957  }
1958 }
1959 
1960 void EAGLE_PLUGIN::packageCircle( MODULE* aModule, wxXmlNode* aTree ) const
1961 {
1962  ECIRCLE e( aTree );
1963 
1964  int width = e.width.ToPcbUnits();
1965  int radius = e.radius.ToPcbUnits();
1966 
1968  || e.layer == EAGLE_LAYER::VRESTRICT )
1969  {
1970  MODULE_ZONE_CONTAINER* zone = new MODULE_ZONE_CONTAINER( aModule );
1971  aModule->Add( zone, ADD_MODE::APPEND );
1972 
1973  setKeepoutSettingsToZone( zone, e.layer );
1974 
1975  // approximate circle as polygon with a edge every 10 degree
1976  wxPoint center( kicad_x( e.x ), kicad_y( e.y ) );
1977  int outlineRadius = radius + ( width / 2 );
1978  for( int angle = 0; angle < 360; angle += 10 )
1979  {
1980  wxPoint rotatedPoint( outlineRadius, 0 );
1981  RotatePoint( &rotatedPoint, angle * 10. );
1982  zone->AppendCorner( center + rotatedPoint, -1 );
1983  }
1984 
1985  if( width > 0 )
1986  {
1987  zone->NewHole();
1988  int innerRadius = radius - ( width / 2 );
1989  for( int angle = 0; angle < 360; angle += 10 )
1990  {
1991  wxPoint rotatedPoint( innerRadius, 0 );
1992  RotatePoint( &rotatedPoint, angle * 10. );
1993  zone->AppendCorner( center + rotatedPoint, 0 );
1994  }
1995  }
1996 
1997  zone->SetHatch(
1999  }
2000  else
2001  {
2002  PCB_LAYER_ID layer = kicad_layer( e.layer );
2003  EDGE_MODULE* gr = new EDGE_MODULE( aModule, S_CIRCLE );
2004 
2005  // with == 0 means filled circle
2006  if( width <= 0 )
2007  {
2008  width = radius;
2009  radius = radius / 2;
2010  }
2011 
2012  aModule->Add( gr );
2013  gr->SetWidth( width );
2014 
2015  switch( (int) layer )
2016  {
2017  case UNDEFINED_LAYER:
2018  layer = Cmts_User;
2019  break;
2020  default:
2021  break;
2022  }
2023 
2024  gr->SetLayer( layer );
2025  gr->SetStart0( wxPoint( kicad_x( e.x ), kicad_y( e.y ) ) );
2026  gr->SetEnd0( wxPoint( kicad_x( e.x ) + radius, kicad_y( e.y ) ) );
2027  gr->SetDrawCoord();
2028  }
2029 }
2030 
2031 
2032 void EAGLE_PLUGIN::packageHole( MODULE* aModule, wxXmlNode* aTree, bool aCenter ) const
2033 {
2034  EHOLE e( aTree );
2035 
2036  // we add a PAD_ATTRIB_HOLE_NOT_PLATED pad to this module.
2037  D_PAD* pad = new D_PAD( aModule );
2038  aModule->Add( pad );
2039 
2040  pad->SetShape( PAD_SHAPE_CIRCLE );
2042 
2043  // Mechanical purpose only:
2044  // no offset, no net name, no pad name allowed
2045  // pad->SetOffset( wxPoint( 0, 0 ) );
2046  // pad->SetName( wxEmptyString );
2047 
2048  wxPoint padpos( kicad_x( e.x ), kicad_y( e.y ) );
2049 
2050  if( aCenter )
2051  {
2052  pad->SetPos0( wxPoint( 0, 0 ) );
2053  aModule->SetPosition( padpos );
2054  pad->SetPosition( padpos );
2055  }
2056  else
2057  {
2058  pad->SetPos0( padpos );
2059  pad->SetPosition( padpos + aModule->GetPosition() );
2060  }
2061 
2062  wxSize sz( e.drill.ToPcbUnits(), e.drill.ToPcbUnits() );
2063 
2064  pad->SetDrillSize( sz );
2065  pad->SetSize( sz );
2066 
2067  pad->SetLayerSet( LSET::AllCuMask().set( B_Mask ).set( F_Mask ) );
2068 }
2069 
2070 
2071 void EAGLE_PLUGIN::packageSMD( MODULE* aModule, wxXmlNode* aTree ) const
2072 {
2073  ESMD e( aTree );
2074  PCB_LAYER_ID layer = kicad_layer( e.layer );
2075 
2076  if( !IsCopperLayer( layer ) )
2077  return;
2078 
2079  D_PAD* pad = new D_PAD( aModule );
2080  aModule->Add( pad );
2081  transferPad( e, pad );
2082 
2083  pad->SetShape( PAD_SHAPE_RECT );
2084  pad->SetAttribute( PAD_ATTRIB_SMD );
2085 
2086  wxSize padSize( e.dx.ToPcbUnits(), e.dy.ToPcbUnits() );
2087  pad->SetSize( padSize );
2088  pad->SetLayer( layer );
2089 
2090  const LSET front( 3, F_Cu, F_Paste, F_Mask );
2091  const LSET back( 3, B_Cu, B_Paste, B_Mask );
2092 
2093  if( layer == F_Cu )
2094  pad->SetLayerSet( front );
2095  else if( layer == B_Cu )
2096  pad->SetLayerSet( back );
2097 
2098  int minPadSize = std::min( padSize.x, padSize.y );
2099 
2100  // Rounded rectangle pads
2101  int roundRadius = eagleClamp( m_rules->srMinRoundness * 2,
2102  (int)( minPadSize * m_rules->srRoundness ), m_rules->srMaxRoundness * 2 );
2103 
2104  if( e.roundness || roundRadius > 0 )
2105  {
2106  double roundRatio = (double) roundRadius / minPadSize / 2.0;
2107 
2108  // Eagle uses a different definition of roundness, hence division by 200
2109  if( e.roundness )
2110  roundRatio = std::fmax( *e.roundness / 200.0, roundRatio );
2111 
2112  pad->SetShape( PAD_SHAPE_ROUNDRECT );
2113  pad->SetRoundRectRadiusRatio( roundRatio );
2114  }
2115 
2116  if( e.rot )
2117  pad->SetOrientation( e.rot->degrees * 10 );
2118 
2120  (int) ( m_rules->mvCreamFrame * minPadSize ),
2121  m_rules->mlMaxCreamFrame ) );
2122 
2123  // Solder mask
2124  if( e.stop && *e.stop == false ) // enabled by default
2125  {
2126  if( layer == F_Cu )
2127  pad->SetLayerSet( pad->GetLayerSet().set( F_Mask, false ) );
2128  else if( layer == B_Cu )
2129  pad->SetLayerSet( pad->GetLayerSet().set( B_Mask, false ) );
2130  }
2131 
2132  // Solder paste (only for SMD pads)
2133  if( e.cream && *e.cream == false ) // enabled by default
2134  {
2135  if( layer == F_Cu )
2136  pad->SetLayerSet( pad->GetLayerSet().set( F_Paste, false ) );
2137  else if( layer == B_Cu )
2138  pad->SetLayerSet( pad->GetLayerSet().set( B_Paste, false ) );
2139  }
2140 }
2141 
2142 
2143 void EAGLE_PLUGIN::transferPad( const EPAD_COMMON& aEaglePad, D_PAD* aPad ) const
2144 {
2145  aPad->SetName( FROM_UTF8( aEaglePad.name.c_str() ) );
2146 
2147  // pad's "Position" is not relative to the module's,
2148  // whereas Pos0 is relative to the module's but is the unrotated coordinate.
2149  wxPoint padPos( kicad_x( aEaglePad.x ), kicad_y( aEaglePad.y ) );
2150  aPad->SetPos0( padPos );
2151 
2152  // Solder mask
2153  const wxSize& padSize( aPad->GetSize() );
2154 
2156  (int)( m_rules->mvStopFrame * std::min( padSize.x, padSize.y ) ),
2157  m_rules->mlMaxStopFrame ) );
2158 
2159  // Solid connection to copper zones
2160  if( aEaglePad.thermals && !*aEaglePad.thermals )
2162 
2163  MODULE* module = aPad->GetParent();
2164  wxCHECK( module, /* void */ );
2165  RotatePoint( &padPos, module->GetOrientation() );
2166  aPad->SetPosition( padPos + module->GetPosition() );
2167 }
2168 
2169 
2171 {
2172  for( auto& t : m_templates )
2173  delete t.second;
2174 
2175  m_templates.clear();
2176 }
2177 
2178 
2179 void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
2180 {
2181  ZONES zones; // per net
2182 
2183  m_xpath->push( "signals.signal", "name" );
2184 
2185  int netCode = 1;
2186 
2187  // Get the first signal and iterate
2188  wxXmlNode* net = aSignals->GetChildren();
2189 
2190  while( net )
2191  {
2192  bool sawPad = false;
2193 
2194  zones.clear();
2195 
2196  const wxString& netName = escapeName( net->GetAttribute( "name" ) );
2197  m_board->Add( new NETINFO_ITEM( m_board, netName, netCode ) );
2198 
2199  m_xpath->Value( netName.c_str() );
2200 
2201  // Get the first net item and iterate
2202  wxXmlNode* netItem = net->GetChildren();
2203 
2204  // (contactref | polygon | wire | via)*
2205  while( netItem )
2206  {
2207  const wxString& itemName = netItem->GetName();
2208 
2209  if( itemName == "wire" )
2210  {
2211  m_xpath->push( "wire" );
2212 
2213  EWIRE w( netItem );
2214  PCB_LAYER_ID layer = kicad_layer( w.layer );
2215 
2216  if( IsCopperLayer( layer ) )
2217  {
2218  wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
2219  double angle = 0.0;
2220  double end_angle = 0.0;
2221  double radius = 0.0;
2222  double delta_angle = 0.0;
2223  wxPoint center;
2224 
2225  int width = w.width.ToPcbUnits();
2226  if( width < m_min_trace )
2227  m_min_trace = width;
2228 
2229  if( w.curve )
2230  {
2231  center = ConvertArcCenter(
2232  wxPoint( kicad_x( w.x1 ), kicad_y( w.y1 ) ),
2233  wxPoint( kicad_x( w.x2 ), kicad_y( w.y2 ) ),
2234  *w.curve );
2235 
2236  angle = DEG2RAD( *w.curve );
2237 
2238  end_angle = atan2( kicad_y( w.y2 ) - center.y,
2239  kicad_x( w.x2 ) - center.x );
2240 
2241  radius = sqrt( pow( center.x - kicad_x( w.x1 ), 2 ) +
2242  pow( center.y - kicad_y( w.y1 ), 2 ) );
2243 
2244  // If we are curving, we need at least 2 segments otherwise
2245  // delta_angle == angle
2246  int segments = std::max( 2, GetArcToSegmentCount( KiROUND( radius ),
2247  ARC_HIGH_DEF, *w.curve ) - 1 );
2248  delta_angle = angle / segments;
2249  }
2250 
2251  while( fabs( angle ) > fabs( delta_angle ) )
2252  {
2253  wxASSERT( radius > 0.0 );
2254  wxPoint end( KiROUND( radius * cos( end_angle + angle ) + center.x ),
2255  KiROUND( radius * sin( end_angle + angle ) + center.y ) );
2256 
2257  TRACK* t = new TRACK( m_board );
2258 
2259  t->SetPosition( start );
2260  t->SetEnd( end );
2261  t->SetWidth( width );
2262  t->SetLayer( layer );
2263  t->SetNetCode( netCode );
2264 
2265  m_board->Add( t );
2266 
2267  start = end;
2268  angle -= delta_angle;
2269  }
2270 
2271  TRACK* t = new TRACK( m_board );
2272 
2273  t->SetPosition( start );
2274  t->SetEnd( wxPoint( kicad_x( w.x2 ), kicad_y( w.y2 ) ) );
2275  t->SetWidth( width );
2276  t->SetLayer( layer );
2277  t->SetNetCode( netCode );
2278 
2279  m_board->Add( t );
2280  }
2281  else
2282  {
2283  // put non copper wires where the sun don't shine.
2284  }
2285 
2286  m_xpath->pop();
2287  }
2288 
2289  else if( itemName == "via" )
2290  {
2291  m_xpath->push( "via" );
2292  EVIA v( netItem );
2293 
2294  PCB_LAYER_ID layer_front_most = kicad_layer( v.layer_front_most );
2295  PCB_LAYER_ID layer_back_most = kicad_layer( v.layer_back_most );
2296 
2297  if( IsCopperLayer( layer_front_most ) &&
2298  IsCopperLayer( layer_back_most ) )
2299  {
2300  int kidiam;
2301  int drillz = v.drill.ToPcbUnits();
2302  VIA* via = new VIA( m_board );
2303  m_board->Add( via );
2304 
2305  via->SetLayerPair( layer_front_most, layer_back_most );
2306 
2307  if( v.diam )
2308  {
2309  kidiam = v.diam->ToPcbUnits();
2310  via->SetWidth( kidiam );
2311  }
2312  else
2313  {
2314  double annulus = drillz * m_rules->rvViaOuter; // eagle "restring"
2315  annulus = eagleClamp( m_rules->rlMinViaOuter, annulus,
2317  kidiam = KiROUND( drillz + 2 * annulus );
2318  via->SetWidth( kidiam );
2319  }
2320 
2321  via->SetDrill( drillz );
2322 
2323  // make sure the via diameter respects the restring rules
2324 
2325  if( !v.diam || via->GetWidth() <= via->GetDrill() )
2326  {
2327  double annulus = eagleClamp( m_rules->rlMinViaOuter,
2328  (double)( via->GetWidth() / 2 - via->GetDrill() ),
2330  via->SetWidth( drillz + 2 * annulus );
2331  }
2332 
2333  if( kidiam < m_min_via )
2334  m_min_via = kidiam;
2335 
2336  if( drillz < m_min_hole )
2337  m_min_hole = drillz;
2338 
2339  if( ( kidiam - drillz ) / 2 < m_min_annulus )
2340  m_min_annulus = ( kidiam - drillz ) / 2;
2341 
2342  if( layer_front_most == F_Cu && layer_back_most == B_Cu )
2343  via->SetViaType( VIATYPE::THROUGH );
2344  else if( layer_front_most == F_Cu || layer_back_most == B_Cu )
2345  via->SetViaType( VIATYPE::MICROVIA );
2346  else
2348 
2349  wxPoint pos( kicad_x( v.x ), kicad_y( v.y ) );
2350 
2351  via->SetPosition( pos );
2352  via->SetEnd( pos );
2353 
2354  via->SetNetCode( netCode );
2355  }
2356 
2357  m_xpath->pop();
2358  }
2359 
2360  else if( itemName == "contactref" )
2361  {
2362  m_xpath->push( "contactref" );
2363  // <contactref element="RN1" pad="7"/>
2364 
2365  const wxString& reference = netItem->GetAttribute( "element" );
2366  const wxString& pad = netItem->GetAttribute( "pad" );
2367  wxString key = makeKey( reference, pad ) ;
2368 
2369  // D(printf( "adding refname:'%s' pad:'%s' netcode:%d netname:'%s'\n", reference.c_str(), pad.c_str(), netCode, netName.c_str() );)
2370 
2371  m_pads_to_nets[ key ] = ENET( netCode, netName );
2372 
2373  m_xpath->pop();
2374 
2375  sawPad = true;
2376  }
2377 
2378  else if( itemName == "polygon" )
2379  {
2380  m_xpath->push( "polygon" );
2381  auto* zone = loadPolygon( netItem );
2382 
2383  if( zone )
2384  {
2385  zones.push_back( zone );
2386 
2387  if( !zone->GetIsKeepout() )
2388  zone->SetNetCode( netCode );
2389  }
2390 
2391  m_xpath->pop(); // "polygon"
2392  }
2393 
2394  netItem = netItem->GetNext();
2395  }
2396 
2397  if( zones.size() && !sawPad )
2398  {
2399  // KiCad does not support an unconnected zone with its own non-zero netcode,
2400  // but only when assigned netcode = 0 w/o a name...
2401  for( ZONE_CONTAINER* zone : zones )
2402  zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
2403 
2404  // therefore omit this signal/net.
2405  }
2406  else
2407  netCode++;
2408 
2409  // Get next signal
2410  net = net->GetNext();
2411  }
2412 
2413  m_xpath->pop(); // "signals.signal"
2414 }
2415 
2416 
2417 PCB_LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const
2418 {
2419  int kiLayer;
2420 
2421  // eagle copper layer:
2422  if( aEagleLayer >= 1 && aEagleLayer < int( arrayDim( m_cu_map ) ) )
2423  {
2424  kiLayer = m_cu_map[aEagleLayer];
2425  }
2426 
2427  else
2428  {
2429  // translate non-copper eagle layer to pcbnew layer
2430  switch( aEagleLayer )
2431  {
2432  // Eagle says "Dimension" layer, but it's for board perimeter
2433  case EAGLE_LAYER::MILLING: kiLayer = Edge_Cuts; break;
2434  case EAGLE_LAYER::DIMENSION: kiLayer = Edge_Cuts; break;
2435 
2436  case EAGLE_LAYER::TPLACE: kiLayer = F_SilkS; break;
2437  case EAGLE_LAYER::BPLACE: kiLayer = B_SilkS; break;
2438  case EAGLE_LAYER::TNAMES: kiLayer = F_SilkS; break;
2439  case EAGLE_LAYER::BNAMES: kiLayer = B_SilkS; break;
2440  case EAGLE_LAYER::TVALUES: kiLayer = F_Fab; break;
2441  case EAGLE_LAYER::BVALUES: kiLayer = B_Fab; break;
2442  case EAGLE_LAYER::TSTOP: kiLayer = F_Mask; break;
2443  case EAGLE_LAYER::BSTOP: kiLayer = B_Mask; break;
2444  case EAGLE_LAYER::TCREAM: kiLayer = F_Paste; break;
2445  case EAGLE_LAYER::BCREAM: kiLayer = B_Paste; break;
2446  case EAGLE_LAYER::TFINISH: kiLayer = F_Mask; break;
2447  case EAGLE_LAYER::BFINISH: kiLayer = B_Mask; break;
2448  case EAGLE_LAYER::TGLUE: kiLayer = F_Adhes; break;
2449  case EAGLE_LAYER::BGLUE: kiLayer = B_Adhes; break;
2450  case EAGLE_LAYER::DOCUMENT: kiLayer = Cmts_User; break;
2451  case EAGLE_LAYER::REFERENCELC: kiLayer = Cmts_User; break;
2452  case EAGLE_LAYER::REFERENCELS: kiLayer = Cmts_User; break;
2453 
2454  // Packages show the future chip pins on SMD parts using layer 51.
2455  // This is an area slightly smaller than the PAD/SMD copper area.
2456  // Carry those visual aids into the MODULE on the fabrication layer,
2457  // not silkscreen. This is perhaps not perfect, but there is not a lot
2458  // of other suitable paired layers
2459  case EAGLE_LAYER::TDOCU: kiLayer = F_Fab; break;
2460  case EAGLE_LAYER::BDOCU: kiLayer = B_Fab; break;
2461 
2462  // these layers are defined as user layers. put them on ECO layers
2463  case EAGLE_LAYER::USERLAYER1: kiLayer = Eco1_User; break;
2464  case EAGLE_LAYER::USERLAYER2: kiLayer = Eco2_User; break;
2465 
2466  // these will also appear in the ratsnest, so there's no need for a warning
2467  case EAGLE_LAYER::UNROUTED: kiLayer = Dwgs_User; break;
2468 
2469  case EAGLE_LAYER::TKEEPOUT: kiLayer = F_CrtYd; break;
2470  case EAGLE_LAYER::BKEEPOUT: kiLayer = B_CrtYd; break;
2471  case EAGLE_LAYER::TTEST:
2472  case EAGLE_LAYER::BTEST:
2473  case EAGLE_LAYER::HOLES:
2474  default:
2475  // some layers do not map to KiCad
2476  wxLogMessage( wxString::Format( _( "Unsupported Eagle layer '%s' (%d), converted to Dwgs.User layer" ),
2477  eagle_layer_name( aEagleLayer ), aEagleLayer ) );
2478 
2479  kiLayer = Dwgs_User;
2480  break;
2481  }
2482  }
2483 
2484  return PCB_LAYER_ID( kiLayer );
2485 }
2486 
2487 
2488 const wxString& EAGLE_PLUGIN::eagle_layer_name( int aLayer ) const
2489 {
2490  static const wxString unknown( "unknown" );
2491  auto it = m_eagleLayers.find( aLayer );
2492  return it == m_eagleLayers.end() ? unknown : it->second.name;
2493 }
2494 
2495 
2497 {
2498  if( m_props )
2499  {
2500  UTF8 page_width;
2501  UTF8 page_height;
2502 
2503  if( m_props->Value( "page_width", &page_width ) &&
2504  m_props->Value( "page_height", &page_height ) )
2505  {
2507 
2508  int w = atoi( page_width.c_str() );
2509  int h = atoi( page_height.c_str() );
2510 
2511  int desired_x = ( w - bbbox.GetWidth() ) / 2;
2512  int desired_y = ( h - bbbox.GetHeight() ) / 2;
2513 
2514  DBG(printf( "bbox.width:%d bbox.height:%d w:%d h:%d desired_x:%d desired_y:%d\n",
2515  bbbox.GetWidth(), bbbox.GetHeight(), w, h, desired_x, desired_y );)
2516 
2517  m_board->Move( wxPoint( desired_x - bbbox.GetX(), desired_y - bbbox.GetY() ) );
2518  }
2519  }
2520 }
2521 
2522 
2523 wxDateTime EAGLE_PLUGIN::getModificationTime( const wxString& aPath )
2524 {
2525  // File hasn't been loaded yet.
2526  if( aPath.IsEmpty() )
2527  return wxDateTime::Now();
2528 
2529  wxFileName fn( aPath );
2530 
2531  if( fn.IsFileReadable() )
2532  return fn.GetModificationTime();
2533  else
2534  return wxDateTime( 0.0 );
2535 }
2536 
2537 
2538 void EAGLE_PLUGIN::cacheLib( const wxString& aLibPath )
2539 {
2540  try
2541  {
2542  wxDateTime modtime = getModificationTime( aLibPath );
2543 
2544  // Fixes assertions in wxWidgets debug builds for the wxDateTime object. Refresh the
2545  // cache if either of the wxDateTime objects are invalid or the last file modification
2546  // time differs from the current file modification time.
2547  bool load = !m_mod_time.IsValid() || !modtime.IsValid() || m_mod_time != modtime;
2548 
2549  if( aLibPath != m_lib_path || load )
2550  {
2551  wxXmlNode* doc;
2552  LOCALE_IO toggle; // toggles on, then off, the C locale.
2553 
2554  deleteTemplates();
2555 
2556  // Set this before completion of loading, since we rely on it for
2557  // text of an exception. Delay setting m_mod_time until after successful load
2558  // however.
2559  m_lib_path = aLibPath;
2560 
2561  // 8 bit "filename" should be encoded according to disk filename encoding,
2562  // (maybe this is current locale, maybe not, its a filesystem issue),
2563  // and is not necessarily utf8.
2564  string filename = (const char*) aLibPath.char_str( wxConvFile );
2565 
2566  // Load the document
2567  wxXmlDocument xmlDocument;
2568  wxFileName fn( filename );
2569 
2570  if( !xmlDocument.Load( fn.GetFullPath() ) )
2571  THROW_IO_ERROR( wxString::Format( _( "Unable to read file \"%s\"" ),
2572  fn.GetFullPath() ) );
2573 
2574  doc = xmlDocument.GetRoot();
2575 
2576  wxXmlNode* drawing = MapChildren( doc )["drawing"];
2577  NODE_MAP drawingChildren = MapChildren( drawing );
2578 
2579  // clear the cu map and then rebuild it.
2580  clear_cu_map();
2581 
2582  m_xpath->push( "eagle.drawing.layers" );
2583  wxXmlNode* layers = drawingChildren["layers"];
2584  loadLayerDefs( layers );
2585  m_xpath->pop();
2586 
2587  m_xpath->push( "eagle.drawing.library" );
2588  wxXmlNode* library = drawingChildren["library"];
2589  loadLibrary( library, NULL );
2590  m_xpath->pop();
2591 
2592  m_mod_time = modtime;
2593  }
2594  }
2595  catch(...){}
2596  // TODO: Handle exceptions
2597  // catch( file_parser_error fpe )
2598  // {
2599  // // for xml_parser_error, what() has the line number in it,
2600  // // but no byte offset. That should be an adequate error message.
2601  // THROW_IO_ERROR( fpe.what() );
2602  // }
2603  //
2604  // // Class ptree_error is a base class for xml_parser_error & file_parser_error,
2605  // // so one catch should be OK for all errors.
2606  // catch( ptree_error pte )
2607  // {
2608  // string errmsg = pte.what();
2609  //
2610  // errmsg += " @\n";
2611  // errmsg += m_xpath->Contents();
2612  //
2613  // THROW_IO_ERROR( errmsg );
2614  // }
2615 }
2616 
2617 
2618 void EAGLE_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
2619  bool aBestEfforts, const PROPERTIES* aProperties )
2620 {
2621  wxString errorMsg;
2622 
2623  init( aProperties );
2624 
2625  try
2626  {
2627  cacheLib( aLibraryPath );
2628  }
2629  catch( const IO_ERROR& ioe )
2630  {
2631  errorMsg = ioe.What();
2632  }
2633 
2634  // Some of the files may have been parsed correctly so we want to add the valid files to
2635  // the library.
2636 
2637  for( MODULE_CITER it = m_templates.begin(); it != m_templates.end(); ++it )
2638  aFootprintNames.Add( FROM_UTF8( it->first.c_str() ) );
2639 
2640  if( !errorMsg.IsEmpty() && !aBestEfforts )
2641  THROW_IO_ERROR( errorMsg );
2642 }
2643 
2644 
2645 MODULE* EAGLE_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
2646  const PROPERTIES* aProperties )
2647 {
2648  init( aProperties );
2649  cacheLib( aLibraryPath );
2650  MODULE_CITER mi = m_templates.find( aFootprintName );
2651 
2652  if( mi == m_templates.end() )
2653  return NULL;
2654 
2655  // Return a copy of the template
2656  return (MODULE*) mi->second->Duplicate();
2657 }
2658 
2659 
2660 void EAGLE_PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const
2661 {
2662  PLUGIN::FootprintLibOptions( aListToAppendTo );
2663 
2664  /*
2665  (*aListToAppendTo)["ignore_duplicates"] = UTF8( _(
2666  "Ignore duplicately named footprints within the same Eagle library. "
2667  "Only the first similarly named footprint will be loaded."
2668  ));
2669  */
2670 }
2671 
2672 
2673 /*
2674 void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
2675 {
2676  // Eagle lovers apply here.
2677 }
2678 
2679 
2680 void EAGLE_PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, const PROPERTIES* aProperties )
2681 {
2682 }
2683 
2684 
2685 void EAGLE_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName )
2686 {
2687 }
2688 
2689 
2690 void EAGLE_PLUGIN::FootprintLibCreate( const wxString& aLibraryPath, const PROPERTIES* aProperties )
2691 {
2692 }
2693 
2694 
2695 bool EAGLE_PLUGIN::FootprintLibDelete( const wxString& aLibraryPath, const PROPERTIES* aProperties )
2696 {
2697 }
2698 
2699 
2700 bool EAGLE_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
2701 {
2702  return true;
2703 }
2704 
2705 */
void SetMirrored(bool isMirrored)
Definition: eda_text.h:187
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:721
wxString Contents()
return the contents of the XPATH as a single string
Definition: eagle_parser.h:139
Eagle vertex.
Definition: eagle_parser.h:746
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:712
#define DEFAULT_EDGE_WIDTH
UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to...
Definition: utf8.h:73
void SetTextAngle(double aAngle) override
MODULE_MAP::iterator MODULE_ITER
void SetEnd0(const wxPoint &aPoint)
int sign(T val)
Definition: util.h:101
void loadAllSections(wxXmlNode *aDocument)
double rlMaxViaOuter
maximum copper annulus on via
Definition: eagle_plugin.h:76
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
void SetHatch(ZONE_HATCH_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetHatch sets all hatch parameters for the zone.
Definition: class_zone.cpp:951
bool mirror
Definition: eagle_parser.h:480
double GetOrientation() const
Definition: class_module.h:211
opt_double curve
range is -359.9..359.9
Definition: eagle_parser.h:516
#define DEFAULT_COURTYARD_WIDTH
int kicad_x(const ECOORD &x) const
Definition: eagle_plugin.h:205
TEXTE_MODULE & Reference()
Definition: class_module.h:474
void SetShape(STROKE_T aShape)
bool IsMirrored() const
Definition: eda_text.h:188
opt_int rank
Definition: eagle_parser.h:779
void clear_cu_map()
static T eagleClamp(T aMin, T aValue, T aMax)
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:114
void centerBoard()
move the BOARD into the center of the page
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: class_zone.h:196
BOARD * m_board
which BOARD is being worked on, no ownership here
Definition: eagle_plugin.h:188
TEXTE_PCB class definition.
PCB_LAYER_ID kicad_layer(int aLayer) const
Convert an Eagle layer to a KiCad layer.
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: common.h:216
void FootprintLibOptions(PROPERTIES *aProperties) const override
Function FootprintLibOptions appends supported PLUGIN options to aListToAppenTo along with internatio...
opt_ecoord diam
Definition: eagle_parser.h:562
void SetPosition(const wxPoint &aPoint) override
Definition: class_track.h:412
int psTop
Shape of the top pads.
Definition: eagle_plugin.h:60
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:114
void clear()
Definition: eagle_parser.h:122
int GetX() const
Definition: eda_rect.h:111
ERULES * m_rules
Eagle design rules.
Definition: eagle_plugin.h:174
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:798
ECOORD drill
< inclusive
Definition: eagle_parser.h:561
void SetDoNotAllowFootprints(bool aEnable)
Definition: class_zone.h:723
void packageText(MODULE *aModule, wxXmlNode *aTree) const
ECOORD y
Definition: eagle_parser.h:749
void push(const char *aPathSegment, const char *aAttribute="")
Definition: eagle_parser.h:117
Eagle element element.
Definition: eagle_parser.h:797
polygon (not yet used for tracks, but could be in microwave apps)
XPATH keeps track of what we are working on within a PTREE.
Definition: eagle_parser.h:112
void SetChamferPositions(int aPositions)
has meaning only for chamfered rect pads set the position of the chamfers for orientation 0.
Definition: class_pad.h:490
ECOORD x2
Definition: eagle_parser.h:587
static const int max_priority
Definition: eagle_parser.h:768
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:81
double rlMaxPadTop
maximum copper annulus on through hole pads
Definition: eagle_plugin.h:72
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:246
void SetVisible(bool aVisible)
Definition: eda_text.h:184
int GetWidth() const
Definition: eda_rect.h:119
PADS & Pads()
Definition: class_module.h:169
int mlMinStopFrame
solder mask, minimum size (Eagle mils, here nanometers)
Definition: eagle_plugin.h:55
const wxString GetValue() const
Function GetValue.
Definition: class_module.h:458
opt_double ratio
Definition: eagle_parser.h:653
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:271
int number
Definition: eagle_parser.h:815
double GetTextAngle() const
Definition: eda_text.h:173
void SetCopperLayerCount(int aCount)
#define DEFAULT_LINE_WIDTH
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
opt_erot rot
Definition: eagle_parser.h:807
static int parseEagle(const wxString &aDistance)
Parse an eagle distance which is either mm, or mils if there is "mil" suffix.
int srMinRoundness
corner rounding radius, minimum size (Eagle mils, here nanometers)
Definition: eagle_plugin.h:65
ECOORD width
Definition: eagle_parser.h:505
opt_bool thermals
Definition: eagle_parser.h:778
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
Definition: string.cpp:714
void SetHeight(int aHeight, int aPrecision)
Function SetHeight Sets the length of feature lines.
opt_bool smashed
Definition: eagle_parser.h:806
void SetHatchStyle(ZONE_HATCH_STYLE aStyle)
Definition: class_zone.h:570
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:156
BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const PROPERTIES *aProperties=NULL) override
Function Load loads information from some input file format that this PLUGIN implementation knows abo...
Template specialization to enable wxStrings for certain containers (e.g. unordered_map)
Definition: bitmap.cpp:56
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:551
usual segment : line with rounded ends
void parse(wxXmlNode *aRules)
wxString name
Definition: eagle_parser.h:682
NET_MAP::const_iterator NET_MAP_CITER
Definition: eagle_plugin.h:42
void init(const PROPERTIES *aProperties)
initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
opt_erot rot
Definition: eagle_parser.h:590
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:226
double degrees
Definition: eagle_parser.h:482
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
ECOORD width
Definition: eagle_parser.h:759
virtual void FootprintLibOptions(PROPERTIES *aListToAppendTo) const
Function FootprintLibOptions appends supported PLUGIN options to aListToAppenTo along with internatio...
Definition: plugin.cpp:140
T
enum T contains all this lexer's tokens.
Eagle SMD pad.
Definition: eagle_parser.h:715
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Function SetLayerType changes the type of the layer given by aLayer.
ECOORD y
Definition: eagle_parser.h:573
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
void SetRoundRectRadiusRatio(double aRadiusScale)
has meaning only for rounded rect pads Set the ratio between the smaller X or Y size and the rounded ...
Definition: class_pad.cpp:178
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
int m_min_via
smallest via we find on Load(), in BIU.
Definition: eagle_plugin.h:192
double rvViaOuter
copper annulus is this percent of via hole
Definition: eagle_plugin.h:74
int GetTextThickness(PCB_LAYER_ID aLayer) const
Function GetTextThickness Returns the default text thickness from the layer class for the given layer...
void SetUnits(EDA_UNITS aUnits, bool aUseMils)
ECOORD y
Definition: eagle_parser.h:804
PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
Eagle hole element.
Definition: eagle_parser.h:786
XML_PARSER_ERROR implements a simple wrapper around runtime_error to isolate the errors thrown by the...
Definition: eagle_parser.h:70
Eagle text element.
Definition: eagle_parser.h:645
const wxString & eagle_layer_name(int aLayer) const
Get Eagle layer name by its number.
void loadLayerDefs(wxXmlNode *aLayers)
opt_erot rot
Definition: eagle_parser.h:611
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Function MapChildren provides an easy access to the children of an XML node via their names.
opt_bool thermals
Definition: eagle_parser.h:686
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
ECOORD width
Definition: eagle_parser.h:575
ECOORD x
Definition: eagle_parser.h:572
void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
XPATH * m_xpath
keeps track of what we are working on within XML document during a Load().
Definition: eagle_plugin.h:175
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
int m_cu_map[17]
map eagle to kicad, cu layers only.
Definition: eagle_plugin.h:171
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:720
This file contains miscellaneous commonly used macros and functions.
void SetWidth(int aWidth)
Definition: class_track.h:111
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:433
const char * c_str() const
Definition: utf8.h:107
OPTIONAL_XML_ATTRIBUTE< wxString > opt_wxString
Definition: eagle_parser.h:373
int layer_back_most
< extent
Definition: eagle_parser.h:560
void SetPriority(unsigned aPriority)
Function SetPriority.
Definition: class_zone.h:95
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate an edge of the footprint.
opt_int align
Definition: eagle_parser.h:620
ECOORD dy
Definition: eagle_parser.h:718
void packageHole(MODULE *aModule, wxXmlNode *aTree, bool aCenter) const
Function packageHole @parameter aModule - The KiCad module to which to assign the hole @parameter aTr...
int GetLineThickness(PCB_LAYER_ID aLayer) const
Function GetLineThickness Returns the default graphic segment thickness from the layer class for the ...
void SetLayerSet(LSET aLayerSet)
Definition: class_zone.cpp:264
opt_ecoord isolate
Definition: eagle_parser.h:776
DIMENSION class definition.
wxString name
Definition: eagle_parser.h:604
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
void SetClosed(bool aClosed)
Function SetClosed()
PCB_LAYER_ID
A quick note on layer IDs:
ECOORD y1
Definition: eagle_parser.h:502
static wxString makeKey(const wxString &aFirst, const wxString &aSecond)
Assemble a two part key as a simple concatenation of aFirst and aSecond parts, using a separator.
void SetHatchFillTypeGap(int aStep)
Definition: class_zone.h:214
wxString value
Definition: eagle_parser.h:802
LSET is a set of PCB_LAYER_IDs.
#define DEFAULT_SILK_LINE_WIDTH
void cacheLib(const wxString &aLibraryPath)
This PLUGIN only caches one footprint library, this determines which one.
void packagePolygon(MODULE *aModule, wxXmlNode *aTree) const
wxString escapeName(const wxString &aNetName)
Translates Eagle special characters to their counterparts in KiCad.
pads are covered by copper
const PROPERTIES * m_props
passed via Save() or Load(), no ownership, may be NULL.
Definition: eagle_plugin.h:187
ECOORD x
Definition: eagle_parser.h:788
void SetOrigin(const wxPoint &aOrigin, int aPrecision)
Function SetOrigin Sets a new origin of the crossbar line.
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:116
LAYER_NUM layer
Definition: eagle_parser.h:506
#define NULL
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
void SetEnd(const wxPoint &aEnd, int aPrecision)
Function SetEnd Sets a new end of the crossbar line.
std::map< int, ELAYER > m_eagleLayers
Eagle layers data stored by the layer number.
Definition: eagle_plugin.h:172
opt_ecoord y
Definition: eagle_parser.h:607
int layer
Definition: eagle_parser.h:589
Eagle thru hole pad.
Definition: eagle_parser.h:693
opt_ecoord spacing
Definition: eagle_parser.h:761
void SetName(const wxString &aName)
Set the pad name (sometimes called pad number, although it can be an array reference like AA12).
Definition: class_pad.h:128
void SetClearance(int aClearance)
Definition: netclass.h:166
wxString name
Definition: eagle_parser.h:799
SHAPE_POLY_SET.
void NewHole()
Function NewHole creates a new hole on the zone; i.e., a new contour on the zone's outline.
Definition: class_zone.h:550
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:473
void SetPos0(const wxPoint &aPos)
Definition: class_pad.h:214
int GetDrill() const
Function GetDrill returns the local drill setting for this VIA.
Definition: class_track.h:454
ECOORD y1
Definition: eagle_parser.h:586
const wxSize & GetTextSize() const
Definition: eda_text.h:238
void packageWire(MODULE *aModule, wxXmlNode *aTree) const
std::vector< DRC_RULE * > m_rules
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:202
Arcs (with rounded ends)
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Function Flip Flip this object, i.e.
Eagle circle.
Definition: eagle_parser.h:570
NETCLASS handles a collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:49
void packageRectangle(MODULE *aModule, wxXmlNode *aTree) const
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:325
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Function SetLayerName changes the name of the layer given by aLayer.
ECOORD dx
Definition: eagle_parser.h:717
wxString m_lib_path
Definition: eagle_plugin.h:195
void Rotate(const wxPoint &centre, double angle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:770
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:256
ECOORD x
Definition: eagle_parser.h:648
void SetSize(const wxSize &aSize)
Definition: class_pad.h:220
a few functions useful in geometry calculations.
subset of eagle.drawing.board.designrules in the XML document
Definition: eagle_plugin.h:46
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_Layer contains the top layer, the other layer is in m_BottomLayer.
void SetReference(const wxString &aReference)
Function SetReference.
Definition: class_module.h:443
#define THROW_IO_ERROR(msg)
SHAPE_POLY_SET & GetPolyShape()
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: class_pad.h:439
void SetFileName(const wxString &aFileName)
Definition: class_board.h:253
ECOORD size
Definition: eagle_parser.h:650
void SetPosition(const wxPoint &aPos) override
void SetZoneClearance(int aZoneClearance)
Definition: class_zone.h:192
int layer
Definition: eagle_parser.h:719
static wxDateTime getModificationTime(const wxString &aPath)
get a file's or dir's modification time.
opt_wxString value
Definition: eagle_parser.h:605
double mdWireWire
wire to wire spacing I presume.
Definition: eagle_plugin.h:77
wxString text
Definition: eagle_parser.h:647
int m_min_trace
smallest trace we find on Load(), in BIU.
Definition: eagle_plugin.h:190
void SetDoNotAllowPads(bool aEnable)
Definition: class_zone.h:722
ECOORD x
Definition: eagle_parser.h:803
opt_int roundness
Definition: eagle_parser.h:720
int NewOutline()
Creates a new empty polygon in the set and returns its index
void SetTextAngle(double aAngle) override
int m_hole_count
generates unique module names from eagle "hole"s.
Definition: eagle_plugin.h:178
void AddPolygon(std::vector< wxPoint > &aPolygon)
add a polygon to the zone outline if the zone outline is empty, this is the main outline else it is a...
Definition: class_zone.cpp:877
LAYER_NUM layer
Definition: eagle_parser.h:576
Eagle XML rectangle in binary.
Definition: eagle_parser.h:583
double srRoundness
corner rounding ratio for SMD pads (percentage)
Definition: eagle_plugin.h:64
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:411
opt_int align
Definition: eagle_parser.h:670
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
int GetHeight() const
Definition: eda_rect.h:120
Eagle net.
Definition: eagle_parser.h:461
void SetPos0(const wxPoint &aPos)
wxPoint GetPosition() const override
Definition: class_zone.cpp:230
int psElongationLong
percent over 100%.
Definition: eagle_plugin.h:48
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
int psFirst
Shape of the first pads.
Definition: eagle_plugin.h:62
opt_double curve
range is -359.9..359.9
Definition: eagle_parser.h:750
void SetStart(const wxPoint &aStart)
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void SetThermalReliefCopperBridge(int aThermalReliefCopperBridge)
Definition: class_zone.h:153
void loadLibraries(wxXmlNode *aLibs)
void loadPlain(wxXmlNode *aPlain)
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:160
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
MODULE * GetParent() const
Definition: class_pad.h:108
void orientModuleAndText(MODULE *m, const EELEMENT &e, const EATTR *nameAttr, const EATTR *valueAttr)
ECOORD y2
Definition: eagle_parser.h:504
void AdjustDimensionDetails(int aPrecision)
Function AdjustDimensionDetails Calculate coordinates of segments used to draw the dimension.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
void Move(const wxPoint &aMoveVector) override
Function Move move this object.
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:719
Use thermal relief for pads.
EATTR parses an Eagle "attribute" XML element.
Definition: eagle_parser.h:602
opt_ecoord x
Definition: eagle_parser.h:606
Eagle via.
Definition: eagle_parser.h:555
std::vector< ELAYER > ELAYERS
Definition: eagle_plugin.h:168
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:324
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
void SetLocalCoord()
Set relative coordinates.
ECOORD x1
Definition: eagle_parser.h:585
wxSize kicad_fontz(const ECOORD &d, int aTextThickness) const
create a font size (fontz) from an eagle font size scalar and KiCAD font thickness
opt_wxString dimensionType
Definition: eagle_parser.h:638
void packagePad(MODULE *aModule, wxXmlNode *aTree)
MODULE_MAP::const_iterator MODULE_CITER
int mlMinCreamFrame
solder paste mask, minimum size (Eagle mils, here nanometers)
Definition: eagle_plugin.h:57
#define ZONE_THICKNESS_MIN_VALUE_MIL
Definition: zones.h:32
opt_erot rot
Definition: eagle_parser.h:654
int netcode
Definition: eagle_parser.h:463
void SetFillMode(ZONE_FILL_MODE aFillMode)
Definition: class_zone.h:147
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
void loadElements(wxXmlNode *aElements)
int GetWidth() const
Definition: class_track.h:112
ZONE_HATCH_STYLE
Zone hatch styles.
Definition: zone_settings.h:46
const char * name
Definition: DXF_plotter.cpp:60
ECOORD x
Definition: eagle_parser.h:748
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
opt_ecoord diameter
Definition: eagle_parser.h:696
double DEG2RAD(double deg)
Definition: trigo.h:214
void packageSMD(MODULE *aModule, wxXmlNode *aTree) const
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:341
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const PROPERTIES *aProperties=NULL) override
Return a list of footprint names contained within the library at aLibraryPath.
Structure holding common properties for through-hole and SMD pads.
Definition: eagle_parser.h:680
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
void SetOrientation(double newangle)
void SetPosition(const wxPoint &aPos) override
Definition: class_track.h:107
wxPoint ConvertArcCenter(const wxPoint &aStart, const wxPoint &aEnd, double aAngle)
Convert an Eagle curve end to a KiCad center for S_ARC
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
void SetHatchFillTypeOrientation(double aStep)
Definition: class_zone.h:217
MODULE_MAP m_templates
is part of a MODULE factory that operates using copy construction.
Definition: eagle_plugin.h:182
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
TEXTE_PCB & Text()
#define DIMENSION_PRECISION
ECOORD radius
Definition: eagle_parser.h:574
ELAYERS::const_iterator EITER
Definition: eagle_plugin.h:169
int GetCopperLayerCount() const
Function GetCopperLayerCount.
wxDateTime m_mod_time
Definition: eagle_plugin.h:196
const wxSize & GetDrillSize() const
Definition: class_pad.h:227
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: class_track.h:447
void SetStart0(const wxPoint &aPoint)
NETCLASS * GetDefault() const
Function GetDefault.
void loadLibrary(wxXmlNode *aLib, const wxString *aLibName)
Function loadLibrary loads the Eagle "library" XML element, which can occur either under a "libraries...
void SetValue(const wxString &aValue)
Function SetValue.
Definition: class_module.h:467
opt_double ratio
Definition: eagle_parser.h:610
opt_erot rot
Definition: eagle_parser.h:684
double mvStopFrame
solder mask, expressed as percentage of the smaller pad/via dimension
Definition: eagle_plugin.h:53
#define IU_PER_MILS
Definition: plotter.cpp:138
int GetY() const
Definition: eda_rect.h:112
ECOORD y
Definition: eagle_parser.h:558
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
int m_min_annulus
smallest via annulus we find on Load(), in BIU.
Definition: eagle_plugin.h:193
NET_MAP m_pads_to_nets
net list
Definition: eagle_plugin.h:180
The common library.
void transferPad(const EPAD_COMMON &aEaglePad, D_PAD *aPad) const
Handles common pad properties
MODULE_ZONE_CONTAINER is the same item as ZONE_CONTAINER, but with a specific type id ZONE_CONTAINER ...
Definition: class_zone.h:952
void SetShape(PAD_SHAPE_T aShape)
Set the new shape of this pad.
Definition: class_pad.h:145
opt_bool first
Definition: eagle_parser.h:708
void SetEnd(const wxPoint &aEnd)
Eagle wire.
Definition: eagle_parser.h:499
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:430
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
ECOORD x
Definition: eagle_parser.h:557
void SetHatchFillTypeThickness(int aThickness)
Definition: class_zone.h:211
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition: class_zone.cpp:894
void SetChamferRectRatio(double aChamferScale)
has meaning only for chamfered rect pads Set the ratio between the smaller X or Y size and chamfered ...
Definition: class_pad.cpp:186
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_pad.h:347
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:157
opt_int shape
Definition: eagle_parser.h:707
int m_min_hole
smallest diameter hole we find on Load(), in BIU.
Definition: eagle_plugin.h:191
#define DBG(x)
Definition: fctsys.h:33
Eagle dimension element.
Definition: eagle_parser.h:628
double rvPadTop
top pad size as percent of drill size
Definition: eagle_plugin.h:68
wxString package
Definition: eagle_parser.h:801
wxPoint GetPosition() const override
Definition: class_module.h:206
void deleteTemplates()
Deletes the footprint templates list
static void setKeepoutSettingsToZone(ZONE_CONTAINER *aZone, LAYER_NUM aLayer)
bool spin
Definition: eagle_parser.h:481
PAD_SHAPE_T GetShape() const
Definition: class_pad.h:154
ECOORD y2
Definition: eagle_parser.h:588
ECOORD y
Definition: eagle_parser.h:649
Eagle polygon, without vertices which are parsed as needed.
Definition: eagle_parser.h:757
opt_int display
Definition: eagle_parser.h:619
void pop()
Definition: eagle_parser.h:124
void SetIsKeepout(bool aEnable)
Definition: class_zone.h:718
std::vector< ZONE_CONTAINER * > ZONES
Definition: eagle_plugin.h:40
void loadDesignRules(wxXmlNode *aDesignRules)
ECOORD drill
Definition: eagle_parser.h:695
const wxSize & GetSize() const
Definition: class_pad.h:221
void SetWidth(int aWidth)
ECOORD y
Definition: eagle_parser.h:789
EDGE_MODULE class definition.
int Parse(const UTF8 &aId, LIB_ID_TYPE aType, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
opt_bool stop
Definition: eagle_parser.h:685
const wxString PluginName() const override
Function PluginName returns a brief hard coded name for this PLUGIN.
int layer
Definition: eagle_parser.h:651
ECOORD x1
Definition: eagle_parser.h:501
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:229
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:202
void packageCircle(MODULE *aModule, wxXmlNode *aTree) const
void SetViaType(VIATYPE aViaType)
Definition: class_track.h:374
wxString library
Definition: eagle_parser.h:800
int psBottom
Shape of the bottom pads.
Definition: eagle_plugin.h:61
ZONE_CONTAINER * loadPolygon(wxXmlNode *aPolyNode)
Loads a copper or keepout polygon and adds it to the board.
double rlMinPadTop
minimum copper annulus on through hole pads
Definition: eagle_plugin.h:71
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
double rlMinViaOuter
minimum copper annulus on via
Definition: eagle_plugin.h:75
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:476
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
ECOORD drill
Definition: eagle_parser.h:790
just inflate the polygon. Acute angles create spikes
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
bool Value(const char *aName, UTF8 *aFetchedValue=NULL) const
Function Value fetches a property by aName and returns true if that property was found,...
Definition: properties.cpp:24
int mlMaxCreamFrame
solder paste mask, maximum size (Eagle mils, here nanometers)
Definition: eagle_plugin.h:58
void SetThermalReliefGap(int aThermalReliefGap)
Definition: class_zone.h:150
wxSize GetTextSize(PCB_LAYER_ID aLayer) const
Function GetTextSize Returns the default text size from the layer class for the given layer.
MODULE * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, const PROPERTIES *aProperties=NULL) override
Function FootprintLoad loads a footprint having aFootprintName from the aLibraryPath containing a lib...
int srMaxRoundness
corner rounding radius, maximum size (Eagle mils, here nanometers)
Definition: eagle_plugin.h:66
MODULE * makeModule(wxXmlNode *aPackage, const wxString &aPkgName)
Function makeModule creates a MODULE from an Eagle package.
DIMENSION.
opt_bool active
Definition: eagle_parser.h:820
ECOORD x2
Definition: eagle_parser.h:503
void loadSignals(wxXmlNode *aSignals)
int kicad_y(const ECOORD &y) const
Convert an Eagle distance to a KiCad distance.
Definition: eagle_plugin.h:204
int ToPcbUnits() const
Definition: eagle_parser.h:438
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
Definition: eagle_parser.h:48
const wxString GetFileExtension() const override
Function GetFileExtension returns the file extension for the PLUGIN.
opt_ecoord size
Definition: eagle_parser.h:608
wxPoint GetCenter() const override
Function GetCenter()
void Value(const char *aValue)
modify the last path node's value
Definition: eagle_parser.h:127
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
int layer_front_most
Definition: eagle_parser.h:559
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int mlMaxStopFrame
solder mask, maximum size (Eagle mils, here nanometers)
Definition: eagle_plugin.h:56
double mvCreamFrame
solderpaste mask, expressed as percentage of the smaller pad/via dimension
Definition: eagle_plugin.h:54
opt_bool cream
Definition: eagle_parser.h:721
void orientModuleText(MODULE *m, const EELEMENT &e, TEXTE_MODULE *txt, const EATTR *a)
void SetWidth(int aWidth)