Altium PCB: import hatched polygon pour fills.

This commit is contained in:
Alex Shvartzkop 2023-11-26 00:23:34 +03:00
parent 37d9b7fac0
commit a8795711a0
3 changed files with 117 additions and 23 deletions

View File

@ -615,7 +615,7 @@ AARC6::AARC6( ALTIUM_PARSER& aReader )
is_keepout = flags2 == 2;
net = aReader.Read<uint16_t>();
subpolyindex = aReader.Read<uint16_t>();
polygon = aReader.Read<uint16_t>();
component = aReader.Read<uint16_t>();
aReader.Skip( 4 );
center = aReader.ReadVector2IPos();
@ -623,10 +623,11 @@ AARC6::AARC6( ALTIUM_PARSER& aReader )
startangle = aReader.Read<double>();
endangle = aReader.Read<double>();
width = aReader.ReadKicadUnit();
subpolyindex = aReader.Read<uint16_t>();
if( aReader.GetRemainingSubrecordBytes() >= 12 )
{
aReader.Skip( 11 );
aReader.Skip( 9 );
keepoutrestrictions = aReader.Read<uint8_t>();
}
else
@ -888,16 +889,17 @@ ATRACK6::ATRACK6( ALTIUM_PARSER& aReader )
is_keepout = flags2 == 2;
net = aReader.Read<uint16_t>();
subpolyindex = aReader.Read<uint16_t>();
polygon = aReader.Read<uint16_t>();
component = aReader.Read<uint16_t>();
aReader.Skip( 4 );
start = aReader.ReadVector2IPos();
end = aReader.ReadVector2IPos();
width = aReader.ReadKicadUnit();
subpolyindex = aReader.Read<uint16_t>();
if( aReader.GetRemainingSubrecordBytes() >= 13 )
{
aReader.Skip( 12 );
aReader.Skip( 10 );
keepoutrestrictions = aReader.Read<uint8_t>();
}
else
@ -1038,7 +1040,7 @@ AREGION6::AREGION6( ALTIUM_PARSER& aReader, bool aExtendedVertices )
is_keepout = flags2 == 2;
net = aReader.Read<uint16_t>();
subpolyindex = aReader.Read<uint16_t>();
polygon = aReader.Read<uint16_t>();
component = aReader.Read<uint16_t>();
aReader.Skip( 5 );
holecount = aReader.Read<uint16_t>();
@ -1057,8 +1059,9 @@ AREGION6::AREGION6( ALTIUM_PARSER& aReader, bool aExtendedVertices )
ALTIUM_PARSER::ReadInt( properties, wxT( "KEEPOUTRESTRIC" ), 0x1F ) );
// TODO: this can differ from the other subpolyindex?!
//subpolyindex = static_cast<uint16_t>(
// ALTIUM_PARSER::ReadInt( properties, "SUBPOLYINDEX", ALTIUM_POLYGON_NONE ) );
// Note: "the other subpolyindex" is "polygon"
subpolyindex = static_cast<uint16_t>(
ALTIUM_PARSER::ReadInt( properties, "SUBPOLYINDEX", ALTIUM_POLYGON_NONE ) );
switch( pkind )
{

View File

@ -549,6 +549,7 @@ struct AREGION6
ALTIUM_LAYER layer;
uint16_t net;
uint16_t component;
uint16_t polygon;
uint16_t subpolyindex;
uint8_t keepoutrestrictions;
uint16_t holecount;
@ -570,6 +571,7 @@ struct AARC6
ALTIUM_LAYER layer;
uint16_t net;
uint16_t component;
uint16_t polygon;
uint16_t subpolyindex;
uint8_t keepoutrestrictions;
@ -683,6 +685,7 @@ struct ATRACK6
ALTIUM_LAYER layer;
uint16_t net;
uint16_t component;
uint16_t polygon;
uint16_t subpolyindex;
uint8_t keepoutrestrictions;

View File

@ -530,6 +530,21 @@ void ALTIUM_PCB::Parse( const ALTIUM_COMPOUND_FILE& altiumPcbFi
for( std::pair<const ALTIUM_LAYER, ZONE*>& zone : m_outer_plane )
zone.second->SetAssignedPriority( 0 );
// Simplify and fracture zone fills in case we constructed them from tracks (hatched fill)
for( ZONE* zone : m_polygons )
{
if( !zone )
continue;
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
{
if( !zone->HasFilledPolysForLayer( layer ) )
continue;
zone->GetFilledPolysList( layer )->Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
}
}
// Altium doesn't appear to store either the dimension value nor the dimensioned object in
// the dimension record. (Yes, there is a REFERENCE0OBJECTID, but it doesn't point to the
// dimensioned object.) We attempt to plug this gap by finding a colocated arc or circle
@ -2038,7 +2053,7 @@ void ALTIUM_PCB::ConvertShapeBasedRegions6ToBoardItem( const AREGION6& aElem )
}
else if( aElem.kind == ALTIUM_REGION_KIND::COPPER )
{
if( aElem.subpolyindex == ALTIUM_POLYGON_NONE )
if( aElem.polygon == ALTIUM_POLYGON_NONE )
{
for( PCB_LAYER_ID klayer : GetKicadLayersToIterate( aElem.layer ) )
ConvertShapeBasedRegions6ToBoardItemOnLayer( aElem, klayer );
@ -2101,7 +2116,7 @@ void ALTIUM_PCB::ConvertShapeBasedRegions6ToFootprintItem( FOOTPRINT* aFoot
}
else if( aElem.kind == ALTIUM_REGION_KIND::COPPER )
{
if( aElem.subpolyindex == ALTIUM_POLYGON_NONE )
if( aElem.polygon == ALTIUM_POLYGON_NONE )
{
for( PCB_LAYER_ID klayer : GetKicadLayersToIterate( aElem.layer ) )
{
@ -2309,28 +2324,22 @@ void ALTIUM_PCB::ParseRegions6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFi
ALTIUM_PARSER reader( aAltiumPcbFile, aEntry );
for( ZONE* zone : m_polygons )
{
if( zone )
zone->UnFill(); // just to be sure
}
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
{
checkpoint();
AREGION6 elem( reader, false );
if( elem.subpolyindex != ALTIUM_POLYGON_NONE )
if( elem.polygon != ALTIUM_POLYGON_NONE )
{
if( m_polygons.size() <= elem.subpolyindex )
if( m_polygons.size() <= elem.polygon )
{
THROW_IO_ERROR( wxString::Format( "Region stream tries to access polygon id %d "
"of %d existing polygons.",
elem.subpolyindex,
elem.polygon,
m_polygons.size() ) );
}
ZONE *zone = m_polygons.at( elem.subpolyindex );
ZONE* zone = m_polygons.at( elem.polygon );
if( zone == nullptr )
{
@ -2440,8 +2449,44 @@ void ALTIUM_PCB::ConvertArcs6ToPcbShape( const AARC6& aElem, PCB_SHAPE* aShape )
void ALTIUM_PCB::ConvertArcs6ToBoardItem( const AARC6& aElem, const int aPrimitiveIndex )
{
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
if( aElem.polygon != ALTIUM_POLYGON_NONE )
{
if( m_polygons.size() <= aElem.polygon )
{
THROW_IO_ERROR( wxString::Format( "Tracks stream tries to access polygon id %d "
"of %d existing polygons.",
aElem.polygon, m_polygons.size() ) );
}
ZONE* zone = m_polygons.at( aElem.polygon );
if( zone == nullptr )
{
return; // we know the zone id, but because we do not know the layer we did not
// add it!
}
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
if( klayer == UNDEFINED_LAYER )
return; // Just skip it for now. Users can fill it themselves.
SHAPE_POLY_SET* fill = zone->GetFill( klayer );
// This is not the actual board item. We can use it to create the polygon for the region
PCB_SHAPE shape( nullptr );
ConvertArcs6ToPcbShape( aElem, &shape );
shape.SetStroke( STROKE_PARAMS( aElem.width, LINE_STYLE::SOLID ) );
shape.EDA_SHAPE::TransformShapeToPolygon( *fill, 0, ARC_HIGH_DEF, ERROR_INSIDE );
// Will be simplified and fractured later
zone->SetIsFilled( true );
zone->SetNeedRefill( false );
return;
}
if( aElem.is_keepout || aElem.layer == ALTIUM_LAYER::KEEP_OUT_LAYER
|| IsAltiumLayerAPlane( aElem.layer ) )
@ -2482,8 +2527,12 @@ void ALTIUM_PCB::ConvertArcs6ToBoardItem( const AARC6& aElem, const int aPrimiti
void ALTIUM_PCB::ConvertArcs6ToFootprintItem( FOOTPRINT* aFootprint, const AARC6& aElem,
const int aPrimitiveIndex, const bool aIsBoardImport )
{
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
if( aElem.polygon != ALTIUM_POLYGON_NONE )
{
wxFAIL_MSG( wxString::Format( "Altium: Unexpected footprint Arc with polygon id %d",
aElem.polygon ) );
return;
}
if( aElem.is_keepout || aElem.layer == ALTIUM_LAYER::KEEP_OUT_LAYER
|| IsAltiumLayerAPlane( aElem.layer ) )
@ -3134,8 +3183,43 @@ void ALTIUM_PCB::ParseTracks6Data( const ALTIUM_COMPOUND_FILE& aAltiumPcbFil
void ALTIUM_PCB::ConvertTracks6ToBoardItem( const ATRACK6& aElem, const int aPrimitiveIndex )
{
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
if( aElem.polygon != ALTIUM_POLYGON_NONE )
{
if( m_polygons.size() <= aElem.polygon )
{
THROW_IO_ERROR( wxString::Format( "Tracks stream tries to access polygon id %d "
"of %d existing polygons.",
aElem.polygon, m_polygons.size() ) );
}
ZONE* zone = m_polygons.at( aElem.polygon );
if( zone == nullptr )
{
return; // we know the zone id, but because we do not know the layer we did not
// add it!
}
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
if( klayer == UNDEFINED_LAYER )
return; // Just skip it for now. Users can fill it themselves.
SHAPE_POLY_SET* fill = zone->GetFill( klayer );
PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
shape.SetStart( aElem.start );
shape.SetEnd( aElem.end );
shape.SetStroke( STROKE_PARAMS( aElem.width, LINE_STYLE::SOLID ) );
shape.EDA_SHAPE::TransformShapeToPolygon( *fill, 0, ARC_HIGH_DEF, ERROR_INSIDE );
// Will be simplified and fractured later
zone->SetIsFilled( true );
zone->SetNeedRefill( false );
return;
}
if( aElem.is_keepout || aElem.layer == ALTIUM_LAYER::KEEP_OUT_LAYER
|| IsAltiumLayerAPlane( aElem.layer ) )
@ -3177,8 +3261,12 @@ void ALTIUM_PCB::ConvertTracks6ToFootprintItem( FOOTPRINT* aFootprint, const ATR
const int aPrimitiveIndex,
const bool aIsBoardImport )
{
if( aElem.is_polygonoutline || aElem.subpolyindex != ALTIUM_POLYGON_NONE )
if( aElem.polygon != ALTIUM_POLYGON_NONE )
{
wxFAIL_MSG( wxString::Format( "Altium: Unexpected footprint Track with polygon id %d",
aElem.polygon ) );
return;
}
if( aElem.is_keepout || aElem.layer == ALTIUM_LAYER::KEEP_OUT_LAYER
|| IsAltiumLayerAPlane( aElem.layer ) )