40#include <wx/datetime.h>
181 switch( footprint->GetSide() )
205 if( track->GetNetCode() == otherTrack->GetNetCode() )
216 auto trackShapeA = track->GetEffectiveShape( layer );
217 auto trackShapeB = otherTrack->GetEffectiveShape( layer );
241 std::vector<DRILL_LINE_ITEM> drills;
272 for(
int j = 0; j < polySet.
HoleCount( i ); ++j )
281 for(
PAD*
pad : footprint->Pads() )
283 if( !
pad->HasHole() )
286 std::shared_ptr<SHAPE_SEGMENT> hole =
pad->GetEffectiveHoleShape();
291 const SEG& seg = hole->GetSeg();
292 double width = hole->GetWidth();
293 double area = seg.
Length() * width;
295 area +=
M_PI * 0.25 * width * width;
305 double drill =
via->GetDrillValue();
325 int minPadClearanceOuter = netSettings->GetDefaultNetclass()->GetClearance();
333 frontShapesForArea.
Append( frontA );
336 backShapesForArea.
Append( backA );
340 for(
PAD*
pad : fp->Pads() )
342 if( !
pad->HasHole() )
347 pad->TransformShapeToPolygon( frontShapesForArea,
F_Cu,
348 std::min( minPadClearanceOuter,
pad->GetOwnClearance(
F_Cu ) ),
350 pad->TransformShapeToPolygon( backShapesForArea,
B_Cu,
351 std::min( minPadClearanceOuter,
pad->GetOwnClearance(
B_Cu ) ),
441 return wxString::Format( wxT(
"%i" ), aCount );
445static void appendTable(
const std::vector<std::vector<wxString>>& aRows,
bool aUseFirstColAsLabel, wxString& aOut )
450 size_t columnCount = 0;
452 for(
const std::vector<wxString>& row : aRows )
454 if( row.size() > columnCount )
455 columnCount = row.size();
458 if( columnCount == 0 )
461 std::vector<int> widths( columnCount, 0 );
463 for(
const std::vector<wxString>& row : aRows )
465 for(
size_t col = 0; col < columnCount; ++col )
467 if( col >= row.size() )
470 int cellWidth =
static_cast<int>( row[col].length() );
472 if( cellWidth > widths[col] )
473 widths[col] = cellWidth;
478 [&](
const std::vector<wxString>& row,
bool treatFirstAsLabel )
480 if( treatFirstAsLabel && aUseFirstColAsLabel )
483 wxString firstColumn;
486 firstColumn = row[0];
488 formatted.Printf( wxS(
"|%-*s |" ), widths[0], firstColumn );
491 for(
size_t col = 1; col < columnCount; ++col )
494 if( col < row.size() )
497 formatted.Printf( wxS(
" %*s |" ), widths[col], value );
505 for(
size_t col = 0; col < columnCount; ++col )
508 if( col < row.size() )
512 formatted.Printf( wxS(
" %*s |" ), widths[col], value );
520 appendDataRow( aRows.front(),
false );
524 for(
size_t col = 0; col < columnCount; ++col )
526 int dashCount = widths[col] + 2;
533 for(
int i = 0; i < dashCount; ++i )
534 dashes << wxS(
"-" );
536 aOut << dashes << wxS(
"|" );
541 for(
size_t rowIdx = 1; rowIdx < aRows.size(); ++rowIdx )
542 appendDataRow( aRows[rowIdx],
true );
548 if( aValue == std::numeric_limits<int>::max() )
549 return _(
"unknown" );
556 const UNITS_PROVIDER& aUnitsProvider,
const wxString& aProjectName,
557 const wxString& aBoardName )
561 report <<
_(
"PCB statistics report\n=====================" ) << wxS(
"\n" );
562 report << wxS(
"- " ) <<
_(
"Date" ) << wxS(
": " ) << wxDateTime::Now().Format() << wxS(
"\n" );
563 report << wxS(
"- " ) <<
_(
"Project" ) << wxS(
": " ) << aProjectName << wxS(
"\n" );
564 report << wxS(
"- " ) <<
_(
"Board name" ) << wxS(
": " ) << aBoardName << wxS(
"\n\n" );
566 report <<
_(
"Board" ) << wxS(
"\n-----\n" );
572 report << wxS(
"- " ) <<
_(
"Height" ) << wxS(
": " )
574 report << wxS(
"- " ) <<
_(
"Area" ) << wxS(
": " )
579 report << wxS(
"- " ) <<
_(
"Dimensions" ) << wxS(
": " ) <<
_(
"unknown" ) << wxS(
"\n" );
580 report << wxS(
"- " ) <<
_(
"Area" ) << wxS(
": " ) <<
_(
"unknown" ) << wxS(
"\n" );
583 report << wxS(
"- " ) <<
_(
"Front copper area" ) << wxS(
": " )
585 report << wxS(
"- " ) <<
_(
"Back copper area" ) << wxS(
": " )
588 report << wxS(
"- " ) <<
_(
"Min track clearance" ) << wxS(
": " )
591 report << wxS(
"- " ) <<
_(
"Min track width" ) << wxS(
": " )
594 report << wxS(
"- " ) <<
_(
"Min drill diameter" ) << wxS(
": " )
597 report << wxS(
"- " ) <<
_(
"Board stackup thickness" ) << wxS(
": " )
601 report << wxS(
"- " ) <<
_(
"Front footprint area" ) << wxS(
": " )
603 report << wxS(
"- " ) <<
_(
"Back footprint area" ) << wxS(
": " )
606 report << wxS(
"- " ) <<
_(
"Front component density" ) << wxS(
": " );
611 report <<
_(
"unknown" );
613 report << wxS(
"\n" );
615 report << wxS(
"- " ) <<
_(
"Back component density" ) << wxS(
": " );
620 report <<
_(
"unknown" );
622 report << wxS(
"\n" );
624 report <<
_(
"Pads" ) << wxS(
"\n----\n" );
627 report << wxS(
"- " ) << padEntry.
title << wxS(
" " ) << padEntry.
quantity << wxS(
"\n" );
630 report << wxS(
"- " ) << propEntry.
title << wxS(
" " ) << propEntry.
quantity << wxS(
"\n" );
632 report << wxS(
"\n" );
633 report <<
_(
"Vias" ) << wxS(
"\n----\n" );
636 report << wxS(
"- " ) << viaEntry.
title << wxS(
" " ) << viaEntry.
quantity << wxS(
"\n" );
638 report << wxS(
"\n" );
639 report <<
_(
"Components" ) << wxS(
"\n----------\n\n" );
641 std::vector<std::vector<wxString>> componentRows;
642 std::vector<wxString> header;
643 header.push_back( wxString() );
644 header.push_back(
_(
"Front Side" ) );
645 header.push_back(
_(
"Back Side" ) );
646 header.push_back(
_(
"Total" ) );
647 componentRows.push_back( std::move( header ) );
654 std::vector<wxString> row;
655 row.push_back( fpEntry.
title );
659 componentRows.push_back( std::move( row ) );
665 std::vector<wxString> totalRow;
666 totalRow.push_back(
_(
"Total:" ) );
669 totalRow.push_back(
formatCount( frontTotal + backTotal ) );
670 componentRows.push_back( std::move( totalRow ) );
674 report << wxS(
"\n" );
675 report <<
_(
"Drill holes" ) << wxS(
"\n-----------\n\n" );
677 std::vector<std::vector<wxString>> drillRows;
678 std::vector<wxString> drillHeader;
679 drillHeader.push_back(
_(
"Count" ) );
680 drillHeader.push_back(
_(
"Shape" ) );
681 drillHeader.push_back(
_(
"X Size" ) );
682 drillHeader.push_back(
_(
"Y Size" ) );
683 drillHeader.push_back(
_(
"Plated" ) );
684 drillHeader.push_back(
_(
"Via/Pad" ) );
685 drillHeader.push_back(
_(
"Start Layer" ) );
686 drillHeader.push_back(
_(
"Stop Layer" ) );
687 drillRows.push_back( std::move( drillHeader ) );
693 switch( drill.
shape )
697 default: shapeStr =
_(
"???" );
break;
700 wxString platedStr = drill.
isPlated ?
_(
"PTH" ) :
_(
"NPTH" );
701 wxString itemStr = drill.
isPad ?
_(
"Pad" ) :
_(
"Via" );
703 wxString startLayerStr;
704 wxString stopLayerStr;
707 startLayerStr =
_(
"N/A" );
711 startLayerStr =
_(
"N/A" );
714 stopLayerStr =
_(
"N/A" );
718 stopLayerStr =
_(
"N/A" );
720 std::vector<wxString> row;
722 row.push_back( shapeStr );
725 row.push_back( platedStr );
726 row.push_back( itemStr );
727 row.push_back( startLayerStr );
728 row.push_back( stopLayerStr );
729 drillRows.push_back( std::move( row ) );
739 const UNITS_PROVIDER& aUnitsProvider,
const wxString& aProjectName,
740 const wxString& aBoardName )
742 const auto formatMinimum = [&aUnitsProvider](
int aValue ) -> nlohmann::json
744 if( aValue == std::numeric_limits<int>::max() )
745 return nlohmann::json();
750 nlohmann::ordered_json root;
752 nlohmann::ordered_json metadata;
755 metadata[
"project"] = aProjectName;
756 metadata[
"board_name"] = aBoardName;
757 root[
"metadata"] = metadata;
759 nlohmann::ordered_json board;
772 board[
"width"] = nlohmann::json();
773 board[
"height"] = nlohmann::json();
774 board[
"area"] = nlohmann::json();
775 board[
"front_component_density"] = nlohmann::json();
776 board[
"back_component_density"] = nlohmann::json();
784 board[
"min_track_width"] = formatMinimum( aData.
minTrackWidth );
785 board[
"min_drill_diameter"] = formatMinimum( aData.
minDrillSize );
799 board[
"front_footprint_density"] = nlohmann::json();
800 board[
"back_footprint_density"] = nlohmann::json();
803 root[
"board"] = board;
805 nlohmann::ordered_json pads = nlohmann::ordered_json::object();
815 nlohmann::ordered_json vias = nlohmann::ordered_json::object();
824 nlohmann::ordered_json components = nlohmann::ordered_json::object();
828 nlohmann::ordered_json component;
832 components[fpEntry.
jsonKey] = component;
838 nlohmann::ordered_json totals;
839 totals[
"front"] = frontTotal;
840 totals[
"back"] = backTotal;
841 totals[
"total"] = frontTotal + backTotal;
842 components[
"total"] = totals;
844 root[
"components"] = components;
846 nlohmann::ordered_json drillHoles = nlohmann::ordered_json::array();
850 nlohmann::ordered_json drillJson;
854 switch( drill.
shape )
858 default: shapeStr =
_(
"???" );
break;
861 wxString sourceStr = drill.
isPad ?
_(
"Pad" ) :
_(
"Via" );
862 wxString startLayerStr =
_(
"N/A" );
863 wxString stopLayerStr =
_(
"N/A" );
871 drillJson[
"count"] = drill.
m_Qty;
872 drillJson[
"shape"] = shapeStr;
875 drillJson[
"plated"] = drill.
isPlated;
876 drillJson[
"source"] = sourceStr;
877 drillJson[
"start_layer"] = startLayerStr;
878 drillJson[
"stop_layer"] = stopLayerStr;
879 drillHoles.push_back( std::move( drillJson ) );
882 root[
"drill_holes"] = drillHoles;
884 std::string jsonText = root.dump( 2 );
885 return wxString::FromUTF8( jsonText.c_str() );
constexpr int ARC_LOW_DEF
void CollectDrillLineItems(BOARD *board, std::vector< DRILL_LINE_ITEM > &out)
static void updatePadCounts(FOOTPRINT *aFootprint, BOARD_STATISTICS_DATA &aData)
wxString FormatBoardStatisticsJson(const BOARD_STATISTICS_DATA &aData, BOARD *aBoard, const UNITS_PROVIDER &aUnitsProvider, const wxString &aProjectName, const wxString &aBoardName)
void ComputeBoardStatistics(BOARD *aBoard, const BOARD_STATISTICS_OPTIONS &aOptions, BOARD_STATISTICS_DATA &aData)
static wxString formatCount(int aCount)
wxString FormatBoardStatisticsReport(const BOARD_STATISTICS_DATA &aData, BOARD *aBoard, const UNITS_PROVIDER &aUnitsProvider, const wxString &aProjectName, const wxString &aBoardName)
wxString FormatBoardStatisticsMinimum(int aValue, const UNITS_PROVIDER &aUnitsProvider)
Format a minimum distance, or "unknown" when no qualifying measurement was found.
void InitializeBoardStatisticsData(BOARD_STATISTICS_DATA &aData)
static void appendTable(const std::vector< std::vector< wxString > > &aRows, bool aUseFirstColAsLabel, wxString &aOut)
wxString GetBuildVersion()
Get the full KiCad version string.
std::shared_ptr< NET_SETTINGS > m_NetSettings
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
virtual void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const
Convert the item shape to a polyset.
int BuildBoardThicknessFromStackup() const
Information pertinent to a Pcbnew printed circuit board.
BOARD_STACKUP GetStackupOrDefault() const
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, bool aInferOutlineIfNecessary, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
BOARD_DESIGN_SETTINGS & GetDesignSettings()
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
KICAD_T Type() const
Returns the type of object.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
int Length() const
Return the length (this).
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
double Area(bool aAbsolute=true) const
Return the area of this chain.
Represent a set of closed polygons.
double Area()
Return the area of this poly set.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
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)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
int OutlineCount() const
Return the number of outlines in the set.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
Some functions to handle hotkeys in KiCad.
PCB_LAYER_ID
A quick note on layer IDs:
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
@ CASTELLATED
a pad with a castellated through hole
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
wxString GetISO8601CurrentDateTime()
int minClearanceTrackToTrack
std::vector< BOARD_STATISTICS_INFO_ENTRY< PAD_ATTRIB > > padEntries
double backFootprintCourtyardArea
double frontFootprintDensity
std::vector< BOARD_STATISTICS_FP_ENTRY > footprintEntries
std::vector< BOARD_STATISTICS_INFO_ENTRY< VIATYPE > > viaEntries
double backFootprintDensity
double frontFootprintCourtyardArea
std::vector< BOARD_STATISTICS_INFO_ENTRY< PAD_PROP > > padPropertyEntries
std::vector< DRILL_LINE_ITEM > drillEntries
bool subtractHolesFromCopperAreas
bool subtractHolesFromBoardArea
bool excludeFootprintsWithoutPads
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I