KiCad PCB EDA Suite
Loading...
Searching...
No Matches
extract_zone_fills.cpp
Go to the documentation of this file.
1/*
2 * This program is part of KiCad, a free EDA CAD application.
3 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
20
23
24#include <board.h>
25#include <zone.h>
26#include <layer_ids.h>
27
28#include <filesystem>
29#include <fstream>
30#include <iostream>
31#include <memory>
32#include <sstream>
33#include <string>
34#include <vector>
35
36namespace fs = std::filesystem;
37
38
39static std::string SerializePolySet( const SHAPE_POLY_SET& aPolySet )
40{
41 std::ostringstream ss;
42
43 ss << "polyset " << aPolySet.OutlineCount() << "\n";
44
45 for( int i = 0; i < aPolySet.OutlineCount(); i++ )
46 {
47 const SHAPE_POLY_SET::POLYGON& poly = aPolySet.CPolygon( i );
48
49 ss << "poly " << poly.size() << "\n";
50
51 for( const SHAPE_LINE_CHAIN& chain : poly )
52 {
53 ss << chain.PointCount() << "\n";
54
55 for( int k = 0; k < chain.PointCount(); k++ )
56 {
57 const VECTOR2I& pt = chain.CPoint( k );
58 ss << pt.x << " " << pt.y << "\n";
59 }
60 }
61 }
62
63 return ss.str();
64}
65
66
67static void CollectBoardFiles( const fs::path& aPath, std::vector<fs::path>& aOut )
68{
69 if( fs::is_regular_file( aPath ) && aPath.extension() == ".kicad_pcb" )
70 {
71 aOut.push_back( aPath );
72 }
73 else if( fs::is_directory( aPath ) )
74 {
75 for( const auto& entry : fs::recursive_directory_iterator( aPath ) )
76 {
77 if( entry.is_regular_file() && entry.path().extension() == ".kicad_pcb" )
78 aOut.push_back( entry.path() );
79 }
80 }
81}
82
83
84static int extract_zone_fills_main( int argc, char* argv[] )
85{
86 std::string outputDir = ".";
87 std::vector<std::string> inputs;
88
89 for( int i = 1; i < argc; i++ )
90 {
91 std::string arg = argv[i];
92
93 if( arg == "--output-dir" && i + 1 < argc )
94 {
95 outputDir = argv[++i];
96 }
97 else
98 {
99 inputs.push_back( arg );
100 }
101 }
102
103 if( inputs.empty() )
104 {
105 std::cerr << "Usage: qa_pcbnew_tools extract_zone_fills [--output-dir <dir>] "
106 "<board_or_dir> [board_or_dir ...]\n";
108 }
109
110 fs::create_directories( outputDir );
111
112 std::vector<fs::path> boardFiles;
113
114 for( const auto& input : inputs )
115 CollectBoardFiles( input, boardFiles );
116
117 std::cout << "Found " << boardFiles.size() << " board files\n";
118
119 int totalZones = 0;
120 int boardsWithData = 0;
121
122 for( const auto& boardPath : boardFiles )
123 {
124 std::unique_ptr<BOARD> board;
125
126 try
127 {
128 board = KI_TEST::ReadBoardFromFileOrStream( boardPath.string() );
129 }
130 catch( const std::exception& e )
131 {
132 std::cerr << "Error loading " << boardPath << ": " << e.what() << "\n";
133 continue;
134 }
135
136 if( !board )
137 {
138 std::cerr << "Failed to load: " << boardPath << "\n";
139 continue;
140 }
141
142 std::ostringstream fileContent;
143 int zonesInBoard = 0;
144 std::string boardName = boardPath.stem().string();
145
146 fileContent << "(zone_fills\n";
147 fileContent << " (source \"" << boardPath.filename().string() << "\")\n";
148
149 for( ZONE* zone : board->Zones() )
150 {
151 if( zone->GetIsRuleArea() )
152 continue;
153
154 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
155 {
156 auto poly = zone->GetFilledPolysList( layer );
157
158 if( !poly || poly->OutlineCount() == 0 )
159 continue;
160
161 fileContent << " (zone (layer \"" << LayerName( layer ).ToStdString() << "\")";
162 fileContent << " (net \"" << zone->GetNetname().ToStdString() << "\")";
163 fileContent << " (outline_count " << poly->OutlineCount() << ")";
164
165 int vertexCount = 0;
166
167 for( int i = 0; i < poly->OutlineCount(); i++ )
168 {
169 const auto& polygon = poly->CPolygon( i );
170
171 for( const SHAPE_LINE_CHAIN& chain : polygon )
172 vertexCount += chain.PointCount();
173 }
174
175 fileContent << " (vertex_count " << vertexCount << ")\n";
176 fileContent << " (polyset\n";
177 fileContent << SerializePolySet( *poly );
178 fileContent << " )\n";
179 fileContent << " )\n";
180
181 zonesInBoard++;
182 }
183 }
184
185 fileContent << ")\n";
186
187 if( zonesInBoard > 0 )
188 {
189 fs::path outPath = fs::path( outputDir ) / ( boardName + ".kicad_polys" );
190 std::ofstream out( outPath );
191 out << fileContent.str();
192 out.close();
193
194 std::cout << boardPath.filename() << " -> " << zonesInBoard << " zones\n";
195 totalZones += zonesInBoard;
196 boardsWithData++;
197 }
198 }
199
200 std::cout << "\nExtracted " << totalZones << " zones from "
201 << boardsWithData << " boards\n";
202
204}
205
206
208 "extract_zone_fills",
209 "Extract zone fill polygons from boards for triangulation benchmarking",
211} );
General utilities for PCB file IO for QA programs.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
int OutlineCount() const
Return the number of outlines in the set.
const POLYGON & CPolygon(int aIndex) const
static bool Register(const KI_TEST::UTILITY_PROGRAM &aProgInfo)
Register a utility program factory function against an ID string.
Handle a list of polygons defining a copper zone.
Definition zone.h:74
static bool registered
static int extract_zone_fills_main(int argc, char *argv[])
static std::string SerializePolySet(const SHAPE_POLY_SET &aPolySet)
static void CollectBoardFiles(const fs::path &aPath, std::vector< fs::path > &aOut)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
Definition layer_id.cpp:31
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
std::unique_ptr< BOARD > ReadBoardFromFileOrStream(const std::string &aFilename, std::istream &aFallback)
Read a board from a file, or another stream, as appropriate.
@ OK
Tool exited OK.
@ BAD_CMDLINE
The command line was not correct for the tool.
const SHAPE_LINE_CHAIN chain
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687