KiCad PCB EDA Suite
ALTIUM_PCB Class Reference

#include <altium_pcb.h>

Public Member Functions

 ALTIUM_PCB (BOARD *aBoard)
 
 ~ALTIUM_PCB ()
 
void Parse (const CFB::CompoundFileReader &aReader, const std::map< ALTIUM_PCB_DIR, std::string > &aFileMapping)
 

Private Member Functions

PCB_LAYER_ID GetKicadLayer (ALTIUM_LAYER aAltiumLayer) const
 
int GetNetCode (uint16_t aId) const
 
const ARULE6GetRule (ALTIUM_RULE_KIND aKind, const wxString &aName) const
 
const ARULE6GetRuleDefault (ALTIUM_RULE_KIND aKind) const
 
void ParseFileHeader (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseBoard6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseClasses6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseComponents6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseDimensions6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseModelsData (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry, const wxString aRootDir)
 
void ParseNets6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParsePolygons6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseRules6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseArcs6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseComponentsBodies6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParsePads6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseVias6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseTracks6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseTexts6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseFills6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseBoardRegionsData (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseShapeBasedRegions6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void ParseRegions6Data (const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
 
void HelperParseDimensions6Linear (const ADIMENSION6 &aElem)
 
void HelperParseDimensions6Leader (const ADIMENSION6 &aElem)
 
void HelperParseDimensions6Datum (const ADIMENSION6 &aElem)
 
void HelperParseDimensions6Center (const ADIMENSION6 &aElem)
 
void HelperParsePad6NonCopper (const APAD6 &aElem)
 
void HelperCreateBoardOutline (const std::vector< ALTIUM_VERTICE > &aVertices)
 
PCB_SHAPEHelperCreateAndAddDrawsegment (uint16_t aComponent)
 
void HelperDrawsegmentSetLocalCoord (PCB_SHAPE *aShape, uint16_t aComponent)
 

Private Attributes

BOARDm_board
 
std::vector< MODULE * > m_components
 
std::vector< ZONE_CONTAINER * > m_polygons
 
std::map< wxString, wxString > m_models
 
size_t m_num_nets
 
std::map< ALTIUM_LAYER, PCB_LAYER_IDm_layermap
 
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
 
std::map< ALTIUM_LAYER, ZONE_CONTAINER * > m_outer_plane
 
int m_highest_pour_index
 Altium stores pour order across all layers. More...
 

Detailed Description

Definition at line 114 of file altium_pcb.h.

Constructor & Destructor Documentation

◆ ALTIUM_PCB()

ALTIUM_PCB::ALTIUM_PCB ( BOARD aBoard)
explicit

Definition at line 294 of file altium_pcb.cpp.

295 {
296  m_board = aBoard;
297  m_num_nets = 0;
299 }
BOARD * m_board
Definition: altium_pcb.h:185
size_t m_num_nets
Definition: altium_pcb.h:189
int m_highest_pour_index
Altium stores pour order across all layers.
Definition: altium_pcb.h:196

References m_board, m_highest_pour_index, and m_num_nets.

◆ ~ALTIUM_PCB()

ALTIUM_PCB::~ALTIUM_PCB ( )

Definition at line 301 of file altium_pcb.cpp.

302 {
303 }

Member Function Documentation

◆ GetKicadLayer()

PCB_LAYER_ID ALTIUM_PCB::GetKicadLayer ( ALTIUM_LAYER  aAltiumLayer) const
private

Definition at line 189 of file altium_pcb.cpp.

190 {
191  auto override = m_layermap.find( aAltiumLayer );
192  if( override != m_layermap.end() )
193  {
194  return override->second;
195  }
196 
197  switch( aAltiumLayer )
198  {
200 
201  case ALTIUM_LAYER::TOP_LAYER: return F_Cu;
202  case ALTIUM_LAYER::MID_LAYER_1: return In1_Cu; // TODO: stackup same as in KiCad?
203  case ALTIUM_LAYER::MID_LAYER_2: return In2_Cu;
204  case ALTIUM_LAYER::MID_LAYER_3: return In3_Cu;
205  case ALTIUM_LAYER::MID_LAYER_4: return In4_Cu;
206  case ALTIUM_LAYER::MID_LAYER_5: return In5_Cu;
207  case ALTIUM_LAYER::MID_LAYER_6: return In6_Cu;
208  case ALTIUM_LAYER::MID_LAYER_7: return In7_Cu;
209  case ALTIUM_LAYER::MID_LAYER_8: return In8_Cu;
210  case ALTIUM_LAYER::MID_LAYER_9: return In9_Cu;
211  case ALTIUM_LAYER::MID_LAYER_10: return In10_Cu;
212  case ALTIUM_LAYER::MID_LAYER_11: return In11_Cu;
213  case ALTIUM_LAYER::MID_LAYER_12: return In12_Cu;
214  case ALTIUM_LAYER::MID_LAYER_13: return In13_Cu;
215  case ALTIUM_LAYER::MID_LAYER_14: return In14_Cu;
216  case ALTIUM_LAYER::MID_LAYER_15: return In15_Cu;
217  case ALTIUM_LAYER::MID_LAYER_16: return In16_Cu;
218  case ALTIUM_LAYER::MID_LAYER_17: return In17_Cu;
219  case ALTIUM_LAYER::MID_LAYER_18: return In18_Cu;
220  case ALTIUM_LAYER::MID_LAYER_19: return In19_Cu;
221  case ALTIUM_LAYER::MID_LAYER_20: return In20_Cu;
222  case ALTIUM_LAYER::MID_LAYER_21: return In21_Cu;
223  case ALTIUM_LAYER::MID_LAYER_22: return In22_Cu;
224  case ALTIUM_LAYER::MID_LAYER_23: return In23_Cu;
225  case ALTIUM_LAYER::MID_LAYER_24: return In24_Cu;
226  case ALTIUM_LAYER::MID_LAYER_25: return In25_Cu;
227  case ALTIUM_LAYER::MID_LAYER_26: return In26_Cu;
228  case ALTIUM_LAYER::MID_LAYER_27: return In27_Cu;
229  case ALTIUM_LAYER::MID_LAYER_28: return In28_Cu;
230  case ALTIUM_LAYER::MID_LAYER_29: return In29_Cu;
231  case ALTIUM_LAYER::MID_LAYER_30: return In30_Cu;
232  case ALTIUM_LAYER::BOTTOM_LAYER: return B_Cu;
233 
234  case ALTIUM_LAYER::TOP_OVERLAY: return F_SilkS;
236  case ALTIUM_LAYER::TOP_PASTE: return F_Paste;
237  case ALTIUM_LAYER::BOTTOM_PASTE: return B_Paste;
238  case ALTIUM_LAYER::TOP_SOLDER: return F_Mask;
239  case ALTIUM_LAYER::BOTTOM_SOLDER: return B_Mask;
240 
257 
260 
261  case ALTIUM_LAYER::MECHANICAL_1: return Dwgs_User; //Edge_Cuts;
273  case ALTIUM_LAYER::MECHANICAL_13: return F_Fab;
274  case ALTIUM_LAYER::MECHANICAL_14: return B_Fab;
277 
288 
289  default: return UNDEFINED_LAYER;
290  }
291 }
std::map< ALTIUM_LAYER, PCB_LAYER_ID > m_layermap
Definition: altium_pcb.h:190

References B_CrtYd, B_Cu, B_Fab, B_Mask, B_Paste, B_SilkS, BACKGROUND, BOTTOM_LAYER, BOTTOM_OVERLAY, BOTTOM_PASTE, BOTTOM_SOLDER, CONNECTIONS, DRC_ERROR_MARKERS, DRILL_DRAWING, DRILL_GUIDE, Dwgs_User, F_CrtYd, F_Cu, F_Fab, F_Mask, F_Paste, F_SilkS, In10_Cu, In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In1_Cu, In20_Cu, In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In2_Cu, In30_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, INTERNAL_PLANE_1, INTERNAL_PLANE_10, INTERNAL_PLANE_11, INTERNAL_PLANE_12, INTERNAL_PLANE_13, INTERNAL_PLANE_14, INTERNAL_PLANE_15, INTERNAL_PLANE_16, INTERNAL_PLANE_2, INTERNAL_PLANE_3, INTERNAL_PLANE_4, INTERNAL_PLANE_5, INTERNAL_PLANE_6, INTERNAL_PLANE_7, INTERNAL_PLANE_8, INTERNAL_PLANE_9, KEEP_OUT_LAYER, m_layermap, Margin, MECHANICAL_1, MECHANICAL_10, MECHANICAL_11, MECHANICAL_12, MECHANICAL_13, MECHANICAL_14, MECHANICAL_15, MECHANICAL_16, MECHANICAL_2, MECHANICAL_3, MECHANICAL_4, MECHANICAL_5, MECHANICAL_6, MECHANICAL_7, MECHANICAL_8, MECHANICAL_9, MID_LAYER_1, MID_LAYER_10, MID_LAYER_11, MID_LAYER_12, MID_LAYER_13, MID_LAYER_14, MID_LAYER_15, MID_LAYER_16, MID_LAYER_17, MID_LAYER_18, MID_LAYER_19, MID_LAYER_2, MID_LAYER_20, MID_LAYER_21, MID_LAYER_22, MID_LAYER_23, MID_LAYER_24, MID_LAYER_25, MID_LAYER_26, MID_LAYER_27, MID_LAYER_28, MID_LAYER_29, MID_LAYER_3, MID_LAYER_30, MID_LAYER_4, MID_LAYER_5, MID_LAYER_6, MID_LAYER_7, MID_LAYER_8, MID_LAYER_9, MULTI_LAYER, PAD_HOLES, SELECTIONS, TOP_LAYER, TOP_OVERLAY, TOP_PASTE, TOP_SOLDER, UNDEFINED_LAYER, UNKNOWN, VIA_HOLES, VISIBLE_GRID_1, and VISIBLE_GRID_2.

Referenced by HelperParseDimensions6Center(), HelperParseDimensions6Datum(), HelperParseDimensions6Leader(), HelperParseDimensions6Linear(), HelperParsePad6NonCopper(), ParseArcs6Data(), ParseFills6Data(), ParsePads6Data(), ParsePolygons6Data(), ParseShapeBasedRegions6Data(), ParseTexts6Data(), ParseTracks6Data(), and ParseVias6Data().

◆ GetNetCode()

int ALTIUM_PCB::GetNetCode ( uint16_t  aId) const
private

Definition at line 457 of file altium_pcb.cpp.

458 {
459  if( aId == ALTIUM_NET_UNCONNECTED )
460  {
462  }
463  else if( m_num_nets < aId )
464  {
466  "Netcode with id %d does not exist. Only %d nets are known", aId, m_num_nets ) );
467  }
468  else
469  {
470  return aId + 1;
471  }
472 }
const uint16_t ALTIUM_NET_UNCONNECTED
size_t m_num_nets
Definition: altium_pcb.h:189
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
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:478
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References ALTIUM_NET_UNCONNECTED, Format(), m_num_nets, THROW_IO_ERROR, and NETINFO_LIST::UNCONNECTED.

Referenced by ParseArcs6Data(), ParseFills6Data(), ParsePads6Data(), ParsePolygons6Data(), ParseTracks6Data(), and ParseVias6Data().

◆ GetRule()

const ARULE6 * ALTIUM_PCB::GetRule ( ALTIUM_RULE_KIND  aKind,
const wxString &  aName 
) const
private

Definition at line 474 of file altium_pcb.cpp.

475 {
476  const auto rules = m_rules.find( aKind );
477  if( rules == m_rules.end() )
478  {
479  return nullptr;
480  }
481  for( const ARULE6& rule : rules->second )
482  {
483  if( rule.name == aName )
484  {
485  return &rule;
486  }
487  }
488  return nullptr;
489 }
wxString name
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
Definition: altium_pcb.h:191

References m_rules, and ARULE6::name.

◆ GetRuleDefault()

const ARULE6 * ALTIUM_PCB::GetRuleDefault ( ALTIUM_RULE_KIND  aKind) const
private

Definition at line 491 of file altium_pcb.cpp.

492 {
493  const auto rules = m_rules.find( aKind );
494  if( rules == m_rules.end() )
495  {
496  return nullptr;
497  }
498  for( const ARULE6& rule : rules->second )
499  {
500  if( rule.scope1expr == "All" && rule.scope2expr == "All" )
501  {
502  return &rule;
503  }
504  }
505  return nullptr;
506 }
wxString scope2expr
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
Definition: altium_pcb.h:191
wxString scope1expr

References m_rules, ARULE6::scope1expr, and ARULE6::scope2expr.

Referenced by ParsePolygons6Data().

◆ HelperCreateAndAddDrawsegment()

PCB_SHAPE * ALTIUM_PCB::HelperCreateAndAddDrawsegment ( uint16_t  aComponent)
private

Definition at line 111 of file altium_pcb.cpp.

112 {
113  if( aComponent == ALTIUM_COMPONENT_NONE )
114  {
115  PCB_SHAPE* shape = new PCB_SHAPE( m_board );
116  m_board->Add( shape, ADD_MODE::APPEND );
117  return shape;
118  }
119  else
120  {
121  if( m_components.size() <= aComponent )
122  {
124  "Component creator tries to access component id %d of %d existing components",
125  aComponent, m_components.size() ) );
126  }
127 
128  MODULE* module = m_components.at( aComponent );
129  PCB_SHAPE* fpShape = new FP_SHAPE( module );
130 
131  module->Add( fpShape, ADD_MODE::APPEND );
132  return fpShape;
133  }
134 }
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
BOARD * m_board
Definition: altium_pcb.h:185
std::vector< MODULE * > m_components
Definition: altium_pcb.h:186
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
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
const int ALTIUM_COMPONENT_NONE
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References MODULE::Add(), BOARD::Add(), ALTIUM_COMPONENT_NONE, APPEND, Format(), m_board, m_components, and THROW_IO_ERROR.

Referenced by HelperParsePad6NonCopper(), ParseArcs6Data(), and ParseTracks6Data().

◆ HelperCreateBoardOutline()

void ALTIUM_PCB::HelperCreateBoardOutline ( const std::vector< ALTIUM_VERTICE > &  aVertices)
private

Definition at line 642 of file altium_pcb.cpp.

643 {
644  if( !aVertices.empty() )
645  {
646  const ALTIUM_VERTICE* last = &aVertices.at( 0 );
647  for( size_t i = 0; i < aVertices.size(); i++ )
648  {
649  const ALTIUM_VERTICE* cur = &aVertices.at( ( i + 1 ) % aVertices.size() );
650 
651  PCB_SHAPE* shape = new PCB_SHAPE( m_board );
652  m_board->Add( shape, ADD_MODE::APPEND );
653 
655  shape->SetLayer( Edge_Cuts );
656 
657  if( !last->isRound && !cur->isRound )
658  {
659  shape->SetShape( S_SEGMENT );
660  shape->SetStart( last->position );
661  shape->SetEnd( cur->position );
662  }
663  else if( cur->isRound )
664  {
665  shape->SetShape( S_ARC );
666  shape->SetAngle( -NormalizeAngleDegreesPos( cur->endangle - cur->startangle ) * 10. );
667 
668  double startradiant = DEG2RAD( cur->startangle );
669  wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * cur->radius ),
670  -KiROUND( std::sin( startradiant ) * cur->radius ) );
671  wxPoint arcStart = cur->center + arcStartOffset;
672  shape->SetCenter( cur->center );
673  shape->SetArcStart( arcStart );
674 
675  if( !last->isRound )
676  {
677  double endradiant = DEG2RAD( cur->endangle );
678  wxPoint arcEndOffset = wxPoint( KiROUND( std::cos( endradiant ) * cur->radius ),
679  -KiROUND( std::sin( endradiant ) * cur->radius ) );
680  wxPoint arcEnd = cur->center + arcEndOffset;
681 
682  PCB_SHAPE* shape2 = new PCB_SHAPE( m_board );
683  shape2->SetShape( S_SEGMENT );
684  m_board->Add( shape2, ADD_MODE::APPEND );
686  shape2->SetLayer( Edge_Cuts );
687  shape2->SetStart( last->position );
688 
689  // TODO: this is more of a hack than the real solution
690  double lineLengthStart = GetLineLength( last->position, arcStart );
691  double lineLengthEnd = GetLineLength( last->position, arcEnd );
692  if( lineLengthStart > lineLengthEnd )
693  {
694  shape2->SetEnd( cur->center + arcEndOffset );
695  }
696  else
697  {
698  shape2->SetEnd( cur->center + arcStartOffset );
699  }
700  }
701  }
702  last = cur;
703  }
704  }
705 }
usual segment : line with rounded ends
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:212
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
const double startangle
Arcs (with rounded ends)
int GetLineThickness(PCB_LAYER_ID aLayer) const
Function GetLineThickness Returns the default graphic segment thickness from the layer class for the ...
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
double NormalizeAngleDegreesPos(double Angle)
Normalize angle to be in the 0.0 .
Definition: trigo.h:285
BOARD * m_board
Definition: altium_pcb.h:185
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
const wxPoint position
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
Definition: pcb_shape.h:213
const int32_t radius
const wxPoint center
double DEG2RAD(double deg)
Definition: trigo.h:220
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:132
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
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
const double endangle
virtual void SetAngle(double aAngle, bool aUpdateEnd=true)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
Definition: pcb_shape.cpp:435
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:143
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
Definition: pcb_shape.h:197

References BOARD::Add(), APPEND, ALTIUM_VERTICE::center, DEG2RAD(), Edge_Cuts, ALTIUM_VERTICE::endangle, BOARD::GetDesignSettings(), GetLineLength(), BOARD_DESIGN_SETTINGS::GetLineThickness(), ALTIUM_VERTICE::isRound, KiROUND(), m_board, NormalizeAngleDegreesPos(), ALTIUM_VERTICE::position, ALTIUM_VERTICE::radius, S_ARC, S_SEGMENT, PCB_SHAPE::SetAngle(), PCB_SHAPE::SetArcStart(), PCB_SHAPE::SetCenter(), PCB_SHAPE::SetEnd(), BOARD_ITEM::SetLayer(), PCB_SHAPE::SetShape(), PCB_SHAPE::SetStart(), PCB_SHAPE::SetWidth(), and ALTIUM_VERTICE::startangle.

Referenced by ParseBoard6Data(), and ParseShapeBasedRegions6Data().

◆ HelperDrawsegmentSetLocalCoord()

void ALTIUM_PCB::HelperDrawsegmentSetLocalCoord ( PCB_SHAPE aShape,
uint16_t  aComponent 
)
private

Definition at line 137 of file altium_pcb.cpp.

138 {
139  if( aComponent != ALTIUM_COMPONENT_NONE )
140  {
141  FP_SHAPE* fpShape = dynamic_cast<FP_SHAPE*>( aShape );
142 
143  if( fpShape )
144  fpShape->SetLocalCoord();
145  }
146 }
void SetLocalCoord()
Set relative coordinates from draw coordinates.
Definition: fp_shape.cpp:52
const int ALTIUM_COMPONENT_NONE

References ALTIUM_COMPONENT_NONE, and FP_SHAPE::SetLocalCoord().

Referenced by HelperParsePad6NonCopper(), ParseArcs6Data(), and ParseTracks6Data().

◆ HelperParseDimensions6Center()

void ALTIUM_PCB::HelperParseDimensions6Center ( const ADIMENSION6 aElem)
private

Definition at line 1042 of file altium_pcb.cpp.

1043 {
1044  PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
1045  if( klayer == UNDEFINED_LAYER )
1046  {
1047  wxLogWarning( wxString::Format(
1048  _( "Dimension on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
1049  aElem.layer ) );
1050  klayer = Eco1_User;
1051  }
1052 
1053  wxPoint vec = wxPoint( 0, aElem.height / 2 );
1054  RotatePoint( &vec, aElem.angle * 10. );
1055 
1056  CENTER_DIMENSION* dimension = new CENTER_DIMENSION( m_board );
1057  m_board->Add( dimension, ADD_MODE::APPEND );
1058  dimension->SetLayer( klayer );
1059  dimension->SetLineThickness( aElem.linewidth );
1060  dimension->SetStart( aElem.xy1 );
1061  dimension->SetEnd( aElem.xy1 + vec );
1062 }
uint32_t linewidth
ALTIUM_LAYER layer
virtual void SetStart(const wxPoint &aPoint)
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
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
#define _(s)
Definition: 3d_actions.cpp:33
void SetLineThickness(int aWidth)
virtual void SetEnd(const wxPoint &aPoint)
Marks the center of a circle or arc with a cross shape The size and orientation of the cross is adjus...

References _, BOARD::Add(), ADIMENSION6::angle, APPEND, Eco1_User, Format(), GetKicadLayer(), ADIMENSION6::height, ADIMENSION6::layer, ADIMENSION6::linewidth, m_board, RotatePoint(), DIMENSION::SetEnd(), DIMENSION::SetLayer(), DIMENSION::SetLineThickness(), DIMENSION::SetStart(), UNDEFINED_LAYER, and ADIMENSION6::xy1.

Referenced by ParseDimensions6Data().

◆ HelperParseDimensions6Datum()

void ALTIUM_PCB::HelperParseDimensions6Datum ( const ADIMENSION6 aElem)
private

Definition at line 1019 of file altium_pcb.cpp.

1020 {
1021  PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
1022  if( klayer == UNDEFINED_LAYER )
1023  {
1024  wxLogWarning( wxString::Format(
1025  _( "Dimension on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
1026  aElem.layer ) );
1027  klayer = Eco1_User;
1028  }
1029 
1030  for( size_t i = 0; i < aElem.referencePoint.size(); i++ )
1031  {
1032  PCB_SHAPE* shape = new PCB_SHAPE( m_board );
1033  m_board->Add( shape, ADD_MODE::APPEND );
1034  shape->SetShape( S_SEGMENT );
1035  shape->SetLayer( klayer );
1036  shape->SetWidth( aElem.linewidth );
1037  shape->SetStart( aElem.referencePoint.at( i ) );
1038  // shape->SetEnd( /* TODO: seems to be based on TEXTY */ );
1039  }
1040 }
uint32_t linewidth
usual segment : line with rounded ends
ALTIUM_LAYER layer
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
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
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:132
#define _(s)
Definition: 3d_actions.cpp:33
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
std::vector< wxPoint > referencePoint

References _, BOARD::Add(), APPEND, Eco1_User, Format(), GetKicadLayer(), ADIMENSION6::layer, ADIMENSION6::linewidth, m_board, ADIMENSION6::referencePoint, S_SEGMENT, BOARD_ITEM::SetLayer(), PCB_SHAPE::SetShape(), PCB_SHAPE::SetStart(), PCB_SHAPE::SetWidth(), and UNDEFINED_LAYER.

◆ HelperParseDimensions6Leader()

void ALTIUM_PCB::HelperParseDimensions6Leader ( const ADIMENSION6 aElem)
private

Definition at line 941 of file altium_pcb.cpp.

942 {
943  PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
944  if( klayer == UNDEFINED_LAYER )
945  {
946  wxLogWarning( wxString::Format(
947  _( "Dimension on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
948  aElem.layer ) );
949  klayer = Eco1_User;
950  }
951 
952  if( !aElem.referencePoint.empty() )
953  {
954  wxPoint referencePoint0 = aElem.referencePoint.at( 0 );
955 
956  // line
957  wxPoint last = referencePoint0;
958  for( size_t i = 1; i < aElem.referencePoint.size(); i++ )
959  {
960  PCB_SHAPE* shape = new PCB_SHAPE( m_board );
961  m_board->Add( shape, ADD_MODE::APPEND );
962  shape->SetShape( S_SEGMENT );
963  shape->SetLayer( klayer );
964  shape->SetWidth( aElem.linewidth );
965  shape->SetStart( last );
966  shape->SetEnd( aElem.referencePoint.at( i ) );
967  last = aElem.referencePoint.at( i );
968  }
969 
970  // arrow
971  if( aElem.referencePoint.size() >= 2 )
972  {
973  wxPoint dirVec = aElem.referencePoint.at( 1 ) - referencePoint0;
974  if( dirVec.x != 0 || dirVec.y != 0 )
975  {
976  double scaling = EuclideanNorm( dirVec ) / aElem.arrowsize;
977  wxPoint arrVec =
978  wxPoint( KiROUND( dirVec.x / scaling ), KiROUND( dirVec.y / scaling ) );
979  RotatePoint( &arrVec, 200. );
980 
981  PCB_SHAPE* shape1 = new PCB_SHAPE( m_board );
982  m_board->Add( shape1, ADD_MODE::APPEND );
983  shape1->SetShape( S_SEGMENT );
984  shape1->SetLayer( klayer );
985  shape1->SetWidth( aElem.linewidth );
986  shape1->SetStart( referencePoint0 );
987  shape1->SetEnd( referencePoint0 + arrVec );
988 
989  RotatePoint( &arrVec, -400. );
990 
991  PCB_SHAPE* shape2 = new PCB_SHAPE( m_board );
992  m_board->Add( shape2, ADD_MODE::APPEND );
993  shape2->SetShape( S_SEGMENT );
994  shape2->SetLayer( klayer );
995  shape2->SetWidth( aElem.linewidth );
996  shape2->SetStart( referencePoint0 );
997  shape2->SetEnd( referencePoint0 + arrVec );
998  }
999  }
1000  }
1001 
1002  if( aElem.textPoint.empty() )
1003  {
1004  wxLogError( "No text position present for leader dimension object" );
1005  return;
1006  }
1007 
1008  PCB_TEXT* text = new PCB_TEXT( m_board );
1009  m_board->Add( text, ADD_MODE::APPEND );
1010  text->SetText( aElem.textformat );
1011  text->SetPosition( aElem.textPoint.at( 0 ) );
1012  text->SetLayer( klayer );
1013  text->SetTextSize( wxSize( aElem.textheight, aElem.textheight ) ); // TODO: parse text width
1014  text->SetTextThickness( aElem.textlinewidth );
1017 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:134
uint32_t textlinewidth
uint32_t linewidth
usual segment : line with rounded ends
virtual void SetPosition(const wxPoint &aPos) override
Definition: pcb_text.h:77
ALTIUM_LAYER layer
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
std::vector< wxPoint > textPoint
wxString textformat
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:120
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:209
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
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:132
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:208
#define _(s)
Definition: 3d_actions.cpp:33
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
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
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:164
std::vector< wxPoint > referencePoint
uint32_t textheight
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:143

References _, BOARD::Add(), APPEND, ADIMENSION6::arrowsize, Eco1_User, EuclideanNorm(), Format(), GetKicadLayer(), GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_BOTTOM, KiROUND(), ADIMENSION6::layer, ADIMENSION6::linewidth, m_board, ADIMENSION6::referencePoint, RotatePoint(), S_SEGMENT, PCB_SHAPE::SetEnd(), EDA_TEXT::SetHorizJustify(), BOARD_ITEM::SetLayer(), PCB_TEXT::SetPosition(), PCB_SHAPE::SetShape(), PCB_SHAPE::SetStart(), EDA_TEXT::SetText(), EDA_TEXT::SetTextSize(), EDA_TEXT::SetTextThickness(), EDA_TEXT::SetVertJustify(), PCB_SHAPE::SetWidth(), ADIMENSION6::textformat, ADIMENSION6::textheight, ADIMENSION6::textlinewidth, ADIMENSION6::textPoint, and UNDEFINED_LAYER.

Referenced by ParseDimensions6Data().

◆ HelperParseDimensions6Linear()

void ALTIUM_PCB::HelperParseDimensions6Linear ( const ADIMENSION6 aElem)
private

Basically REFERENCE0POINT and REFERENCE1POINT are the two end points of the dimension. XY1 is the position of the arrow above REFERENCE0POINT. those three points are not necesarily in 90degree angle, but KiCad requires this to show the correct measurements.

Therefore, we take the vector of REFERENCE0POINT -> XY1, calculate the normal, and intersect it with REFERENCE1POINT pointing the same direction as REFERENCE0POINT -> XY1. This should give us a valid measurement point where we can place the drawsegment.

Definition at line 858 of file altium_pcb.cpp.

859 {
860  if( aElem.referencePoint.size() != 2 )
861  {
862  THROW_IO_ERROR( "Incorrect number of reference points for linear dimension object" );
863  }
864 
865  PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
866 
867  if( klayer == UNDEFINED_LAYER )
868  {
869  wxLogWarning( wxString::Format(
870  _( "Dimension on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
871  aElem.layer ) );
872  klayer = Eco1_User;
873  }
874 
875  wxPoint referencePoint0 = aElem.referencePoint.at( 0 );
876  wxPoint referencePoint1 = aElem.referencePoint.at( 1 );
877 
878  ALIGNED_DIMENSION* dimension = new ALIGNED_DIMENSION( m_board );
879  m_board->Add( dimension, ADD_MODE::APPEND );
880 
881  dimension->SetPrecision( aElem.textprecission );
882  dimension->SetLayer( klayer );
883  dimension->SetStart( referencePoint0 );
884 
885  if( referencePoint0 != aElem.xy1 )
886  {
896  wxPoint direction = aElem.xy1 - referencePoint0;
897  wxPoint directionNormalVector = wxPoint( -direction.y, direction.x );
898  SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
899  SEG segm2( referencePoint1, referencePoint1 + direction );
900  wxPoint intersection( segm1.Intersect( segm2, true, true ).get() );
901  dimension->SetEnd( intersection );
902 
903  int height = static_cast<int>( EuclideanNorm( direction ) );
904 
905  if( direction.x <= 0 && direction.y <= 0 ) // TODO: I suspect this is not always correct
906  {
907  height = -height;
908  }
909 
910  dimension->SetHeight( height );
911  }
912  else
913  {
914  dimension->SetEnd( referencePoint1 );
915  }
916 
917  dimension->SetLineThickness( aElem.linewidth );
918 
919  dimension->Text().SetTextThickness( aElem.textlinewidth );
920  dimension->Text().SetTextSize( wxSize( aElem.textheight, aElem.textheight ) );
921  dimension->Text().SetBold( aElem.textbold );
922  dimension->Text().SetItalic( aElem.textitalic );
923 
924  switch( aElem.textunit )
925  {
926  case ALTIUM_UNIT::INCHES:
927  dimension->SetUnits( EDA_UNITS::INCHES );
928  break;
929  case ALTIUM_UNIT::MILS:
930  dimension->SetUnits( EDA_UNITS::MILS );
931  break;
934  dimension->SetUnits( EDA_UNITS::MILLIMETRES );
935  break;
936  default:
937  break;
938  }
939 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:134
uint32_t textlinewidth
uint32_t linewidth
ALTIUM_LAYER layer
int32_t textprecission
virtual void SetStart(const wxPoint &aPoint)
void SetItalic(bool isItalic)
Definition: eda_text.h:185
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
void SetHeight(int aHeight)
Sets the distance from the feature points to the crossbar line.
PCB_TEXT & Text()
void SetPrecision(int aPrecision)
Definition: seg.h:39
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
#define _(s)
Definition: 3d_actions.cpp:33
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:164
ALTIUM_UNIT textunit
std::vector< wxPoint > referencePoint
For better understanding of the points that make a dimension:
void SetBold(bool aBold)
Definition: eda_text.h:188
uint32_t textheight
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void SetLineThickness(int aWidth)
virtual void SetEnd(const wxPoint &aPoint)
void SetUnits(EDA_UNITS aUnits)

References _, BOARD::Add(), APPEND, CENTIMETER, Eco1_User, EuclideanNorm(), Format(), GetKicadLayer(), INCHES, SEG::Intersect(), ADIMENSION6::layer, ADIMENSION6::linewidth, m_board, MILLIMETERS, MILLIMETRES, MILS, ADIMENSION6::referencePoint, EDA_TEXT::SetBold(), DIMENSION::SetEnd(), ALIGNED_DIMENSION::SetHeight(), EDA_TEXT::SetItalic(), DIMENSION::SetLayer(), DIMENSION::SetLineThickness(), DIMENSION::SetPrecision(), DIMENSION::SetStart(), EDA_TEXT::SetTextSize(), EDA_TEXT::SetTextThickness(), DIMENSION::SetUnits(), DIMENSION::Text(), ADIMENSION6::textbold, ADIMENSION6::textheight, ADIMENSION6::textitalic, ADIMENSION6::textlinewidth, ADIMENSION6::textprecission, ADIMENSION6::textunit, THROW_IO_ERROR, UNDEFINED_LAYER, and ADIMENSION6::xy1.

Referenced by ParseDimensions6Data().

◆ HelperParsePad6NonCopper()

void ALTIUM_PCB::HelperParsePad6NonCopper ( const APAD6 aElem)
private

Definition at line 1882 of file altium_pcb.cpp.

1883 {
1884  PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
1885 
1886  if( klayer == UNDEFINED_LAYER )
1887  {
1888  wxLogWarning( wxString::Format(
1889  _( "Non-Copper Pad on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
1890  aElem.layer ) );
1891  klayer = Eco1_User;
1892  }
1893 
1894  if( aElem.net != ALTIUM_NET_UNCONNECTED )
1895  {
1896  wxLogError( wxString::Format(
1897  "Non-Copper Pad '%s' is connected to a net. This is not supported", aElem.name ) );
1898  }
1899 
1900  if( aElem.holesize != 0 )
1901  {
1902  wxLogError( wxString::Format(
1903  "Non-Copper Pad '%s' has a hole. This should not happen", aElem.name ) );
1904  }
1905 
1906  if( aElem.padmode != ALTIUM_PAD_MODE::SIMPLE )
1907  {
1908  wxLogWarning( wxString::Format(
1909  _( "Non-Copper Pad '%s' uses a complex pad stack (kind %d). This should not happen" ),
1910  aElem.name, aElem.padmode ) );
1911  }
1912 
1913  switch( aElem.topshape )
1914  {
1916  {
1917  // filled rect
1919  shape->SetShape( S_POLYGON );
1920  shape->SetLayer( klayer );
1921  shape->SetWidth( 0 );
1922 
1923  shape->SetPolyPoints( { aElem.position + wxPoint( aElem.topsize.x / 2, aElem.topsize.y / 2 ),
1924  aElem.position + wxPoint( aElem.topsize.x / 2, -aElem.topsize.y / 2 ),
1925  aElem.position + wxPoint( -aElem.topsize.x / 2, -aElem.topsize.y / 2 ),
1926  aElem.position + wxPoint( -aElem.topsize.x / 2, aElem.topsize.y / 2 ) } );
1927 
1928  if( aElem.direction != 0 )
1929  shape->Rotate( aElem.position, aElem.direction * 10 );
1930 
1931  HelperDrawsegmentSetLocalCoord( shape, aElem.component );
1932  }
1933  break;
1934 
1936  if( aElem.sizeAndShape
1937  && aElem.sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
1938  {
1939  // filled roundrect
1940  int cornerradius = aElem.sizeAndShape->cornerradius[0];
1941  int offset = ( std::min( aElem.topsize.x, aElem.topsize.y ) * cornerradius ) / 200;
1942 
1944  shape->SetLayer( klayer );
1945  shape->SetWidth( offset * 2 );
1946 
1947  if( cornerradius < 100 )
1948  {
1949  int offsetX = aElem.topsize.x / 2 - offset;
1950  int offsetY = aElem.topsize.y / 2 - offset;
1951 
1952  wxPoint p11 = aElem.position + wxPoint( offsetX, offsetY );
1953  wxPoint p12 = aElem.position + wxPoint( offsetX, -offsetY );
1954  wxPoint p22 = aElem.position + wxPoint( -offsetX, -offsetY );
1955  wxPoint p21 = aElem.position + wxPoint( -offsetX, offsetY );
1956 
1957  shape->SetShape( S_POLYGON );
1958  shape->SetPolyPoints( { p11, p12, p22, p21 } );
1959  }
1960  else if( aElem.topsize.x == aElem.topsize.y )
1961  {
1962  // circle
1963  shape->SetShape( S_CIRCLE );
1964  shape->SetCenter( aElem.position );
1965  shape->SetWidth( aElem.topsize.x / 2 );
1966  shape->SetArcStart( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) );
1967  }
1968  else if( aElem.topsize.x < aElem.topsize.y )
1969  {
1970  // short vertical line
1971  shape->SetShape( S_SEGMENT );
1972  wxPoint pointOffset( 0, ( aElem.topsize.y - aElem.topsize.x ) / 2 );
1973  shape->SetStart( aElem.position + pointOffset );
1974  shape->SetEnd( aElem.position - pointOffset );
1975  }
1976  else
1977  {
1978  // short horizontal line
1979  shape->SetShape( S_SEGMENT );
1980  wxPoint pointOffset( ( aElem.topsize.x - aElem.topsize.y ) / 2, 0 );
1981  shape->SetStart( aElem.position + pointOffset );
1982  shape->SetEnd( aElem.position - pointOffset );
1983  }
1984 
1985  if( aElem.direction != 0 )
1986  shape->Rotate( aElem.position, aElem.direction * 10 );
1987 
1988  HelperDrawsegmentSetLocalCoord( shape, aElem.component );
1989  }
1990  else if( aElem.topsize.x == aElem.topsize.y )
1991  {
1992  // filled circle
1994  shape->SetShape( S_CIRCLE );
1995  shape->SetLayer( klayer );
1996  shape->SetCenter( aElem.position );
1997  shape->SetWidth( aElem.topsize.x / 2 );
1998  shape->SetArcStart( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) );
1999  HelperDrawsegmentSetLocalCoord( shape, aElem.component );
2000  }
2001  else
2002  {
2003  // short line
2005  shape->SetShape( S_SEGMENT );
2006  shape->SetLayer( klayer );
2007  shape->SetWidth( std::min( aElem.topsize.x, aElem.topsize.y ) );
2008 
2009  if( aElem.topsize.x < aElem.topsize.y )
2010  {
2011  wxPoint offset( 0, ( aElem.topsize.y - aElem.topsize.x ) / 2 );
2012  shape->SetStart( aElem.position + offset );
2013  shape->SetEnd( aElem.position - offset );
2014  }
2015  else
2016  {
2017  wxPoint offset( ( aElem.topsize.x - aElem.topsize.y ) / 2, 0 );
2018  shape->SetStart( aElem.position + offset );
2019  shape->SetEnd( aElem.position - offset );
2020  }
2021 
2022  if( aElem.direction != 0 )
2023  shape->Rotate( aElem.position, aElem.direction * 10. );
2024 
2025  HelperDrawsegmentSetLocalCoord( shape, aElem.component );
2026  }
2027  break;
2028 
2030  {
2031  // filled octagon
2033  shape->SetShape( S_POLYGON );
2034  shape->SetLayer( klayer );
2035  shape->SetWidth( 0 );
2036 
2037  wxPoint p11 = aElem.position + wxPoint( aElem.topsize.x / 2, aElem.topsize.y / 2 );
2038  wxPoint p12 = aElem.position + wxPoint( aElem.topsize.x / 2, -aElem.topsize.y / 2 );
2039  wxPoint p22 = aElem.position + wxPoint( -aElem.topsize.x / 2, -aElem.topsize.y / 2 );
2040  wxPoint p21 = aElem.position + wxPoint( -aElem.topsize.x / 2, aElem.topsize.y / 2 );
2041 
2042  int chamfer = std::min( aElem.topsize.x, aElem.topsize.y ) / 4;
2043  wxPoint chamferX( chamfer, 0 );
2044  wxPoint chamferY( 0, chamfer );
2045 
2046  shape->SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
2047  p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
2048 
2049  if( aElem.direction != 0. )
2050  shape->Rotate( aElem.position, aElem.direction * 10 );
2051 
2052  HelperDrawsegmentSetLocalCoord( shape, aElem.component );
2053  }
2054  break;
2055 
2057  default:
2058  wxLogError(
2059  wxString::Format( "Non-Copper Pad '%s' uses a unknown pad-shape", aElem.name ) );
2060  break;
2061  }
2062 }
usual segment : line with rounded ends
ALTIUM_PAD_SHAPE topshape
wxSize topsize
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
uint16_t component
wxString name
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
Definition: pcb_shape.cpp:193
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
PCB_LAYER_ID
A quick note on layer IDs:
double direction
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
const uint16_t ALTIUM_NET_UNCONNECTED
uint32_t holesize
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
Definition: pcb_shape.h:213
ALTIUM_LAYER layer
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
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:132
polygon (not yet used for tracks, but could be in microwave apps)
#define _(s)
Definition: 3d_actions.cpp:33
wxPoint position
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
ALTIUM_PAD_MODE padmode
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
PCB_SHAPE * HelperCreateAndAddDrawsegment(uint16_t aComponent)
Definition: altium_pcb.cpp:111
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
Definition: pcb_shape.cpp:1057
void HelperDrawsegmentSetLocalCoord(PCB_SHAPE *aShape, uint16_t aComponent)
Definition: altium_pcb.cpp:137
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:143
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
Definition: pcb_shape.h:197
uint16_t net

References _, ALTIUM_NET_UNCONNECTED, CIRCLE, APAD6::component, APAD6::direction, Eco1_User, Format(), GetKicadLayer(), HelperCreateAndAddDrawsegment(), HelperDrawsegmentSetLocalCoord(), APAD6::holesize, APAD6::layer, APAD6::name, APAD6::net, OCTAGONAL, APAD6::padmode, APAD6::position, RECT, PCB_SHAPE::Rotate(), ROUNDRECT, S_CIRCLE, S_POLYGON, S_SEGMENT, PCB_SHAPE::SetArcStart(), PCB_SHAPE::SetCenter(), PCB_SHAPE::SetEnd(), BOARD_ITEM::SetLayer(), PCB_SHAPE::SetPolyPoints(), PCB_SHAPE::SetShape(), PCB_SHAPE::SetStart(), PCB_SHAPE::SetWidth(), SIMPLE, APAD6::sizeAndShape, APAD6::topshape, APAD6::topsize, UNDEFINED_LAYER, and UNKNOWN.

Referenced by ParsePads6Data().

◆ Parse()

void ALTIUM_PCB::Parse ( const CFB::CompoundFileReader &  aReader,
const std::map< ALTIUM_PCB_DIR, std::string > &  aFileMapping 
)

Definition at line 305 of file altium_pcb.cpp.

307 {
308  // this vector simply declares in which order which functions to call.
309  const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
311  [this]( auto aReader, auto fileHeader ) {
312  this->ParseFileHeader( aReader, fileHeader );
313  } },
314  { true, ALTIUM_PCB_DIR::BOARD6,
315  [this]( auto aReader, auto fileHeader ) {
316  this->ParseBoard6Data( aReader, fileHeader );
317  } },
319  [this]( auto aReader, auto fileHeader ) {
320  this->ParseComponents6Data( aReader, fileHeader );
321  } },
322  { true, ALTIUM_PCB_DIR::MODELS,
323  [this, aFileMapping]( auto aReader, auto fileHeader ) {
324  wxString dir( aFileMapping.at( ALTIUM_PCB_DIR::MODELS ) );
325  dir.RemoveLast( 4 ); // Remove "Data" from the path
326  this->ParseModelsData( aReader, fileHeader, dir );
327  } },
329  [this]( auto aReader, auto fileHeader ) {
330  this->ParseComponentsBodies6Data( aReader, fileHeader );
331  } },
332  { true, ALTIUM_PCB_DIR::NETS6,
333  [this]( auto aReader, auto fileHeader ) {
334  this->ParseNets6Data( aReader, fileHeader );
335  } },
336  { true, ALTIUM_PCB_DIR::CLASSES6,
337  [this]( auto aReader, auto fileHeader ) {
338  this->ParseClasses6Data( aReader, fileHeader );
339  } },
340  { true, ALTIUM_PCB_DIR::RULES6,
341  [this]( auto aReader, auto fileHeader ) {
342  this->ParseRules6Data( aReader, fileHeader );
343  } },
345  [this]( auto aReader, auto fileHeader ) {
346  this->ParseDimensions6Data( aReader, fileHeader );
347  } },
349  [this]( auto aReader, auto fileHeader ) {
350  this->ParsePolygons6Data( aReader, fileHeader );
351  } },
352  { true, ALTIUM_PCB_DIR::ARCS6,
353  [this]( auto aReader, auto fileHeader ) {
354  this->ParseArcs6Data( aReader, fileHeader );
355  } },
356  { true, ALTIUM_PCB_DIR::PADS6,
357  [this]( auto aReader, auto fileHeader ) {
358  this->ParsePads6Data( aReader, fileHeader );
359  } },
360  { true, ALTIUM_PCB_DIR::VIAS6,
361  [this]( auto aReader, auto fileHeader ) {
362  this->ParseVias6Data( aReader, fileHeader );
363  } },
364  { true, ALTIUM_PCB_DIR::TRACKS6,
365  [this]( auto aReader, auto fileHeader ) {
366  this->ParseTracks6Data( aReader, fileHeader );
367  } },
368  { true, ALTIUM_PCB_DIR::TEXTS6,
369  [this]( auto aReader, auto fileHeader ) {
370  this->ParseTexts6Data( aReader, fileHeader );
371  } },
372  { true, ALTIUM_PCB_DIR::FILLS6,
373  [this]( auto aReader, auto fileHeader ) {
374  this->ParseFills6Data( aReader, fileHeader );
375  } },
377  [this]( auto aReader, auto fileHeader ) {
378  this->ParseBoardRegionsData( aReader, fileHeader );
379  } },
381  [this]( auto aReader, auto fileHeader ) {
382  this->ParseShapeBasedRegions6Data( aReader, fileHeader );
383  } },
384  { true, ALTIUM_PCB_DIR::REGIONS6,
385  [this]( auto aReader, auto fileHeader ) {
386  this->ParseRegions6Data( aReader, fileHeader );
387  } }
388  };
389 
390  // Parse data in specified order
391  for( const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
392  {
393  bool isRequired;
394  ALTIUM_PCB_DIR directory;
396  std::tie( isRequired, directory, fp ) = cur;
397 
398  const auto& mappedDirectory = aFileMapping.find( directory );
399  if( mappedDirectory == aFileMapping.end() )
400  {
401  wxASSERT_MSG( !isRequired,
403  "Altium Directory of kind %d was expected, but no mapping is present in the code",
404  directory ) );
405  continue;
406  }
407 
408  const CFB::COMPOUND_FILE_ENTRY* file =
409  FindStream( aReader, mappedDirectory->second.c_str() );
410  if( file != nullptr )
411  {
412  fp( aReader, file );
413  }
414  else if( isRequired )
415  {
416  wxLogError( wxString::Format( _( "File not found: '%s'" ), mappedDirectory->second ) );
417  }
418  }
419 
420  // fixup zone priorities since Altium stores them in the opposite order
421  for( auto& zone : m_polygons )
422  {
423  if( !zone )
424  continue;
425 
426  // Altium "fills" - not poured in Altium
427  if( zone->GetPriority() == 1000 )
428  {
429  // Unlikely, but you never know
430  if( m_highest_pour_index >= 1000 )
431  zone->SetPriority( m_highest_pour_index + 1 );
432 
433  continue;
434  }
435 
436  int priority = m_highest_pour_index - zone->GetPriority();
437 
438  zone->SetPriority( priority >= 0 ? priority : 0 );
439  }
440 
441  // change priority of outer zone to zero
442  for( auto& zone : m_outer_plane )
443  {
444  zone.second->SetPriority( 0 );
445  }
446 
447  // Finish Board by recalculating module boundingboxes
448  for( auto& module : m_board->Modules() )
449  {
450  module->CalculateBoundingBox();
451  }
452 
453  // Otherwise we cannot save the imported board
454  m_board->SetModified();
455 }
void SetModified()
Definition: eda_item.cpp:79
void ParseVias6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseShapeBasedRegions6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseComponents6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
Definition: altium_pcb.cpp:743
void ParseRules6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParsePolygons6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::vector< ZONE_CONTAINER * > m_polygons
Definition: altium_pcb.h:187
void ParseComponentsBodies6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
Definition: altium_pcb.cpp:786
void ParseArcs6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
const CFB::COMPOUND_FILE_ENTRY * FindStream(const CFB::CompoundFileReader &aReader, const char *aStreamName)
void ParsePads6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseRegions6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
BOARD * m_board
Definition: altium_pcb.h:185
void ParseDimensions6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
MODULES & Modules()
Definition: class_board.h:284
void ParseTexts6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseClasses6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
Definition: altium_pcb.cpp:707
ALTIUM_PCB_DIR
Definition: altium_pcb.h:34
std::map< ALTIUM_LAYER, ZONE_CONTAINER * > m_outer_plane
Definition: altium_pcb.h:193
void ParseFileHeader(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
Definition: altium_pcb.cpp:508
void ParseBoardRegionsData(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
int m_highest_pour_index
Altium stores pour order across all layers.
Definition: altium_pcb.h:196
void ParseModelsData(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry, const wxString aRootDir)
void ParseTracks6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
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
void ParseNets6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
#define _(s)
Definition: 3d_actions.cpp:33
void ParseFills6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseBoard6Data(const CFB::CompoundFileReader &aReader, const CFB::COMPOUND_FILE_ENTRY *aEntry)
Definition: altium_pcb.cpp:527
std::function< void(const CFB::CompoundFileReader &, const CFB::COMPOUND_FILE_ENTRY *)> PARSE_FUNCTION_POINTER_fp
Definition: altium_pcb.h:109

References _, ARCS6, BOARD6, BOARDREGIONS, CLASSES6, COMPONENTBODIES6, COMPONENTS6, DIMENSIONS6, FILE_HEADER, FILLS6, FindStream(), Format(), m_board, m_highest_pour_index, m_outer_plane, m_polygons, MODELS, BOARD::Modules(), NETS6, PADS6, ParseArcs6Data(), ParseBoard6Data(), ParseBoardRegionsData(), ParseClasses6Data(), ParseComponents6Data(), ParseComponentsBodies6Data(), ParseDimensions6Data(), ParseFileHeader(), ParseFills6Data(), ParseModelsData(), ParseNets6Data(), ParsePads6Data(), ParsePolygons6Data(), ParseRegions6Data(), ParseRules6Data(), ParseShapeBasedRegions6Data(), ParseTexts6Data(), ParseTracks6Data(), ParseVias6Data(), POLYGONS6, REGIONS6, RULES6, EDA_ITEM::SetModified(), SHAPEBASEDREGIONS6, TEXTS6, TRACKS6, and VIAS6.

◆ ParseArcs6Data()

void ALTIUM_PCB::ParseArcs6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1534 of file altium_pcb.cpp.

1536 {
1537  ALTIUM_PARSER reader( aReader, aEntry );
1538 
1539  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1540  {
1541  AARC6 elem( reader );
1542 
1543  if( elem.is_polygonoutline || elem.subpolyindex != ALTIUM_POLYGON_NONE )
1544  continue;
1545 
1546  // element in plane is in fact substracted from the plane. Should be already done by Altium?
1547  //if( IsAltiumLayerAPlane( elem.layer ) )
1548  // continue;
1549 
1550  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
1551 
1552  if( elem.is_keepout || IsAltiumLayerAPlane( elem.layer ) )
1553  {
1554  PCB_SHAPE shape( nullptr ); // just a helper to get the graphic
1555  shape.SetWidth( elem.width );
1556  shape.SetCenter( elem.center );
1557 
1558  if( elem.startangle == 0. && elem.endangle == 360. )
1559  { // TODO: other variants to define circle?
1560  shape.SetShape( S_CIRCLE );
1561  shape.SetArcStart( elem.center - wxPoint( 0, elem.radius ) );
1562  }
1563  else
1564  {
1565  shape.SetShape( S_ARC );
1566  shape.SetAngle( -NormalizeAngleDegreesPos( elem.endangle - elem.startangle ) * 10. );
1567 
1568  double startradiant = DEG2RAD( elem.startangle );
1569  wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ),
1570  -KiROUND( std::sin( startradiant ) * elem.radius ) );
1571  shape.SetArcStart( elem.center + arcStartOffset );
1572  }
1573 
1574  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
1575  m_board->Add( zone, ADD_MODE::APPEND );
1576 
1577  zone->SetIsRuleArea( true );
1578  zone->SetDoNotAllowTracks( false );
1579  zone->SetDoNotAllowVias( false );
1580  zone->SetDoNotAllowPads( false );
1581  zone->SetDoNotAllowFootprints( false );
1582  zone->SetDoNotAllowCopperPour( true );
1583 
1584  if( elem.layer == ALTIUM_LAYER::MULTI_LAYER )
1585  {
1586  zone->SetLayer( F_Cu );
1587  zone->SetLayerSet( LSET::AllCuMask() );
1588  }
1589  else
1590  {
1591  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
1592  if( klayer == UNDEFINED_LAYER )
1593  {
1594  wxLogWarning( wxString::Format(
1595  _( "Arc Keepout on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
1596  elem.layer ) );
1597  klayer = Eco1_User;
1598  }
1599  zone->SetLayer( klayer );
1600  }
1601 
1602  shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF,
1603  ERROR_INSIDE );
1604  zone->Outline()->Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); // the outline is not a single polygon!
1605 
1608  continue;
1609  }
1610 
1611  if( klayer == UNDEFINED_LAYER )
1612  {
1613  wxLogWarning( wxString::Format(
1614  _( "Arc on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
1615  elem.layer ) );
1616  klayer = Eco1_User;
1617  }
1618 
1619  if( klayer >= F_Cu && klayer <= B_Cu )
1620  {
1621  double angle = -NormalizeAngleDegreesPos( elem.endangle - elem.startangle );
1622  double startradiant = DEG2RAD( elem.startangle );
1623  wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ),
1624  -KiROUND( std::sin( startradiant ) * elem.radius ) );
1625 
1626  SHAPE_ARC shapeArc( elem.center, elem.center + arcStartOffset, angle, elem.width );
1627  ARC* arc = new ARC( m_board, &shapeArc );
1628  m_board->Add( arc, ADD_MODE::APPEND );
1629 
1630  arc->SetWidth( elem.width );
1631  arc->SetLayer( klayer );
1632  arc->SetNetCode( GetNetCode( elem.net ) );
1633  }
1634  else
1635  {
1636  PCB_SHAPE* shape = HelperCreateAndAddDrawsegment( elem.component );
1637  shape->SetCenter( elem.center );
1638  shape->SetWidth( elem.width );
1639  shape->SetLayer( klayer );
1640 
1641  if( elem.startangle == 0. && elem.endangle == 360. )
1642  { // TODO: other variants to define circle?
1643  shape->SetShape( S_CIRCLE );
1644  shape->SetArcStart( elem.center - wxPoint( 0, elem.radius ) );
1645  }
1646  else
1647  {
1648  shape->SetShape( S_ARC );
1649  shape->SetAngle( -NormalizeAngleDegreesPos( elem.endangle - elem.startangle ) * 10. );
1650 
1651  double startradiant = DEG2RAD( elem.startangle );
1652  wxPoint arcStartOffset = wxPoint( KiROUND( std::cos( startradiant ) * elem.radius ),
1653  -KiROUND( std::sin( startradiant ) * elem.radius ) );
1654  shape->SetArcStart( elem.center + arcStartOffset );
1655  }
1656 
1657  HelperDrawsegmentSetLocalCoord( shape, elem.component );
1658  }
1659  }
1660 
1661  if( reader.GetRemainingBytes() != 0 )
1662  {
1663  THROW_IO_ERROR( "Arcs6 stream is not fully parsed" );
1664  }
1665 }
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:738
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void SetDoNotAllowFootprints(bool aEnable)
Definition: class_zone.h:740
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:300
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
const uint16_t ALTIUM_POLYGON_NONE
void SetIsRuleArea(bool aEnable)
Definition: class_zone.h:735
Arcs (with rounded ends)
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:737
void SetWidth(int aWidth)
Definition: class_track.h:109
int GetNetCode(uint16_t aId) const
Definition: altium_pcb.cpp:457
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
double NormalizeAngleDegreesPos(double Angle)
Normalize angle to be in the 0.0 .
Definition: trigo.h:285
BOARD * m_board
Definition: altium_pcb.h:185
void SetLayerSet(LSET aLayerSet) override
Definition: class_zone.cpp:242
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:234
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
Definition: pcb_shape.h:213
void SetDoNotAllowPads(bool aEnable)
Definition: class_zone.h:739
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetBorderDisplayStyle sets all hatch parameters for the zone.
Definition: class_zone.cpp:888
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:736
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
double DEG2RAD(double deg)
Definition: trigo.h:220
#define _(s)
Definition: 3d_actions.cpp:33
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
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
virtual void SetAngle(double aAngle, bool aUpdateEnd=true)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
Definition: pcb_shape.cpp:435
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
Definition: altium_pcb.cpp:105
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
PCB_SHAPE * HelperCreateAndAddDrawsegment(uint16_t aComponent)
Definition: altium_pcb.cpp:111
void HelperDrawsegmentSetLocalCoord(PCB_SHAPE *aShape, uint16_t aComponent)
Definition: altium_pcb.cpp:137
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
Definition: pcb_shape.h:197

References _, BOARD::Add(), LSET::AllCuMask(), ALTIUM_POLYGON_NONE, PNS::angle(), APPEND, ARC, B_Cu, AARC6::center, AARC6::component, DEG2RAD(), DIAGONAL_EDGE, Eco1_User, AARC6::endangle, ERROR_INSIDE, F_Cu, Format(), ZONE_CONTAINER::GetDefaultHatchPitch(), GetKicadLayer(), GetNetCode(), ALTIUM_PARSER::GetRemainingBytes(), HelperCreateAndAddDrawsegment(), HelperDrawsegmentSetLocalCoord(), AARC6::is_keepout, AARC6::is_polygonoutline, IsAltiumLayerAPlane(), KiROUND(), AARC6::layer, m_board, MULTI_LAYER, AARC6::net, NormalizeAngleDegreesPos(), ZONE_CONTAINER::Outline(), SHAPE_POLY_SET::PM_STRICTLY_SIMPLE, AARC6::radius, S_ARC, S_CIRCLE, PCB_SHAPE::SetAngle(), PCB_SHAPE::SetArcStart(), ZONE_CONTAINER::SetBorderDisplayStyle(), PCB_SHAPE::SetCenter(), ZONE_CONTAINER::SetDoNotAllowCopperPour(), ZONE_CONTAINER::SetDoNotAllowFootprints(), ZONE_CONTAINER::SetDoNotAllowPads(), ZONE_CONTAINER::SetDoNotAllowTracks(), ZONE_CONTAINER::SetDoNotAllowVias(), ZONE_CONTAINER::SetIsRuleArea(), ZONE_CONTAINER::SetLayer(), BOARD_ITEM::SetLayer(), ZONE_CONTAINER::SetLayerSet(), BOARD_CONNECTED_ITEM::SetNetCode(), PCB_SHAPE::SetShape(), PCB_SHAPE::SetWidth(), TRACK::SetWidth(), SHAPE_POLY_SET::Simplify(), AARC6::startangle, AARC6::subpolyindex, THROW_IO_ERROR, PCB_SHAPE::TransformShapeWithClearanceToPolygon(), UNDEFINED_LAYER, and AARC6::width.

Referenced by Parse().

◆ ParseBoard6Data()

void ALTIUM_PCB::ParseBoard6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 527 of file altium_pcb.cpp.

529 {
530  ALTIUM_PARSER reader( aReader, aEntry );
531 
532  ABOARD6 elem( reader );
533 
534  if( reader.GetRemainingBytes() != 0 )
535  {
536  THROW_IO_ERROR( "Board6 stream is not fully parsed" );
537  }
538 
539  m_board->GetDesignSettings().m_AuxOrigin = elem.sheetpos;
540  m_board->GetDesignSettings().m_GridOrigin = elem.sheetpos;
541 
542  // read layercount from stackup, because LAYERSETSCOUNT is not always correct?!
543  size_t layercount = 0;
544  for( size_t i = static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
545  i < elem.stackup.size() && i != 0; i = elem.stackup[i - 1].nextId, layercount++ )
546  ;
547  size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
548  m_board->SetCopperLayerCount( kicadLayercount );
549 
550  BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
551  BOARD_STACKUP& stackup = designSettings.GetStackupDescriptor();
552 
553  // create board stackup
554  stackup.RemoveAll(); // Just to be sure
555  stackup.BuildDefaultStackupList( &designSettings, layercount );
556 
557  auto it = stackup.GetList().begin();
558  // find first copper layer
559  for( ; it != stackup.GetList().end() && ( *it )->GetType() != BS_ITEM_TYPE_COPPER; ++it )
560  ;
561 
562  auto curLayer = static_cast<int>( F_Cu );
563  for( size_t altiumLayerId = static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
564  altiumLayerId < elem.stackup.size() && altiumLayerId != 0;
565  altiumLayerId = elem.stackup[altiumLayerId - 1].nextId )
566  {
567  // array starts with 0, but stackup with 1
568  ABOARD6_LAYER_STACKUP& layer = elem.stackup.at( altiumLayerId - 1 );
569 
570  // handle unused layer in case of odd layercount
571  if( layer.nextId == 0 && layercount != kicadLayercount )
572  {
573  m_board->SetLayerName( ( *it )->GetBrdLayerId(), "[unused]" );
574 
575  if( ( *it )->GetType() != BS_ITEM_TYPE_COPPER )
576  {
577  THROW_IO_ERROR( "Board6 stream, unexpected item while parsing stackup" );
578  }
579  ( *it )->SetThickness( 0 );
580 
581  ++it;
582  if( ( *it )->GetType() != BS_ITEM_TYPE_DIELECTRIC )
583  {
584  THROW_IO_ERROR( "Board6 stream, unexpected item while parsing stackup" );
585  }
586  ( *it )->SetThickness( 0, 0 );
587  ( *it )->SetThicknessLocked( true, 0 );
588  ++it;
589  }
590 
591  m_layermap.insert( { static_cast<ALTIUM_LAYER>( altiumLayerId ),
592  static_cast<PCB_LAYER_ID>( curLayer++ ) } );
593 
594  if( ( *it )->GetType() != BS_ITEM_TYPE_COPPER )
595  {
596  THROW_IO_ERROR( "Board6 stream, unexpected item while parsing stackup" );
597  }
598  ( *it )->SetThickness( layer.copperthick );
599 
600  ALTIUM_LAYER alayer = static_cast<ALTIUM_LAYER>( altiumLayerId );
601  PCB_LAYER_ID klayer = ( *it )->GetBrdLayerId();
602 
603  m_board->SetLayerName( klayer, layer.name );
604 
605  if( layer.copperthick == 0 )
606  {
607  m_board->SetLayerType( klayer, LAYER_T::LT_JUMPER ); // used for things like wirebonding
608  }
609  else if( IsAltiumLayerAPlane( alayer ) )
610  {
612  }
613 
614  if( klayer == B_Cu )
615  {
616  if( layer.nextId != 0 )
617  {
618  THROW_IO_ERROR( "Board6 stream, unexpected id while parsing last stackup layer" );
619  }
620  // overwrite entry from internal -> bottom
621  m_layermap[alayer] = B_Cu;
622  break;
623  }
624 
625  ++it;
626  if( ( *it )->GetType() != BS_ITEM_TYPE_DIELECTRIC )
627  {
628  THROW_IO_ERROR( "Board6 stream, unexpected item while parsing stackup" );
629  }
630  ( *it )->SetThickness( layer.dielectricthick, 0 );
631  ( *it )->SetMaterial( layer.dielectricmaterial.empty() ?
632  NotSpecifiedPrm() :
633  wxString( layer.dielectricmaterial ) );
634  ( *it )->SetEpsilonR( layer.dielectricconst, 0 );
635 
636  ++it;
637  }
638 
639  HelperCreateBoardOutline( elem.board_vertices );
640 }
wxPoint m_GridOrigin
origin for grid offsets
std::vector< BOARD_STACKUP_ITEM * > & GetList()
this class manage the layers needed to make a physical board they are solder mask,...
void SetCopperLayerCount(int aCount)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
BOARD_STACKUP & GetStackupDescriptor()
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
std::map< ALTIUM_LAYER, PCB_LAYER_ID > m_layermap
Definition: altium_pcb.h:190
wxString NotSpecifiedPrm()
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
void RemoveAll()
Delete all items in list and clear the list.
void HelperCreateBoardOutline(const std::vector< ALTIUM_VERTICE > &aVertices)
Definition: altium_pcb.cpp:642
ALTIUM_LAYER
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
Definition: altium_pcb.cpp:105
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
wxPoint m_AuxOrigin
origin for plot exports
void BuildDefaultStackupList(BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Creates a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.

References B_Cu, ABOARD6::board_vertices, BS_ITEM_TYPE_COPPER, BS_ITEM_TYPE_DIELECTRIC, BOARD_STACKUP::BuildDefaultStackupList(), ABOARD6_LAYER_STACKUP::copperthick, ABOARD6_LAYER_STACKUP::dielectricconst, ABOARD6_LAYER_STACKUP::dielectricmaterial, ABOARD6_LAYER_STACKUP::dielectricthick, F_Cu, BOARD::GetDesignSettings(), BOARD_STACKUP::GetList(), ALTIUM_PARSER::GetRemainingBytes(), BOARD_DESIGN_SETTINGS::GetStackupDescriptor(), HelperCreateBoardOutline(), IsAltiumLayerAPlane(), LT_JUMPER, LT_POWER, BOARD_DESIGN_SETTINGS::m_AuxOrigin, m_board, BOARD_DESIGN_SETTINGS::m_GridOrigin, m_layermap, ABOARD6_LAYER_STACKUP::name, ABOARD6_LAYER_STACKUP::nextId, NotSpecifiedPrm(), BOARD_STACKUP::RemoveAll(), BOARD::SetCopperLayerCount(), BOARD::SetLayerName(), BOARD::SetLayerType(), ABOARD6::sheetpos, ABOARD6::stackup, THROW_IO_ERROR, and TOP_LAYER.

Referenced by Parse().

◆ ParseBoardRegionsData()

void ALTIUM_PCB::ParseBoardRegionsData ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1350 of file altium_pcb.cpp.

1352 {
1353  ALTIUM_PARSER reader( aReader, aEntry );
1354 
1355  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1356  {
1357  AREGION6 elem( reader, false );
1358 
1359  // TODO: implement?
1360  }
1361 
1362  if( reader.GetRemainingBytes() != 0 )
1363  {
1364  THROW_IO_ERROR( "BoardRegions stream is not fully parsed" );
1365  }
1366 }
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References ALTIUM_PARSER::GetRemainingBytes(), and THROW_IO_ERROR.

Referenced by Parse().

◆ ParseClasses6Data()

void ALTIUM_PCB::ParseClasses6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 707 of file altium_pcb.cpp.

709 {
710  ALTIUM_PARSER reader( aReader, aEntry );
711 
712  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
713  {
714  ACLASS6 elem( reader );
715 
716  if( elem.kind == ALTIUM_CLASS_KIND::NET_CLASS )
717  {
718  NETCLASSPTR nc = std::make_shared<NETCLASS>( elem.name );
719 
720  for( const auto& name : elem.names )
721  {
722  // TODO: it seems it can happen that we have names not attached to any net.
723  nc->Add( name );
724  }
725 
726  if( !m_board->GetDesignSettings().GetNetClasses().Add( nc ) )
727  {
728  // Name conflict, this is likely a bad board file.
729  // unique_ptr will delete nc on this code path
730  THROW_IO_ERROR( wxString::Format( _( "Duplicated Netclass name \"%s\"" ), elem.name ) );
731  }
732  }
733  }
734 
735  if( reader.GetRemainingBytes() != 0 )
736  {
737  THROW_IO_ERROR( "Classes6 stream is not fully parsed" );
738  }
739 
741 }
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition: class_board.h:320
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
BOARD * m_board
Definition: altium_pcb.h:185
NETCLASSES & GetNetClasses() const
bool Add(const NETCLASSPTR &aNetclass)
Function Add takes aNetclass and puts it into this NETCLASSES container.
Definition: netclass.cpp:90
const char * name
Definition: DXF_plotter.cpp:59
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
#define _(s)
Definition: 3d_actions.cpp:33
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, NETCLASSES::Add(), Format(), BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetNetClasses(), ALTIUM_PARSER::GetRemainingBytes(), ACLASS6::kind, m_board, BOARD::m_LegacyNetclassesLoaded, name, ACLASS6::name, ACLASS6::names, NET_CLASS, and THROW_IO_ERROR.

Referenced by Parse().

◆ ParseComponents6Data()

void ALTIUM_PCB::ParseComponents6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 743 of file altium_pcb.cpp.

745 {
746  ALTIUM_PARSER reader( aReader, aEntry );
747 
748  uint16_t componentId = 0;
749  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
750  {
751  ACOMPONENT6 elem( reader );
752 
753  MODULE* module = new MODULE( m_board );
754  m_board->Add( module, ADD_MODE::APPEND );
755  m_components.emplace_back( module );
756 
757  LIB_ID fpID = AltiumToKiCadLibID(LIB_ID::ID_PCB, elem.sourcefootprintlibrary, elem.sourcelibreference );
758 
759  module->SetFPID( fpID );
760 
761  module->SetPosition( elem.position );
762  module->SetOrientationDegrees( elem.rotation );
763 
764  // KiCad netlisting requires parts to have non-digit + digit annotation.
765  // If the reference begins with a number, we prepend 'UNK' (unknown) for the source designator
766  wxString reference = elem.sourcedesignator;
767  if( reference.find_first_not_of( "0123456789" ) == wxString::npos )
768  reference.Prepend( "UNK" );
769  module->SetReference( reference );
770 
771  module->SetLocked( elem.locked );
772  module->Reference().SetVisible( elem.nameon );
773  module->Value().SetVisible( elem.commenton );
774  module->SetLayer( elem.layer == ALTIUM_LAYER::TOP_LAYER ? F_Cu : B_Cu );
775 
776  componentId++;
777  }
778 
779  if( reader.GetRemainingBytes() != 0 )
780  {
781  THROW_IO_ERROR( "Components6 stream is not fully parsed" );
782  }
783 }
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
FP_TEXT & Value()
read/write accessors:
Definition: class_module.h:475
void SetVisible(bool aVisible)
Definition: eda_text.h:191
void SetOrientationDegrees(double aOrientation)
Definition: class_module.h:205
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
FP_TEXT & Reference()
Definition: class_module.h:476
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
BOARD * m_board
Definition: altium_pcb.h:185
void SetReference(const wxString &aReference)
Function SetReference.
Definition: class_module.h:445
void SetPosition(const wxPoint &aPos) override
std::vector< MODULE * > m_components
Definition: altium_pcb.h:186
LIB_ID AltiumToKiCadLibID(LIB_ID::LIB_ID_TYPE aType, wxString aLibName, wxString aLibReference)
void SetLocked(bool isLocked) override
Function SetLocked sets the MODULE_is_LOCKED bit in the m_ModuleStatus.
Definition: class_module.h:303
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void SetFPID(const LIB_ID &aFPID)
Definition: class_module.h:211

References BOARD::Add(), AltiumToKiCadLibID(), APPEND, B_Cu, ACOMPONENT6::commenton, F_Cu, ALTIUM_PARSER::GetRemainingBytes(), LIB_ID::ID_PCB, ACOMPONENT6::layer, ACOMPONENT6::locked, m_board, m_components, ACOMPONENT6::nameon, ACOMPONENT6::position, MODULE::Reference(), ACOMPONENT6::rotation, MODULE::SetFPID(), BOARD_ITEM::SetLayer(), MODULE::SetLocked(), MODULE::SetOrientationDegrees(), MODULE::SetPosition(), MODULE::SetReference(), EDA_TEXT::SetVisible(), ACOMPONENT6::sourcedesignator, ACOMPONENT6::sourcefootprintlibrary, ACOMPONENT6::sourcelibreference, THROW_IO_ERROR, TOP_LAYER, and MODULE::Value().

Referenced by Parse().

◆ ParseComponentsBodies6Data()

void ALTIUM_PCB::ParseComponentsBodies6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 786 of file altium_pcb.cpp.

788 {
789  ALTIUM_PARSER reader( aReader, aEntry );
790 
791  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
792  {
793  ACOMPONENTBODY6 elem( reader ); // TODO: implement
794 
795  if( elem.component == ALTIUM_COMPONENT_NONE )
796  {
797  continue; // TODO: we do not support components for the board yet
798  }
799 
800  if( m_components.size() <= elem.component )
801  {
803  "ComponentsBodies6 stream tries to access component id %d of %d existing components",
804  elem.component, m_components.size() ) );
805  }
806 
807  if( !elem.modelIsEmbedded )
808  {
809  continue;
810  }
811 
812  auto modelTuple = m_models.find( elem.modelId );
813  if( modelTuple == m_models.end() )
814  {
816  "ComponentsBodies6 stream tries to access model id %s which does not exist",
817  elem.modelId ) );
818  }
819 
820  MODULE* module = m_components.at( elem.component );
821  const wxPoint& modulePosition = module->GetPosition();
822 
823  MODULE_3D_SETTINGS modelSettings;
824 
825  modelSettings.m_Filename = modelTuple->second;
826 
827  modelSettings.m_Offset.x = Iu2Millimeter( (int) elem.modelPosition.x - modulePosition.x );
828  modelSettings.m_Offset.y = -Iu2Millimeter( (int) elem.modelPosition.y - modulePosition.y );
829  modelSettings.m_Offset.z = Iu2Millimeter( (int) elem.modelPosition.z );
830 
831  double orientation = module->GetOrientation();
832 
833  if( module->IsFlipped() )
834  {
835  modelSettings.m_Offset.y = -modelSettings.m_Offset.y;
836  orientation = -orientation;
837  }
838 
839  RotatePoint( &modelSettings.m_Offset.x, &modelSettings.m_Offset.y, orientation );
840 
841  modelSettings.m_Rotation.x = NormalizeAngleDegrees( -elem.modelRotation.x, -180, 180 );
842  modelSettings.m_Rotation.y = NormalizeAngleDegrees( -elem.modelRotation.y, -180, 180 );
843  modelSettings.m_Rotation.z = NormalizeAngleDegrees(
844  -elem.modelRotation.z + elem.rotation + orientation / 10, -180, 180 );
845 
846  modelSettings.m_Opacity = elem.bodyOpacity;
847 
848  module->Models().push_back( modelSettings );
849  }
850 
851  if( reader.GetRemainingBytes() != 0 )
852  {
853  THROW_IO_ERROR( "ComponentsBodies6 stream is not fully parsed" );
854  }
855 }
double GetOrientation() const
Definition: class_module.h:206
bool IsFlipped() const
function IsFlipped
Definition: class_module.h:284
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
VECTOR3D m_Offset
3D model offset (mm)
Definition: class_module.h:95
std::map< wxString, wxString > m_models
Definition: altium_pcb.h:188
std::vector< MODULE * > m_components
Definition: altium_pcb.h:186
wxString m_Filename
The 3D shape filename in 3D library.
Definition: class_module.h:97
std::list< MODULE_3D_SETTINGS > & Models()
Definition: class_module.h:196
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
VECTOR3D m_Rotation
3D model rotation (degrees)
Definition: class_module.h:94
double NormalizeAngleDegrees(double Angle, double aMin, double aMax)
Normalize angle to be aMin < angle <= aMax angle is in degrees.
Definition: trigo.h:312
const int ALTIUM_COMPONENT_NONE
wxPoint GetPosition() const override
Definition: class_module.h:201
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References ALTIUM_COMPONENT_NONE, ACOMPONENTBODY6::bodyOpacity, ACOMPONENTBODY6::component, Format(), MODULE::GetOrientation(), MODULE::GetPosition(), ALTIUM_PARSER::GetRemainingBytes(), MODULE::IsFlipped(), m_components, MODULE_3D_SETTINGS::m_Filename, m_models, MODULE_3D_SETTINGS::m_Offset, MODULE_3D_SETTINGS::m_Opacity, MODULE_3D_SETTINGS::m_Rotation, ACOMPONENTBODY6::modelId, ACOMPONENTBODY6::modelIsEmbedded, ACOMPONENTBODY6::modelPosition, ACOMPONENTBODY6::modelRotation, MODULE::Models(), NormalizeAngleDegrees(), RotatePoint(), ACOMPONENTBODY6::rotation, THROW_IO_ERROR, MODULE_3D_SETTINGS::VECTOR3D::x, MODULE_3D_SETTINGS::VECTOR3D::y, and MODULE_3D_SETTINGS::VECTOR3D::z.

Referenced by Parse().

◆ ParseDimensions6Data()

void ALTIUM_PCB::ParseDimensions6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1065 of file altium_pcb.cpp.

1067 {
1068  ALTIUM_PARSER reader( aReader, aEntry );
1069 
1070  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1071  {
1072  ADIMENSION6 elem( reader );
1073 
1074  switch( elem.kind )
1075  {
1078  break;
1081  break;
1083  wxLogWarning( wxString::Format( "Ignore dimension object of kind %d", elem.kind ) );
1084  // HelperParseDimensions6Datum( elem );
1085  break;
1088  break;
1089  default:
1090  wxLogWarning( wxString::Format( "Ignore dimension object of kind %d", elem.kind ) );
1091  break;
1092  }
1093  }
1094 
1095  if( reader.GetRemainingBytes() != 0 )
1096  {
1097  THROW_IO_ERROR( "Dimensions6 stream is not fully parsed" );
1098  }
1099 }
void HelperParseDimensions6Leader(const ADIMENSION6 &aElem)
Definition: altium_pcb.cpp:941
void HelperParseDimensions6Center(const ADIMENSION6 &aElem)
void HelperParseDimensions6Linear(const ADIMENSION6 &aElem)
Definition: altium_pcb.cpp:858
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
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References CENTER, DATUM, Format(), ALTIUM_PARSER::GetRemainingBytes(), HelperParseDimensions6Center(), HelperParseDimensions6Leader(), HelperParseDimensions6Linear(), ADIMENSION6::kind, LEADER, LINEAR, and THROW_IO_ERROR.

Referenced by Parse().

◆ ParseFileHeader()

void ALTIUM_PCB::ParseFileHeader ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 508 of file altium_pcb.cpp.

510 {
511  ALTIUM_PARSER reader( aReader, aEntry );
512 
513  reader.ReadAndSetSubrecordLength();
514  wxString header = reader.ReadWxString();
515 
516  //std::cout << "HEADER: " << header << std::endl; // tells me: PCB 5.0 Binary File
517 
518  //reader.SkipSubrecord();
519 
520  // TODO: does not seem to work all the time at the moment
521  //if( reader.GetRemainingBytes() != 0 )
522  //{
523  // THROW_IO_ERROR( "FileHeader stream is not fully parsed" );
524  //}
525 }

References ALTIUM_PARSER::ReadAndSetSubrecordLength(), and ALTIUM_PARSER::ReadWxString().

Referenced by Parse().

◆ ParseFills6Data()

void ALTIUM_PCB::ParseFills6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 2401 of file altium_pcb.cpp.

2403 {
2404  ALTIUM_PARSER reader( aReader, aEntry );
2405 
2406  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
2407  {
2408  AFILL6 elem( reader );
2409 
2410  wxPoint p11( elem.pos1.x, elem.pos1.y );
2411  wxPoint p12( elem.pos1.x, elem.pos2.y );
2412  wxPoint p22( elem.pos2.x, elem.pos2.y );
2413  wxPoint p21( elem.pos2.x, elem.pos1.y );
2414 
2415  wxPoint center( ( elem.pos1.x + elem.pos2.x ) / 2, ( elem.pos1.y + elem.pos2.y ) / 2 );
2416 
2417  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
2418  if( klayer == UNDEFINED_LAYER )
2419  {
2420  wxLogWarning( wxString::Format(
2421  _( "Fill on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
2422  elem.layer ) );
2423  klayer = Eco1_User;
2424  }
2425 
2426  if( elem.is_keepout || elem.net != ALTIUM_NET_UNCONNECTED )
2427  {
2428  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
2429  m_board->Add( zone, ADD_MODE::APPEND );
2430 
2431  zone->SetNetCode( GetNetCode( elem.net ) );
2432  zone->SetLayer( klayer );
2433  zone->SetPosition( elem.pos1 );
2434  zone->SetPriority( 1000 );
2435 
2436  const int outlineIdx = -1; // this is the id of the copper zone main outline
2437  zone->AppendCorner( p11, outlineIdx );
2438  zone->AppendCorner( p12, outlineIdx );
2439  zone->AppendCorner( p22, outlineIdx );
2440  zone->AppendCorner( p21, outlineIdx );
2441 
2442  // should be correct?
2443  zone->SetLocalClearance( 0 );
2445 
2446  if( elem.is_keepout )
2447  {
2448  zone->SetIsRuleArea( true );
2449  zone->SetDoNotAllowTracks( false );
2450  zone->SetDoNotAllowVias( false );
2451  zone->SetDoNotAllowPads( false );
2452  zone->SetDoNotAllowFootprints( false );
2453  zone->SetDoNotAllowCopperPour( true );
2454  }
2455 
2456  if( elem.rotation != 0. )
2457  zone->Rotate( center, elem.rotation * 10 );
2458 
2461  }
2462  else
2463  {
2464  PCB_SHAPE* shape = new PCB_SHAPE( m_board );
2465  m_board->Add( shape, ADD_MODE::APPEND );
2466 
2467  shape->SetShape( S_POLYGON );
2468  shape->SetLayer( klayer );
2469  shape->SetWidth( 0 );
2470 
2471  shape->SetPolyPoints( { p11, p12, p22, p21 } );
2472 
2473  if( elem.rotation != 0. )
2474  shape->Rotate( center, elem.rotation * 10 );
2475  }
2476  }
2477 
2478  if( reader.GetRemainingBytes() != 0 )
2479  {
2480  THROW_IO_ERROR( "Fills6 stream is not fully parsed" );
2481  }
2482 }
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:738
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: class_zone.h:222
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void SetDoNotAllowFootprints(bool aEnable)
Definition: class_zone.h:740
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
void SetIsRuleArea(bool aEnable)
Definition: class_zone.h:735
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
Definition: pcb_shape.cpp:193
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:737
int GetNetCode(uint16_t aId) const
Definition: altium_pcb.cpp:457
void SetPriority(unsigned aPriority)
Function SetPriority.
Definition: class_zone.h:100
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
pads are covered by copper
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
const uint16_t ALTIUM_NET_UNCONNECTED
void Rotate(const wxPoint &aCentre, double aAngle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:702
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:234
void SetDoNotAllowPads(bool aEnable)
Definition: class_zone.h:739
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetBorderDisplayStyle sets all hatch parameters for the zone.
Definition: class_zone.cpp:888
void SetLocalClearance(int aClearance)
Definition: class_zone.h:138
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:736
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
polygon (not yet used for tracks, but could be in microwave apps)
#define _(s)
Definition: 3d_actions.cpp:33
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
void SetPosition(const wxPoint &aPos) override
Definition: class_zone.h:94
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:831
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
Definition: pcb_shape.cpp:1057

References _, BOARD::Add(), ALTIUM_NET_UNCONNECTED, APPEND, ZONE_CONTAINER::AppendCorner(), DIAGONAL_EDGE, Eco1_User, Format(), FULL, ZONE_CONTAINER::GetDefaultHatchPitch(), GetKicadLayer(), GetNetCode(), ALTIUM_PARSER::GetRemainingBytes(), AFILL6::is_keepout, AFILL6::layer, m_board, AFILL6::net, AFILL6::pos1, AFILL6::pos2, PCB_SHAPE::Rotate(), ZONE_CONTAINER::Rotate(), AFILL6::rotation, S_POLYGON, ZONE_CONTAINER::SetBorderDisplayStyle(), ZONE_CONTAINER::SetDoNotAllowCopperPour(), ZONE_CONTAINER::SetDoNotAllowFootprints(), ZONE_CONTAINER::SetDoNotAllowPads(), ZONE_CONTAINER::SetDoNotAllowTracks(), ZONE_CONTAINER::SetDoNotAllowVias(), ZONE_CONTAINER::SetIsRuleArea(), ZONE_CONTAINER::SetLayer(), BOARD_ITEM::SetLayer(), ZONE_CONTAINER::SetLocalClearance(), BOARD_CONNECTED_ITEM::SetNetCode(), ZONE_CONTAINER::SetPadConnection(), PCB_SHAPE::SetPolyPoints(), ZONE_CONTAINER::SetPosition(), ZONE_CONTAINER::SetPriority(), PCB_SHAPE::SetShape(), PCB_SHAPE::SetWidth(), THROW_IO_ERROR, and UNDEFINED_LAYER.

Referenced by Parse().

◆ ParseModelsData()

void ALTIUM_PCB::ParseModelsData ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry,
const wxString  aRootDir 
)
private

Definition at line 1102 of file altium_pcb.cpp.

1104 {
1105  ALTIUM_PARSER reader( aReader, aEntry );
1106 
1107  if( reader.GetRemainingBytes() == 0 )
1108  {
1109  return; // fast path: no 3d-models present which need to be imported -> no directory needs to be created
1110  }
1111 
1112  wxString projectPath = wxPathOnly( m_board->GetFileName() );
1113  // TODO: set KIPRJMOD always after import (not only when loading project)?
1114  wxSetEnv( PROJECT_VAR_NAME, projectPath );
1115 
1116  // TODO: make this path configurable?
1117  const wxString altiumModelDir = "ALTIUM_EMBEDDED_MODELS";
1118 
1119  wxFileName altiumModelsPath = wxFileName::DirName( projectPath );
1120  wxString kicadModelPrefix = "${KIPRJMOD}/" + altiumModelDir + "/";
1121  if( !altiumModelsPath.AppendDir( altiumModelDir ) )
1122  {
1123  THROW_IO_ERROR( "Cannot construct directory path for step models" );
1124  }
1125 
1126  // Create dir if it does not exist
1127  if( !altiumModelsPath.DirExists() )
1128  {
1129  if( !altiumModelsPath.Mkdir() )
1130  {
1131  wxLogError( wxString::Format(
1132  _( "Cannot create directory \"%s\" -> no 3D-models will be imported." ),
1133  altiumModelsPath.GetFullPath() ) );
1134  return;
1135  }
1136  }
1137 
1138  int idx = 0;
1139  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1140  {
1141  AMODEL elem( reader );
1142 
1143  wxString stepPath = aRootDir + std::to_string( idx++ );
1144 
1145  const CFB::COMPOUND_FILE_ENTRY* stepEntry = FindStream( aReader, stepPath.c_str() );
1146 
1147  size_t stepSize = static_cast<size_t>( stepEntry->size );
1148  std::unique_ptr<char[]> stepContent( new char[stepSize] );
1149 
1150  // read file into buffer
1151  aReader.ReadFile( stepEntry, 0, stepContent.get(), stepSize );
1152 
1153  wxFileName storagePath( altiumModelsPath.GetPath(), elem.name );
1154  if( !storagePath.IsDirWritable() )
1155  {
1156  wxLogError(
1157  wxString::Format( _( "You do not have write permissions to save file \"%s\"." ),
1158  storagePath.GetFullPath() ) );
1159  continue;
1160  }
1161 
1162  wxMemoryInputStream stepStream( stepContent.get(), stepSize );
1163  wxZlibInputStream zlibInputStream( stepStream );
1164 
1165  wxFileOutputStream outputStream( storagePath.GetFullPath() );
1166  outputStream.Write( zlibInputStream );
1167  outputStream.Close();
1168 
1169  m_models.insert( { elem.id, kicadModelPrefix + elem.name } );
1170  }
1171 
1172  if( reader.GetRemainingBytes() != 0 )
1173  {
1174  THROW_IO_ERROR( "Models stream is not fully parsed" );
1175  }
1176 }
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:38
const wxString & GetFileName() const
Definition: class_board.h:279
std::map< wxString, wxString > m_models
Definition: altium_pcb.h:188
const CFB::COMPOUND_FILE_ENTRY * FindStream(const CFB::CompoundFileReader &aReader, const char *aStreamName)
BOARD * m_board
Definition: altium_pcb.h:185
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
#define _(s)
Definition: 3d_actions.cpp:33
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, FindStream(), Format(), BOARD::GetFileName(), ALTIUM_PARSER::GetRemainingBytes(), AMODEL::id, m_board, m_models, AMODEL::name, PROJECT_VAR_NAME, and THROW_IO_ERROR.

Referenced by Parse().

◆ ParseNets6Data()

void ALTIUM_PCB::ParseNets6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1179 of file altium_pcb.cpp.

1181 {
1182  ALTIUM_PARSER reader( aReader, aEntry );
1183 
1184  wxASSERT( m_num_nets == 0 );
1185  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1186  {
1187  ANET6 elem( reader );
1188 
1189  m_board->Add( new NETINFO_ITEM( m_board, elem.name, ++m_num_nets ), ADD_MODE::APPEND );
1190  }
1191 
1192  if( reader.GetRemainingBytes() != 0 )
1193  {
1194  THROW_IO_ERROR( "Nets6 stream is not fully parsed" );
1195  }
1196 }
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
BOARD * m_board
Definition: altium_pcb.h:185
size_t m_num_nets
Definition: altium_pcb.h:189
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References BOARD::Add(), APPEND, ALTIUM_PARSER::GetRemainingBytes(), m_board, m_num_nets, ANET6::name, and THROW_IO_ERROR.

Referenced by Parse().

◆ ParsePads6Data()

void ALTIUM_PCB::ParsePads6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1668 of file altium_pcb.cpp.

1670 {
1671  ALTIUM_PARSER reader( aReader, aEntry );
1672 
1673  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1674  {
1675  APAD6 elem( reader );
1676 
1677  // It is possible to place altium pads on non-copper layers -> we need to interpolate them using drawings!
1678  if( !IsAltiumLayerCopper( elem.layer ) && !IsAltiumLayerAPlane( elem.layer )
1679  && elem.layer != ALTIUM_LAYER::MULTI_LAYER )
1680  {
1681  HelperParsePad6NonCopper( elem );
1682  continue;
1683  }
1684 
1685  // Create Pad
1686  MODULE* module = nullptr;
1687  if( elem.component == ALTIUM_COMPONENT_NONE )
1688  {
1689  module = new MODULE( m_board ); // We cannot add a pad directly into the PCB
1690  m_board->Add( module, ADD_MODE::APPEND );
1691  module->SetPosition( elem.position );
1692  }
1693  else
1694  {
1695  if( m_components.size() <= elem.component )
1696  {
1698  "Pads6 stream tries to access component id %d of %d existing components",
1699  elem.component, m_components.size() ) );
1700  }
1701  module = m_components.at( elem.component );
1702  }
1703 
1704  D_PAD* pad = new D_PAD( module );
1705  module->Add( pad, ADD_MODE::APPEND );
1706 
1707  pad->SetName( elem.name );
1708  pad->SetNetCode( GetNetCode( elem.net ) );
1709  pad->SetLocked( elem.is_locked );
1710 
1711  pad->SetPosition( elem.position );
1712  pad->SetOrientationDegrees( elem.direction );
1713  pad->SetLocalCoord();
1714 
1715  pad->SetSize( elem.topsize );
1716 
1717  if( elem.holesize == 0 )
1718  {
1720  }
1721  else
1722  {
1723  if( elem.layer != ALTIUM_LAYER::MULTI_LAYER )
1724  {
1725  // TODO: I assume other values are possible as well?
1726  wxLogError( wxString::Format(
1727  "Pad '%s' of Footprint %s is not marked as multilayer, but it is an THT pad",
1728  elem.name, module->GetReference() ) );
1729  }
1730  pad->SetAttribute( elem.plated ? PAD_ATTR_T::PAD_ATTRIB_PTH :
1732  if( !elem.sizeAndShape || elem.sizeAndShape->holeshape == ALTIUM_PAD_HOLE_SHAPE::ROUND )
1733  {
1735  pad->SetDrillSize( wxSize( elem.holesize, elem.holesize ) );
1736  }
1737  else
1738  {
1739  switch( elem.sizeAndShape->holeshape )
1740  {
1742  wxFAIL_MSG( "Round holes are handled before the switch" );
1743  break;
1744 
1746  wxLogWarning( wxString::Format(
1747  _( "Pad '%s' of Footprint %s has a square hole. KiCad does not support this yet" ),
1748  elem.name, module->GetReference() ) );
1750  pad->SetDrillSize( wxSize( elem.holesize, elem.holesize ) ); // Workaround
1751  // TODO: elem.sizeAndShape->slotsize was 0 in testfile. Either use holesize in this case or rect holes have a different id
1752  break;
1753 
1755  {
1757  double normalizedSlotrotation =
1758  NormalizeAngleDegreesPos( elem.sizeAndShape->slotrotation );
1759  if( normalizedSlotrotation == 0. || normalizedSlotrotation == 180. )
1760  {
1761  pad->SetDrillSize( wxSize( elem.sizeAndShape->slotsize, elem.holesize ) );
1762  }
1763  else
1764  {
1765  if( normalizedSlotrotation != 90. && normalizedSlotrotation != 270. )
1766  {
1767  wxLogWarning( wxString::Format(
1768  _( "Pad '%s' of Footprint %s has a hole-rotation of %f degree. KiCad only supports 90 degree angles" ),
1769  elem.name, module->GetReference(), normalizedSlotrotation ) );
1770  }
1771 
1772  pad->SetDrillSize( wxSize( elem.holesize, elem.sizeAndShape->slotsize ) );
1773  }
1774  }
1775  break;
1776 
1777  default:
1779  wxLogError( wxString::Format(
1780  "Pad '%s' of Footprint %s uses a hole of unknown kind %d", elem.name,
1781  module->GetReference(), elem.sizeAndShape->holeshape ) );
1783  pad->SetDrillSize( wxSize( elem.holesize, elem.holesize ) ); // Workaround
1784  break;
1785  }
1786  }
1787 
1788  if( elem.sizeAndShape )
1789  {
1790  pad->SetOffset( elem.sizeAndShape->holeoffset[0] );
1791  }
1792  }
1793 
1794  if( elem.padmode != ALTIUM_PAD_MODE::SIMPLE )
1795  {
1796  wxLogWarning( wxString::Format(
1797  _( "Pad '%s' of Footprint %s uses a complex pad stack (kind %d), which is not supported yet" ),
1798  elem.name, module->GetReference(), elem.padmode ) );
1799  }
1800 
1801  switch( elem.topshape )
1802  {
1805  break;
1807  if( elem.sizeAndShape
1808  && elem.sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
1809  {
1810  pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_ROUNDRECT ); // 100 = round, 0 = rectangular
1811  double ratio = elem.sizeAndShape->cornerradius[0] / 200.;
1812  pad->SetRoundRectRadiusRatio( ratio );
1813  }
1814  else if( elem.topsize.x == elem.topsize.y )
1815  {
1817  }
1818  else
1819  {
1821  }
1822  break;
1826  pad->SetChamferRectRatio( 0.25 );
1827  break;
1829  default:
1830  wxLogError( wxString::Format( "Pad '%s' of Footprint %s uses a unknown pad-shape",
1831  elem.name, module->GetReference() ) );
1832  break;
1833  }
1834 
1835  switch( elem.layer )
1836  {
1838  pad->SetLayer( F_Cu );
1839  pad->SetLayerSet( D_PAD::SMDMask() );
1840  break;
1842  pad->SetLayer( B_Cu );
1844  break;
1846  pad->SetLayerSet( elem.plated ? D_PAD::PTHMask() : D_PAD::UnplatedHoleMask() );
1847  break;
1848  default:
1849  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
1850  pad->SetLayer( klayer );
1851  pad->SetLayerSet( LSET( 1, klayer ) );
1852  break;
1853  }
1854 
1855  if( elem.pastemaskexpansionmode == ALTIUM_PAD_RULE::MANUAL )
1856  {
1857  pad->SetLocalSolderPasteMargin( elem.pastemaskexpansionmanual );
1858  }
1859 
1860  if( elem.soldermaskexpansionmode == ALTIUM_PAD_RULE::MANUAL )
1861  {
1862  pad->SetLocalSolderMaskMargin( elem.soldermaskexpansionmanual );
1863  }
1864 
1865  if( elem.is_tent_top )
1866  {
1867  pad->SetLayerSet( pad->GetLayerSet().reset( F_Mask ) );
1868  }
1869  if( elem.is_tent_bottom )
1870  {
1871  pad->SetLayerSet( pad->GetLayerSet().reset( B_Mask ) );
1872  }
1873  }
1874 
1875  if( reader.GetRemainingBytes() != 0 )
1876  {
1877  THROW_IO_ERROR( "Pads6 stream is not fully parsed" );
1878  }
1879 }
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:566
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: class_pad.cpp:159
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: class_pad.cpp:145
void SetChamferPositions(int aPositions)
has meaning only for chamfered rect pads set the position of the chamfers for orientation 0.
Definition: class_pad.h:522
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:81
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:166
static LSET PTHMask()
layer set for a through hole pad
Definition: class_pad.cpp:138
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:240
virtual void SetLocked(bool aLocked)
Function SetLocked modifies 'lock' status for of the item.
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
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:236
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
void SetLocalCoord()
Set relative coordinates.
Definition: class_pad.cpp:497
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:435
int GetNetCode(uint16_t aId) const
Definition: altium_pcb.cpp:457
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
double NormalizeAngleDegreesPos(double Angle)
Normalize angle to be in the 0.0 .
Definition: trigo.h:285
BOARD * m_board
Definition: altium_pcb.h:185
LSET is a set of PCB_LAYER_IDs.
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:131
LSET GetLayerSet() const override
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
Definition: class_pad.h:349
void SetSize(const wxSize &aSize)
Definition: class_pad.h:230
void SetOrientationDegrees(double aOrientation)
Set orientation in degrees.
Definition: class_pad.h:331
void SetPosition(const wxPoint &aPos) override
std::vector< MODULE * > m_components
Definition: altium_pcb.h:186
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:512
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: class_pad.h:342
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
void HelperParsePad6NonCopper(const APAD6 &aElem)
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:365
#define _(s)
Definition: 3d_actions.cpp:33
Plated through hole pad.
Definition: pad_shapes.h:80
void SetShape(PAD_SHAPE_T aShape)
Set the new shape of this pad.
Definition: class_pad.h:155
bool IsAltiumLayerCopper(ALTIUM_LAYER aLayer)
Definition: altium_pcb.cpp:99
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:244
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_pad.h:372
const int ALTIUM_COMPONENT_NONE
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:247
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
Definition: altium_pcb.cpp:105
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void SetLayerSet(LSET aLayers) override
Definition: class_pad.h:348

References _, MODULE::Add(), BOARD::Add(), ALTIUM_COMPONENT_NONE, APPEND, B_Cu, B_Mask, BOTTOM_LAYER, CIRCLE, APAD6::component, APAD6::direction, F_Cu, F_Mask, FlipLayerMask(), Format(), GetKicadLayer(), D_PAD::GetLayerSet(), GetNetCode(), MODULE::GetReference(), ALTIUM_PARSER::GetRemainingBytes(), HelperParsePad6NonCopper(), APAD6::holesize, APAD6::is_locked, APAD6::is_tent_bottom, APAD6::is_tent_top, IsAltiumLayerAPlane(), IsAltiumLayerCopper(), APAD6::layer, m_board, m_components, MANUAL, MULTI_LAYER, APAD6::name, APAD6::net, NormalizeAngleDegreesPos(), OCTAGONAL, PAD_ATTRIB_NPTH, PAD_ATTRIB_PTH, PAD_ATTRIB_SMD, PAD_DRILL_SHAPE_CIRCLE, PAD_DRILL_SHAPE_OBLONG, PAD_SHAPE_CHAMFERED_RECT, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, APAD6::padmode, APAD6::pastemaskexpansionmanual, APAD6::pastemaskexpansionmode, APAD6::plated, APAD6::position, D_PAD::PTHMask(), RECT, RECT_CHAMFER_ALL, ROUND, ROUNDRECT, D_PAD::SetAttribute(), D_PAD::SetChamferPositions(), D_PAD::SetChamferRectRatio(), D_PAD::SetDrillShape(), D_PAD::SetDrillSize(), BOARD_ITEM::SetLayer(), D_PAD::SetLayerSet(), D_PAD::SetLocalCoord(), D_PAD::SetLocalSolderMaskMargin(), D_PAD::SetLocalSolderPasteMargin(), BOARD_ITEM::SetLocked(), D_PAD::SetName(), BOARD_CONNECTED_ITEM::SetNetCode(), D_PAD::SetOffset(), D_PAD::SetOrientationDegrees(), D_PAD::SetPosition(), MODULE::SetPosition(), D_PAD::SetRoundRectRadiusRatio(), D_PAD::SetShape(), D_PAD::SetSize(), SIMPLE, APAD6::sizeAndShape, SLOT, D_PAD::SMDMask(), APAD6::soldermaskexpansionmanual, APAD6::soldermaskexpansionmode, SQUARE, THROW_IO_ERROR, TOP_LAYER, APAD6::topshape, APAD6::topsize, UNKNOWN, and D_PAD::UnplatedHoleMask().

Referenced by Parse().

◆ ParsePolygons6Data()

void ALTIUM_PCB::ParsePolygons6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1198 of file altium_pcb.cpp.

1200 {
1201  ALTIUM_PARSER reader( aReader, aEntry );
1202 
1203  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1204  {
1205  APOLYGON6 elem( reader );
1206 
1207  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
1208  if( klayer == UNDEFINED_LAYER )
1209  {
1210  wxLogWarning( wxString::Format(
1211  _( "Polygon on Altium layer %d has no KiCad equivalent. Ignore it instead" ),
1212  elem.layer ) );
1213  m_polygons.emplace_back( nullptr );
1214  continue;
1215  }
1216 
1217  SHAPE_LINE_CHAIN linechain;
1218  HelperShapeLineChainFromAltiumVertices( linechain, elem.vertices );
1219 
1220  if( linechain.PointCount() < 2 )
1221  {
1222  wxLogError( wxString::Format(
1223  _( "Polygon has only %d point extracted from %ld vertices. At least 2 points are required." ),
1224  linechain.PointCount(), elem.vertices.size() ) );
1225  m_polygons.emplace_back( nullptr );
1226  continue;
1227  }
1228 
1229  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
1230  m_board->Add( zone, ADD_MODE::APPEND );
1231  m_polygons.emplace_back( zone );
1232 
1233  zone->SetNetCode( GetNetCode( elem.net ) );
1234  zone->SetLayer( klayer );
1235  zone->SetPosition( elem.vertices.at( 0 ).position );
1236  zone->SetLocked( elem.locked );
1237  zone->SetPriority( elem.pourindex > 0 ? elem.pourindex : 0 );
1238  zone->Outline()->AddOutline( linechain );
1239 
1240  if( elem.pourindex > m_highest_pour_index )
1241  m_highest_pour_index = elem.pourindex;
1242 
1243  // TODO: more flexible rule parsing
1244  const ARULE6* clearanceRule = GetRuleDefault( ALTIUM_RULE_KIND::PLANE_CLEARANCE );
1245 
1246  if( clearanceRule != nullptr )
1247  {
1248  zone->SetLocalClearance( clearanceRule->planeclearanceClearance );
1249  }
1250 
1251  const ARULE6* polygonConnectRule = GetRuleDefault( ALTIUM_RULE_KIND::POLYGON_CONNECT );
1252 
1253  if( polygonConnectRule != nullptr )
1254  {
1255  switch( polygonConnectRule->polygonconnectStyle )
1256  {
1259  break;
1260 
1263  break;
1264 
1265  default:
1268  break;
1269  }
1270 
1271  // TODO: correct variables?
1273  polygonConnectRule->polygonconnectReliefconductorwidth );
1274  zone->SetThermalReliefGap( polygonConnectRule->polygonconnectAirgapwidth );
1275 
1276  if( polygonConnectRule->polygonconnectReliefconductorwidth < zone->GetMinThickness() )
1277  zone->SetMinThickness( polygonConnectRule->polygonconnectReliefconductorwidth );
1278  }
1279 
1280  if( IsAltiumLayerAPlane( elem.layer ) )
1281  {
1282  // outer zone will be set to priority 0 later.
1283  zone->SetPriority( 1 );
1284 
1285  // check if this is the outer zone by simply comparing the BBOX
1286  const auto& cur_outer_plane = m_outer_plane.find( elem.layer );
1287  if( cur_outer_plane == m_outer_plane.end()
1288  || zone->GetBoundingBox().Contains(
1289  cur_outer_plane->second->GetBoundingBox() ) )
1290  {
1291  m_outer_plane[elem.layer] = zone;
1292  }
1293  }
1294 
1295  if( elem.hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID
1296  && elem.hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::UNKNOWN )
1297  {
1299  zone->SetHatchThickness( elem.trackwidth );
1300 
1301  if( elem.hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::NONE )
1302  {
1303  // use a small hack to get us only an outline (hopefully)
1304  const EDA_RECT& bbox = zone->GetBoundingBox();
1305  zone->SetHatchGap( std::max( bbox.GetHeight(), bbox.GetWidth() ) );
1306  }
1307  else
1308  {
1309  zone->SetHatchGap( elem.gridsize - elem.trackwidth );
1310  }
1311 
1312  zone->SetHatchOrientation( elem.hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45 ? 45 : 0 );
1313  }
1314 
1317  }
1318 
1319  if( reader.GetRemainingBytes() != 0 )
1320  {
1321  THROW_IO_ERROR( "Polygons6 stream is not fully parsed" );
1322  }
1323 }
void SetHatchGap(int aStep)
Definition: class_zone.h:237
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
int planeclearanceClearance
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: class_zone.h:222
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:318
int32_t polygonconnectAirgapwidth
int GetWidth() const
Definition: eda_rect.h:119
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:300
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
std::vector< ZONE_CONTAINER * > m_polygons
Definition: altium_pcb.h:187
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
Definition: class_zone.h:175
virtual void SetLocked(bool aLocked)
Function SetLocked modifies 'lock' status for of the item.
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
int PointCount() const
Function PointCount()
bool Contains(const wxPoint &aPoint) const
Function Contains.
Definition: eda_rect.cpp:57
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
const ARULE6 * GetRuleDefault(ALTIUM_RULE_KIND aKind) const
Definition: altium_pcb.cpp:491
ALTIUM_CONNECT_STYLE polygonconnectStyle
int GetNetCode(uint16_t aId) const
Definition: altium_pcb.cpp:457
void SetPriority(unsigned aPriority)
Function SetPriority.
Definition: class_zone.h:100
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
void SetHatchThickness(int aThickness)
Definition: class_zone.h:234
pads are covered by copper
std::map< ALTIUM_LAYER, ZONE_CONTAINER * > m_outer_plane
Definition: altium_pcb.h:193
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:234
void HelperShapeLineChainFromAltiumVertices(SHAPE_LINE_CHAIN &aLine, const std::vector< ALTIUM_VERTICE > &aVertices)
Definition: altium_pcb.cpp:149
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetBorderDisplayStyle sets all hatch parameters for the zone.
Definition: class_zone.cpp:888
int GetHeight() const
Definition: eda_rect.h:120
int m_highest_pour_index
Altium stores pour order across all layers.
Definition: altium_pcb.h:196
void SetLocalClearance(int aClearance)
Definition: class_zone.h:138
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
Use thermal relief for pads.
void SetHatchOrientation(double aStep)
Definition: class_zone.h:240
void SetFillMode(ZONE_FILL_MODE aFillMode)
Definition: class_zone.h:162
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
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetMinThickness() const
Definition: class_zone.h:224
Pads are not covered.
void SetPosition(const wxPoint &aPos) override
Definition: class_zone.h:94
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
Definition: altium_pcb.cpp:105
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:225
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void SetThermalReliefGap(int aThermalReliefGap)
Definition: class_zone.h:165
int32_t polygonconnectReliefconductorwidth

References _, BOARD::Add(), SHAPE_POLY_SET::AddOutline(), APPEND, EDA_RECT::Contains(), DEGREE_45, DIAGONAL_EDGE, DIRECT, Format(), FULL, ZONE_CONTAINER::GetBoundingBox(), ZONE_CONTAINER::GetDefaultHatchPitch(), EDA_RECT::GetHeight(), GetKicadLayer(), ZONE_CONTAINER::GetMinThickness(), GetNetCode(), ALTIUM_PARSER::GetRemainingBytes(), GetRuleDefault(), EDA_RECT::GetWidth(), APOLYGON6::gridsize, HATCH_PATTERN, APOLYGON6::hatchstyle, HelperShapeLineChainFromAltiumVertices(), IsAltiumLayerAPlane(), APOLYGON6::layer, APOLYGON6::locked, m_board, m_highest_pour_index, m_outer_plane, m_polygons, APOLYGON6::net, NONE, ZONE_CONTAINER::Outline(), PLANE_CLEARANCE, ARULE6::planeclearanceClearance, SHAPE_LINE_CHAIN::PointCount(), POLYGON_CONNECT, ARULE6::polygonconnectAirgapwidth, ARULE6::polygonconnectReliefconductorwidth, ARULE6::polygonconnectStyle, APOLYGON6::pourindex, RELIEF, ZONE_CONTAINER::SetBorderDisplayStyle(), ZONE_CONTAINER::SetFillMode(), ZONE_CONTAINER::SetHatchGap(), ZONE_CONTAINER::SetHatchOrientation(), ZONE_CONTAINER::SetHatchThickness(), ZONE_CONTAINER::SetLayer(), ZONE_CONTAINER::SetLocalClearance(), BOARD_ITEM::SetLocked(), ZONE_CONTAINER::SetMinThickness(), BOARD_CONNECTED_ITEM::SetNetCode(), ZONE_CONTAINER::SetPadConnection(), ZONE_CONTAINER::SetPosition(), ZONE_CONTAINER::SetPriority(), ZONE_CONTAINER::SetThermalReliefGap(), ZONE_CONTAINER::SetThermalReliefSpokeWidth(), SOLID, THERMAL, THROW_IO_ERROR, APOLYGON6::trackwidth, UNDEFINED_LAYER, UNKNOWN, and APOLYGON6::vertices.

Referenced by Parse().

◆ ParseRegions6Data()

void ALTIUM_PCB::ParseRegions6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1475 of file altium_pcb.cpp.

1477 {
1478  ALTIUM_PARSER reader( aReader, aEntry );
1479 
1480  for( ZONE_CONTAINER* zone : m_polygons )
1481  {
1482  if( zone != nullptr )
1483  {
1484  zone->UnFill(); // just to be sure
1485  }
1486  }
1487 
1488  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1489  {
1490  AREGION6 elem( reader, false );
1491 
1492 #if 0 // TODO: it seems this code has multiple issues right now, and we can manually fill anyways
1493  if( elem.subpolyindex != ALTIUM_POLYGON_NONE )
1494  {
1495  if( m_polygons.size() <= elem.subpolyindex )
1496  {
1498  "Region stream tries to access polygon id %d of %d existing polygons",
1499  elem.subpolyindex, m_polygons.size() ) );
1500  }
1501 
1502  ZONE_CONTAINER *zone = m_polygons.at(elem.subpolyindex);
1503 
1504  if( zone == nullptr )
1505  {
1506  continue; // we know the zone id, but because we do not know the layer we did not add it!
1507  }
1508 
1509  SHAPE_LINE_CHAIN linechain;
1510  for( auto& vertice : elem.vertices )
1511  {
1512  linechain.Append( vertice.position );
1513  }
1514  linechain.Append( elem.vertices.at( 0 ).position );
1515  linechain.SetClosed( true );
1516 
1517  SHAPE_POLY_SET polyset;
1518  polyset.AddOutline( linechain );
1519  polyset.BooleanAdd( zone->GetFilledPolysList(), SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
1520 
1521  zone->SetFilledPolysList( polyset );
1522  zone->SetIsFilled( true );
1523  }
1524 #endif
1525  }
1526 
1527  if( reader.GetRemainingBytes() != 0 )
1528  {
1529  THROW_IO_ERROR( "Regions6 stream is not fully parsed" );
1530  }
1531 }
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
const SHAPE_POLY_SET & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:629
const uint16_t ALTIUM_POLYGON_NONE
std::vector< ZONE_CONTAINER * > m_polygons
Definition: altium_pcb.h:187
void SetIsFilled(bool isFilled)
Definition: class_zone.h:215
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void SetClosed(bool aClosed)
Function SetClosed()
SHAPE_POLY_SET.
void SetFilledPolysList(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:644
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
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
SHAPE_LINE_CHAIN.
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References SHAPE_POLY_SET::AddOutline(), ALTIUM_POLYGON_NONE, SHAPE_LINE_CHAIN::Append(), SHAPE_POLY_SET::BooleanAdd(), Format(), ZONE_CONTAINER::GetFilledPolysList(), ALTIUM_PARSER::GetRemainingBytes(), m_polygons, SHAPE_LINE_CHAIN::SetClosed(), ZONE_CONTAINER::SetFilledPolysList(), ZONE_CONTAINER::SetIsFilled(), AREGION6::subpolyindex, THROW_IO_ERROR, and AREGION6::vertices.

Referenced by Parse().

◆ ParseRules6Data()

void ALTIUM_PCB::ParseRules6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1325 of file altium_pcb.cpp.

1327 {
1328  ALTIUM_PARSER reader( aReader, aEntry );
1329 
1330  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1331  {
1332  ARULE6 elem( reader );
1333 
1334  m_rules[elem.kind].emplace_back( elem );
1335  }
1336 
1337  // sort rules by priority
1338  for( auto&& val : m_rules )
1339  {
1340  std::sort( val.second.begin(), val.second.end(),
1341  []( const auto& lhs, const auto& rhs ) { return lhs.priority < rhs.priority; } );
1342  }
1343 
1344  if( reader.GetRemainingBytes() != 0 )
1345  {
1346  THROW_IO_ERROR( "Rules6 stream is not fully parsed" );
1347  }
1348 }
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
Definition: altium_pcb.h:191
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References ALTIUM_PARSER::GetRemainingBytes(), ARULE6::kind, m_rules, and THROW_IO_ERROR.

Referenced by Parse().

◆ ParseShapeBasedRegions6Data()

void ALTIUM_PCB::ParseShapeBasedRegions6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 1368 of file altium_pcb.cpp.

1370 {
1371  ALTIUM_PARSER reader( aReader, aEntry );
1372 
1373  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
1374  {
1375  AREGION6 elem( reader, true );
1376 
1377  if( elem.kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
1378  {
1379  HelperCreateBoardOutline( elem.vertices );
1380  }
1381  else if( elem.kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || elem.is_keepout )
1382  {
1383  SHAPE_LINE_CHAIN linechain;
1384  HelperShapeLineChainFromAltiumVertices( linechain, elem.vertices );
1385 
1386  if( linechain.PointCount() < 2 )
1387  {
1388  wxLogError( wxString::Format(
1389  _( "ShapeBasedRegion has only %d point extracted from %ld vertices. At least 2 points are required." ),
1390  linechain.PointCount(), elem.vertices.size() ) );
1391  continue;
1392  }
1393 
1394  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
1395  m_board->Add( zone, ADD_MODE::APPEND );
1396 
1397  zone->SetIsRuleArea( true );
1398  zone->SetDoNotAllowTracks( false );
1399  zone->SetDoNotAllowVias( false );
1400  zone->SetDoNotAllowPads( false );
1401  zone->SetDoNotAllowFootprints( false );
1402  zone->SetDoNotAllowCopperPour( true );
1403 
1404  zone->SetPosition( elem.vertices.at( 0 ).position );
1405  zone->Outline()->AddOutline( linechain );
1406 
1407  if( elem.layer == ALTIUM_LAYER::MULTI_LAYER )
1408  {
1409  zone->SetLayer( F_Cu );
1410  zone->SetLayerSet( LSET::AllCuMask() );
1411  }
1412  else
1413  {
1414  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
1415  if( klayer == UNDEFINED_LAYER )
1416  {
1417  wxLogWarning( wxString::Format(
1418  _( "Zone on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
1419  elem.layer ) );
1420  klayer = Eco1_User;
1421  }
1422  zone->SetLayer( klayer );
1423  }
1424 
1427  }
1428  else if( elem.kind == ALTIUM_REGION_KIND::COPPER )
1429  {
1430  if( elem.subpolyindex == ALTIUM_POLYGON_NONE )
1431  {
1432  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
1433  if( klayer == UNDEFINED_LAYER )
1434  {
1435  wxLogWarning( wxString::Format(
1436  _( "Polygon on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
1437  elem.layer ) );
1438  klayer = Eco1_User;
1439  }
1440 
1441  SHAPE_LINE_CHAIN linechain;
1442  HelperShapeLineChainFromAltiumVertices( linechain, elem.vertices );
1443 
1444  if( linechain.PointCount() < 2 )
1445  {
1446  wxLogError( wxString::Format(
1447  _( "Polygon has only %d point extracted from %ld vertices. At least 2 points are required." ),
1448  linechain.PointCount(), elem.vertices.size() ) );
1449  continue;
1450  }
1451 
1452  PCB_SHAPE* shape = new PCB_SHAPE( m_board );
1453  m_board->Add( shape, ADD_MODE::APPEND );
1454  shape->SetShape( S_POLYGON );
1455  shape->SetLayer( klayer );
1456  shape->SetWidth( 0 );
1457 
1458  shape->SetPolyShape( linechain );
1459  }
1460  }
1461  else
1462  {
1463  wxLogError( wxString::Format(
1464  "Ignore polygon shape of kind %d on layer %s, because not implemented yet",
1465  elem.kind, LSET::Name( GetKicadLayer( elem.layer ) ) ) );
1466  }
1467  }
1468 
1469  if( reader.GetRemainingBytes() != 0 )
1470  {
1471  THROW_IO_ERROR( "ShapeBasedRegions6 stream is not fully parsed" );
1472  }
1473 }
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:738
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void SetDoNotAllowFootprints(bool aEnable)
Definition: class_zone.h:740
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:300
const uint16_t ALTIUM_POLYGON_NONE
void SetIsRuleArea(bool aEnable)
Definition: class_zone.h:735
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
int PointCount() const
Function PointCount()
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:737
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
void SetLayerSet(LSET aLayerSet) override
Definition: class_zone.cpp:242
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:81
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:234
void HelperShapeLineChainFromAltiumVertices(SHAPE_LINE_CHAIN &aLine, const std::vector< ALTIUM_VERTICE > &aVertices)
Definition: altium_pcb.cpp:149
void SetDoNotAllowPads(bool aEnable)
Definition: class_zone.h:739
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetBorderDisplayStyle sets all hatch parameters for the zone.
Definition: class_zone.cpp:888
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:736
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
polygon (not yet used for tracks, but could be in microwave apps)
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
void HelperCreateBoardOutline(const std::vector< ALTIUM_VERTICE > &aVertices)
Definition: altium_pcb.cpp:642
void SetPosition(const wxPoint &aPos) override
Definition: class_zone.h:94
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: pcb_shape.h:251
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, BOARD::Add(), SHAPE_POLY_SET::AddOutline(), LSET::AllCuMask(), ALTIUM_POLYGON_NONE, APPEND, BOARD_CUTOUT, COPPER, DIAGONAL_EDGE, Eco1_User, F_Cu, Format(), ZONE_CONTAINER::GetDefaultHatchPitch(), GetKicadLayer(), ALTIUM_PARSER::GetRemainingBytes(), HelperCreateBoardOutline(), HelperShapeLineChainFromAltiumVertices(), AREGION6::is_keepout, AREGION6::kind, AREGION6::layer, m_board, MULTI_LAYER, LSET::Name(), ZONE_CONTAINER::Outline(), SHAPE_LINE_CHAIN::PointCount(), POLYGON_CUTOUT, S_POLYGON, ZONE_CONTAINER::SetBorderDisplayStyle(), ZONE_CONTAINER::SetDoNotAllowCopperPour(), ZONE_CONTAINER::SetDoNotAllowFootprints(), ZONE_CONTAINER::SetDoNotAllowPads(), ZONE_CONTAINER::SetDoNotAllowTracks(), ZONE_CONTAINER::SetDoNotAllowVias(), ZONE_CONTAINER::SetIsRuleArea(), ZONE_CONTAINER::SetLayer(), BOARD_ITEM::SetLayer(), ZONE_CONTAINER::SetLayerSet(), PCB_SHAPE::SetPolyShape(), ZONE_CONTAINER::SetPosition(), PCB_SHAPE::SetShape(), PCB_SHAPE::SetWidth(), AREGION6::subpolyindex, THROW_IO_ERROR, UNDEFINED_LAYER, and AREGION6::vertices.

Referenced by Parse().

◆ ParseTexts6Data()

void ALTIUM_PCB::ParseTexts6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 2221 of file altium_pcb.cpp.

2223 {
2224  ALTIUM_PARSER reader( aReader, aEntry );
2225 
2226  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
2227  {
2228  ATEXT6 elem( reader );
2229 
2230  if( elem.fonttype == ALTIUM_TEXT_TYPE::BARCODE )
2231  {
2232  wxLogWarning( wxString::Format(
2233  _( "Ignore Barcode on Altium layer %d because it is not supported right now." ),
2234  elem.layer ) );
2235  continue;
2236  }
2237 
2238  // TODO: better approach to select if item belongs to a MODULE
2239  EDA_TEXT* tx = nullptr;
2240  BOARD_ITEM* itm = nullptr;
2241 
2242  if( elem.component == ALTIUM_COMPONENT_NONE )
2243  {
2244  PCB_TEXT* pcbText = new PCB_TEXT( m_board );
2245  tx = pcbText;
2246  itm = pcbText;
2247  m_board->Add( pcbText, ADD_MODE::APPEND );
2248  }
2249  else
2250  {
2251  if( m_components.size() <= elem.component )
2252  {
2254  "Texts6 stream tries to access component id %d of %d existing components",
2255  elem.component, m_components.size() ) );
2256  }
2257 
2258  MODULE* module = m_components.at( elem.component );
2259  FP_TEXT* fpText;
2260 
2261  if( elem.isDesignator )
2262  {
2263  fpText = &module->Reference();
2264  }
2265  else if( elem.isComment )
2266  {
2267  fpText = &module->Value();
2268  }
2269  else
2270  {
2271  fpText = new FP_TEXT( module );
2272  module->Add( fpText, ADD_MODE::APPEND );
2273  }
2274 
2275  fpText->SetKeepUpright( false );
2276 
2277  tx = fpText;
2278  itm = fpText;
2279  }
2280 
2281  wxString trimmedText = elem.text.Trim();
2282  if( !elem.isDesignator && trimmedText.CmpNoCase( ".Designator" ) == 0 )
2283  {
2284  tx->SetText( "${REFERENCE}" );
2285  }
2286  else if( !elem.isComment && trimmedText.CmpNoCase( ".Comment" ) == 0 )
2287  {
2288  tx->SetText( "${VALUE}" );
2289  }
2290  else if( trimmedText.CmpNoCase( ".Layer_Name" ) == 0 )
2291  {
2292  tx->SetText( "${LAYER}" );
2293  }
2294  else
2295  {
2296  tx->SetText( elem.text );
2297  }
2298 
2299  itm->SetPosition( elem.position );
2300  tx->SetTextAngle( elem.rotation * 10. );
2301 
2302  if( elem.component != ALTIUM_COMPONENT_NONE )
2303  {
2304  FP_TEXT* fpText = dynamic_cast<FP_TEXT*>( tx );
2305 
2306  if( fpText )
2307  {
2308  double orientation =
2309  static_cast<const MODULE*>( fpText->GetParent() )->GetOrientation();
2310  fpText->SetTextAngle( fpText->GetTextAngle() - orientation );
2311  fpText->SetLocalCoord();
2312  }
2313  }
2314 
2315  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
2316 
2317  if( klayer == UNDEFINED_LAYER )
2318  {
2319  wxLogWarning( wxString::Format(
2320  _( "Text on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
2321  elem.layer ) );
2322  klayer = Eco1_User;
2323  }
2324 
2325  itm->SetLayer( klayer );
2326 
2327  if( elem.fonttype == ALTIUM_TEXT_TYPE::TRUETYPE )
2328  {
2329  // TODO: why is this required? Somehow, truetype size is calculated differently
2330  tx->SetTextSize( wxSize( elem.height / 2, elem.height / 2 ) );
2331  }
2332  else
2333  {
2334  tx->SetTextSize( wxSize( elem.height, elem.height ) ); // TODO: parse text width
2335  }
2336 
2337  tx->SetTextThickness( elem.strokewidth );
2338  tx->SetBold( elem.isBold );
2339  tx->SetItalic( elem.isItalic );
2340  tx->SetMirrored( elem.isMirrored );
2341 
2342  if( elem.isDesignator || elem.isComment ) // That's just a bold assumption
2343  {
2346  }
2347  else
2348  {
2349  switch( elem.textposition )
2350  {
2355  break;
2360  break;
2365  break;
2366  default:
2367  wxLogError( "Unexpected horizontal Text Position. This should never happen." );
2368  break;
2369  }
2370 
2371  switch( elem.textposition )
2372  {
2377  break;
2382  break;
2387  break;
2388  default:
2389  wxLogError( "Unexpected vertical text position. This should never happen." );
2390  break;
2391  }
2392  }
2393  }
2394 
2395  if( reader.GetRemainingBytes() != 0 )
2396  {
2397  THROW_IO_ERROR( "Texts6 stream is not fully parsed" );
2398  }
2399 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:194
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
virtual void SetPosition(const wxPoint &aPos)
Definition: eda_item.h:327
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
FP_TEXT & Value()
read/write accessors:
Definition: class_module.h:475
void SetTextAngle(double aAngle) override
Definition: fp_text.cpp:68
void SetItalic(bool isItalic)
Definition: eda_text.h:185
double GetTextAngle() const
Definition: eda_text.h:180
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:244
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
FP_TEXT & Reference()
Definition: class_module.h:476
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:119
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:120
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:209
std::vector< MODULE * > m_components
Definition: altium_pcb.h:186
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
void SetKeepUpright(bool aKeepUpright)
Definition: fp_text.h:117
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
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:208
#define _(s)
Definition: 3d_actions.cpp:33
void SetLocalCoord()
Set relative coordinates.
Definition: fp_text.cpp:217
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:164
const int ALTIUM_COMPONENT_NONE
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:173
BOARD_ITEM_CONTAINER * GetParent() const
void SetBold(bool aBold)
Definition: eda_text.h:188
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, MODULE::Add(), BOARD::Add(), ALTIUM_COMPONENT_NONE, APPEND, BARCODE, CENTER_BOTTOM, CENTER_CENTER, CENTER_TOP, ATEXT6::component, Eco1_User, ATEXT6::fonttype, Format(), GetKicadLayer(), BOARD_ITEM::GetParent(), ALTIUM_PARSER::GetRemainingBytes(), EDA_TEXT::GetTextAngle(), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_TOP, ATEXT6::height, ATEXT6::isBold, ATEXT6::isComment, ATEXT6::isDesignator, ATEXT6::isItalic, ATEXT6::isMirrored, ATEXT6::layer, LEFT_BOTTOM, LEFT_CENTER, LEFT_TOP, m_board, m_components, ATEXT6::position, MODULE::Reference(), RIGHT_BOTTOM, RIGHT_CENTER, RIGHT_TOP, ATEXT6::rotation, EDA_TEXT::SetBold(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetItalic(), FP_TEXT::SetKeepUpright(), BOARD_ITEM::SetLayer(), FP_TEXT::SetLocalCoord(), EDA_TEXT::SetMirrored(), EDA_ITEM::SetPosition(), EDA_TEXT::SetText(), FP_TEXT::SetTextAngle(), EDA_TEXT::SetTextAngle(), EDA_TEXT::SetTextSize(), EDA_TEXT::SetTextThickness(), EDA_TEXT::SetVertJustify(), ATEXT6::strokewidth, ATEXT6::text, ATEXT6::textposition, THROW_IO_ERROR, TRUETYPE, UNDEFINED_LAYER, and MODULE::Value().

Referenced by Parse().

◆ ParseTracks6Data()

void ALTIUM_PCB::ParseTracks6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 2120 of file altium_pcb.cpp.

2122 {
2123  ALTIUM_PARSER reader( aReader, aEntry );
2124 
2125  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
2126  {
2127  ATRACK6 elem( reader );
2128 
2129  if( elem.is_polygonoutline || elem.subpolyindex != ALTIUM_POLYGON_NONE )
2130  continue;
2131 
2132  // element in plane is in fact substracted from the plane. Already done by Altium?
2133  //if( IsAltiumLayerAPlane( elem.layer ) )
2134  // continue;
2135 
2136  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
2137 
2138  if( elem.is_keepout || IsAltiumLayerAPlane( elem.layer ) )
2139  {
2140  PCB_SHAPE shape( nullptr ); // just a helper to get the graphic
2141  shape.SetShape( S_SEGMENT );
2142  shape.SetStart( elem.start );
2143  shape.SetEnd( elem.end );
2144  shape.SetWidth( elem.width );
2145 
2146  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
2147  m_board->Add( zone, ADD_MODE::APPEND );
2148 
2149  zone->SetIsRuleArea( true );
2150  zone->SetDoNotAllowTracks( false );
2151  zone->SetDoNotAllowVias( false );
2152  zone->SetDoNotAllowPads( false );
2153  zone->SetDoNotAllowFootprints( false );
2154  zone->SetDoNotAllowCopperPour( true );
2155 
2156  if( elem.layer == ALTIUM_LAYER::MULTI_LAYER )
2157  {
2158  zone->SetLayer( F_Cu );
2159  zone->SetLayerSet( LSET::AllCuMask() );
2160  }
2161  else
2162  {
2163  PCB_LAYER_ID klayer = GetKicadLayer( elem.layer );
2164  if( klayer == UNDEFINED_LAYER )
2165  {
2166  wxLogWarning( wxString::Format(
2167  _( "Track Keepout on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
2168  elem.layer ) );
2169  klayer = Eco1_User;
2170  }
2171  zone->SetLayer( klayer );
2172  }
2173 
2174  shape.TransformShapeWithClearanceToPolygon( *zone->Outline(), klayer, 0, ARC_HIGH_DEF,
2175  ERROR_INSIDE );
2176 
2179  continue;
2180  }
2181 
2182  if( klayer == UNDEFINED_LAYER )
2183  {
2184  wxLogWarning( wxString::Format(
2185  _( "Track on Altium layer %d has no KiCad equivalent. Put it on Eco1_User instead" ),
2186  elem.layer ) );
2187  klayer = Eco1_User;
2188  }
2189 
2190  if( klayer >= F_Cu && klayer <= B_Cu )
2191  {
2192  TRACK* track = new TRACK( m_board );
2193  m_board->Add( track, ADD_MODE::APPEND );
2194 
2195  track->SetStart( elem.start );
2196  track->SetEnd( elem.end );
2197  track->SetWidth( elem.width );
2198  track->SetLayer( klayer );
2199  track->SetNetCode( GetNetCode( elem.net ) );
2200  }
2201  else
2202  {
2203  PCB_SHAPE* shape = HelperCreateAndAddDrawsegment( elem.component );
2204  shape->SetShape( S_SEGMENT );
2205  shape->SetStart( elem.start );
2206  shape->SetEnd( elem.end );
2207  shape->SetWidth( elem.width );
2208  shape->SetLayer( klayer );
2209  HelperDrawsegmentSetLocalCoord( shape, elem.component );
2210  }
2211 
2212  reader.SkipSubrecord();
2213  }
2214 
2215  if( reader.GetRemainingBytes() != 0 )
2216  {
2217  THROW_IO_ERROR( "Tracks6 stream is not fully parsed" );
2218  }
2219 }
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:738
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
usual segment : line with rounded ends
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
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:112
void SetDoNotAllowFootprints(bool aEnable)
Definition: class_zone.h:740
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:300
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
const uint16_t ALTIUM_POLYGON_NONE
void SetIsRuleArea(bool aEnable)
Definition: class_zone.h:735
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:737
void SetWidth(int aWidth)
Definition: class_track.h:109
int GetNetCode(uint16_t aId) const
Definition: altium_pcb.cpp:457
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
void SetLayerSet(LSET aLayerSet) override
Definition: class_zone.cpp:242
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:234
void SetDoNotAllowPads(bool aEnable)
Definition: class_zone.h:739
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetBorderDisplayStyle sets all hatch parameters for the zone.
Definition: class_zone.cpp:888
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:736
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
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:132
#define _(s)
Definition: 3d_actions.cpp:33
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
void SetStart(const wxPoint &aStart)
Definition: class_track.h:115
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
Definition: altium_pcb.cpp:105
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
PCB_SHAPE * HelperCreateAndAddDrawsegment(uint16_t aComponent)
Definition: altium_pcb.cpp:111
void HelperDrawsegmentSetLocalCoord(PCB_SHAPE *aShape, uint16_t aComponent)
Definition: altium_pcb.cpp:137
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:143

References _, BOARD::Add(), LSET::AllCuMask(), ALTIUM_POLYGON_NONE, APPEND, B_Cu, ATRACK6::component, DIAGONAL_EDGE, Eco1_User, ATRACK6::end, ERROR_INSIDE, F_Cu, Format(), ZONE_CONTAINER::GetDefaultHatchPitch(), GetKicadLayer(), GetNetCode(), ALTIUM_PARSER::GetRemainingBytes(), HelperCreateAndAddDrawsegment(), HelperDrawsegmentSetLocalCoord(), ATRACK6::is_keepout, ATRACK6::is_polygonoutline, IsAltiumLayerAPlane(), ATRACK6::layer, m_board, MULTI_LAYER, ATRACK6::net, ZONE_CONTAINER::Outline(), S_SEGMENT, ZONE_CONTAINER::SetBorderDisplayStyle(), ZONE_CONTAINER::SetDoNotAllowCopperPour(), ZONE_CONTAINER::SetDoNotAllowFootprints(), ZONE_CONTAINER::SetDoNotAllowPads(), ZONE_CONTAINER::SetDoNotAllowTracks(), ZONE_CONTAINER::SetDoNotAllowVias(), TRACK::SetEnd(), PCB_SHAPE::SetEnd(), ZONE_CONTAINER::SetIsRuleArea(), ZONE_CONTAINER::SetLayer(), BOARD_ITEM::SetLayer(), ZONE_CONTAINER::SetLayerSet(), BOARD_CONNECTED_ITEM::SetNetCode(), PCB_SHAPE::SetShape(), TRACK::SetStart(), PCB_SHAPE::SetStart(), PCB_SHAPE::SetWidth(), TRACK::SetWidth(), ALTIUM_PARSER::SkipSubrecord(), ATRACK6::start, ATRACK6::subpolyindex, THROW_IO_ERROR, TRACK, PCB_SHAPE::TransformShapeWithClearanceToPolygon(), UNDEFINED_LAYER, and ATRACK6::width.

Referenced by Parse().

◆ ParseVias6Data()

void ALTIUM_PCB::ParseVias6Data ( const CFB::CompoundFileReader &  aReader,
const CFB::COMPOUND_FILE_ENTRY *  aEntry 
)
private

Definition at line 2064 of file altium_pcb.cpp.

2066 {
2067  ALTIUM_PARSER reader( aReader, aEntry );
2068 
2069  while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
2070  {
2071  AVIA6 elem( reader );
2072 
2073  VIA* via = new VIA( m_board );
2074  m_board->Add( via, ADD_MODE::APPEND );
2075 
2076  via->SetPosition( elem.position );
2077  via->SetWidth( elem.diameter );
2078  via->SetDrill( elem.holesize );
2079  via->SetNetCode( GetNetCode( elem.net ) );
2080  via->SetLocked( elem.is_locked );
2081 
2082  bool start_layer_outside = elem.layer_start == ALTIUM_LAYER::TOP_LAYER
2083  || elem.layer_start == ALTIUM_LAYER::BOTTOM_LAYER;
2084  bool end_layer_outside = elem.layer_end == ALTIUM_LAYER::TOP_LAYER
2085  || elem.layer_end == ALTIUM_LAYER::BOTTOM_LAYER;
2086 
2087  if( start_layer_outside && end_layer_outside )
2088  {
2089  via->SetViaType( VIATYPE::THROUGH );
2090  }
2091  else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
2092  {
2094  }
2095  else
2096  {
2097  via->SetViaType( VIATYPE::MICROVIA ); // TODO: always a microvia?
2098  }
2099 
2100  PCB_LAYER_ID start_klayer = GetKicadLayer( elem.layer_start );
2101  PCB_LAYER_ID end_klayer = GetKicadLayer( elem.layer_end );
2102  if( !IsCopperLayer( start_klayer ) || !IsCopperLayer( end_klayer ) )
2103  {
2104  wxLogError( wxString::Format(
2105  "Via from layer %d <-> %d uses non-copper layer. This should not happen.",
2106  elem.layer_start, elem.layer_end ) );
2107  continue; // just assume through-hole instead.
2108  }
2109 
2110  // we need VIATYPE set!
2111  via->SetLayerPair( start_klayer, end_klayer );
2112  }
2113 
2114  if( reader.GetRemainingBytes() != 0 )
2115  {
2116  THROW_IO_ERROR( "Vias6 stream is not fully parsed" );
2117  }
2118 }
void SetPosition(const wxPoint &aPoint) override
Definition: class_track.h:424
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
Definition: altium_pcb.cpp:189
void SetWidth(int aWidth)
Definition: class_track.h:109
int GetNetCode(uint16_t aId) const
Definition: altium_pcb.cpp:457
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
void SetLocked(bool aLocked) override
Function SetLocked modifies 'lock' status for of the item.
Definition: class_track.h:141
PCB_LAYER_ID
A quick note on layer IDs:
BOARD * m_board
Definition: altium_pcb.h:185
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 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
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: class_track.h:486
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
void SetViaType(VIATYPE aViaType)
Definition: class_track.h:385
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References BOARD::Add(), APPEND, BLIND_BURIED, BOTTOM_LAYER, AVIA6::diameter, Format(), GetKicadLayer(), GetNetCode(), ALTIUM_PARSER::GetRemainingBytes(), AVIA6::holesize, AVIA6::is_locked, IsCopperLayer(), AVIA6::layer_end, AVIA6::layer_start, m_board, MICROVIA, AVIA6::net, AVIA6::position, VIA::SetDrill(), VIA::SetLayerPair(), TRACK::SetLocked(), BOARD_CONNECTED_ITEM::SetNetCode(), VIA::SetPosition(), VIA::SetViaType(), TRACK::SetWidth(), THROUGH, THROW_IO_ERROR, TOP_LAYER, and VIA.

Referenced by Parse().

Member Data Documentation

◆ m_board

◆ m_components

std::vector<MODULE*> ALTIUM_PCB::m_components
private

◆ m_highest_pour_index

int ALTIUM_PCB::m_highest_pour_index
private

Altium stores pour order across all layers.

Definition at line 196 of file altium_pcb.h.

Referenced by ALTIUM_PCB(), Parse(), and ParsePolygons6Data().

◆ m_layermap

std::map<ALTIUM_LAYER, PCB_LAYER_ID> ALTIUM_PCB::m_layermap
private

Definition at line 190 of file altium_pcb.h.

Referenced by GetKicadLayer(), and ParseBoard6Data().

◆ m_models

std::map<wxString, wxString> ALTIUM_PCB::m_models
private

Definition at line 188 of file altium_pcb.h.

Referenced by ParseComponentsBodies6Data(), and ParseModelsData().

◆ m_num_nets

size_t ALTIUM_PCB::m_num_nets
private

Definition at line 189 of file altium_pcb.h.

Referenced by ALTIUM_PCB(), GetNetCode(), and ParseNets6Data().

◆ m_outer_plane

std::map<ALTIUM_LAYER, ZONE_CONTAINER*> ALTIUM_PCB::m_outer_plane
private

Definition at line 193 of file altium_pcb.h.

Referenced by Parse(), and ParsePolygons6Data().

◆ m_polygons

std::vector<ZONE_CONTAINER*> ALTIUM_PCB::m_polygons
private

Definition at line 187 of file altium_pcb.h.

Referenced by Parse(), ParsePolygons6Data(), and ParseRegions6Data().

◆ m_rules

std::map<ALTIUM_RULE_KIND, std::vector<ARULE6> > ALTIUM_PCB::m_rules
private

Definition at line 191 of file altium_pcb.h.

Referenced by GetRule(), GetRuleDefault(), and ParseRules6Data().


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