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", "" );
277  pattern = ALTIUM_PARSER::PropertiesReadString( properties, "PATTERN", "" );
278 
280  ALTIUM_PARSER::PropertiesReadString( properties, "SOURCECOMPONENTLIBRARY", "" );
282  ALTIUM_PARSER::PropertiesReadString( properties, "SOURCELIBREFERENCE", "" );
283 
284  nameautoposition = static_cast<ALTIUM_TEXT_POSITION>(
285  ALTIUM_PARSER::PropertiesReadInt( properties, "NAMEAUTOPOSITION", 0 ) );
286  commentautoposition = static_cast<ALTIUM_TEXT_POSITION>(
287  ALTIUM_PARSER::PropertiesReadInt( properties, "COMMENTAUTOPOSITION", 0 ) );
288 
289  if( aReader.HasParsingError() )
290  {
291  THROW_IO_ERROR( "Components6 stream was not parsed correctly" );
292  }
293 }
294 
296 {
297  aReader.Skip( 2 );
298 
299  std::map<wxString, wxString> properties = aReader.ReadProperties();
300  if( properties.empty() )
301  {
302  THROW_IO_ERROR( "Dimensions6 stream has no properties" );
303  }
304 
306  ALTIUM_PARSER::PropertiesReadString( properties, "LAYER", "" ) );
307  kind = static_cast<ALTIUM_DIMENSION_KIND>(
308  ALTIUM_PARSER::PropertiesReadInt( properties, "DIMENSIONKIND", 0 ) );
309 
310  textformat = ALTIUM_PARSER::PropertiesReadString( properties, "TEXTFORMAT", "" );
311 
312  height = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "HEIGHT", "0mil" );
313  angle = ALTIUM_PARSER::PropertiesReadDouble( properties, "ANGLE", 0. );
314 
315  linewidth = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "LINEWIDTH", "10mil" );
316  textheight = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "TEXTHEIGHT", "10mil" );
317  textlinewidth = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "TEXTLINEWIDTH", "6mil" );
318  textprecission = ALTIUM_PARSER::PropertiesReadInt( properties, "TEXTPRECISION", 2 );
319  textbold = ALTIUM_PARSER::PropertiesReadBool( properties, "TEXTLINEWIDTH", false );
320  textitalic = ALTIUM_PARSER::PropertiesReadBool( properties, "ITALIC", false );
321 
322  arrowsize = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "ARROWSIZE", "60mil" );
323 
324  xy1 = wxPoint( ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "X1", "0mil" ),
325  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "Y1", "0mil" ) );
326 
327  int refcount = ALTIUM_PARSER::PropertiesReadInt( properties, "REFERENCES_COUNT", 0 );
328  for( int i = 0; i < refcount; i++ )
329  {
330  const std::string refi = "REFERENCE" + std::to_string( i );
331  referencePoint.emplace_back(
332  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, refi + "POINTX", "0mil" ),
333  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, refi + "POINTY", "0mil" ) );
334  }
335 
336  for( size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
337  {
338  const std::string texti = "TEXT" + std::to_string( i );
339  const std::string textix = texti + "X";
340  const std::string textiy = texti + "Y";
341 
342  if( properties.find( textix ) == properties.end()
343  || properties.find( textiy ) == properties.end() )
344  {
345  break; // it doesn't seem like we know beforehand how many vertices are inside a polygon
346  }
347 
348  textPoint.emplace_back(
349  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, textix, "0mil" ),
350  -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, textiy, "0mil" ) );
351  }
352 
353  wxString dimensionunit =
354  ALTIUM_PARSER::PropertiesReadString( properties, "TEXTDIMENSIONUNIT", "Millimeters" );
355  if( dimensionunit == "Inches" )
356  {
358  }
359  else if( dimensionunit == "Mils" )
360  {
362  }
363  else if( dimensionunit == "Millimeters" )
364  {
366  }
367  else if( dimensionunit == "Centimeters" )
368  {
370  }
371  else
372  {
374  }
375 
376  if( aReader.HasParsingError() )
377  {
378  THROW_IO_ERROR( "Dimensions6 stream was not parsed correctly" );
379  }
380 }
381 
383 {
384  std::map<wxString, wxString> properties = aReader.ReadProperties();
385  if( properties.empty() )
386  {
387  THROW_IO_ERROR( "Classes6 stream has no properties!" );
388  }
389 
390  name = ALTIUM_PARSER::PropertiesReadString( properties, "NAME", "" );
391  id = ALTIUM_PARSER::PropertiesReadString( properties, "ID", "" );
392  isEmbedded = ALTIUM_PARSER::PropertiesReadBool( properties, "EMBED", false );
393 
394  rotation.x = ALTIUM_PARSER::PropertiesReadDouble( properties, "ROTX", 0. );
395  rotation.y = ALTIUM_PARSER::PropertiesReadDouble( properties, "ROTY", 0. );
396  rotation.z = ALTIUM_PARSER::PropertiesReadDouble( properties, "ROTZ", 0. );
397 
398  if( aReader.HasParsingError() )
399  {
400  THROW_IO_ERROR( "Classes6 stream was not parsed correctly" );
401  }
402 }
403 
405 {
406  std::map<wxString, wxString> properties = aReader.ReadProperties();
407  if( properties.empty() )
408  {
409  THROW_IO_ERROR( "Nets6 stream has no properties" );
410  }
411 
412  name = ALTIUM_PARSER::PropertiesReadString( properties, "NAME", "" );
413 
414  if( aReader.HasParsingError() )
415  {
416  THROW_IO_ERROR( "Nets6 stream was not parsed correctly" );
417  }
418 }
419 
421 {
422  std::map<wxString, wxString> properties = aReader.ReadProperties();
423  if( properties.empty() )
424  {
425  THROW_IO_ERROR( "Polygons6 stream has no properties" );
426  }
427 
429  ALTIUM_PARSER::PropertiesReadString( properties, "LAYER", "" ) );
431  locked = ALTIUM_PARSER::PropertiesReadBool( properties, "LOCKED", false );
432 
433  // TODO: kind
434 
435  gridsize = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "GRIDSIZE", "0mil" );
436  trackwidth = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "TRACKWIDTH", "0mil" );
437  minprimlength = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MINPRIMLENGTH", "0mil" );
438  useoctagons = ALTIUM_PARSER::PropertiesReadBool( properties, "USEOCTAGONS", false );
439 
440  pourindex = ALTIUM_PARSER::PropertiesReadInt( properties, "POURINDEX", 0 );
441 
442  wxString hatchstyleraw = ALTIUM_PARSER::PropertiesReadString( properties, "HATCHSTYLE", "" );
443 
444  if( hatchstyleraw == "Solid" )
445  {
447  }
448  else if( hatchstyleraw == "45Degree" )
449  {
451  }
452  else if( hatchstyleraw == "90Degree" )
453  {
455  }
456  else if( hatchstyleraw == "Horizontal" )
457  {
459  }
460  else if( hatchstyleraw == "Vertical" )
461  {
463  }
464  else if( hatchstyleraw == "None" )
465  {
467  }
468  else
469  {
471  }
472 
473  altium_parse_polygons( properties, vertices );
474 
475  if( aReader.HasParsingError() )
476  {
477  THROW_IO_ERROR( "Polygons6 stream was not parsed correctly" );
478  }
479 }
480 
482 {
483  // Initalize all variables and make Coverity happy
484  clearanceGap = 0;
490 
491  aReader.Skip( 2 );
492 
493  std::map<wxString, wxString> properties = aReader.ReadProperties();
494  if( properties.empty() )
495  {
496  THROW_IO_ERROR( "Rules6 stream has no properties" );
497  }
498 
499  name = ALTIUM_PARSER::PropertiesReadString( properties, "NAME", "" );
500  priority = ALTIUM_PARSER::PropertiesReadInt( properties, "PRIORITY", 1 );
501 
502  scope1expr = ALTIUM_PARSER::PropertiesReadString( properties, "SCOPE1EXPRESSION", "" );
503  scope2expr = ALTIUM_PARSER::PropertiesReadString( properties, "SCOPE2EXPRESSION", "" );
504 
505  wxString rulekind = ALTIUM_PARSER::PropertiesReadString( properties, "RULEKIND", "" );
506  if( rulekind == "Clearance" )
507  {
509  clearanceGap = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "GAP", "10mil" );
510  }
511  else if( rulekind == "DiffPairsRouting" )
512  {
514  }
515  else if( rulekind == "Height" )
516  {
518  }
519  else if( rulekind == "HoleSize" )
520  {
522  }
523  else if( rulekind == "HoleToHoleClearance" )
524  {
526  }
527  else if( rulekind == "Width" )
528  {
530  }
531  else if( rulekind == "PasteMaskExpansion" )
532  {
534  }
535  else if( rulekind == "PlaneClearance" )
536  {
539  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "CLEARANCE", "10mil" );
540  }
541  else if( rulekind == "PolygonConnect" )
542  {
545  ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "AIRGAPWIDTH", "10mil" );
547  properties, "RELIEFCONDUCTORWIDTH", "10mil" );
549  ALTIUM_PARSER::PropertiesReadInt( properties, "RELIEFENTRIES", 4 );
550 
551  wxString style = ALTIUM_PARSER::PropertiesReadString( properties, "CONNECTSTYLE", "" );
552 
553  if( style == "Direct" )
555  else if( style == "Relief" )
557  else if( style == "NoConnect" )
559  else
561  }
562  else
563  {
565  }
566 
567  if( aReader.HasParsingError() )
568  {
569  THROW_IO_ERROR( "Rules6 stream was not parsed correctly" );
570  }
571 }
572 
574 {
575  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
576  if( recordtype != ALTIUM_RECORD::ARC )
577  {
578  THROW_IO_ERROR( "Arcs6 stream has invalid recordtype" );
579  }
580 
581  // Subrecord 1
582  aReader.ReadAndSetSubrecordLength();
583 
584  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
585 
586  uint8_t flags1 = aReader.Read<uint8_t>();
587  is_locked = ( flags1 & 0x04 ) == 0;
588  is_polygonoutline = ( flags1 & 0x02 ) != 0;
589 
590  uint8_t flags2 = aReader.Read<uint8_t>();
591  is_keepout = flags2 == 2;
592 
593  net = aReader.Read<uint16_t>();
594  subpolyindex = aReader.Read<uint16_t>();
595  component = aReader.Read<uint16_t>();
596  aReader.Skip( 4 );
597  center = aReader.ReadWxPoint();
598  radius = aReader.ReadKicadUnit();
599  startangle = aReader.Read<double>();
600  endangle = aReader.Read<double>();
601  width = aReader.ReadKicadUnit();
602 
603  aReader.SkipSubrecord();
604 
605  if( aReader.HasParsingError() )
606  {
607  THROW_IO_ERROR( "Arcs6 stream was not parsed correctly" );
608  }
609 }
610 
612 {
613  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
614  if( recordtype != ALTIUM_RECORD::MODEL )
615  {
616  THROW_IO_ERROR( "ComponentsBodies6 stream has invalid recordtype" );
617  }
618 
619  aReader.ReadAndSetSubrecordLength();
620 
621  aReader.Skip( 7 );
622  component = aReader.Read<uint16_t>();
623  aReader.Skip( 9 );
624 
625  std::map<wxString, wxString> properties = aReader.ReadProperties();
626  if( properties.empty() )
627  {
628  THROW_IO_ERROR( "ComponentsBodies6 stream has no properties" );
629  }
630 
631  modelName = ALTIUM_PARSER::PropertiesReadString( properties, "MODEL.NAME", "" );
632  modelId = ALTIUM_PARSER::PropertiesReadString( properties, "MODELID", "" );
633  modelIsEmbedded = ALTIUM_PARSER::PropertiesReadBool( properties, "MODEL.EMBED", false );
634 
635  modelPosition.x = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MODEL.2D.X", "0mil" );
636  modelPosition.y = -ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MODEL.2D.Y", "0mil" );
637  modelPosition.z = ALTIUM_PARSER::PropertiesReadKicadUnit( properties, "MODEL.3D.DZ", "0mil" );
638 
639  modelRotation.x = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.3D.ROTX", 0. );
640  modelRotation.y = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.3D.ROTY", 0. );
641  modelRotation.z = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.3D.ROTZ", 0. );
642 
643  rotation = ALTIUM_PARSER::PropertiesReadDouble( properties, "MODEL.2D.ROTATION", 0. );
644 
645  bodyOpacity = ALTIUM_PARSER::PropertiesReadDouble( properties, "BODYOPACITY3D", 1. );
646 
647  aReader.SkipSubrecord();
648 
649  if( aReader.HasParsingError() )
650  {
651  THROW_IO_ERROR( "Components6 stream was not parsed correctly" );
652  }
653 }
654 
656 {
657  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
658 
659  if( recordtype != ALTIUM_RECORD::PAD )
660  THROW_IO_ERROR( "Pads6 stream has invalid recordtype" );
661 
662  // Subrecord 1
663  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
664 
665  if( subrecord1 == 0 )
666  THROW_IO_ERROR( "Pads6 stream has no subrecord1 data" );
667 
668  name = aReader.ReadWxString();
669 
670  if( aReader.GetRemainingSubrecordBytes() != 0 )
671  THROW_IO_ERROR( "Pads6 stream has invalid subrecord1 length" );
672 
673  aReader.SkipSubrecord();
674 
675  // Subrecord 2
676  aReader.ReadAndSetSubrecordLength();
677  aReader.SkipSubrecord();
678 
679  // Subrecord 3
680  aReader.ReadAndSetSubrecordLength();
681  aReader.SkipSubrecord();
682 
683  // Subrecord 4
684  aReader.ReadAndSetSubrecordLength();
685  aReader.SkipSubrecord();
686 
687  // Subrecord 5
688  size_t subrecord5 = aReader.ReadAndSetSubrecordLength();
689 
690  if( subrecord5 < 114 )
691  THROW_IO_ERROR( "Pads6 stream subrecord has length < 114, which is unexpected" );
692 
693  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
696 
697  uint8_t flags1 = aReader.Read<uint8_t>();
698  is_test_fab_top = ( flags1 & 0x80 ) != 0;
699  is_tent_bottom = ( flags1 & 0x40 ) != 0;
700  is_tent_top = ( flags1 & 0x20 ) != 0;
701  is_locked = ( flags1 & 0x04 ) == 0;
702 
703  uint8_t flags2 = aReader.Read<uint8_t>();
704  is_test_fab_bottom = ( flags2 & 0x01 ) != 0;
705 
706  net = aReader.Read<uint16_t>();
707  aReader.Skip( 2 );
708  component = aReader.Read<uint16_t>();
709  aReader.Skip( 4 );
710 
711  position = aReader.ReadWxPoint();
712  topsize = aReader.ReadWxSize();
713  midsize = aReader.ReadWxSize();
714  botsize = aReader.ReadWxSize();
715  holesize = aReader.ReadKicadUnit();
716 
717  topshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
718  midshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
719  botshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
720 
721  direction = aReader.Read<double>();
722  plated = aReader.Read<uint8_t>() != 0;
723  aReader.Skip( 1 );
724  padmode = static_cast<ALTIUM_PAD_MODE>( aReader.Read<uint8_t>() );
725  aReader.Skip( 23 );
728  aReader.Skip( 7 );
729  pastemaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() );
730  soldermaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() );
731  aReader.Skip( 3 );
732  holerotation = aReader.Read<double>();
733 
734  if( subrecord5 >= 120 )
735  {
736  tolayer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
737  aReader.Skip( 2 );
738  fromlayer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
739  //aReader.skip( 2 );
740  }
741  else if( subrecord5 == 171 )
742  {
743  }
744 
745  aReader.SkipSubrecord();
746 
747  // Subrecord 6
748  size_t subrecord6 = aReader.ReadAndSetSubrecordLength();
749  // Known lengths: 596, 628, 651
750  // 596 is the number of bytes read in this code-block
751  if( subrecord6 >= 596 )
752  { // TODO: detect type from something else than the size?
753  sizeAndShape = std::make_unique<APAD6_SIZE_AND_SHAPE>();
754 
755  for( wxSize& size : sizeAndShape->inner_size )
756  size.x = aReader.ReadKicadUnitX();
757 
758  for( wxSize& size : sizeAndShape->inner_size )
759  size.y = aReader.ReadKicadUnitY();
760 
761  for( ALTIUM_PAD_SHAPE& shape : sizeAndShape->inner_shape )
762  shape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
763 
764  aReader.Skip( 1 );
765 
766  sizeAndShape->holeshape = static_cast<ALTIUM_PAD_HOLE_SHAPE>( aReader.Read<uint8_t>() );
767  sizeAndShape->slotsize = aReader.ReadKicadUnit();
768  sizeAndShape->slotrotation = aReader.Read<double>();
769 
770  for( wxPoint& pt : sizeAndShape->holeoffset )
771  pt.x = aReader.ReadKicadUnitX();
772 
773  for( wxPoint& pt : sizeAndShape->holeoffset )
774  pt.y = aReader.ReadKicadUnitY();
775 
776  aReader.Skip( 1 );
777 
778  for( ALTIUM_PAD_SHAPE_ALT& shape : sizeAndShape->alt_shape )
779  shape = static_cast<ALTIUM_PAD_SHAPE_ALT>( aReader.Read<uint8_t>() );
780 
781  for( uint8_t& radius : sizeAndShape->cornerradius )
782  radius = aReader.Read<uint8_t>();
783  }
784  else if( subrecord6 != 0 )
785  {
786  wxLogError( wxString::Format(
787  "Pads6 stream has unexpected length for subrecord 6: %d", subrecord6 ) );
788  }
789 
790  aReader.SkipSubrecord();
791 
792  if( aReader.HasParsingError() )
793  THROW_IO_ERROR( "Pads6 stream was not parsed correctly" );
794 }
795 
797 {
798  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
799  if( recordtype != ALTIUM_RECORD::VIA )
800  {
801  THROW_IO_ERROR( "Vias6 stream has invalid recordtype" );
802  }
803 
804  // Subrecord 1
805  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
806 
807  aReader.Skip( 1 );
808 
809  uint8_t flags1 = aReader.Read<uint8_t>();
810  is_test_fab_top = ( flags1 & 0x80 ) != 0;
811  is_tent_bottom = ( flags1 & 0x40 ) != 0;
812  is_tent_top = ( flags1 & 0x20 ) != 0;
813  is_locked = ( flags1 & 0x04 ) == 0;
814 
815  uint8_t flags2 = aReader.Read<uint8_t>();
816  is_test_fab_bottom = ( flags2 & 0x01 ) != 0;
817 
818  net = aReader.Read<uint16_t>();
819  aReader.Skip( 8 );
820  position = aReader.ReadWxPoint();
821  diameter = aReader.ReadKicadUnit();
822  holesize = aReader.ReadKicadUnit();
823 
824  layer_start = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
825  layer_end = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
826 
827  if( subrecord1 <= 74 )
828  {
830  }
831  else
832  {
833  aReader.Skip( 43 );
834  viamode = static_cast<ALTIUM_PAD_MODE>( aReader.Read<uint8_t>() );
835  }
836 
837  aReader.SkipSubrecord();
838 
839  if( aReader.HasParsingError() )
840  {
841  THROW_IO_ERROR( "Vias6 stream was not parsed correctly" );
842  }
843 }
844 
846 {
847  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
848  if( recordtype != ALTIUM_RECORD::TRACK )
849  {
850  THROW_IO_ERROR( "Tracks6 stream has invalid recordtype" );
851  }
852 
853  // Subrecord 1
854  aReader.ReadAndSetSubrecordLength();
855 
856  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
857 
858  uint8_t flags1 = aReader.Read<uint8_t>();
859  is_locked = ( flags1 & 0x04 ) == 0;
860  is_polygonoutline = ( flags1 & 0x02 ) != 0;
861 
862  uint8_t flags2 = aReader.Read<uint8_t>();
863  is_keepout = flags2 == 2;
864 
865  net = aReader.Read<uint16_t>();
866  subpolyindex = aReader.Read<uint16_t>();
867  component = aReader.Read<uint16_t>();
868  aReader.Skip( 4 );
869  start = aReader.ReadWxPoint();
870  end = aReader.ReadWxPoint();
871  width = aReader.ReadKicadUnit();
872 
873  aReader.SkipSubrecord();
874 
875  if( aReader.HasParsingError() )
876  {
877  THROW_IO_ERROR( "Tracks6 stream was not parsed correctly" );
878  }
879 }
880 
882 {
883  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
884  if( recordtype != ALTIUM_RECORD::TEXT )
885  {
886  THROW_IO_ERROR( "Texts6 stream has invalid recordtype" );
887  }
888 
889  // Subrecord 1 - Properties
890  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
891 
892  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
893  aReader.Skip( 6 );
894  component = aReader.Read<uint16_t>();
895  aReader.Skip( 4 );
896  position = aReader.ReadWxPoint();
897  height = aReader.ReadKicadUnit();
898  aReader.Skip( 2 );
899  rotation = aReader.Read<double>();
900  isMirrored = aReader.Read<uint8_t>() != 0;
901  strokewidth = aReader.ReadKicadUnit();
902  isComment = aReader.Read<uint8_t>() != 0;
903  isDesignator = aReader.Read<uint8_t>() != 0;
904  aReader.Skip( 2 );
905  isBold = aReader.Read<uint8_t>() != 0;
906  isItalic = aReader.Read<uint8_t>() != 0;
907  aReader.Skip( 64 ); // font_name
908  isInverted = aReader.Read<uint8_t>() != 0;
909  aReader.Skip( 21 );
910  textposition = static_cast<ALTIUM_TEXT_POSITION>( aReader.Read<uint8_t>() );
915  if( subrecord1 <= 230 )
916  {
918  }
919  aReader.Skip( 27 );
920  fonttype = static_cast<ALTIUM_TEXT_TYPE>( aReader.Read<uint8_t>() );
921 
922  aReader.SkipSubrecord();
923 
924  // Subrecord 2 - String
925  aReader.ReadAndSetSubrecordLength();
926 
927  text = aReader.ReadWxString(); // TODO: what about strings with length > 255?
928 
929  // Normalize Windows line endings
930  text.Replace( "\r\n", "\n" );
931 
932  aReader.SkipSubrecord();
933 
934  if( aReader.HasParsingError() )
935  {
936  THROW_IO_ERROR( "Texts6 stream was not parsed correctly" );
937  }
938 }
939 
941 {
942  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
943  if( recordtype != ALTIUM_RECORD::FILL )
944  {
945  THROW_IO_ERROR( "Fills6 stream has invalid recordtype" );
946  }
947 
948  // Subrecord 1
949  aReader.ReadAndSetSubrecordLength();
950 
951  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
952 
953  uint8_t flags1 = aReader.Read<uint8_t>();
954  is_locked = ( flags1 & 0x04 ) == 0;
955 
956  uint8_t flags2 = aReader.Read<uint8_t>();
957  is_keepout = flags2 == 2;
958 
959  net = aReader.Read<uint16_t>();
960  aReader.Skip( 2 );
961  component = aReader.Read<uint16_t>();
962  aReader.Skip( 4 );
963  pos1 = aReader.ReadWxPoint();
964  pos2 = aReader.ReadWxPoint();
965  rotation = aReader.Read<double>();
966 
967  aReader.SkipSubrecord();
968 
969  if( aReader.HasParsingError() )
970  {
971  THROW_IO_ERROR( "Fills6 stream was not parsed correctly" );
972  }
973 }
974 
975 AREGION6::AREGION6( ALTIUM_PARSER& aReader, bool aExtendedVertices )
976 {
977  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
978  if( recordtype != ALTIUM_RECORD::REGION )
979  {
980  THROW_IO_ERROR( "Regions6 stream has invalid recordtype" );
981  }
982 
983  // Subrecord 1
984  aReader.ReadAndSetSubrecordLength();
985 
986  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
987 
988  uint8_t flags1 = aReader.Read<uint8_t>();
989  is_locked = ( flags1 & 0x04 ) == 0;
990 
991  uint8_t flags2 = aReader.Read<uint8_t>();
992  is_keepout = flags2 == 2;
993 
994  net = aReader.Read<uint16_t>();
995  subpolyindex = aReader.Read<uint16_t>();
996  component = aReader.Read<uint16_t>();
997  aReader.Skip( 5 );
998  holecount = aReader.Read<uint16_t>();
999  aReader.Skip( 2 );
1000 
1001  std::map<wxString, wxString> properties = aReader.ReadProperties();
1002  if( properties.empty() )
1003  {
1004  THROW_IO_ERROR( "Regions6 stream has empty properties" );
1005  }
1006 
1007  int pkind = ALTIUM_PARSER::PropertiesReadInt( properties, "KIND", 0 );
1008  bool is_cutout = ALTIUM_PARSER::PropertiesReadBool( properties, "ISBOARDCUTOUT", false );
1009 
1010  is_shapebased = ALTIUM_PARSER::PropertiesReadBool( properties, "ISSHAPEBASED", false );
1011 
1012  // TODO: this can differ from the other subpolyindex?!
1013  //subpolyindex = static_cast<uint16_t>(
1014  // ALTIUM_PARSER::PropertiesReadInt( properties, "SUBPOLYINDEX", ALTIUM_POLYGON_NONE ) );
1015 
1016  switch( pkind )
1017  {
1018  case 0:
1019  if( is_cutout )
1020  {
1022  }
1023  else
1024  {
1026  }
1027  break;
1028  case 1:
1030  break;
1031  case 2:
1032  kind = ALTIUM_REGION_KIND::UNKNOWN_2; // TODO: what kind is this?
1033  break;
1034  case 3:
1035  kind = ALTIUM_REGION_KIND::UNKNOWN_3; // TODO: what kind is this?
1036  break;
1037  case 4:
1039  break;
1040  default:
1042  break;
1043  }
1044 
1045  uint32_t num_outline_vertices = aReader.Read<uint32_t>();
1046 
1047  for( uint32_t i = 0; i < num_outline_vertices; i++ )
1048  {
1049  if( aExtendedVertices )
1050  {
1051  bool isRound = aReader.Read<uint8_t>() != 0;
1052  wxPoint position = aReader.ReadWxPoint();
1053  wxPoint center = aReader.ReadWxPoint();
1054  int32_t radius = aReader.ReadKicadUnit();
1055  double angle1 = aReader.Read<double>();
1056  double angle2 = aReader.Read<double>();
1057  outline.emplace_back( isRound, radius, angle1, angle2, position, center );
1058  }
1059  else
1060  {
1061  // For some regions the coordinates are stored as double and not as int32_t
1062  int32_t x = ALTIUM_PARSER::ConvertToKicadUnit( aReader.Read<double>() );
1063  int32_t y = ALTIUM_PARSER::ConvertToKicadUnit( -aReader.Read<double>() );
1064  outline.emplace_back( wxPoint( x, y ) );
1065  }
1066  }
1067 
1068  // TODO: for now we only support holes in regions where there are stored as double
1069  if( !aExtendedVertices )
1070  {
1071  holes.resize( holecount );
1072  for( uint16_t k = 0; k < holecount; k++ )
1073  {
1074  uint32_t num_hole_vertices = aReader.Read<uint32_t>();
1075  holes.at( k ).reserve( num_hole_vertices );
1076 
1077  for( uint32_t i = 0; i < num_hole_vertices; i++ )
1078  {
1079  int32_t x = ALTIUM_PARSER::ConvertToKicadUnit( aReader.Read<double>() );
1080  int32_t y = ALTIUM_PARSER::ConvertToKicadUnit( -aReader.Read<double>() );
1081  holes.at( k ).emplace_back( wxPoint( x, y ) );
1082  }
1083  }
1084  }
1085 
1086  aReader.SkipSubrecord();
1087 
1088  if( aReader.HasParsingError() )
1089  {
1090  THROW_IO_ERROR( "Regions6 stream was not parsed correctly" );
1091  }
1092 }
AREGION6(ALTIUM_PARSER &aReader, bool aExtendedVertices)
ADIMENSION6(ALTIUM_PARSER &aReader)
uint32_t textlinewidth
uint32_t linewidth
ALTIUM_LAYER tolayer
FP_3DMODEL::VECTOR3D modelPosition
int32_t soldermaskexpansionmanual
ALTIUM_RULE_KIND kind
double rotation
uint32_t holesize
uint32_t width
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
std::vector< std::vector< ALTIUM_VERTICE > > holes
static int32_t ConvertToKicadUnit(const double aValue)
wxString sourcedesignator
ALTIUM_LAYER layer
ALTIUM_RECORD
ALTIUM_LAYER layer_end
ALTIUM_PAD_SHAPE
ALTIUM_PAD_RULE soldermaskexpansionmode
ALTIUM_LAYER layer
uint16_t net
wxString sourcefootprintlibrary
AVIA6(ALTIUM_PARSER &aReader)
uint16_t holecount
FP_3DMODEL::VECTOR3D rotation
wxString name
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
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
FP_3DMODEL::VECTOR3D modelRotation
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
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
bool is_test_fab_top
bool is_tent_top
ATRACK6(ALTIUM_PARSER &aReader)
uint32_t radius
wxPoint position
std::vector< ALTIUM_VERTICE > outline
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