mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-18 20:09:18 +00:00
Import POURED items as zone fills from EasyEDA/LCEDA Pro v2.2+ PCBs.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/18664
(cherry picked from commit 6b199c52a1
)
This commit is contained in:
parent
5e0abadb23
commit
e0291133f2
common/io/easyedapro
pcbnew/pcb_io/easyedapro
@ -41,7 +41,8 @@
|
||||
namespace EASYEDAPRO
|
||||
{
|
||||
|
||||
static const bool IMPORT_POURED = false;
|
||||
static const bool IMPORT_POURED = true;
|
||||
static const bool IMPORT_POURED_ECOP = false;
|
||||
|
||||
enum class SYMBOL_TYPE
|
||||
{
|
||||
|
@ -356,7 +356,7 @@ void PCB_IO_EASYEDAPRO::LoadAllDataFromProject( const wxString& aProjectPa
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( name.EndsWith( wxS( ".ecop" ) ) && EASYEDAPRO::IMPORT_POURED )
|
||||
else if( name.EndsWith( wxS( ".ecop" ) ) && EASYEDAPRO::IMPORT_POURED_ECOP )
|
||||
{
|
||||
for( const nlohmann::json& line : lines )
|
||||
{
|
||||
|
@ -958,6 +958,9 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
||||
std::map<wxString, std::vector<nlohmann::json>> componentLines;
|
||||
std::map<wxString, std::vector<nlohmann::json>> ruleLines;
|
||||
|
||||
std::multimap<wxString, EASYEDAPRO::POURED> boardPouredMap = aPouredMap;
|
||||
std::map<wxString, ZONE*> poursToFill;
|
||||
|
||||
BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings();
|
||||
|
||||
for( const nlohmann::json& line : aLines )
|
||||
@ -1027,6 +1030,14 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
||||
|
||||
ruleLines[ruleType].push_back( line );
|
||||
}
|
||||
else if( type == wxS( "POURED" ) )
|
||||
{
|
||||
if( !line.at( 2 ).is_string() )
|
||||
continue; // Unknown type of POURED
|
||||
|
||||
EASYEDAPRO::POURED poured = line;
|
||||
boardPouredMap.emplace( poured.parentId, poured );
|
||||
}
|
||||
else if( type == wxS( "VIA" ) || type == wxS( "LINE" ) || type == wxS( "ARC" )
|
||||
|| type == wxS( "POLY" ) || type == wxS( "FILL" ) || type == wxS( "POUR" ) )
|
||||
{
|
||||
@ -1211,88 +1222,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
||||
|
||||
wxASSERT( zone->Outline()->OutlineCount() == 1 );
|
||||
|
||||
SHAPE_POLY_SET fillPolySet;
|
||||
SHAPE_POLY_SET thermalSpokes;
|
||||
int entryId = 0;
|
||||
|
||||
if( EASYEDAPRO::IMPORT_POURED )
|
||||
{
|
||||
auto range = aPouredMap.equal_range( uuid );
|
||||
for( auto& it = range.first; it != range.second; ++it )
|
||||
{
|
||||
const EASYEDAPRO::POURED& poured = it->second;
|
||||
int unki = poured.unki;
|
||||
|
||||
SHAPE_POLY_SET thisPoly;
|
||||
|
||||
for( int dataId = 0; dataId < poured.polyData.size(); dataId++ )
|
||||
{
|
||||
const nlohmann::json& fillData = poured.polyData[dataId];
|
||||
const double ptScale = 10;
|
||||
|
||||
SHAPE_LINE_CHAIN contour =
|
||||
ParseContour( fillData, false, ARC_HIGH_DEF / ptScale );
|
||||
|
||||
// Scale the fill
|
||||
for( int i = 0; i < contour.PointCount(); i++ )
|
||||
contour.SetPoint( i, contour.GetPoint( i ) * ptScale );
|
||||
|
||||
if( poured.isPoly )
|
||||
{
|
||||
contour.SetClosed( true );
|
||||
|
||||
// The contour can be self-intersecting
|
||||
SHAPE_POLY_SET simple( contour );
|
||||
simple.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
if( dataId == 0 )
|
||||
{
|
||||
thisPoly.Append( simple );
|
||||
}
|
||||
else
|
||||
{
|
||||
thisPoly.BooleanSubtract( simple,
|
||||
SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const int thermalWidth = pcbIUScale.mmToIU( 0.2 ); // Generic
|
||||
|
||||
for( int segId = 0; segId < contour.SegmentCount(); segId++ )
|
||||
{
|
||||
const SEG& seg = contour.CSegment( segId );
|
||||
|
||||
TransformOvalToPolygon( thermalSpokes, seg.A, seg.B,
|
||||
thermalWidth, ARC_LOW_DEF,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fillPolySet.Append( thisPoly );
|
||||
|
||||
entryId++;
|
||||
}
|
||||
|
||||
if( !fillPolySet.IsEmpty() )
|
||||
{
|
||||
fillPolySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
const int strokeWidth = pcbIUScale.MilsToIU( 8 ); // Seems to be 8 mils
|
||||
|
||||
fillPolySet.Inflate( strokeWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||
ARC_HIGH_DEF, false );
|
||||
|
||||
fillPolySet.BooleanAdd( thermalSpokes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
fillPolySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
zone->SetFilledPolysList( klayer, fillPolySet );
|
||||
zone->SetNeedRefill( false );
|
||||
zone->SetIsFilled( true );
|
||||
}
|
||||
}
|
||||
poursToFill.emplace( uuid, zone.get() );
|
||||
|
||||
aBoard->Add( zone.release(), ADD_MODE::APPEND );
|
||||
}
|
||||
@ -1801,6 +1731,88 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
||||
aBoard->Add( footprint.release(), ADD_MODE::APPEND );
|
||||
}
|
||||
|
||||
// Set zone fills
|
||||
if( EASYEDAPRO::IMPORT_POURED )
|
||||
{
|
||||
for( auto& [uuid, zone] : poursToFill )
|
||||
{
|
||||
SHAPE_POLY_SET fillPolySet;
|
||||
SHAPE_POLY_SET thermalSpokes;
|
||||
|
||||
auto range = boardPouredMap.equal_range( uuid );
|
||||
for( auto& it = range.first; it != range.second; ++it )
|
||||
{
|
||||
const EASYEDAPRO::POURED& poured = it->second;
|
||||
int unki = poured.unki;
|
||||
|
||||
SHAPE_POLY_SET thisPoly;
|
||||
|
||||
for( int dataId = 0; dataId < poured.polyData.size(); dataId++ )
|
||||
{
|
||||
const nlohmann::json& fillData = poured.polyData[dataId];
|
||||
const double ptScale = 10;
|
||||
|
||||
SHAPE_LINE_CHAIN contour =
|
||||
ParseContour( fillData, false, ARC_HIGH_DEF / ptScale );
|
||||
|
||||
// Scale the fill
|
||||
for( int i = 0; i < contour.PointCount(); i++ )
|
||||
contour.SetPoint( i, contour.GetPoint( i ) * ptScale );
|
||||
|
||||
if( poured.isPoly )
|
||||
{
|
||||
contour.SetClosed( true );
|
||||
|
||||
// The contour can be self-intersecting
|
||||
SHAPE_POLY_SET simple( contour );
|
||||
simple.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
if( dataId == 0 )
|
||||
{
|
||||
thisPoly.Append( simple );
|
||||
}
|
||||
else
|
||||
{
|
||||
thisPoly.BooleanSubtract( simple, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const int thermalWidth = pcbIUScale.mmToIU( 0.2 ); // Generic
|
||||
|
||||
for( int segId = 0; segId < contour.SegmentCount(); segId++ )
|
||||
{
|
||||
const SEG& seg = contour.CSegment( segId );
|
||||
|
||||
TransformOvalToPolygon( thermalSpokes, seg.A, seg.B, thermalWidth,
|
||||
ARC_LOW_DEF, ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fillPolySet.Append( thisPoly );
|
||||
}
|
||||
|
||||
if( !fillPolySet.IsEmpty() )
|
||||
{
|
||||
fillPolySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
const int strokeWidth = pcbIUScale.MilsToIU( 8 ); // Seems to be 8 mils
|
||||
|
||||
fillPolySet.Inflate( strokeWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS,
|
||||
ARC_HIGH_DEF, false );
|
||||
|
||||
fillPolySet.BooleanAdd( thermalSpokes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
fillPolySet.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
zone->SetFilledPolysList( zone->GetFirstLayer(), fillPolySet );
|
||||
zone->SetNeedRefill( false );
|
||||
zone->SetIsFilled( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Heal board outlines
|
||||
std::vector<PCB_SHAPE*> shapes;
|
||||
std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
|
||||
|
Loading…
Reference in New Issue
Block a user