36#include <wx/mstream.h>
86 nlohmann::json holeObj = aRow.
inner.value(
"hole", nlohmann::json() );
87 nlohmann::json padDef = aRow.
inner.value(
"defaultPad", nlohmann::json() );
89 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
91 pad->SetNumber( padNumber );
93 pad->SetOrientationDegrees( orientation );
98 if( holeObj.is_object() )
100 wxString holeType =
V3GetString( holeObj,
"holeType", wxS(
"ROUND" ) );
102 if( holeType == wxS(
"RECT" ) )
103 holeType = wxS(
"SLOT" );
105 if( holeType != wxS(
"ROUND" ) && holeType != wxS(
"SLOT" ) )
106 holeType = wxS(
"ROUND" );
112 if( drill.
x > 0 || drill.
y > 0 )
121 std::swap( drill.
x, drill.
y );
123 if( holeType == wxS(
"SLOT" ) )
136 else if( klayer ==
B_Cu )
143 if( padDef.is_object() )
145 wxString padType =
V3GetString( padDef,
"padType", wxS(
"RECT" ) );
147 if( padType == wxS(
"RECT" ) )
153 double radiusRatio = std::clamp(
radius, 0.0, 100.0 ) / 100 / 2;
158 if( radiusRatio == 0 )
166 else if( padType == wxS(
"ELLIPSE" ) )
177 else if( padType == wxS(
"OVAL" ) )
187 else if( padType == wxS(
"POLY" ) || padType == wxS(
"POLYGON" ) )
193 nlohmann::json polyData = padDef.value(
"path", nlohmann::json() );
195 std::vector<std::unique_ptr<PCB_SHAPE>> results =
196 m_v2Parser.ParsePoly( aFootprint, polyData,
true,
false );
198 for(
auto& shape : results )
200 shape->SetLayer( klayer );
201 shape->SetWidth( 0 );
202 shape->Move( -
pad->GetPosition() );
236 wxString originStr =
V3GetString( aRow.
inner,
"origin", wxS(
"LEFT_BOTTOM" ) );
244 text->SetText(
string );
245 text->SetLayer( klayer );
247 text->SetIsKnockout( inverted );
252 if( font != wxS(
"default" ) )
259 text->SetMirrored(
true );
260 text->SetTextAngleDegrees( -angle );
264 text->SetTextAngleDegrees( angle );
274 std::unique_ptr<FOOTPRINT> footprintPtr = std::make_unique<FOOTPRINT>(
m_board );
275 FOOTPRINT* footprint = footprintPtr.get();
278 const int defaultTextThickness(
pcbIUScale.mmToIU( 0.15 ) );
282 field->SetTextSize( defaultTextSize );
283 field->SetTextThickness( defaultTextThickness );
288 if( row.
type == wxS(
"POLY" ) )
294 nlohmann::json polyData = row.
inner.value(
"path", nlohmann::json::array() );
296 std::vector<std::unique_ptr<PCB_SHAPE>> results =
297 m_v2Parser.ParsePoly( footprint, polyData,
false,
false );
299 for(
auto& shape : results )
301 shape->SetLayer( klayer );
306 else if( row.
type == wxS(
"PAD" ) )
311 else if( row.
type == wxS(
"FILL" ) )
316 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
318 if( !polyDataList.is_null() && !polyDataList.empty() )
320 if( !polyDataList.at( 0 ).is_array() )
321 polyDataList = nlohmann::json::array( { polyDataList } );
323 std::vector<SHAPE_LINE_CHAIN> contours;
325 for( nlohmann::json& polyData : polyDataList )
329 contours.push_back( contour );
339 std::unique_ptr<PCB_GROUP>
group;
342 group = std::make_unique<PCB_GROUP>( footprint );
346 std::unique_ptr<PCB_SHAPE> shape =
349 shape->SetFilled(
true );
350 shape->SetPolyShape( poly );
351 shape->SetLayer( klayer );
352 shape->SetWidth( 0 );
355 group->AddItem( shape.get() );
364 else if( row.
type == wxS(
"ATTR" ) )
369 if( key == wxS(
"Designator" ) )
372 else if( row.
type == wxS(
"REGION" ) )
377 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
378 nlohmann::json prohibitTypes = row.
inner.value(
"prohibitType", nlohmann::json::array() );
382 if( prohibitTypes.is_array() )
384 for(
const auto& pt : prohibitTypes )
389 ptStr = pt.get<std::string>();
391 if( ptStr == wxS(
"COMPONENT" ) )
393 else if( ptStr == wxS(
"TRACK" ) )
395 else if( ptStr == wxS(
"COPPER" ) )
397 else if( ptStr == wxS(
"VIA" ) )
399 else if( ptStr == wxS(
"FILL" ) || ptStr == wxS(
"PLANE" ) )
404 for( nlohmann::json& polyData : polyDataList )
408 std::vector<std::unique_ptr<PCB_SHAPE>> results =
409 m_v2Parser.ParsePoly(
nullptr, polyData,
true,
false );
411 for(
auto& shape : results )
413 shape->SetFilled(
true );
414 shape->TransformShapeToPolygon( polySet, klayer, 0,
ARC_HIGH_DEF,
420 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( footprint );
422 zone->SetIsRuleArea(
true );
423 zone->SetDoNotAllowFootprints( !!flags.count( 2 ) );
424 zone->SetDoNotAllowZoneFills( !!flags.count( 7 ) || !!flags.count( 6 )
425 || !!flags.count( 8 ) );
426 zone->SetDoNotAllowPads( !!flags.count( 7 ) );
427 zone->SetDoNotAllowTracks( !!flags.count( 7 ) || !!flags.count( 5 ) );
428 zone->SetDoNotAllowVias( !!flags.count( 7 ) );
430 zone->SetLayer( klayer );
431 zone->Outline()->Append( polySet );
436 else if( row.
type == wxS(
"IMAGE" ) )
451 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
454 std::vector<SHAPE_LINE_CHAIN> contours;
455 for( nlohmann::json& polyData : polyDataList )
460 contours.push_back( contour );
475 for(
int i = 0; i < contour.PointCount(); i++ )
486 std::unique_ptr<PCB_GROUP>
group;
489 group = std::make_unique<PCB_GROUP>( footprint );
495 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( footprint,
SHAPE_T::POLY );
497 shape->SetFilled(
true );
498 shape->SetPolyShape( poly );
499 shape->SetLayer( klayer );
500 shape->SetWidth( 0 );
512 group->AddItem( shape.get() );
520 else if( row.
type == wxS(
"OBJ" ) )
537 if( imageUrl.empty() )
540 wxString mimeType, base64Data;
542 if( imageUrl.BeforeFirst(
':' ) == wxS(
"blob" ) )
544 wxString objectId = imageUrl.AfterLast(
':' );
546 if(
auto blob =
get_opt( aBlobMap, objectId ) )
548 wxString blobUrl = blob->url;
550 if( blobUrl.BeforeFirst(
':' ) == wxS(
"data" ) )
552 wxArrayString paramsArr =
553 wxSplit( blobUrl.AfterFirst(
':' ).BeforeFirst(
',' ),
';',
'\0' );
555 base64Data = blobUrl.AfterFirst(
',' );
557 if( paramsArr.size() > 0 )
558 mimeType = paramsArr[0];
566 if( mimeType.empty() || base64Data.empty() )
569 wxMemoryBuffer buf = wxBase64Decode( base64Data );
571 if( mimeType == wxS(
"image/svg+xml" ) )
577 VECTOR2D kcenter = kstart + ksize / 2;
579 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap =
580 std::make_unique<PCB_REFERENCE_IMAGE>( footprint, kcenter, klayer );
583 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
584 & ~wxImage::Load_Verbose );
596 int x = bitmap->GetPosition().x;
607 else if( row.
type == wxS(
"STRING" ) )
618 std::vector<PCB_SHAPE*> edgeShapes;
623 edgeShapes.push_back(
static_cast<PCB_SHAPE*
>( item ) );
634 std::unique_ptr<PCB_SHAPE> shape =
640 shape->SetEnd( bbox.
GetEnd() );
646 bool hasFabRef =
false;
652 if(
static_cast<PCB_TEXT*
>( item )->GetText() == wxT(
"${REFERENCE}" ) )
663 int c_refTextThickness =
pcbIUScale.mmToIU( 0.1 );
664 std::unique_ptr<PCB_TEXT> refText = std::make_unique<PCB_TEXT>( footprint );
666 refText->SetLayer(
F_Fab );
667 refText->SetTextSize(
VECTOR2I( c_refTextSize, c_refTextSize ) );
668 refText->SetTextThickness( c_refTextThickness );
669 refText->SetText( wxT(
"${REFERENCE}" ) );
674 return footprintPtr.release();
724 if( aAlign == wxS(
"LEFT_TOP" ) )
726 if( aAlign == wxS(
"LEFT_CENTER" ) || aAlign == wxS(
"LEFT_MIDDLE" ) )
728 if( aAlign == wxS(
"LEFT_BOTTOM" ) )
730 if( aAlign == wxS(
"CENTER_TOP" ) )
732 if( aAlign == wxS(
"CENTER_MIDDLE" ) || aAlign == wxS(
"CENTER_CENTER" ) )
734 if( aAlign == wxS(
"CENTER_BOTTOM" ) )
736 if( aAlign == wxS(
"RIGHT_TOP" ) )
738 if( aAlign == wxS(
"RIGHT_CENTER" ) || aAlign == wxS(
"RIGHT_MIDDLE" ) )
740 if( aAlign == wxS(
"RIGHT_BOTTOM" ) )
748 BOARD* aBoard,
const nlohmann::json& aProject,
749 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap,
750 const std::map<wxString, EASYEDAPRO::BLOB>& aBlobMap,
751 const std::multimap<wxString, EASYEDAPRO::POURED>& aPouredMap,
752 const V3_DOC_RAW& aDoc,
const wxString& aFpLibName )
760 std::map<wxString, wxString> attrs;
772 bool keyVisible =
false;
773 bool valVisible =
false;
775 double fontSize = 45.0;
776 double strokeWidth = 6.0;
790 std::map<wxString, COMP_DATA> componentMap;
791 std::multimap<wxString, ATTR_DATA> attrMap;
792 std::multimap<wxString, PAD_NET_DATA> padNetMap;
794 std::multimap<wxString, EASYEDAPRO::POURED> boardPouredMap = aPouredMap;
795 std::map<wxString, ZONE*> poursToFill;
801 if( row.
type == wxS(
"LAYER" ) )
812 blayers.
set( klayer );
815 if( !layerName.IsEmpty() )
819 else if( row.
type == wxS(
"NET" ) )
824 if( idArr.is_array() && idArr.size() > 1 )
827 if( !netname.IsEmpty() )
834 else if( row.
type == wxS(
"RULE" ) )
838 if( !idArr.is_array() || idArr.size() < 3 )
844 nlohmann::json context = row.
inner.value(
"ruleContext", nlohmann::json() );
846 if( ruleType == wxS(
"TRACK" ) && isDefault )
848 nlohmann::json track = context.value(
"track", nlohmann::json() );
849 nlohmann::json content = track.value(
"content", nlohmann::json::array() );
851 if( content.is_array() && !content.empty() )
853 double minVal =
V3GetDouble( content[0],
"stroMin" );
857 else if( ruleType == wxS(
"SAFE" ) && isDefault )
859 nlohmann::json safeSpacing = context.value(
"safeSpacing",
860 nlohmann::json::array() );
862 if( safeSpacing.is_array() && !safeSpacing.empty() )
864 nlohmann::json content = safeSpacing[0].value(
"content",
865 nlohmann::json::array() );
867 int minVal = INT_MAX;
869 for(
const auto& arr : content )
873 for(
const auto& val : arr )
875 int v = val.is_number() ? val.get<
int>() : 0;
882 if( minVal != INT_MAX )
887 else if( row.
type == wxS(
"VIA" ) )
897 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( aBoard );
907 else if( row.
type == wxS(
"LINE" ) )
923 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>( aBoard );
925 track->SetLayer( klayer );
929 track->SetNet( aBoard->
FindNet( netname ) );
933 else if( row.
type == wxS(
"ARC" ) )
953 double ha = angle / 2;
954 double hd =
delta.EuclideanNorm() / 2;
955 double cdist = hd / tan(
DEG2RAD( ha ) );
964 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( aBoard, &sarc );
966 arc->SetLayer( klayer );
967 arc->SetNet( aBoard->
FindNet( netname ) );
971 else if( row.
type == wxS(
"POLY" ) )
977 nlohmann::json polyData = row.
inner.value(
"path", nlohmann::json::array() );
979 std::vector<std::unique_ptr<PCB_SHAPE>> results =
980 m_v2Parser.ParsePoly( aBoard, polyData,
false,
false );
982 for(
auto& shape : results )
984 shape->SetLayer( klayer );
990 else if( row.
type == wxS(
"FILL" ) )
997 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
999 if( polyDataList.is_null() || polyDataList.empty() )
1002 if( !polyDataList.at( 0 ).is_array() )
1003 polyDataList = nlohmann::json::array( { polyDataList } );
1005 std::vector<SHAPE_LINE_CHAIN> contours;
1007 for( nlohmann::json& polyData : polyDataList )
1011 contours.push_back( contour );
1022 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
1024 zone->SetNet( aBoard->
FindNet( netname ) );
1025 zone->SetLayer( klayer );
1027 zone->SetFilledPolysList( klayer, zoneFillPoly );
1028 zone->SetAssignedPriority( 500 );
1029 zone->SetIsFilled(
true );
1030 zone->SetNeedRefill(
false );
1037 else if( row.
type == wxS(
"POUR" ) )
1045 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
1047 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
1049 zone->SetNet( aBoard->
FindNet( netname ) );
1050 zone->SetLayer( klayer );
1051 zone->SetAssignedPriority( 500 - fillOrder );
1055 for( nlohmann::json& polyData : polyDataList )
1059 zone->Outline()->Append( contour );
1062 wxASSERT( zone->Outline()->OutlineCount() == 1 );
1064 poursToFill.emplace( row.
id, zone.get() );
1068 else if( row.
type == wxS(
"POURED" ) )
1073 if( idArr.is_array() && idArr.size() > 1 )
1076 nlohmann::json fills = row.
inner.value(
"pourFill", nlohmann::json::array() );
1078 if( !fills.is_array() )
1081 for(
const nlohmann::json& fill : fills )
1085 nlohmann::json( row.
id ) ) );
1089 poured.
polyData = fill.value(
"path", nlohmann::json::array() );
1091 boardPouredMap.emplace( poured.
parentId, poured );
1094 else if( row.
type == wxS(
"REGION" ) )
1099 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
1100 nlohmann::json prohibitTypes = row.
inner.value(
"prohibitType",
1101 nlohmann::json::array() );
1103 std::set<int> flags;
1105 if( prohibitTypes.is_array() )
1107 for(
const auto& pt : prohibitTypes )
1111 if( pt.is_string() )
1112 ptStr = pt.get<std::string>();
1114 if( ptStr == wxS(
"COMPONENT" ) )
1116 else if( ptStr == wxS(
"TRACK" ) )
1118 else if( ptStr == wxS(
"COPPER" ) )
1120 else if( ptStr == wxS(
"VIA" ) )
1122 else if( ptStr == wxS(
"FILL" ) || ptStr == wxS(
"PLANE" ) )
1127 for( nlohmann::json& polyData : polyDataList )
1132 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
1134 zone->SetIsRuleArea(
true );
1135 zone->SetDoNotAllowFootprints( !!flags.count( 2 ) );
1136 zone->SetDoNotAllowZoneFills( !!flags.count( 7 ) || !!flags.count( 6 )
1137 || !!flags.count( 8 ) );
1138 zone->SetDoNotAllowPads( !!flags.count( 7 ) );
1139 zone->SetDoNotAllowTracks( !!flags.count( 7 ) || !!flags.count( 5 ) );
1140 zone->SetDoNotAllowVias( !!flags.count( 7 ) );
1142 zone->SetLayer( klayer );
1143 zone->Outline()->Append( contour );
1148 else if( row.
type == wxS(
"STRING" ) )
1152 else if( row.
type == wxS(
"COMPONENT" ) )
1160 nlohmann::json attrsObj = row.
inner.value(
"attrs", nlohmann::json::object() );
1162 if( attrsObj.is_object() )
1164 for(
auto& [k, v] : attrsObj.items() )
1168 componentMap[row.
id] =
comp;
1170 else if( row.
type == wxS(
"ATTR" ) )
1195 attrMap.emplace( attr.parentId, attr );
1197 else if( row.
type == wxS(
"PAD_NET" ) )
1202 pn.compId = idArr.is_array() && idArr.size() > 1
1205 pn.padNumber = idArr.is_array() && idArr.size() > 2
1210 if( !pn.compId.IsEmpty() )
1211 padNetMap.emplace( pn.compId, pn );
1213 else if( row.
type == wxS(
"PAD" ) )
1217 std::unique_ptr<FOOTPRINT> footprint =
1218 std::make_unique<FOOTPRINT>( aBoard );
1230 footprint->SetPosition( pos );
1231 footprint->SetOrientation( orient );
1233 wxString fpName = wxS(
"Pad_" ) + row.
id;
1236 footprint->SetFPID( fpID );
1237 footprint->Reference().SetVisible(
true );
1238 footprint->Value().SetVisible(
true );
1239 footprint->AutoPositionFields();
1243 else if( row.
type == wxS(
"IMAGE" ) )
1258 nlohmann::json polyDataList = row.
inner.value(
"path", nlohmann::json::array() );
1261 std::vector<SHAPE_LINE_CHAIN> contours;
1262 for( nlohmann::json& polyData : polyDataList )
1267 contours.push_back( contour );
1282 for(
int i = 0; i < contour.PointCount(); i++ )
1293 std::unique_ptr<PCB_GROUP>
group;
1296 group = std::make_unique<PCB_GROUP>( aBoard );
1302 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aBoard,
SHAPE_T::POLY );
1304 shape->SetFilled(
true );
1305 shape->SetPolyShape( poly );
1306 shape->SetLayer( klayer );
1307 shape->SetWidth( 0 );
1319 group->AddItem( shape.get() );
1327 else if( row.
type == wxS(
"OBJ" ) )
1344 if( imageUrl.empty() )
1347 wxString mimeType, base64Data;
1349 if( imageUrl.BeforeFirst(
':' ) == wxS(
"blob" ) )
1351 wxString objectId = imageUrl.AfterLast(
':' );
1353 if(
auto blob =
get_opt( aBlobMap, objectId ) )
1355 wxString blobUrl = blob->url;
1357 if( blobUrl.BeforeFirst(
':' ) == wxS(
"data" ) )
1359 wxArrayString paramsArr =
1360 wxSplit( blobUrl.AfterFirst(
':' ).BeforeFirst(
',' ),
';',
'\0' );
1362 base64Data = blobUrl.AfterFirst(
',' );
1364 if( paramsArr.size() > 0 )
1365 mimeType = paramsArr[0];
1373 if( mimeType.empty() || base64Data.empty() )
1376 wxMemoryBuffer buf = wxBase64Decode( base64Data );
1378 if( mimeType == wxS(
"image/svg+xml" ) )
1384 VECTOR2D kcenter = kstart + ksize / 2;
1386 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap =
1387 std::make_unique<PCB_REFERENCE_IMAGE>( aBoard, kcenter, klayer );
1390 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
1391 & ~wxImage::Load_Verbose );
1403 int x = bitmap->GetPosition().x;
1417 for(
auto const& [compId,
comp] : componentMap )
1420 wxString fpIdOverride;
1421 wxString fpDesignator;
1424 auto attrRange = attrMap.equal_range( compId );
1426 for(
auto it = attrRange.first; it != attrRange.second; ++it )
1428 const ATTR_DATA& attr = it->second;
1430 if( attr.key == wxS(
"Device" ) )
1431 deviceId = attr.value;
1432 else if( attr.key == wxS(
"Footprint" ) )
1433 fpIdOverride = attr.value;
1434 else if( attr.key == wxS(
"Designator" ) )
1435 fpDesignator = attr.value;
1440 const std::map<wxString, wxString>& deviceAttrs = deviceData.
attributes;
1442 wxString fpId = fpIdOverride;
1445 fpId =
get_def( deviceAttrs, wxS(
"Footprint" ), wxEmptyString );
1449 wxLogWarning( wxString::Format(
1450 _(
"EasyEDA Pro v3 component '%s' (%s): no footprint mapping, skipping." ),
1451 compId, fpDesignator ) );
1455 auto it = aFootprintMap.find( fpId );
1457 if( it == aFootprintMap.end() )
1459 wxLogError(
"Footprint of '%s' with uuid '%s' not found.", fpDesignator, fpId );
1463 std::unique_ptr<FOOTPRINT>& footprintOrig = it->second;
1464 std::unique_ptr<FOOTPRINT> footprint(
1465 static_cast<FOOTPRINT*
>( footprintOrig->Clone() ) );
1467 footprint->SetParent( aBoard );
1471 wxString libItemName = footprint->GetFPID().GetLibItemName();
1473 if( libItemName.empty() )
1476 footprint->SetFPID(
ToKiCadLibID( aFpLibName, libItemName ) );
1478 wxString modelUuid =
get_def( deviceAttrs, wxS(
"3D Model" ), wxEmptyString );
1479 wxString modelTitle =
get_def( deviceAttrs, wxS(
"3D Model Title" ), modelUuid ).Trim();
1480 wxString modelTransform =
get_def( deviceAttrs, wxS(
"3D Model Transform" ), wxEmptyString );
1482 m_v2Parser.FillFootprintModelInfo( footprint.get(), modelUuid, modelTitle, modelTransform );
1486 if( !valueText.empty() )
1487 footprint->SetValue( valueText );
1491 if( description.empty() )
1492 description =
get_def( deviceAttrs, wxS(
"Description" ), wxEmptyString );
1494 if( !description.empty() )
1502 [&](
const wxString& attrKey,
const wxString& value )
1506 if( attrKey == wxS(
"Datasheet" ) )
1509 field = footprint->GetField( attrKey );
1524 if( klayer ==
B_Cu )
1527 footprint->SetOrientationDegrees(
comp.angle );
1531 for(
auto attrIt = attrRange.first; attrIt != attrRange.second; ++attrIt )
1533 const ATTR_DATA& attr = attrIt->second;
1535 if( attr.key == wxS(
"Designator" ) )
1539 if( attr.fontName != wxS(
"default" ) )
1542 if( attr.valVisible && attr.keyVisible )
1543 field->
SetText( attr.key +
':' + attr.value );
1544 else if( attr.keyVisible )
1549 field->
SetVisible( attr.keyVisible || attr.valVisible );
1576 auto padNetRange = padNetMap.equal_range( compId );
1578 for(
auto pnIt = padNetRange.first; pnIt != padNetRange.second; ++pnIt )
1580 const PAD_NET_DATA& pn = pnIt->second;
1582 PAD*
pad = footprint->FindPadByNumber( pn.padNumber );
1594 for(
auto& [uuid, zone] : poursToFill )
1599 auto range = boardPouredMap.equal_range( uuid );
1601 for(
auto& pIt = range.first; pIt != range.second; ++pIt )
1607 for(
int dataId = 0;
1608 dataId < static_cast<int>( poured.
polyData.size() ); dataId++ )
1610 const nlohmann::json& fillData = poured.
polyData[dataId];
1611 const double ptScale = 10;
1617 for(
int i = 0; i < contour.
PointCount(); i++ )
1630 thisPoly.
Append( simple );
1639 const int thermalWidth =
pcbIUScale.mmToIU( 0.2 );
1641 for(
int segId = 0; segId < contour.
SegmentCount(); segId++ )
1652 fillPolySet.
Append( thisPoly );
1659 const int strokeWidth =
pcbIUScale.MilsToIU( 8 );
1661 fillPolySet.
Inflate( strokeWidth / 2,
1668 zone->SetFilledPolysList( zone->GetFirstLayer(), fillPolySet );
1669 zone->SetNeedRefill(
false );
1670 zone->SetIsFilled(
true );
1676 std::vector<PCB_SHAPE*> shapes;
1684 shapes.push_back(
static_cast<PCB_SHAPE*
>( item ) );
1699 offset.
x =
KiROUND( offset.
x / alignGrid ) * alignGrid;
1700 offset.
y =
KiROUND( offset.
y / alignGrid ) * alignGrid;
1702 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.
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
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
FOOTPRINT * ParseFootprint(const std::map< wxString, EASYEDAPRO::BLOB > &aBlobMap, const EASYEDAPRO::V3_DOC_RAW &aDoc)
std::unique_ptr< PAD > createV3PAD(FOOTPRINT *aFootprint, const EASYEDAPRO::V3_ROW &aRow)
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
virtual 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)...
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".
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