36#include <wx/mstream.h>
87 nlohmann::json holeObj = aRow.
inner.value(
"hole", nlohmann::json() );
88 nlohmann::json padDef = aRow.
inner.value(
"defaultPad", nlohmann::json() );
90 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
92 pad->SetNumber( padNumber );
94 pad->SetOrientationDegrees( orientation );
100 if( holeObj.is_object() )
102 wxString holeType =
V3GetString( holeObj,
"holeType", wxS(
"ROUND" ) );
104 if( holeType == wxS(
"RECT" ) )
105 holeType = wxS(
"SLOT" );
107 if( holeType != wxS(
"ROUND" ) && holeType != wxS(
"SLOT" ) )
108 holeType = wxS(
"ROUND" );
114 if( drill.
x > 0 || drill.
y > 0 )
123 std::swap( drill.
x, drill.
y );
125 if( holeType == wxS(
"SLOT" ) )
138 else if( klayer ==
B_Cu )
145 if( padDef.is_object() )
147 wxString padType =
V3GetString( padDef,
"padType", wxS(
"RECT" ) );
149 if( padType == wxS(
"RECT" ) )
155 double radiusRatio = std::clamp(
radius, 0.0, 100.0 ) / 100 / 2;
159 if( radiusRatio == 0 )
167 else if( padType == wxS(
"ELLIPSE" ) )
177 else if( padType == wxS(
"OVAL" ) )
186 else if( padType == wxS(
"POLY" ) || padType == wxS(
"POLYGON" ) )
192 nlohmann::json polyData = padDef.value(
"path", nlohmann::json() );
194 std::vector<std::unique_ptr<PCB_SHAPE>> results =
195 m_v2Parser.ParsePoly( aFootprint, polyData,
true,
false );
197 for(
auto& shape : results )
199 shape->SetLayer( klayer );
200 shape->SetWidth( 0 );
201 shape->Move( -
pad->GetPosition() );
234 wxString originStr =
V3GetString( aRow.
inner,
"origin", wxS(
"LEFT_BOTTOM" ) );
242 text->SetText(
string );
243 text->SetLayer( klayer );
245 text->SetIsKnockout( inverted );
250 if( font != wxS(
"default" ) )
257 text->SetMirrored(
true );
258 text->SetTextAngleDegrees( -angle );
262 text->SetTextAngleDegrees( angle );
269std::unique_ptr<FOOTPRINT>
273 std::unique_ptr<FOOTPRINT> footprintPtr = std::make_unique<FOOTPRINT>(
m_board );
274 FOOTPRINT* footprint = footprintPtr.get();
277 const int defaultTextThickness(
pcbIUScale.mmToIU( 0.15 ) );
281 field->SetTextSize( defaultTextSize );
282 field->SetTextThickness( defaultTextThickness );
287 if( row.
type == wxS(
"POLY" ) )
293 nlohmann::json polyData = row.
inner.value(
"path", nlohmann::json::array() );
295 std::vector<std::unique_ptr<PCB_SHAPE>> results =
296 m_v2Parser.ParsePoly( footprint, polyData,
false,
false );
298 for(
auto& shape : results )
300 shape->SetLayer( klayer );
305 else if( row.
type == wxS(
"PAD" ) )
310 else if( row.
type == wxS(
"FILL" ) )
315 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
317 if( !polyDataList.is_null() && !polyDataList.empty() )
319 if( !polyDataList.at( 0 ).is_array() )
320 polyDataList = nlohmann::json::array( { polyDataList } );
322 std::vector<SHAPE_LINE_CHAIN> contours;
324 for( nlohmann::json& polyData : polyDataList )
328 contours.push_back( contour );
338 std::unique_ptr<PCB_GROUP>
group;
341 group = std::make_unique<PCB_GROUP>( footprint );
345 std::unique_ptr<PCB_SHAPE> shape =
348 shape->SetFilled(
true );
349 shape->SetPolyShape( poly );
350 shape->SetLayer( klayer );
351 shape->SetWidth( 0 );
354 group->AddItem( shape.get() );
363 else if( row.
type == wxS(
"ATTR" ) )
368 if( key == wxS(
"Designator" ) )
371 else if( row.
type == wxS(
"REGION" ) )
376 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
377 nlohmann::json prohibitTypes = row.
inner.value(
"prohibitType", nlohmann::json::array() );
381 if( prohibitTypes.is_array() )
383 for(
const auto& pt : prohibitTypes )
388 ptStr = pt.get<std::string>();
390 if( ptStr == wxS(
"COMPONENT" ) )
392 else if( ptStr == wxS(
"TRACK" ) )
394 else if( ptStr == wxS(
"COPPER" ) )
396 else if( ptStr == wxS(
"VIA" ) )
398 else if( ptStr == wxS(
"FILL" ) || ptStr == wxS(
"PLANE" ) )
403 for( nlohmann::json& polyData : polyDataList )
407 std::vector<std::unique_ptr<PCB_SHAPE>> results =
408 m_v2Parser.ParsePoly(
nullptr, polyData,
true,
false );
410 for(
auto& shape : results )
412 shape->SetFilled(
true );
413 shape->TransformShapeToPolygon( polySet, klayer, 0,
ARC_HIGH_DEF,
419 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( footprint );
421 zone->SetIsRuleArea(
true );
422 zone->SetDoNotAllowFootprints( !!flags.count( 2 ) );
423 zone->SetDoNotAllowZoneFills( !!flags.count( 7 ) || !!flags.count( 6 )
424 || !!flags.count( 8 ) );
425 zone->SetDoNotAllowPads( !!flags.count( 7 ) );
426 zone->SetDoNotAllowTracks( !!flags.count( 7 ) || !!flags.count( 5 ) );
427 zone->SetDoNotAllowVias( !!flags.count( 7 ) );
429 zone->SetLayer( klayer );
430 zone->Outline()->Append( polySet );
435 else if( row.
type == wxS(
"IMAGE" ) )
450 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
453 std::vector<SHAPE_LINE_CHAIN> contours;
454 for( nlohmann::json& polyData : polyDataList )
459 contours.push_back( contour );
474 for(
int i = 0; i < contour.PointCount(); i++ )
485 std::unique_ptr<PCB_GROUP>
group;
488 group = std::make_unique<PCB_GROUP>( footprint );
494 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( footprint,
SHAPE_T::POLY );
496 shape->SetFilled(
true );
497 shape->SetPolyShape( poly );
498 shape->SetLayer( klayer );
499 shape->SetWidth( 0 );
511 group->AddItem( shape.get() );
519 else if( row.
type == wxS(
"OBJ" ) )
536 if( imageUrl.empty() )
539 wxString mimeType, base64Data;
541 if( imageUrl.BeforeFirst(
':' ) == wxS(
"blob" ) )
543 wxString objectId = imageUrl.AfterLast(
':' );
545 if(
auto blob =
get_opt( aBlobMap, objectId ) )
547 wxString blobUrl = blob->url;
549 if( blobUrl.BeforeFirst(
':' ) == wxS(
"data" ) )
551 wxArrayString paramsArr =
552 wxSplit( blobUrl.AfterFirst(
':' ).BeforeFirst(
',' ),
';',
'\0' );
554 base64Data = blobUrl.AfterFirst(
',' );
556 if( paramsArr.size() > 0 )
557 mimeType = paramsArr[0];
565 if( mimeType.empty() || base64Data.empty() )
568 wxMemoryBuffer buf = wxBase64Decode( base64Data );
570 if( mimeType == wxS(
"image/svg+xml" ) )
576 VECTOR2D kcenter = kstart + ksize / 2;
578 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap =
579 std::make_unique<PCB_REFERENCE_IMAGE>( footprint, kcenter, klayer );
582 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
583 & ~wxImage::Load_Verbose );
595 int x = bitmap->GetPosition().x;
606 else if( row.
type == wxS(
"STRING" ) )
617 std::vector<PCB_SHAPE*> edgeShapes;
622 edgeShapes.push_back(
static_cast<PCB_SHAPE*
>( item ) );
633 std::unique_ptr<PCB_SHAPE> shape =
639 shape->SetEnd( bbox.
GetEnd() );
645 bool hasFabRef =
false;
651 if(
static_cast<PCB_TEXT*
>( item )->GetText() == wxT(
"${REFERENCE}" ) )
662 int c_refTextThickness =
pcbIUScale.mmToIU( 0.1 );
663 std::unique_ptr<PCB_TEXT> refText = std::make_unique<PCB_TEXT>( footprint );
665 refText->SetLayer(
F_Fab );
666 refText->SetTextSize(
VECTOR2I( c_refTextSize, c_refTextSize ) );
667 refText->SetTextThickness( c_refTextThickness );
668 refText->SetText( wxT(
"${REFERENCE}" ) );
723 if( aAlign == wxS(
"LEFT_TOP" ) )
725 if( aAlign == wxS(
"LEFT_CENTER" ) || aAlign == wxS(
"LEFT_MIDDLE" ) )
727 if( aAlign == wxS(
"LEFT_BOTTOM" ) )
729 if( aAlign == wxS(
"CENTER_TOP" ) )
731 if( aAlign == wxS(
"CENTER_MIDDLE" ) || aAlign == wxS(
"CENTER_CENTER" ) )
733 if( aAlign == wxS(
"CENTER_BOTTOM" ) )
735 if( aAlign == wxS(
"RIGHT_TOP" ) )
737 if( aAlign == wxS(
"RIGHT_CENTER" ) || aAlign == wxS(
"RIGHT_MIDDLE" ) )
739 if( aAlign == wxS(
"RIGHT_BOTTOM" ) )
747 BOARD* aBoard,
const nlohmann::json& aProject,
748 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap,
749 const std::map<wxString, EASYEDAPRO::BLOB>& aBlobMap,
750 const std::multimap<wxString, EASYEDAPRO::POURED>& aPouredMap,
751 const V3_DOC_RAW& aDoc,
const wxString& aFpLibName )
759 std::map<wxString, wxString> attrs;
771 bool keyVisible =
false;
772 bool valVisible =
false;
774 double fontSize = 45.0;
775 double strokeWidth = 6.0;
789 std::map<wxString, COMP_DATA> componentMap;
790 std::multimap<wxString, ATTR_DATA> attrMap;
791 std::multimap<wxString, PAD_NET_DATA> padNetMap;
793 std::multimap<wxString, EASYEDAPRO::POURED> boardPouredMap = aPouredMap;
794 std::map<wxString, ZONE*> poursToFill;
800 if( row.
type == wxS(
"LAYER" ) )
811 blayers.
set( klayer );
814 if( !layerName.IsEmpty() )
818 else if( row.
type == wxS(
"NET" ) )
823 if( idArr.is_array() && idArr.size() > 1 )
826 if( !netname.IsEmpty() )
833 else if( row.
type == wxS(
"RULE" ) )
837 if( !idArr.is_array() || idArr.size() < 3 )
843 nlohmann::json context = row.
inner.value(
"ruleContext", nlohmann::json() );
845 if( ruleType == wxS(
"TRACK" ) && isDefault )
847 nlohmann::json track = context.value(
"track", nlohmann::json() );
848 nlohmann::json content = track.value(
"content", nlohmann::json::array() );
850 if( content.is_array() && !content.empty() )
852 double minVal =
V3GetDouble( content[0],
"stroMin" );
856 else if( ruleType == wxS(
"SAFE" ) && isDefault )
858 nlohmann::json safeSpacing = context.value(
"safeSpacing",
859 nlohmann::json::array() );
861 if( safeSpacing.is_array() && !safeSpacing.empty() )
863 nlohmann::json content = safeSpacing[0].value(
"content",
864 nlohmann::json::array() );
866 int minVal = INT_MAX;
868 for(
const auto& arr : content )
872 for(
const auto& val : arr )
874 int v = val.is_number() ? val.get<
int>() : 0;
881 if( minVal != INT_MAX )
886 else if( row.
type == wxS(
"VIA" ) )
896 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( aBoard );
906 else if( row.
type == wxS(
"LINE" ) )
922 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>( aBoard );
924 track->SetLayer( klayer );
928 track->SetNet( aBoard->
FindNet( netname ) );
932 else if( row.
type == wxS(
"ARC" ) )
952 double ha = angle / 2;
953 double hd =
delta.EuclideanNorm() / 2;
954 double cdist = hd / tan(
DEG2RAD( ha ) );
963 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( aBoard, &sarc );
965 arc->SetLayer( klayer );
966 arc->SetNet( aBoard->
FindNet( netname ) );
970 else if( row.
type == wxS(
"POLY" ) )
976 nlohmann::json polyData = row.
inner.value(
"path", nlohmann::json::array() );
978 std::vector<std::unique_ptr<PCB_SHAPE>> results =
979 m_v2Parser.ParsePoly( aBoard, polyData,
false,
false );
981 for(
auto& shape : results )
983 shape->SetLayer( klayer );
989 else if( row.
type == wxS(
"FILL" ) )
996 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
998 if( polyDataList.is_null() || polyDataList.empty() )
1001 if( !polyDataList.at( 0 ).is_array() )
1002 polyDataList = nlohmann::json::array( { polyDataList } );
1004 std::vector<SHAPE_LINE_CHAIN> contours;
1006 for( nlohmann::json& polyData : polyDataList )
1010 contours.push_back( contour );
1021 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
1023 zone->SetNet( aBoard->
FindNet( netname ) );
1024 zone->SetLayer( klayer );
1026 zone->SetFilledPolysList( klayer, zoneFillPoly );
1027 zone->SetAssignedPriority( 500 );
1028 zone->SetIsFilled(
true );
1029 zone->SetNeedRefill(
false );
1036 else if( row.
type == wxS(
"POUR" ) )
1044 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
1046 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
1048 zone->SetNet( aBoard->
FindNet( netname ) );
1049 zone->SetLayer( klayer );
1050 zone->SetAssignedPriority( 500 - fillOrder );
1054 for( nlohmann::json& polyData : polyDataList )
1058 zone->Outline()->Append( contour );
1061 wxASSERT( zone->Outline()->OutlineCount() == 1 );
1063 poursToFill.emplace( row.
id, zone.get() );
1067 else if( row.
type == wxS(
"POURED" ) )
1072 if( idArr.is_array() && idArr.size() > 1 )
1075 nlohmann::json fills = row.
inner.value(
"pourFill", nlohmann::json::array() );
1077 if( !fills.is_array() )
1080 for(
const nlohmann::json& fill : fills )
1084 nlohmann::json( row.
id ) ) );
1088 poured.
polyData = fill.value(
"path", nlohmann::json::array() );
1090 boardPouredMap.emplace( poured.
parentId, poured );
1093 else if( row.
type == wxS(
"REGION" ) )
1098 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
1099 nlohmann::json prohibitTypes = row.
inner.value(
"prohibitType",
1100 nlohmann::json::array() );
1102 std::set<int> flags;
1104 if( prohibitTypes.is_array() )
1106 for(
const auto& pt : prohibitTypes )
1110 if( pt.is_string() )
1111 ptStr = pt.get<std::string>();
1113 if( ptStr == wxS(
"COMPONENT" ) )
1115 else if( ptStr == wxS(
"TRACK" ) )
1117 else if( ptStr == wxS(
"COPPER" ) )
1119 else if( ptStr == wxS(
"VIA" ) )
1121 else if( ptStr == wxS(
"FILL" ) || ptStr == wxS(
"PLANE" ) )
1126 for( nlohmann::json& polyData : polyDataList )
1131 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
1133 zone->SetIsRuleArea(
true );
1134 zone->SetDoNotAllowFootprints( !!flags.count( 2 ) );
1135 zone->SetDoNotAllowZoneFills( !!flags.count( 7 ) || !!flags.count( 6 )
1136 || !!flags.count( 8 ) );
1137 zone->SetDoNotAllowPads( !!flags.count( 7 ) );
1138 zone->SetDoNotAllowTracks( !!flags.count( 7 ) || !!flags.count( 5 ) );
1139 zone->SetDoNotAllowVias( !!flags.count( 7 ) );
1141 zone->SetLayer( klayer );
1142 zone->Outline()->Append( contour );
1147 else if( row.
type == wxS(
"STRING" ) )
1151 else if( row.
type == wxS(
"COMPONENT" ) )
1159 nlohmann::json attrsObj = row.
inner.value(
"attrs", nlohmann::json::object() );
1161 if( attrsObj.is_object() )
1163 for(
auto& [k, v] : attrsObj.items() )
1167 componentMap[row.
id] =
comp;
1169 else if( row.
type == wxS(
"ATTR" ) )
1194 attrMap.emplace( attr.parentId, attr );
1196 else if( row.
type == wxS(
"PAD_NET" ) )
1201 pn.compId = idArr.is_array() && idArr.size() > 1
1204 pn.padNumber = idArr.is_array() && idArr.size() > 2
1209 if( !pn.compId.IsEmpty() )
1210 padNetMap.emplace( pn.compId, pn );
1212 else if( row.
type == wxS(
"PAD" ) )
1216 std::unique_ptr<FOOTPRINT> footprint =
1217 std::make_unique<FOOTPRINT>( aBoard );
1229 footprint->SetPosition( pos );
1230 footprint->SetOrientation( orient );
1232 wxString fpName = wxS(
"Pad_" ) + row.
id;
1235 footprint->SetFPID( fpID );
1236 footprint->Reference().SetVisible(
true );
1237 footprint->Value().SetVisible(
true );
1238 footprint->AutoPositionFields();
1242 else if( row.
type == wxS(
"IMAGE" ) )
1257 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
1260 std::vector<SHAPE_LINE_CHAIN> contours;
1261 for( nlohmann::json& polyData : polyDataList )
1266 contours.push_back( contour );
1281 for(
int i = 0; i < contour.PointCount(); i++ )
1292 std::unique_ptr<PCB_GROUP>
group;
1295 group = std::make_unique<PCB_GROUP>( aBoard );
1301 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aBoard,
SHAPE_T::POLY );
1303 shape->SetFilled(
true );
1304 shape->SetPolyShape( poly );
1305 shape->SetLayer( klayer );
1306 shape->SetWidth( 0 );
1318 group->AddItem( shape.get() );
1326 else if( row.
type == wxS(
"OBJ" ) )
1343 if( imageUrl.empty() )
1346 wxString mimeType, base64Data;
1348 if( imageUrl.BeforeFirst(
':' ) == wxS(
"blob" ) )
1350 wxString objectId = imageUrl.AfterLast(
':' );
1352 if(
auto blob =
get_opt( aBlobMap, objectId ) )
1354 wxString blobUrl = blob->url;
1356 if( blobUrl.BeforeFirst(
':' ) == wxS(
"data" ) )
1358 wxArrayString paramsArr =
1359 wxSplit( blobUrl.AfterFirst(
':' ).BeforeFirst(
',' ),
';',
'\0' );
1361 base64Data = blobUrl.AfterFirst(
',' );
1363 if( paramsArr.size() > 0 )
1364 mimeType = paramsArr[0];
1372 if( mimeType.empty() || base64Data.empty() )
1375 wxMemoryBuffer buf = wxBase64Decode( base64Data );
1377 if( mimeType == wxS(
"image/svg+xml" ) )
1383 VECTOR2D kcenter = kstart + ksize / 2;
1385 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap =
1386 std::make_unique<PCB_REFERENCE_IMAGE>( aBoard, kcenter, klayer );
1389 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
1390 & ~wxImage::Load_Verbose );
1402 int x = bitmap->GetPosition().x;
1416 for(
auto const& [compId,
comp] : componentMap )
1419 wxString fpIdOverride;
1420 wxString fpDesignator;
1423 auto attrRange = attrMap.equal_range( compId );
1425 for(
auto it = attrRange.first; it != attrRange.second; ++it )
1427 const ATTR_DATA& attr = it->second;
1429 if( attr.key == wxS(
"Device" ) )
1430 deviceId = attr.value;
1431 else if( attr.key == wxS(
"Footprint" ) )
1432 fpIdOverride = attr.value;
1433 else if( attr.key == wxS(
"Designator" ) )
1434 fpDesignator = attr.value;
1439 const std::map<wxString, wxString>& deviceAttrs = deviceData.
attributes;
1441 wxString fpId = fpIdOverride;
1444 fpId =
get_def( deviceAttrs, wxS(
"Footprint" ), wxEmptyString );
1448 wxLogTrace(
traceEasyEdaIo, wxT(
"EasyEDA Pro v3 component '%s' (%s): no footprint mapping, skipping." ),
1449 compId, fpDesignator );
1453 auto it = aFootprintMap.find( fpId );
1455 if( it == aFootprintMap.end() )
1457 wxLogTrace(
traceEasyEdaIo,
"Footprint of '%s' with uuid '%s' not found.", fpDesignator, fpId );
1461 std::unique_ptr<FOOTPRINT>& footprintOrig = it->second;
1462 std::unique_ptr<FOOTPRINT> footprint(
1463 static_cast<FOOTPRINT*
>( footprintOrig->Clone() ) );
1465 footprint->SetParent( aBoard );
1469 wxString libItemName = footprint->GetFPID().GetLibItemName();
1471 if( libItemName.empty() )
1474 footprint->SetFPID(
ToKiCadLibID( aFpLibName, libItemName ) );
1476 wxString modelUuid =
get_def( deviceAttrs, wxS(
"3D Model" ), wxEmptyString );
1477 wxString modelTitle =
get_def( deviceAttrs, wxS(
"3D Model Title" ), modelUuid ).Trim();
1478 wxString modelTransform =
get_def( deviceAttrs, wxS(
"3D Model Transform" ), wxEmptyString );
1480 m_v2Parser.FillFootprintModelInfo( footprint.get(), modelUuid, modelTitle, modelTransform );
1484 if( !valueText.empty() )
1485 footprint->SetValue( valueText );
1489 if( description.empty() )
1490 description =
get_def( deviceAttrs, wxS(
"Description" ), wxEmptyString );
1492 if( !description.empty() )
1500 [&](
const wxString& attrKey,
const wxString& value )
1504 if( attrKey == wxS(
"Datasheet" ) )
1507 field = footprint->GetField( attrKey );
1522 if( klayer ==
B_Cu )
1525 footprint->SetOrientationDegrees(
comp.angle );
1529 for(
auto attrIt = attrRange.first; attrIt != attrRange.second; ++attrIt )
1531 const ATTR_DATA& attr = attrIt->second;
1533 if( attr.key == wxS(
"Designator" ) )
1537 if( attr.fontName != wxS(
"default" ) )
1540 if( attr.valVisible && attr.keyVisible )
1541 field->
SetText( attr.key +
':' + attr.value );
1542 else if( attr.keyVisible )
1547 field->
SetVisible( attr.keyVisible || attr.valVisible );
1574 auto padNetRange = padNetMap.equal_range( compId );
1576 for(
auto pnIt = padNetRange.first; pnIt != padNetRange.second; ++pnIt )
1578 const PAD_NET_DATA& pn = pnIt->second;
1580 PAD*
pad = footprint->FindPadByNumber( pn.padNumber );
1592 for(
auto& [uuid, zone] : poursToFill )
1597 auto range = boardPouredMap.equal_range( uuid );
1599 for(
auto& pIt = range.first; pIt != range.second; ++pIt )
1605 for(
int dataId = 0;
1606 dataId < static_cast<int>( poured.
polyData.size() ); dataId++ )
1608 const nlohmann::json& fillData = poured.
polyData[dataId];
1609 const double ptScale = 10;
1615 for(
int i = 0; i < contour.
PointCount(); i++ )
1628 thisPoly.
Append( simple );
1637 const int thermalWidth =
pcbIUScale.mmToIU( 0.2 );
1639 for(
int segId = 0; segId < contour.
SegmentCount(); segId++ )
1650 fillPolySet.
Append( thisPoly );
1657 const int strokeWidth =
pcbIUScale.MilsToIU( 8 );
1659 fillPolySet.
Inflate( strokeWidth / 2,
1666 zone->SetFilledPolysList( zone->GetFirstLayer(), fillPolySet );
1667 zone->SetNeedRefill(
false );
1668 zone->SetIsFilled(
true );
1674 std::vector<PCB_SHAPE*> shapes;
1682 shapes.push_back(
static_cast<PCB_SHAPE*
>( item ) );
1697 offset.
x =
KiROUND( offset.
x / alignGrid ) * alignGrid;
1698 offset.
y =
KiROUND( offset.
y / alignGrid ) * alignGrid;
1700 aBoard->
Move( offset );
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
#define DEFAULT_COURTYARD_WIDTH
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & set(size_t pos)
void Mirror(FLIP_DIRECTION aFlipDirection)
Mirror image vertically (i.e.
Container for design settings for a BOARD object.
void SetAuxOrigin(const VECTOR2I &aOrigin)
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Information pertinent to a Pcbnew printed circuit board.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
const PAGE_INFO & GetPageSettings() const
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false, bool aPhysicalLayersOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
unsigned GetNetCount() const
void SetEnabledLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
const DRAWINGS & Drawings() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
constexpr const Vec GetEnd() const
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr const Vec GetCenter() const
constexpr const Vec & GetOrigin() const
constexpr const SizeVec & GetSize() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
virtual void SetVisible(bool aVisible)
void SetTextAngleDegrees(double aOrientation)
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
void SetFont(KIFONT::FONT *aFont)
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
A logical library item identifier and consists of various portions much like a URI.
LSET is a set of PCB_LAYER_IDs.
Handle the data for a net.
@ NORMAL
Shape is the same on all layers.
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
static LSET PTHMask()
layer set for a through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
Describe the page size and margins of a paper page on which to eventually print or plot.
double GetHeightMils() const
double GetWidthMils() const
static T ScaleSize(T aValue)
static VECTOR2< T > ScalePos(VECTOR2< T > aValue)
void ParseBoard(BOARD *aBoard, const nlohmann::json &aProject, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, const std::map< wxString, EASYEDAPRO::BLOB > &aBlobMap, const std::multimap< wxString, EASYEDAPRO::POURED > &aPouredMap, const EASYEDAPRO::V3_DOC_RAW &aDoc, const wxString &aFpLibName)
PCB_IO_EASYEDAPRO_V3_PARSER(BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter)
PCB_IO_EASYEDAPRO_PARSER m_v2Parser
std::unique_ptr< PAD > createV3PAD(FOOTPRINT *aFootprint, const EASYEDAPRO::V3_ROW &aRow)
std::unique_ptr< FOOTPRINT > ParseFootprint(const std::map< wxString, EASYEDAPRO::BLOB > &aBlobMap, const EASYEDAPRO::V3_DOC_RAW &aDoc)
PCB_TEXT * createV3Text(BOARD_ITEM_CONTAINER *aContainer, const EASYEDAPRO::V3_ROW &aRow)
void SetTextThickness(int aWidth) override
The TextThickness is that set by the user.
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true) override
void SetPosition(const VECTOR2I &aPos) override
A progress reporter interface for use in multi-threaded environments.
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
BITMAP_BASE & MutableImage() const
Only use this if you really need to modify the underlying image.
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
void SetImageScale(double aScale)
Set the image "zoom" value.
SHAPE_ARC & ConstructFromStartEndCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aClockwise=false, double aWidth=0)
Constructs this arc from the given start, end and center.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a set of closed polygons.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
void RebuildHolesFromContours()
Extract all contours from this polygon set, then recreate polygons with holes.
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const std::vector< POLYGON > & CPolygons() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
const SHAPE_LINE_CHAIN Outline() const
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
void ConnectBoardShapes(std::vector< PCB_SHAPE * > &aShapeList, int aChainingEpsilon)
Connects shapes to each other, making continious contours (adjacent shapes will have a common vertex)...
const wxChar *const traceEasyEdaIo
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
PCB_LAYER_ID
A quick note on layer IDs:
wxString get_def(const std::map< wxString, wxString > &aMap, const char *aKey, const char *aDefval="")
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
@ LEFT_RIGHT
Flip left to right (around the Y axis)
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
LIB_ID ToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
bool V3GetBool(const nlohmann::json &aObj, const char *aKey, bool aDefault)
void ForEachImportedDeviceField(const std::map< wxString, wxString > &aDeviceAttributes, bool aIncludeValue, const std::function< void(const wxString &aKey, const wxString &aValue)> &aCallback)
Invoke aCallback for each non-empty whitelisted Device field (resolved + normalized).
wxString ResolveDeviceFieldVariables(const wxString &aInput, const std::map< wxString, wxString > &aDeviceAttributes)
Resolve EasyEDA ={Var} / ={A}text{B} field expressions against device attributes.
wxString NormalizeEasyEDAText(wxString aText)
Replace EasyEDA temperature glyph (℃) with °C.
V3_DEVICE_DATA GetV3DeviceData(const nlohmann::json &aProject, const wxString &aDeviceUuid)
static const bool IMPORT_POURED
nlohmann::json V3ParseIdArray(const wxString &aId)
bool V3IsNullOrMissing(const nlohmann::json &aObj, const char *aKey)
double V3GetDouble(const nlohmann::json &aObj, const char *aKey, double aDefault)
wxString V3JsonToString(const nlohmann::json &aValue, const wxString &aDefault)
wxString ResolveV3DeviceValueText(const std::map< wxString, wxString > &aDeviceAttributes)
Preferred Value text: Value attribute, else Name, with variables resolved.
int V3GetInt(const nlohmann::json &aObj, const char *aKey, int aDefault)
wxString V3GetString(const nlohmann::json &aObj, const char *aKey, const wxString &aDefault)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
Class to handle a set of BOARD_ITEMs.
static const int SHAPE_JOIN_DISTANCE
static int V3AlignToOriginCode(const wxString &aAlign)
static void V3AlignText(EDA_TEXT *text, int align)
std::map< wxString, wxString > attributes
Raw parsed document from an EasyEDA Pro v3 .epru stream.
std::vector< V3_ROW > rows
One parsed row from an EasyEDA Pro v3 .epru document stream.
@ USER
The field ID hasn't been set yet; field is invalid.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
wxLogTrace helper definitions.
double DEG2RAD(double deg)
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D