KiCad PCB EDA Suite
altium_parser_pcb.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) 2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <map>
25 #include <unordered_map>
26 
27 #include <ki_exception.h>
28 #include <math/util.h>
29 
30 #include "altium_parser_pcb.h"
32 
33 
34 ALTIUM_LAYER altium_layer_from_name( const wxString& aName )
35 {
36  static const std::unordered_map<std::string, ALTIUM_LAYER> hash_map = {
37  { "TOP", ALTIUM_LAYER::TOP_LAYER },
38  { "MID1", ALTIUM_LAYER::MID_LAYER_1 },
39  { "MID2", ALTIUM_LAYER::MID_LAYER_2 },
40  { "MID3", ALTIUM_LAYER::MID_LAYER_3 },
41  { "MID4", ALTIUM_LAYER::MID_LAYER_4 },
42  { "MID5", ALTIUM_LAYER::MID_LAYER_5 },
43  { "MID6", ALTIUM_LAYER::MID_LAYER_6 },
44  { "MID7", ALTIUM_LAYER::MID_LAYER_7 },
45  { "MID8", ALTIUM_LAYER::MID_LAYER_8 },
46  { "MID9", ALTIUM_LAYER::MID_LAYER_9 },
47  { "MID10", ALTIUM_LAYER::MID_LAYER_10 },
48  { "MID11", ALTIUM_LAYER::MID_LAYER_11 },
49  { "MID12", ALTIUM_LAYER::MID_LAYER_12 },
50  { "MID13", ALTIUM_LAYER::MID_LAYER_13 },
51  { "MID14", ALTIUM_LAYER::MID_LAYER_14 },
52  { "MID15", ALTIUM_LAYER::MID_LAYER_15 },
53  { "MID16", ALTIUM_LAYER::MID_LAYER_16 },
54  { "MID17", ALTIUM_LAYER::MID_LAYER_17 },
55  { "MID18", ALTIUM_LAYER::MID_LAYER_18 },
56  { "MID19", ALTIUM_LAYER::MID_LAYER_19 },
57  { "MID20", ALTIUM_LAYER::MID_LAYER_20 },
58  { "MID21", ALTIUM_LAYER::MID_LAYER_21 },
59  { "MID22", ALTIUM_LAYER::MID_LAYER_22 },
60  { "MID23", ALTIUM_LAYER::MID_LAYER_23 },
61  { "MID24", ALTIUM_LAYER::MID_LAYER_24 },
62  { "MID25", ALTIUM_LAYER::MID_LAYER_25 },
63  { "MID26", ALTIUM_LAYER::MID_LAYER_26 },
64  { "MID27", ALTIUM_LAYER::MID_LAYER_27 },
65  { "MID28", ALTIUM_LAYER::MID_LAYER_28 },
66  { "MID29", ALTIUM_LAYER::MID_LAYER_29 },
67  { "MID30", ALTIUM_LAYER::MID_LAYER_30 },
68  { "BOTTOM", ALTIUM_LAYER::BOTTOM_LAYER },
69 
70  { "TOPOVERLAY", ALTIUM_LAYER::TOP_OVERLAY },
71  { "BOTTOMOVERLAY", ALTIUM_LAYER::BOTTOM_OVERLAY },
72  { "TOPPASTE", ALTIUM_LAYER::TOP_PASTE },
73  { "BOTTOMPASTE", ALTIUM_LAYER::BOTTOM_PASTE },
74  { "TOPSOLDER", ALTIUM_LAYER::TOP_SOLDER },
75  { "BOTTOMSOLDER", ALTIUM_LAYER::BOTTOM_SOLDER },
76 
77  { "PLANE1", ALTIUM_LAYER::INTERNAL_PLANE_1 },
78  { "PLANE2", ALTIUM_LAYER::INTERNAL_PLANE_2 },
79  { "PLANE3", ALTIUM_LAYER::INTERNAL_PLANE_3 },
80  { "PLANE4", ALTIUM_LAYER::INTERNAL_PLANE_4 },
81  { "PLANE5", ALTIUM_LAYER::INTERNAL_PLANE_5 },
82  { "PLANE6", ALTIUM_LAYER::INTERNAL_PLANE_6 },
83  { "PLANE7", ALTIUM_LAYER::INTERNAL_PLANE_7 },
84  { "PLANE8", ALTIUM_LAYER::INTERNAL_PLANE_8 },
85  { "PLANE9", ALTIUM_LAYER::INTERNAL_PLANE_9 },
86  { "PLANE10", ALTIUM_LAYER::INTERNAL_PLANE_10 },
87  { "PLANE11", ALTIUM_LAYER::INTERNAL_PLANE_11 },
88  { "PLANE12", ALTIUM_LAYER::INTERNAL_PLANE_12 },
89  { "PLANE13", ALTIUM_LAYER::INTERNAL_PLANE_13 },
90  { "PLANE14", ALTIUM_LAYER::INTERNAL_PLANE_14 },
91  { "PLANE15", ALTIUM_LAYER::INTERNAL_PLANE_15 },
92  { "PLANE16", ALTIUM_LAYER::INTERNAL_PLANE_16 },
93 
94  { "DRILLGUIDE", ALTIUM_LAYER::DRILL_GUIDE },
95  { "KEEPOUT", ALTIUM_LAYER::KEEP_OUT_LAYER },
96 
97  { "MECHANICAL1", ALTIUM_LAYER::MECHANICAL_1 },
98  { "MECHANICAL2", ALTIUM_LAYER::MECHANICAL_2 },
99  { "MECHANICAL3", ALTIUM_LAYER::MECHANICAL_3 },
100  { "MECHANICAL4", ALTIUM_LAYER::MECHANICAL_4 },
101  { "MECHANICAL5", ALTIUM_LAYER::MECHANICAL_5 },
102  { "MECHANICAL6", ALTIUM_LAYER::MECHANICAL_6 },
103  { "MECHANICAL7", ALTIUM_LAYER::MECHANICAL_7 },
104  { "MECHANICAL8", ALTIUM_LAYER::MECHANICAL_8 },
105  { "MECHANICAL9", ALTIUM_LAYER::MECHANICAL_9 },
106  { "MECHANICAL10", ALTIUM_LAYER::MECHANICAL_10 },
107  { "MECHANICAL11", ALTIUM_LAYER::MECHANICAL_11 },
108  { "MECHANICAL12", ALTIUM_LAYER::MECHANICAL_12 },
109  { "MECHANICAL13", ALTIUM_LAYER::MECHANICAL_13 },
110  { "MECHANICAL14", ALTIUM_LAYER::MECHANICAL_14 },
111  { "MECHANICAL15", ALTIUM_LAYER::MECHANICAL_15 },
112  { "MECHANICAL16", ALTIUM_LAYER::MECHANICAL_16 },
113 
114  { "DRILLDRAWING", ALTIUM_LAYER::DRILL_DRAWING },
115  { "MULTILAYER", ALTIUM_LAYER::MULTI_LAYER },
116 
117  // FIXME: the following mapping is just a guess
118  { "CONNECTIONS", ALTIUM_LAYER::CONNECTIONS },
119  { "BACKGROUND", ALTIUM_LAYER::BACKGROUND },
120  { "DRCERRORMARKERS", ALTIUM_LAYER::DRC_ERROR_MARKERS },
121  { "SELECTIONS", ALTIUM_LAYER::SELECTIONS },
122  { "VISIBLEGRID1", ALTIUM_LAYER::VISIBLE_GRID_1 },
123  { "VISIBLEGRID2", ALTIUM_LAYER::VISIBLE_GRID_2 },
124  { "PADHOLES", ALTIUM_LAYER::PAD_HOLES },
125  { "VIAHOLES", ALTIUM_LAYER::VIA_HOLES },
126  };
127 
128  auto it = hash_map.find( std::string( aName.c_str() ) );
129  if( it == hash_map.end() )
130  {
131  wxLogError( wxString::Format(
132  "Unknown mapping of the Altium layer '%s'. Please report as issue.", aName ) );
133  return ALTIUM_LAYER::UNKNOWN;
134  }
135  else
136  {
137  return it->second;
138  }
139 }
140 
142  std::map<wxString, wxString>& aProperties, std::vector<ALTIUM_VERTICE>& aVertices )
143 {
144  for( size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
145  {
146  const wxString si = std::to_string( i );
147 
148  const wxString vxi = "VX" + si;
149  const wxString vyi = "VY" + si;
150 
151  if( aProperties.find( vxi ) == aProperties.end()
152  || aProperties.find( vyi ) == aProperties.end() )
153  {
154  break; // it doesn't seem like we know beforehand how many vertices are inside a polygon
155  }
156 
157  const bool isRound = ALTIUM_PARSER::PropertiesReadInt( aProperties, "KIND" + si, 0 ) != 0;
158  const int32_t radius =
159  ALTIUM_PARSER::PropertiesReadKicadUnit( aProperties, "R" + si, "0mil" );
160  const double sa = ALTIUM_PARSER::PropertiesReadDouble( aProperties, "SA" + si, 0. );
161  const double ea = ALTIUM_PARSER::PropertiesReadDouble( aProperties, "EA" + si, 0. );
162  const wxPoint vp =
163  wxPoint( ALTIUM_PARSER::PropertiesReadKicadUnit( aProperties, vxi, "0mil" ),
164  -ALTIUM_PARSER::PropertiesReadKicadUnit( aProperties, vyi, "0mil" ) );
165  const wxPoint cp =
166  wxPoint( ALTIUM_PARSER::PropertiesReadKicadUnit( aProperties, "CX" + si, "0mil" ),
167  -ALTIUM_PARSER::PropertiesReadKicadUnit( aProperties, "CY" + si, "0mil" ) );
168 
169  aVertices.emplace_back( isRound, radius, sa, ea, vp, cp );
170  }
171 }
172 
174 {
175  std::map<wxString, wxString> properties = aReader.ReadProperties();
176  if( properties.empty() )
177  {
178  THROW_IO_ERROR( "Board6 stream has no properties!" );
179  }
180 
181  /*for (auto & property : properties) {
182  std::cout << " * '" << property.first << "' = '" << property.second << "'" << std::endl;
183  }*/
184 
185  sheetpos = wxPoint( ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "SHEETX", "0mil" ),
186  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "SHEETY", "0mil" ) );
187  sheetsize = wxSize( ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "SHEETWIDTH", "0mil" ),
188  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "SHEETHEIGHT", "0mil" ) );
189 
190  layercount = ALTIUM_PARSER::PropertiesReadInt( properties, "LAYERSETSCOUNT", 1 ) + 1;
191 
192  for( size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
193  {
194  const wxString layeri = "LAYER" + std::to_string( i );
195  const wxString layername = layeri + "NAME";
196 
197  auto layernameit = properties.find( layername );
198  if( layernameit == properties.end() )
199  {
200  break; // it doesn't seem like we know beforehand how many vertices are inside a polygon
201  }
202 
203  ABOARD6_LAYER_STACKUP curlayer;
204 
205  curlayer.name = ALTIUM_PARSER::PropertiesReadString( properties, layername, "" );
206  curlayer.nextId = ALTIUM_PARSER::PropertiesReadInt( properties, layeri + "NEXT", 0 );
207  curlayer.prevId = ALTIUM_PARSER::PropertiesReadInt( properties, layeri + "PREV", 0 );
208  curlayer.copperthick =
209  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, layeri + "COPTHICK", "1.4mil" );
210 
211  curlayer.dielectricconst =
212  ALTIUM_PARSER::PropertiesReadDouble( properties, layeri + "DIELCONST", 0. );
214  properties, layeri + "DIELHEIGHT", "60mil" );
215  curlayer.dielectricmaterial =
216  ALTIUM_PARSER::PropertiesReadString( properties, layeri + "DIELMATERIAL", "FR-4" );
217 
218  stackup.push_back( curlayer );
219  }
220 
221  altium_parse_polygons( properties, board_vertices );
222 
223  if( aReader.HasParsingError() )
224  {
225  THROW_IO_ERROR( "Board6 stream was not parsed correctly!" );
226  }
227 }
228 
230 {
231  std::map<wxString, wxString> properties = aReader.ReadProperties();
232  if( properties.empty() )
233  {
234  THROW_IO_ERROR( "Classes6 stream has no properties!" );
235  }
236 
237  name = ALTIUM_PARSER::PropertiesReadString( properties, "NAME", "" );
238  uniqueid = ALTIUM_PARSER::PropertiesReadString( properties, "UNIQUEID", "" );
239  kind = static_cast<ALTIUM_CLASS_KIND>(
240  ALTIUM_PARSER::PropertiesReadInt( properties, "KIND", -1 ) );
241 
242  for( size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
243  {
244  auto mit = properties.find( "M" + std::to_string( i ) );
245  if( mit == properties.end() )
246  {
247  break; // it doesn't seem like we know beforehand how many components are in the netclass
248  }
249  names.push_back( mit->second );
250  }
251 
252  if( aReader.HasParsingError() )
253  {
254  THROW_IO_ERROR( "Classes6 stream was not parsed correctly" );
255  }
256 }
257 
259 {
260  std::map<wxString, wxString> properties = aReader.ReadProperties();
261  if( properties.empty() )
262  {
263  THROW_IO_ERROR( "Components6 stream has no properties" );
264  }
265 
267  ALTIUM_PARSER::PropertiesReadString( properties, "LAYER", "" ) );
268  position = wxPoint( ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "X", "0mil" ),
269  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "Y", "0mil" ) );
270  rotation = ALTIUM_PARSER::PropertiesReadDouble( properties, "ROTATION", 0. );
271  locked = ALTIUM_PARSER::PropertiesReadBool( properties, "LOCKED", false );
272  nameon = ALTIUM_PARSER::PropertiesReadBool( properties, "NAMEON", true );
273  commenton = ALTIUM_PARSER::PropertiesReadBool( properties, "COMMENTON", false );
274  sourcedesignator = ALTIUM_PARSER::PropertiesReadString( properties, "SOURCEDESIGNATOR", "" );
276  ALTIUM_PARSER::PropertiesReadString( properties, "SOURCEFOOTPRINTLIBRARY", "" );
278  ALTIUM_PARSER::PropertiesReadString( properties, "SOURCECOMPONENTLIBRARY", "" );
280  ALTIUM_PARSER::PropertiesReadString( properties, "SOURCELIBREFERENCE", "" );
281 
282  nameautoposition = static_cast<ALTIUM_TEXT_POSITION>(
283  ALTIUM_PARSER::PropertiesReadInt( properties, "NAMEAUTOPOSITION", 0 ) );
284  commentautoposition = static_cast<ALTIUM_TEXT_POSITION>(
285  ALTIUM_PARSER::PropertiesReadInt( properties, "COMMENTAUTOPOSITION", 0 ) );
286 
287  if( aReader.HasParsingError() )
288  {
289  THROW_IO_ERROR( "Components6 stream was not parsed correctly" );
290  }
291 }
292 
294 {
295  aReader.Skip( 2 );
296 
297  std::map<wxString, wxString> properties = aReader.ReadProperties();
298  if( properties.empty() )
299  {
300  THROW_IO_ERROR( "Dimensions6 stream has no properties" );
301  }
302 
304  ALTIUM_PARSER::PropertiesReadString( properties, "LAYER", "" ) );
305  kind = static_cast<ALTIUM_DIMENSION_KIND>(
306  ALTIUM_PARSER::PropertiesReadInt( properties, "DIMENSIONKIND", 0 ) );
307 
308  textformat = ALTIUM_PARSER::PropertiesReadString( properties, "TEXTFORMAT", "" );
309 
310  height = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "HEIGHT", "0mil" );
311  angle = ALTIUM_PARSER::PropertiesReadDouble( properties, "ANGLE", 0. );
312 
313  linewidth = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "LINEWIDTH", "10mil" );
314  textheight = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "TEXTHEIGHT", "10mil" );
315  textlinewidth = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "TEXTLINEWIDTH", "6mil" );
316  textprecission = ALTIUM_PARSER::PropertiesReadInt( properties, "TEXTPRECISION", 2 );
317  textbold = ALTIUM_PARSER::PropertiesReadBool( properties, "TEXTLINEWIDTH", false );
318  textitalic = ALTIUM_PARSER::PropertiesReadBool( properties, "ITALIC", false );
319 
320  arrowsize = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "ARROWSIZE", "60mil" );
321 
322  xy1 = wxPoint( ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "X1", "0mil" ),
323  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "Y1", "0mil" ) );
324 
325  int refcount = ALTIUM_PARSER::PropertiesReadInt( properties, "REFERENCES_COUNT", 0 );
326  for( int i = 0; i < refcount; i++ )
327  {
328  const std::string refi = "REFERENCE" + std::to_string( i );
329  referencePoint.emplace_back(
330  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, refi + "POINTX", "0mil" ),
331  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, refi + "POINTY", "0mil" ) );
332  }
333 
334  for( size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
335  {
336  const std::string texti = "TEXT" + std::to_string( i );
337  const std::string textix = texti + "X";
338  const std::string textiy = texti + "Y";
339 
340  if( properties.find( textix ) == properties.end()
341  || properties.find( textiy ) == properties.end() )
342  {
343  break; // it doesn't seem like we know beforehand how many vertices are inside a polygon
344  }
345 
346  textPoint.emplace_back(
347  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, textix, "0mil" ),
348  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, textiy, "0mil" ) );
349  }
350 
351  wxString dimensionunit =
352  ALTIUM_PARSER::PropertiesReadString( properties, "TEXTDIMENSIONUNIT", "Millimeters" );
353  if( dimensionunit == "Inches" )
354  {
356  }
357  else if( dimensionunit == "Mils" )
358  {
360  }
361  else if( dimensionunit == "Millimeters" )
362  {
364  }
365  else if( dimensionunit == "Centimeters" )
366  {
368  }
369  else
370  {
372  }
373 
374  if( aReader.HasParsingError() )
375  {
376  THROW_IO_ERROR( "Dimensions6 stream was not parsed correctly" );
377  }
378 }
379 
381 {
382  std::map<wxString, wxString> properties = aReader.ReadProperties();
383  if( properties.empty() )
384  {
385  THROW_IO_ERROR( "Classes6 stream has no properties!" );
386  }
387 
388  name = ALTIUM_PARSER::PropertiesReadString( properties, "NAME", "" );
389  id = ALTIUM_PARSER::PropertiesReadString( properties, "ID", "" );
390  isEmbedded = ALTIUM_PARSER::PropertiesReadBool( properties, "EMBED", false );
391 
392  rotation.x = ALTIUM_PARSER::PropertiesReadDouble( properties, "ROTX", 0. );
393  rotation.y = ALTIUM_PARSER::PropertiesReadDouble( properties, "ROTY", 0. );
394  rotation.z = ALTIUM_PARSER::PropertiesReadDouble( properties, "ROTZ", 0. );
395 
396  if( aReader.HasParsingError() )
397  {
398  THROW_IO_ERROR( "Classes6 stream was not parsed correctly" );
399  }
400 }
401 
403 {
404  std::map<wxString, wxString> properties = aReader.ReadProperties();
405  if( properties.empty() )
406  {
407  THROW_IO_ERROR( "Nets6 stream has no properties" );
408  }
409 
410  name = ALTIUM_PARSER::PropertiesReadString( properties, "NAME", "" );
411 
412  if( aReader.HasParsingError() )
413  {
414  THROW_IO_ERROR( "Nets6 stream was not parsed correctly" );
415  }
416 }
417 
419 {
420  std::map<wxString, wxString> properties = aReader.ReadProperties();
421  if( properties.empty() )
422  {
423  THROW_IO_ERROR( "Polygons6 stream has no properties" );
424  }
425 
427  ALTIUM_PARSER::PropertiesReadString( properties, "LAYER", "" ) );
429  locked = ALTIUM_PARSER::PropertiesReadBool( properties, "LOCKED", false );
430 
431  // TODO: kind
432 
433  gridsize = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "GRIDSIZE", "0mil" );
434  trackwidth = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "TRACKWIDTH", "0mil" );
435  minprimlength = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MINPRIMLENGTH", "0mil" );
436  useoctagons = ALTIUM_PARSER::PropertiesReadBool( properties, "USEOCTAGONS", false );
437 
438  pourindex = ALTIUM_PARSER::PropertiesReadInt( properties, "POURINDEX", 0 );
439 
440  wxString hatchstyleraw = ALTIUM_PARSER::PropertiesReadString( properties, "HATCHSTYLE", "" );
441 
442  if( hatchstyleraw == "Solid" )
443  {
445  }
446  else if( hatchstyleraw == "45Degree" )
447  {
449  }
450  else if( hatchstyleraw == "90Degree" )
451  {
453  }
454  else if( hatchstyleraw == "Horizontal" )
455  {
457  }
458  else if( hatchstyleraw == "Vertical" )
459  {
461  }
462  else if( hatchstyleraw == "None" )
463  {
465  }
466  else
467  {
469  }
470 
471  altium_parse_polygons( properties, vertices );
472 
473  if( aReader.HasParsingError() )
474  {
475  THROW_IO_ERROR( "Polygons6 stream was not parsed correctly" );
476  }
477 }
478 
480 {
481  // Initalize all variables and make Coverity happy
482  clearanceGap = 0;
488 
489  aReader.Skip( 2 );
490 
491  std::map<wxString, wxString> properties = aReader.ReadProperties();
492  if( properties.empty() )
493  {
494  THROW_IO_ERROR( "Rules6 stream has no properties" );
495  }
496 
497  name = ALTIUM_PARSER::PropertiesReadString( properties, "NAME", "" );
498  priority = ALTIUM_PARSER::PropertiesReadInt( properties, "PRIORITY", 1 );
499 
500  scope1expr = ALTIUM_PARSER::PropertiesReadString( properties, "SCOPE1EXPRESSION", "" );
501  scope2expr = ALTIUM_PARSER::PropertiesReadString( properties, "SCOPE2EXPRESSION", "" );
502 
503  wxString rulekind = ALTIUM_PARSER::PropertiesReadString( properties, "RULEKIND", "" );
504  if( rulekind == "Clearance" )
505  {
507  clearanceGap = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "GAP", "10mil" );
508  }
509  else if( rulekind == "DiffPairsRouting" )
510  {
512  }
513  else if( rulekind == "Height" )
514  {
516  }
517  else if( rulekind == "HoleSize" )
518  {
520  }
521  else if( rulekind == "HoleToHoleClearance" )
522  {
524  }
525  else if( rulekind == "Width" )
526  {
528  }
529  else if( rulekind == "PasteMaskExpansion" )
530  {
532  }
533  else if( rulekind == "PlaneClearance" )
534  {
537  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "CLEARANCE", "10mil" );
538  }
539  else if( rulekind == "PolygonConnect" )
540  {
543  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "AIRGAPWIDTH", "10mil" );
545  properties, "RELIEFCONDUCTORWIDTH", "10mil" );
547  ALTIUM_PARSER::PropertiesReadInt( properties, "RELIEFENTRIES", 4 );
548 
549  wxString style = ALTIUM_PARSER::PropertiesReadString( properties, "CONNECTSTYLE", "" );
550 
551  if( style == "Direct" )
553  else if( style == "Relief" )
555  else if( style == "NoConnect" )
557  else
559  }
560  else
561  {
563  }
564 
565  if( aReader.HasParsingError() )
566  {
567  THROW_IO_ERROR( "Rules6 stream was not parsed correctly" );
568  }
569 }
570 
572 {
573  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
574  if( recordtype != ALTIUM_RECORD::ARC )
575  {
576  THROW_IO_ERROR( "Arcs6 stream has invalid recordtype" );
577  }
578 
579  // Subrecord 1
580  aReader.ReadAndSetSubrecordLength();
581 
582  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
583 
584  uint8_t flags1 = aReader.Read<uint8_t>();
585  is_locked = ( flags1 & 0x04 ) == 0;
586  is_polygonoutline = ( flags1 & 0x02 ) != 0;
587 
588  uint8_t flags2 = aReader.Read<uint8_t>();
589  is_keepout = flags2 == 2;
590 
591  net = aReader.Read<uint16_t>();
592  subpolyindex = aReader.Read<uint16_t>();
593  component = aReader.Read<uint16_t>();
594  aReader.Skip( 4 );
595  center = aReader.ReadWxPoint();
596  radius = aReader.ReadKicadUnit();
597  startangle = aReader.Read<double>();
598  endangle = aReader.Read<double>();
599  width = aReader.ReadKicadUnit();
600 
601  aReader.SkipSubrecord();
602 
603  if( aReader.HasParsingError() )
604  {
605  THROW_IO_ERROR( "Arcs6 stream was not parsed correctly" );
606  }
607 }
608 
610 {
611  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
612  if( recordtype != ALTIUM_RECORD::MODEL )
613  {
614  THROW_IO_ERROR( "ComponentsBodies6 stream has invalid recordtype" );
615  }
616 
617  aReader.ReadAndSetSubrecordLength();
618 
619  aReader.Skip( 7 );
620  component = aReader.Read<uint16_t>();
621  aReader.Skip( 9 );
622 
623  std::map<wxString, wxString> properties = aReader.ReadProperties();
624  if( properties.empty() )
625  {
626  THROW_IO_ERROR( "ComponentsBodies6 stream has no properties" );
627  }
628 
629  modelName = ALTIUM_PARSER::PropertiesReadString( properties, "MODEL.NAME", "" );
630  modelId = ALTIUM_PARSER::PropertiesReadString( properties, "MODELID", "" );
631  modelIsEmbedded = ALTIUM_PARSER::PropertiesReadBool( properties, "MODEL.EMBED", false );
632 
633  modelPosition.x = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MODEL.2D.X", "0mil" );
634  modelPosition.y = -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MODEL.2D.Y", "0mil" );
635  modelPosition.z = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MODEL.3D.DZ", "0mil" );
636 
637  modelRotation.x = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.3D.ROTX", 0. );
638  modelRotation.y = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.3D.ROTY", 0. );
639  modelRotation.z = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.3D.ROTZ", 0. );
640 
641  rotation = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.2D.ROTATION", 0. );
642 
643  bodyOpacity = ALTIUM_PARSER::PropertiesReadDouble( properties, "BODYOPACITY3D", 1. );
644 
645  aReader.SkipSubrecord();
646 
647  if( aReader.HasParsingError() )
648  {
649  THROW_IO_ERROR( "Components6 stream was not parsed correctly" );
650  }
651 }
652 
654 {
655  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
656 
657  if( recordtype != ALTIUM_RECORD::PAD )
658  THROW_IO_ERROR( "Pads6 stream has invalid recordtype" );
659 
660  // Subrecord 1
661  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
662 
663  if( subrecord1 == 0 )
664  THROW_IO_ERROR( "Pads6 stream has no subrecord1 data" );
665 
666  name = aReader.ReadWxString();
667 
668  if( aReader.GetRemainingSubrecordBytes() != 0 )
669  THROW_IO_ERROR( "Pads6 stream has invalid subrecord1 length" );
670 
671  aReader.SkipSubrecord();
672 
673  // Subrecord 2
674  aReader.ReadAndSetSubrecordLength();
675  aReader.SkipSubrecord();
676 
677  // Subrecord 3
678  aReader.ReadAndSetSubrecordLength();
679  aReader.SkipSubrecord();
680 
681  // Subrecord 4
682  aReader.ReadAndSetSubrecordLength();
683  aReader.SkipSubrecord();
684 
685  // Subrecord 5
686  size_t subrecord5 = aReader.ReadAndSetSubrecordLength();
687 
688  if( subrecord5 < 114 )
689  THROW_IO_ERROR( "Pads6 stream subrecord has length < 114, which is unexpected" );
690 
691  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
694 
695  uint8_t flags1 = aReader.Read<uint8_t>();
696  is_test_fab_top = ( flags1 & 0x80 ) != 0;
697  is_tent_bottom = ( flags1 & 0x40 ) != 0;
698  is_tent_top = ( flags1 & 0x20 ) != 0;
699  is_locked = ( flags1 & 0x04 ) == 0;
700 
701  uint8_t flags2 = aReader.Read<uint8_t>();
702  is_test_fab_bottom = ( flags2 & 0x01 ) != 0;
703 
704  net = aReader.Read<uint16_t>();
705  aReader.Skip( 2 );
706  component = aReader.Read<uint16_t>();
707  aReader.Skip( 4 );
708 
709  position = aReader.ReadWxPoint();
710  topsize = aReader.ReadWxSize();
711  midsize = aReader.ReadWxSize();
712  botsize = aReader.ReadWxSize();
713  holesize = aReader.ReadKicadUnit();
714 
715  topshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
716  midshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
717  botshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
718 
719  direction = aReader.Read<double>();
720  plated = aReader.Read<uint8_t>() != 0;
721  aReader.Skip( 1 );
722  padmode = static_cast<ALTIUM_PAD_MODE>( aReader.Read<uint8_t>() );
723  aReader.Skip( 23 );
726  aReader.Skip( 7 );
727  pastemaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() );
728  soldermaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() );
729  aReader.Skip( 3 );
730  holerotation = aReader.Read<double>();
731 
732  if( subrecord5 >= 120 )
733  {
734  tolayer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
735  aReader.Skip( 2 );
736  fromlayer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
737  //aReader.skip( 2 );
738  }
739  else if( subrecord5 == 171 )
740  {
741  }
742 
743  aReader.SkipSubrecord();
744 
745  // Subrecord 6
746  size_t subrecord6 = aReader.ReadAndSetSubrecordLength();
747  // Known lengths: 596, 628, 651
748  // 596 is the number of bytes read in this code-block
749  if( subrecord6 >= 596 )
750  { // TODO: detect type from something else than the size?
751  sizeAndShape = std::make_unique<APAD6_SIZE_AND_SHAPE>();
752 
753  for( wxSize& size : sizeAndShape->inner_size )
754  size.x = aReader.ReadKicadUnitX();
755 
756  for( wxSize& size : sizeAndShape->inner_size )
757  size.y = aReader.ReadKicadUnitY();
758 
759  for( ALTIUM_PAD_SHAPE& shape : sizeAndShape->inner_shape )
760  shape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
761 
762  aReader.Skip( 1 );
763 
764  sizeAndShape->holeshape = static_cast<ALTIUM_PAD_HOLE_SHAPE>( aReader.Read<uint8_t>() );
765  sizeAndShape->slotsize = aReader.ReadKicadUnit();
766  sizeAndShape->slotrotation = aReader.Read<double>();
767 
768  for( wxPoint& pt : sizeAndShape->holeoffset )
769  pt.x = aReader.ReadKicadUnitX();
770 
771  for( wxPoint& pt : sizeAndShape->holeoffset )
772  pt.y = aReader.ReadKicadUnitY();
773 
774  aReader.Skip( 1 );
775 
776  for( ALTIUM_PAD_SHAPE_ALT& shape : sizeAndShape->alt_shape )
777  shape = static_cast<ALTIUM_PAD_SHAPE_ALT>( aReader.Read<uint8_t>() );
778 
779  for( uint8_t& radius : sizeAndShape->cornerradius )
780  radius = aReader.Read<uint8_t>();
781  }
782  else if( subrecord6 != 0 )
783  {
784  wxLogError( wxString::Format(
785  "Pads6 stream has unexpected length for subrecord 6: %d", subrecord6 ) );
786  }
787 
788  aReader.SkipSubrecord();
789 
790  if( aReader.HasParsingError() )
791  THROW_IO_ERROR( "Pads6 stream was not parsed correctly" );
792 }
793 
795 {
796  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
797  if( recordtype != ALTIUM_RECORD::VIA )
798  {
799  THROW_IO_ERROR( "Vias6 stream has invalid recordtype" );
800  }
801 
802  // Subrecord 1
803  aReader.ReadAndSetSubrecordLength();
804 
805  aReader.Skip( 1 );
806 
807  uint8_t flags1 = aReader.Read<uint8_t>();
808  is_test_fab_top = ( flags1 & 0x80 ) != 0;
809  is_tent_bottom = ( flags1 & 0x40 ) != 0;
810  is_tent_top = ( flags1 & 0x20 ) != 0;
811  is_locked = ( flags1 & 0x04 ) == 0;
812 
813  uint8_t flags2 = aReader.Read<uint8_t>();
814  is_test_fab_bottom = ( flags2 & 0x01 ) != 0;
815 
816  net = aReader.Read<uint16_t>();
817  aReader.Skip( 8 );
818  position = aReader.ReadWxPoint();
819  diameter = aReader.ReadKicadUnit();
820  holesize = aReader.ReadKicadUnit();
821 
822  layer_start = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
823  layer_end = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
824  aReader.Skip( 43 );
825  viamode = static_cast<ALTIUM_PAD_MODE>( aReader.Read<uint8_t>() );
826 
827  aReader.SkipSubrecord();
828 
829  if( aReader.HasParsingError() )
830  {
831  THROW_IO_ERROR( "Vias6 stream was not parsed correctly" );
832  }
833 }
834 
836 {
837  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
838  if( recordtype != ALTIUM_RECORD::TRACK )
839  {
840  THROW_IO_ERROR( "Tracks6 stream has invalid recordtype" );
841  }
842 
843  // Subrecord 1
844  aReader.ReadAndSetSubrecordLength();
845 
846  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
847 
848  uint8_t flags1 = aReader.Read<uint8_t>();
849  is_locked = ( flags1 & 0x04 ) == 0;
850  is_polygonoutline = ( flags1 & 0x02 ) != 0;
851 
852  uint8_t flags2 = aReader.Read<uint8_t>();
853  is_keepout = flags2 == 2;
854 
855  net = aReader.Read<uint16_t>();
856  subpolyindex = aReader.Read<uint16_t>();
857  component = aReader.Read<uint16_t>();
858  aReader.Skip( 4 );
859  start = aReader.ReadWxPoint();
860  end = aReader.ReadWxPoint();
861  width = aReader.ReadKicadUnit();
862 
863  aReader.SkipSubrecord();
864 
865  if( aReader.HasParsingError() )
866  {
867  THROW_IO_ERROR( "Tracks6 stream was not parsed correctly" );
868  }
869 }
870 
872 {
873  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
874  if( recordtype != ALTIUM_RECORD::TEXT )
875  {
876  THROW_IO_ERROR( "Texts6 stream has invalid recordtype" );
877  }
878 
879  // Subrecord 1 - Properties
880  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
881 
882  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
883  aReader.Skip( 6 );
884  component = aReader.Read<uint16_t>();
885  aReader.Skip( 4 );
886  position = aReader.ReadWxPoint();
887  height = aReader.ReadKicadUnit();
888  aReader.Skip( 2 );
889  rotation = aReader.Read<double>();
890  isMirrored = aReader.Read<uint8_t>() != 0;
891  strokewidth = aReader.ReadKicadUnit();
892  isComment = aReader.Read<uint8_t>() != 0;
893  isDesignator = aReader.Read<uint8_t>() != 0;
894  aReader.Skip( 2 );
895  isBold = aReader.Read<uint8_t>() != 0;
896  isItalic = aReader.Read<uint8_t>() != 0;
897  aReader.Skip( 64 ); // font_name
898  isInverted = aReader.Read<uint8_t>() != 0;
899  aReader.Skip( 21 );
900  textposition = static_cast<ALTIUM_TEXT_POSITION>( aReader.Read<uint8_t>() );
905  if( subrecord1 <= 230 )
906  {
908  }
909  aReader.Skip( 27 );
910  fonttype = static_cast<ALTIUM_TEXT_TYPE>( aReader.Read<uint8_t>() );
911 
912  aReader.SkipSubrecord();
913 
914  // Subrecord 2 - String
915  aReader.ReadAndSetSubrecordLength();
916 
917  text = aReader.ReadWxString(); // TODO: what about strings with length > 255?
918 
919  // Normalize Windows line endings
920  text.Replace( "\r\n", "\n" );
921 
922  aReader.SkipSubrecord();
923 
924  if( aReader.HasParsingError() )
925  {
926  THROW_IO_ERROR( "Texts6 stream was not parsed correctly" );
927  }
928 }
929 
931 {
932  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
933  if( recordtype != ALTIUM_RECORD::FILL )
934  {
935  THROW_IO_ERROR( "Fills6 stream has invalid recordtype" );
936  }
937 
938  // Subrecord 1
939  aReader.ReadAndSetSubrecordLength();
940 
941  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
942 
943  uint8_t flags1 = aReader.Read<uint8_t>();
944  is_locked = ( flags1 & 0x04 ) == 0;
945 
946  uint8_t flags2 = aReader.Read<uint8_t>();
947  is_keepout = flags2 == 2;
948 
949  net = aReader.Read<uint16_t>();
950  aReader.Skip( 2 );
951  component = aReader.Read<uint16_t>();
952  aReader.Skip( 4 );
953  pos1 = aReader.ReadWxPoint();
954  pos2 = aReader.ReadWxPoint();
955  rotation = aReader.Read<double>();
956 
957  aReader.SkipSubrecord();
958 
959  if( aReader.HasParsingError() )
960  {
961  THROW_IO_ERROR( "Fills6 stream was not parsed correctly" );
962  }
963 }
964 
965 AREGION6::AREGION6( ALTIUM_PARSER& aReader, bool aExtendedVertices )
966 {
967  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
968  if( recordtype != ALTIUM_RECORD::REGION )
969  {
970  THROW_IO_ERROR( "Regions6 stream has invalid recordtype" );
971  }
972 
973  // Subrecord 1
974  aReader.ReadAndSetSubrecordLength();
975 
976  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
977 
978  uint8_t flags1 = aReader.Read<uint8_t>();
979  is_locked = ( flags1 & 0x04 ) == 0;
980 
981  uint8_t flags2 = aReader.Read<uint8_t>();
982  is_keepout = flags2 == 2;
983 
984  net = aReader.Read<uint16_t>();
985  aReader.Skip( 2 );
986  component = aReader.Read<uint16_t>();
987  aReader.Skip( 9 );
988 
989  std::map<wxString, wxString> properties = aReader.ReadProperties();
990  if( properties.empty() )
991  {
992  THROW_IO_ERROR( "Regions6 stream has empty properties" );
993  }
994 
995  int pkind = ALTIUM_PARSER::PropertiesReadInt( properties, "KIND", 0 );
996  bool is_cutout = ALTIUM_PARSER::PropertiesReadBool( properties, "ISBOARDCUTOUT", false );
997 
998  is_shapebased = ALTIUM_PARSER::PropertiesReadBool( properties, "ISSHAPEBASED", false );
999 
1000  subpolyindex = static_cast<uint16_t>(
1001  ALTIUM_PARSER::PropertiesReadInt( properties, "SUBPOLYINDEX", ALTIUM_POLYGON_NONE ) );
1002 
1003  switch( pkind )
1004  {
1005  case 0:
1006  if( is_cutout )
1007  {
1009  }
1010  else
1011  {
1013  }
1014  break;
1015  case 1:
1017  break;
1018  case 4:
1020  break;
1021  default:
1023  break;
1024  }
1025 
1026  uint32_t num_vertices = aReader.Read<uint32_t>();
1027 
1028  for( uint32_t i = 0; i < num_vertices; i++ )
1029  {
1030  if( aExtendedVertices )
1031  {
1032  bool isRound = aReader.Read<uint8_t>() != 0;
1033  wxPoint position = aReader.ReadWxPoint();
1034  wxPoint center = aReader.ReadWxPoint();
1035  int32_t radius = aReader.ReadKicadUnit();
1036  double angle1 = aReader.Read<double>();
1037  double angle2 = aReader.Read<double>();
1038  vertices.emplace_back( isRound, radius, angle1, angle2, position, center );
1039  }
1040  else
1041  {
1042  // For some regions the coordinates are stored as double and not as int32_t
1043  int32_t x = ALTIUM_PARSER::ConvertToKicadUnit( aReader.Read<double>() );
1044  int32_t y = ALTIUM_PARSER::ConvertToKicadUnit( -aReader.Read<double>() );
1045  vertices.emplace_back( wxPoint( x, y ) );
1046  }
1047  }
1048 
1049  aReader.SkipSubrecord();
1050 
1051  if( aReader.HasParsingError() )
1052  {
1053  THROW_IO_ERROR( "Regions6 stream was not parsed correctly" );
1054  }
1055 }
AREGION6(ALTIUM_PARSER &aReader, bool aExtendedVertices)
ADIMENSION6(ALTIUM_PARSER &aReader)
uint32_t textlinewidth
uint32_t linewidth
ALTIUM_LAYER tolayer
int32_t soldermaskexpansionmanual
ALTIUM_RULE_KIND kind
double rotation
uint32_t holesize
uint32_t width
std::vector< ALTIUM_VERTICE > vertices
static int PropertiesReadInt(const std::map< wxString, wxString > &aProperties, const wxString &aKey, int aDefault)
int planeclearanceClearance
wxString name
bool isDesignator
bool is_locked
ALTIUM_TEXT_POSITION nameautoposition
ALTIUM_PAD_SHAPE topshape
wxPoint pos1
ALTIUM_LAYER layer
AMODEL(ALTIUM_PARSER &aReader)
wxPoint start
wxSize topsize
ALTIUM_LAYER layer
ALTIUM_DIMENSION_KIND kind
int32_t textprecission
ARULE6(ALTIUM_PARSER &aReader)
ALTIUM_REGION_KIND kind
wxPoint position
double startangle
uint16_t component
bool is_test_fab_bottom
static bool PropertiesReadBool(const std::map< wxString, wxString > &aProperties, const wxString &aKey, bool aDefault)
int32_t polygonconnectAirgapwidth
static int32_t PropertiesReadKicadUnit(const std::map< wxString, wxString > &aProperties, const wxString &aKey, const wxString &aDefault)
wxPoint center
ALTIUM_LAYER layer
static int32_t ConvertToKicadUnit(const double aValue)
wxString sourcedesignator
const uint16_t ALTIUM_POLYGON_NONE
ALTIUM_LAYER layer
ALTIUM_RECORD
ALTIUM_LAYER layer_end
ALTIUM_PAD_SHAPE
ALTIUM_PAD_RULE soldermaskexpansionmode
ALTIUM_LAYER layer
MODULE_3D_SETTINGS::VECTOR3D modelRotation
uint16_t net
wxString sourcefootprintlibrary
AVIA6(ALTIUM_PARSER &aReader)
wxString name
MODULE_3D_SETTINGS::VECTOR3D modelPosition
wxString sourcelibreference
wxString text
wxSize sheetsize
wxString scope2expr
bool is_tent_bottom
bool is_polygonoutline
ATEXT6(ALTIUM_PARSER &aReader)
uint32_t height
ALTIUM_PAD_SHAPE_ALT
void Skip(size_t aLength)
ALTIUM_CONNECT_STYLE polygonconnectStyle
MODULE_3D_SETTINGS::VECTOR3D rotation
std::vector< wxString > names
int32_t trackwidth
std::vector< wxPoint > textPoint
size_t GetRemainingSubrecordBytes() const
wxString textformat
wxString sourcecomponentlibrary
uint16_t subpolyindex
wxSize ReadWxSize()
uint16_t net
APAD6(ALTIUM_PARSER &aReader)
size_t ReadAndSetSubrecordLength()
wxSize botsize
std::map< wxString, wxString > ReadProperties()
ALTIUM_PAD_RULE pastemaskexpansionmode
wxPoint position
uint16_t subpolyindex
double direction
double endangle
wxPoint ReadWxPoint()
ALTIUM_CLASS_KIND kind
ALTIUM_LAYER layer
const uint16_t ALTIUM_NET_UNCONNECTED
wxSize midsize
wxString name
uint16_t component
uint32_t holesize
static double PropertiesReadDouble(const std::map< wxString, wxString > &aProperties, const wxString &aKey, double aDefault)
bool is_test_fab_top
ACOMPONENTBODY6(ALTIUM_PARSER &aReader)
wxPoint sheetpos
ABOARD6(ALTIUM_PARSER &aReader)
uint16_t net
bool is_test_fab_bottom
int32_t ReadKicadUnit()
Definition: altium_parser.h:86
bool is_keepout
bool is_locked
double rotation
bool is_polygonoutline
AFILL6(ALTIUM_PARSER &aReader)
bool is_tent_bottom
uint16_t subpolyindex
ACLASS6(ALTIUM_PARSER &aReader)
wxString uniqueid
ALTIUM_PAD_SHAPE botshape
std::vector< ALTIUM_VERTICE > vertices
ANET6(ALTIUM_PARSER &aReader)
uint32_t width
ALTIUM_TEXT_POSITION textposition
ALTIUM_LAYER layer
uint16_t net
ALTIUM_LAYER layer_start
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:201
bool is_test_fab_top
bool is_tent_top
ATRACK6(ALTIUM_PARSER &aReader)
uint32_t radius
wxPoint position
wxString ReadWxString()
Definition: altium_parser.h:68
ALTIUM_PAD_MODE viamode
int32_t pastemaskexpansionmanual
wxString name
APOLYGON6(ALTIUM_PARSER &aReader)
uint16_t net
uint16_t component
ALTIUM_LAYER
ALTIUM_PAD_MODE padmode
ALTIUM_LAYER layer
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
uint16_t component
std::vector< ALTIUM_VERTICE > board_vertices
ALTIUM_UNIT textunit
int32_t ReadKicadUnitX()
Definition: altium_parser.h:91
ALTIUM_LAYER layer
ALTIUM_TEXT_POSITION commentautoposition
uint16_t component
void SkipSubrecord()
ALTIUM_PAD_SHAPE midshape
std::vector< wxPoint > referencePoint
std::vector< ABOARD6_LAYER_STACKUP > stackup
uint32_t strokewidth
bool is_tent_top
int32_t ReadKicadUnitY()
Definition: altium_parser.h:96
ALTIUM_LAYER altium_layer_from_name(const wxString &aName)
int32_t minprimlength
int32_t gridsize
ACOMPONENT6(ALTIUM_PARSER &aReader)
static wxString PropertiesReadString(const std::map< wxString, wxString > &aProperties, const wxString &aKey, const wxString &aDefault)
uint32_t textheight
ALTIUM_POLYGON_HATCHSTYLE hatchstyle
uint16_t component
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
bool HasParsingError()
ALTIUM_TEXT_TYPE fonttype
wxPoint pos2
uint32_t diameter
AARC6(ALTIUM_PARSER &aReader)
double holerotation
bool is_locked
ALTIUM_LAYER fromlayer
wxString name
void altium_parse_polygons(std::map< wxString, wxString > &aProperties, std::vector< ALTIUM_VERTICE > &aVertices)
uint16_t net
wxString scope1expr
int32_t polygonconnectReliefconductorwidth
int32_t pourindex
int polygonconnectReliefentries