Fix a few issues with zone islands

This commit is contained in:
Jon Evans 2020-06-29 12:16:37 -04:00
parent 9cbcf3fe56
commit 44f3cdb31e
7 changed files with 64 additions and 27 deletions

View File

@ -230,9 +230,25 @@ void StripTrailingZeros( wxString& aStringValue, unsigned aTrailingZeroAllowed )
* otherwise the actual value is rounded when read from dialog and converted * otherwise the actual value is rounded when read from dialog and converted
* in internal units, and therefore modified. * in internal units, and therefore modified.
*/ */
wxString StringFromValue( EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils ) wxString StringFromValue( EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils,
EDA_DATA_TYPE aType )
{ {
double value_to_print = To_User_Unit( aUnits, aValue, aUseMils ); double value_to_print = aValue;
switch( aType )
{
case EDA_DATA_TYPE::VOLUME:
value_to_print = To_User_Unit( aUnits, value_to_print, aUseMils );
KI_FALLTHROUGH;
case EDA_DATA_TYPE::AREA:
value_to_print = To_User_Unit( aUnits, value_to_print, aUseMils );
KI_FALLTHROUGH;
case EDA_DATA_TYPE::DISTANCE:
value_to_print = To_User_Unit( aUnits, value_to_print, aUseMils );
}
#if defined( EESCHEMA ) #if defined( EESCHEMA )
wxString stringValue = wxString::Format( wxT( "%.3f" ), value_to_print ); wxString stringValue = wxString::Format( wxT( "%.3f" ), value_to_print );
@ -327,9 +343,9 @@ double From_User_Unit( EDA_UNITS aUnits, double aValue, bool aUseMils )
} }
double DoubleValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, bool aUseMils ) double DoubleValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, bool aUseMils,
EDA_DATA_TYPE aType )
{ {
double value;
double dtmp = 0; double dtmp = 0;
// Acquire the 'right' decimal point separator // Acquire the 'right' decimal point separator
@ -395,9 +411,21 @@ double DoubleValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, bool
} }
} }
value = From_User_Unit( aUnits, dtmp, aUseMils ); switch( aType )
{
case EDA_DATA_TYPE::VOLUME:
dtmp = From_User_Unit( aUnits, dtmp, aUseMils );
KI_FALLTHROUGH;
return value; case EDA_DATA_TYPE::AREA:
dtmp = From_User_Unit( aUnits, dtmp, aUseMils );
KI_FALLTHROUGH;
case EDA_DATA_TYPE::DISTANCE:
dtmp = From_User_Unit( aUnits, dtmp, aUseMils );
}
return dtmp;
} }
@ -440,9 +468,10 @@ void FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS& aUnits, bool&
} }
long long int ValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, bool aUseMils ) long long int ValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, bool aUseMils,
EDA_DATA_TYPE aType )
{ {
double value = DoubleValueFromString( aUnits, aTextValue, aUseMils ); double value = DoubleValueFromString( aUnits, aTextValue, aUseMils, aType );
return KiROUND<double, long long int>( value ); return KiROUND<double, long long int>( value );
} }

View File

@ -187,6 +187,8 @@ bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits, bool aUs
return true; return true;
} }
// TODO: Validate() does not currently support m_dataType being anything other than DISTANCE
if( GetValue() < From_User_Unit( aUnits, aMin, aUseMils ) ) if( GetValue() < From_User_Unit( aUnits, aMin, aUseMils ) )
{ {
m_errorMessage = wxString::Format( _( "%s must be at least %s." ), m_errorMessage = wxString::Format( _( "%s must be at least %s." ),
@ -219,13 +221,13 @@ bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits, bool aUs
void UNIT_BINDER::SetValue( int aValue ) void UNIT_BINDER::SetValue( int aValue )
{ {
SetValue( StringFromValue( m_units, aValue, false, m_useMils ) ); SetValue( StringFromValue( m_units, aValue, false, m_useMils, m_dataType ) );
} }
void UNIT_BINDER::SetDoubleValue( double aValue ) void UNIT_BINDER::SetDoubleValue( double aValue )
{ {
SetValue( StringFromValue( m_units, aValue, false, m_useMils ) ); SetValue( StringFromValue( m_units, aValue, false, m_useMils, m_dataType ) );
} }
@ -287,7 +289,7 @@ long long int UNIT_BINDER::GetValue()
else else
return 0; return 0;
return ValueFromString( m_units, value, m_useMils ); return ValueFromString( m_units, value, m_useMils, m_dataType );
} }
@ -309,7 +311,7 @@ double UNIT_BINDER::GetDoubleValue()
else else
return 0.0; return 0.0;
return DoubleValueFromString( m_units, value, m_useMils ); return DoubleValueFromString( m_units, value, m_useMils, m_dataType );
} }

View File

@ -150,7 +150,7 @@ wxString MessageTextFromValue( EDA_UNITS aUnits, long long int aValue, bool aUse
* @return A wxString object containing value and optionally the symbol unit (like 2.000 mm) * @return A wxString object containing value and optionally the symbol unit (like 2.000 mm)
*/ */
wxString StringFromValue( EDA_UNITS aUnit, double aValue, bool aAddUnitSymbol = false, wxString StringFromValue( EDA_UNITS aUnit, double aValue, bool aAddUnitSymbol = false,
bool aUseMils = false ); bool aUseMils = false, EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
/** /**
* Return in internal units the value "val" given in a real unit * Return in internal units the value "val" given in a real unit
@ -167,8 +167,8 @@ double From_User_Unit( EDA_UNITS aUnit, double aValue, bool aUseMils = false );
* @param aUseMils Indicates mils should be used for imperial units (inches). * @param aUseMils Indicates mils should be used for imperial units (inches).
* @return A double representing that value in internal units * @return A double representing that value in internal units
*/ */
double DoubleValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, double DoubleValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, bool aUseMils = false,
bool aUseMils = false ); EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
/** /**
* Function ValueFromString * Function ValueFromString
@ -179,8 +179,8 @@ double DoubleValueFromString( EDA_UNITS aUnits, const wxString& aTextValue,
* @param aUseMils Indicates mils should be used for imperial units (inches). * @param aUseMils Indicates mils should be used for imperial units (inches).
* @return The string from Value, according to units (inch, mm ...) for display, * @return The string from Value, according to units (inch, mm ...) for display,
*/ */
long long int ValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, long long int ValueFromString( EDA_UNITS aUnits, const wxString& aTextValue, bool aUseMils = false,
bool aUseMils = false ); EDA_DATA_TYPE aType = EDA_DATA_TYPE::DISTANCE );
/** /**
* Function FetchUnitsFromString * Function FetchUnitsFromString

View File

@ -1905,7 +1905,7 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
{ {
m_out->Print( 0, " (island_removal_mode %d) (island_area_min %s)", m_out->Print( 0, " (island_removal_mode %d) (island_area_min %s)",
static_cast<int>( aZone->GetIslandRemovalMode() ), static_cast<int>( aZone->GetIslandRemovalMode() ),
FormatInternalUnits( aZone->GetMinIslandArea() ).c_str() ); FormatInternalUnits( aZone->GetMinIslandArea() / IU_PER_MM ).c_str() );
} }
if( aZone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN ) if( aZone->GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN )

View File

@ -3981,9 +3981,12 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER( BOARD_ITEM_CONTAINER* aParent )
break; break;
case T_island_area_min: case T_island_area_min:
zone->SetMinIslandArea( parseBoardUnits( T_island_area_min ) ); {
int area = parseBoardUnits( T_island_area_min );
zone->SetMinIslandArea( area * IU_PER_MM );
NeedRIGHT(); NeedRIGHT();
break; break;
}
default: default:
Expecting( "mode, arc_segments, thermal_gap, thermal_bridge_width, " Expecting( "mode, arc_segments, thermal_gap, thermal_bridge_width, "

View File

@ -500,7 +500,7 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
// aggregateArea will be simplified and fractured // aggregateArea will be simplified and fractured
// (Long calculation time) // (Long calculation time)
for( int i = 0; i < aggregateArea.OutlineCount(); i++ ) for( int i = aggregateArea.OutlineCount() - 1; i >= 0; i-- )
{ {
if( zone->IsIsland( layer, i ) ) if( zone->IsIsland( layer, i ) )
{ {
@ -539,7 +539,7 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
SHAPE_POLY_SET candidateArea = candidate->GetFilledPolysList( layer ); SHAPE_POLY_SET candidateArea = candidate->GetFilledPolysList( layer );
for( int i = 0; i < candidateArea.OutlineCount(); i++ ) for( int i = candidateArea.OutlineCount() - 1; i >= 0; i-- )
{ {
if( candidate->IsIsland( layer, i ) ) if( candidate->IsIsland( layer, i ) )
{ {

View File

@ -230,17 +230,20 @@ bool ZONE_FILLER::Fill( const std::vector<ZONE_CONTAINER*>& aZones, bool aCheck
// Remove solid areas outside the board cutouts and the insulated islands // Remove solid areas outside the board cutouts and the insulated islands
// only zones with net code > 0 can have insulated islands by definition // only zones with net code > 0 can have insulated islands by definition
if( zone.m_zone->GetNetCode() > 0 && mode != ISLAND_REMOVAL_MODE::NEVER ) if( zone.m_zone->GetNetCode() > 0 )
{ {
// Area threshold is stored 1-D in internal units
if( mode == ISLAND_REMOVAL_MODE::AREA )
minArea *= minArea;
// solid areas outside the board cutouts are also removed, because they are usually // solid areas outside the board cutouts are also removed, because they are usually
// insulated islands // insulated islands
for( auto idx : zone.m_islands ) for( auto idx : zone.m_islands )
{ {
if( mode == ISLAND_REMOVAL_MODE::ALWAYS || poly.Outline( idx ).Area() < minArea double metricMin = minArea * ( MM_PER_IU * MM_PER_IU );
double metricArea = poly.Outline( idx ).Area() * ( MM_PER_IU * MM_PER_IU );
std::cout << ( metricArea < metricMin ) << std::endl;
if( mode == ISLAND_REMOVAL_MODE::ALWAYS
|| ( mode == ISLAND_REMOVAL_MODE::AREA
&& poly.Outline( idx ).Area() < minArea )
|| !m_boardOutline.Contains( poly.Polygon( idx ).front().CPoint( 0 ) ) ) || !m_boardOutline.Contains( poly.Polygon( idx ).front().CPoint( 0 ) ) )
poly.DeletePolygon( idx ); poly.DeletePolygon( idx );
else else