Eagle PCB import: disable copper pour for imported *Restrict layer polygons
Fixes: lp:1772245 * https://bugs.launchpad.net/kicad/+bug/1772245
This commit is contained in:
parent
3893c43eb0
commit
190d4d6f55
|
@ -1080,130 +1080,129 @@ ZONE_CONTAINER* EAGLE_PLUGIN::loadPolygon( wxXmlNode* aPolyNode )
|
||||||
EPOLYGON p( aPolyNode );
|
EPOLYGON p( aPolyNode );
|
||||||
PCB_LAYER_ID layer = kicad_layer( p.layer );
|
PCB_LAYER_ID layer = kicad_layer( p.layer );
|
||||||
ZONE_CONTAINER* zone = nullptr;
|
ZONE_CONTAINER* zone = nullptr;
|
||||||
|
bool keepout = ( p.layer == EAGLE_LAYER::TRESTRICT || p.layer == EAGLE_LAYER::BRESTRICT );
|
||||||
|
|
||||||
// Handle copper and keepout layers
|
if( !IsCopperLayer( layer ) && !keepout )
|
||||||
if( IsCopperLayer( layer )
|
return nullptr;
|
||||||
|| p.layer == EAGLE_LAYER::TRESTRICT || p.layer == EAGLE_LAYER::BRESTRICT )
|
|
||||||
|
// use a "netcode = 0" type ZONE:
|
||||||
|
zone = new ZONE_CONTAINER( m_board );
|
||||||
|
zone->SetTimeStamp( EagleTimeStamp( aPolyNode ) );
|
||||||
|
m_board->Add( zone, ADD_APPEND );
|
||||||
|
|
||||||
|
if( p.layer == EAGLE_LAYER::TRESTRICT ) // front layer keepout
|
||||||
|
zone->SetLayer( F_Cu );
|
||||||
|
else if( p.layer == EAGLE_LAYER::BRESTRICT ) // bottom layer keepout
|
||||||
|
zone->SetLayer( B_Cu );
|
||||||
|
else
|
||||||
|
zone->SetLayer( layer );
|
||||||
|
|
||||||
|
if( keepout )
|
||||||
{
|
{
|
||||||
// use a "netcode = 0" type ZONE:
|
zone->SetIsKeepout( true );
|
||||||
zone = new ZONE_CONTAINER( m_board );
|
zone->SetDoNotAllowVias( true );
|
||||||
zone->SetTimeStamp( EagleTimeStamp( aPolyNode ) );
|
zone->SetDoNotAllowTracks( true );
|
||||||
m_board->Add( zone, ADD_APPEND );
|
zone->SetDoNotAllowCopperPour( true );
|
||||||
|
}
|
||||||
|
|
||||||
if( p.layer == EAGLE_LAYER::TRESTRICT )
|
// Get the first vertex and iterate
|
||||||
|
wxXmlNode* vertex = aPolyNode->GetChildren();
|
||||||
|
std::vector<EVERTEX> vertices;
|
||||||
|
|
||||||
|
// Create a circular vector of vertices
|
||||||
|
// The "curve" parameter indicates a curve from the current
|
||||||
|
// to the next vertex, so we keep the first at the end as well
|
||||||
|
// to allow the curve to link back
|
||||||
|
while( vertex )
|
||||||
|
{
|
||||||
|
if( vertex->GetName() == "vertex" )
|
||||||
|
vertices.push_back( EVERTEX( vertex ) );
|
||||||
|
|
||||||
|
vertex = vertex->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices.push_back( vertices[0] );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < vertices.size() - 1; i++ )
|
||||||
|
{
|
||||||
|
EVERTEX v1 = vertices[i];
|
||||||
|
|
||||||
|
// Append the corner
|
||||||
|
zone->AppendCorner( wxPoint( kicad_x( v1.x ), kicad_y( v1.y ) ), -1 );
|
||||||
|
|
||||||
|
if( v1.curve )
|
||||||
{
|
{
|
||||||
zone->SetIsKeepout( true );
|
EVERTEX v2 = vertices[i + 1];
|
||||||
zone->SetLayer( F_Cu );
|
wxPoint center = ConvertArcCenter(
|
||||||
}
|
wxPoint( kicad_x( v1.x ), kicad_y( v1.y ) ),
|
||||||
else if( p.layer == EAGLE_LAYER::BRESTRICT )
|
wxPoint( kicad_x( v2.x ), kicad_y( v2.y ) ), *v1.curve );
|
||||||
{
|
double angle = DEG2RAD( *v1.curve );
|
||||||
zone->SetIsKeepout( true );
|
double end_angle = atan2( kicad_y( v2.y ) - center.y,
|
||||||
zone->SetLayer( B_Cu );
|
kicad_x( v2.x ) - center.x );
|
||||||
}
|
double radius = sqrt( pow( center.x - kicad_x( v1.x ), 2 )
|
||||||
else
|
+ pow( center.y - kicad_y( v1.y ), 2 ) );
|
||||||
{
|
|
||||||
zone->SetLayer( layer );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the first vertex and iterate
|
// If we are curving, we need at least 2 segments otherwise
|
||||||
wxXmlNode* vertex = aPolyNode->GetChildren();
|
// delta_angle == angle
|
||||||
std::vector<EVERTEX> vertices;
|
double delta_angle = angle / std::max(
|
||||||
|
2, GetArcToSegmentCount( KiROUND( radius ),
|
||||||
|
ARC_HIGH_DEF, *v1.curve ) - 1 );
|
||||||
|
|
||||||
// Create a circular vector of vertices
|
for( double a = end_angle + angle;
|
||||||
// The "curve" parameter indicates a curve from the current
|
fabs( a - end_angle ) > fabs( delta_angle );
|
||||||
// to the next vertex, so we keep the first at the end as well
|
a -= delta_angle )
|
||||||
// to allow the curve to link back
|
|
||||||
while( vertex )
|
|
||||||
{
|
|
||||||
if( vertex->GetName() == "vertex" )
|
|
||||||
vertices.push_back( EVERTEX( vertex ) );
|
|
||||||
|
|
||||||
vertex = vertex->GetNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
vertices.push_back( vertices[0] );
|
|
||||||
|
|
||||||
for( size_t i = 0; i < vertices.size() - 1; i++ )
|
|
||||||
{
|
|
||||||
EVERTEX v1 = vertices[i];
|
|
||||||
|
|
||||||
// Append the corner
|
|
||||||
zone->AppendCorner( wxPoint( kicad_x( v1.x ), kicad_y( v1.y ) ), -1 );
|
|
||||||
|
|
||||||
if( v1.curve )
|
|
||||||
{
|
{
|
||||||
EVERTEX v2 = vertices[i + 1];
|
zone->AppendCorner(
|
||||||
wxPoint center = ConvertArcCenter(
|
wxPoint( KiROUND( radius * cos( a ) ),
|
||||||
wxPoint( kicad_x( v1.x ), kicad_y( v1.y ) ),
|
KiROUND( radius * sin( a ) ) ) + center,
|
||||||
wxPoint( kicad_x( v2.x ), kicad_y( v2.y ) ), *v1.curve );
|
-1 );
|
||||||
double angle = DEG2RAD( *v1.curve );
|
|
||||||
double end_angle = atan2( kicad_y( v2.y ) - center.y,
|
|
||||||
kicad_x( v2.x ) - center.x );
|
|
||||||
double radius = sqrt( pow( center.x - kicad_x( v1.x ), 2 )
|
|
||||||
+ pow( center.y - kicad_y( v1.y ), 2 ) );
|
|
||||||
|
|
||||||
// If we are curving, we need at least 2 segments otherwise
|
|
||||||
// delta_angle == angle
|
|
||||||
double delta_angle = angle / std::max(
|
|
||||||
2, GetArcToSegmentCount( KiROUND( radius ),
|
|
||||||
ARC_HIGH_DEF, *v1.curve ) - 1 );
|
|
||||||
|
|
||||||
for( double a = end_angle + angle;
|
|
||||||
fabs( a - end_angle ) > fabs( delta_angle );
|
|
||||||
a -= delta_angle )
|
|
||||||
{
|
|
||||||
zone->AppendCorner(
|
|
||||||
wxPoint( KiROUND( radius * cos( a ) ),
|
|
||||||
KiROUND( radius * sin( a ) ) ) + center,
|
|
||||||
-1 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the pour is a cutout it needs to be set to a keepout
|
|
||||||
if( p.pour == EPOLYGON::CUTOUT )
|
|
||||||
{
|
|
||||||
zone->SetIsKeepout( true );
|
|
||||||
zone->SetDoNotAllowCopperPour( true );
|
|
||||||
zone->SetHatchStyle( ZONE_CONTAINER::NO_HATCH );
|
|
||||||
}
|
|
||||||
|
|
||||||
// if spacing is set the zone should be hatched
|
|
||||||
// However, use the default hatch step, p.spacing value has no meaning for Kicad
|
|
||||||
// TODO: see if this parameter is related to a grid fill option.
|
|
||||||
if( p.spacing )
|
|
||||||
zone->SetHatch( ZONE_CONTAINER::DIAGONAL_EDGE, zone->GetDefaultHatchPitch(), true );
|
|
||||||
|
|
||||||
// clearances, etc.
|
|
||||||
zone->SetArcSegmentCount( 32 ); // @todo: should be a constructor default?
|
|
||||||
zone->SetMinThickness( p.width.ToPcbUnits() );
|
|
||||||
|
|
||||||
// FIXME: KiCad zones have very rounded corners compared to eagle.
|
|
||||||
// This means that isolation amounts that work well in eagle
|
|
||||||
// tend to make copper intrude in soldermask free areas around pads.
|
|
||||||
if( p.isolate )
|
|
||||||
zone->SetZoneClearance( p.isolate->ToPcbUnits() );
|
|
||||||
else
|
|
||||||
zone->SetZoneClearance( 0 );
|
|
||||||
|
|
||||||
// missing == yes per DTD.
|
|
||||||
bool thermals = !p.thermals || *p.thermals;
|
|
||||||
zone->SetPadConnection( thermals ? PAD_ZONE_CONN_THERMAL : PAD_ZONE_CONN_FULL );
|
|
||||||
|
|
||||||
if( thermals )
|
|
||||||
{
|
|
||||||
// FIXME: eagle calculates dimensions for thermal spokes
|
|
||||||
// based on what the zone is connecting to.
|
|
||||||
// (i.e. width of spoke is half of the smaller side of an smd pad)
|
|
||||||
// This is a basic workaround
|
|
||||||
zone->SetThermalReliefGap( p.width.ToPcbUnits() + 50000 ); // 50000nm == 0.05mm
|
|
||||||
zone->SetThermalReliefCopperBridge( p.width.ToPcbUnits() + 50000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int rank = p.rank ? (p.max_priority - *p.rank) : p.max_priority;
|
|
||||||
zone->SetPriority( rank );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the pour is a cutout it needs to be set to a keepout
|
||||||
|
if( p.pour == EPOLYGON::CUTOUT )
|
||||||
|
{
|
||||||
|
zone->SetIsKeepout( true );
|
||||||
|
zone->SetDoNotAllowCopperPour( true );
|
||||||
|
zone->SetHatchStyle( ZONE_CONTAINER::NO_HATCH );
|
||||||
|
}
|
||||||
|
|
||||||
|
// if spacing is set the zone should be hatched
|
||||||
|
// However, use the default hatch step, p.spacing value has no meaning for Kicad
|
||||||
|
// TODO: see if this parameter is related to a grid fill option.
|
||||||
|
if( p.spacing )
|
||||||
|
zone->SetHatch( ZONE_CONTAINER::DIAGONAL_EDGE, zone->GetDefaultHatchPitch(), true );
|
||||||
|
|
||||||
|
// clearances, etc.
|
||||||
|
zone->SetArcSegmentCount( 32 ); // @todo: should be a constructor default?
|
||||||
|
zone->SetMinThickness( p.width.ToPcbUnits() );
|
||||||
|
|
||||||
|
// FIXME: KiCad zones have very rounded corners compared to eagle.
|
||||||
|
// This means that isolation amounts that work well in eagle
|
||||||
|
// tend to make copper intrude in soldermask free areas around pads.
|
||||||
|
if( p.isolate )
|
||||||
|
zone->SetZoneClearance( p.isolate->ToPcbUnits() );
|
||||||
|
else
|
||||||
|
zone->SetZoneClearance( 0 );
|
||||||
|
|
||||||
|
// missing == yes per DTD.
|
||||||
|
bool thermals = !p.thermals || *p.thermals;
|
||||||
|
zone->SetPadConnection( thermals ? PAD_ZONE_CONN_THERMAL : PAD_ZONE_CONN_FULL );
|
||||||
|
|
||||||
|
if( thermals )
|
||||||
|
{
|
||||||
|
// FIXME: eagle calculates dimensions for thermal spokes
|
||||||
|
// based on what the zone is connecting to.
|
||||||
|
// (i.e. width of spoke is half of the smaller side of an smd pad)
|
||||||
|
// This is a basic workaround
|
||||||
|
zone->SetThermalReliefGap( p.width.ToPcbUnits() + 50000 ); // 50000nm == 0.05mm
|
||||||
|
zone->SetThermalReliefCopperBridge( p.width.ToPcbUnits() + 50000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int rank = p.rank ? (p.max_priority - *p.rank) : p.max_priority;
|
||||||
|
zone->SetPriority( rank );
|
||||||
|
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue