1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2014 Cirilo Bernardo
5 * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25 #include <iostream>
26 #include <fstream>
27 #include <string>
28 #include <sstream>
29 #include <cmath>
30 #include <cstdio>
31 #include <list>
32 #include <utility>
33 #include <clocale>
34
35 using namespace std;
36
37 void writeLeaded( FILE* fp, double width, double length, double wireDia, double pitch, bool inch );
38
39 void writeLeadless( FILE* fp, double width, double length, double chamfer, bool inch );
40
main(int argc,char ** argv)41 int main( int argc, char** argv )
42 {
43 // IDF implicitly requires the C locale
44 setlocale( LC_ALL, "C" );
45
46 if( argc == 1 )
47 {
48 cout << "idfrect: This program generates an outline for a rectangular component.\n";
49 cout << " The component may have a single lead (axial) or a chamfer on the\n";
50 cout << " upper left corner.\n";
51 cout << "Input:\n";
52 cout << " Unit: mm, in (millimeters or inches)\n";
53 cout << " Width:\n";
54 cout << " Length:\n";
55 cout << " Height:\n";
56 cout << " Chamfer: length of the 45 deg. chamfer\n";
57 cout << " * Leaded: Y,N (lead is always to the right)\n";
58 cout << " ** Wire diameter\n";
59 cout << " ** Pitch\n";
60 cout << " File name (must end in *.idf)\n\n";
61 cout << " NOTES:\n";
62 cout << " * only required if chamfer = 0\n\n";
63 cout << " ** only required for leaded components\n\n";
64 }
65
66 bool inch = false; // default mm
67 double width = 0.0;
68 double length = 0.0;
69 double height = 0.0;
70 double wireDia = 0.0;
71 double pitch = 0.0;
72 double chamfer = 0.0;
73 bool leaded = false;
74 bool ok = false;
75
76 stringstream tstr;
77 string line;
78
79 line.clear();
80
81 while( line.compare( "mm" ) && line.compare( "in" ) )
82 {
83 cout << "* Units (mm,in): ";
84 line.clear();
85 std::getline( cin, line );
86 }
87
88 if( line.compare( "mm" ) )
89 inch = true;
90
91 ok = false;
92
93 while( !ok )
94 {
95 cout << "* Width: ";
96
97 line.clear();
98 std::getline( cin, line );
99
100 tstr.clear();
101 tstr.str( line );
102
103 tstr >> width;
104
105 if( !tstr.fail() && width >= 0.001 )
106 ok = true;
107 }
108
109 ok = false;
110
111 while( !ok )
112 {
113 cout << "* Length: ";
114
115 line.clear();
116 std::getline( cin, line );
117
118 tstr.clear();
119 tstr.str( line );
120
121 tstr >> length;
122
123 if( !tstr.fail() && length > 0.0 )
124 ok = true;
125 }
126
127 ok = false;
128
129 while( !ok )
130 {
131 cout << "* Height: ";
132
133 line.clear();
134 std::getline( cin, line );
135
136 tstr.clear();
137 tstr.str( line );
138
139 tstr >> height;
140
141 if( !tstr.fail() && height >= 0.001 )
142 ok = true;
143 }
144
145 ok = false;
146
147 while( !ok )
148 {
149 cout << "* Chamfer (0 for none): ";
150
151 line.clear();
152 std::getline( cin, line );
153
154 tstr.clear();
155 tstr.str( line );
156
157 tstr >> chamfer;
158
159 if( !tstr.fail() && chamfer >= 0.0 )
160 {
161 if( chamfer > width / 3.0 || chamfer > length / 3.0 )
162 cout << "* WARNING: chamfer must be <= MIN( width, length )/3\n";
163 else
164 ok = true;
165 }
166 }
167
168 if( chamfer < 1e-6 )
169 {
170 ok = false;
171
172 while( !ok )
173 {
174 cout << "* Leaded: Y, N: ";
175
176 line.clear();
177 std::getline( cin, line );
178
179 if( !line.compare( "Y" ) || !line.compare( "y" ) )
180 {
181 leaded = true;
182 ok = true;
183 }
184 else if( !line.compare( "N" ) || !line.compare( "n" ) )
185 {
186 leaded = false;
187 ok = true;
188 }
189 }
190 }
191
192 ok = false;
193
194 while( leaded && !ok )
195 {
196 cout << "* Wire dia.: ";
197
198 line.clear();
199 std::getline( cin, line );
200
201 tstr.clear();
202 tstr.str( line );
203
204 tstr >> wireDia;
205
206 if( !tstr.fail() && wireDia >= 0.001 )
207 {
208 if( wireDia >= length )
209 cout << "* WARNING: wire diameter must be < length\n";
210 else
211 ok = true;
212 }
213 }
214
215 ok = false;
216
217 while( leaded && !ok )
218 {
219 cout << "* Pitch: ";
220
221 line.clear();
222 std::getline( cin, line );
223
224 tstr.clear();
225 tstr.str( line );
226
227 tstr >> pitch;
228
229 if( !tstr.fail() && pitch >= 0.001 )
230 {
231 if( pitch <= ( length + wireDia ) / 2.0 )
232 cout << "* WARNING: pitch must be > (length + wireDia)/2\n";
233 else
234 ok = true;
235 }
236 }
237
238 line.clear();
239
240 while( line.empty() || line.find( ".idf" ) == string::npos )
241 {
242 cout << "* File name (*.idf): ";
243
244 line.clear();
245 std::getline( cin, line );
246 }
247
248 FILE* fp = fopen( line.c_str(), "w" );
249
250 if( !fp )
251 {
252 cerr << "Could not open output file: " << line << "\n";
253 }
254 else
255 {
256 fprintf( fp, "# rectangular outline%s\n", leaded ? ", leaded" : "" );
257 fprintf( fp, "# file: \"%s\"\n", line.c_str() );
258
259 if( inch )
260 {
261 width *= 1000.0;
262 length *= 1000.0;
263 height *= 1000.0;
264 wireDia *= 1000.0;
265 pitch *= 1000.0;
266 chamfer *= 1000.0;
267
268 fprintf( fp, "# width: %d THOU\n", (int) width );
269 fprintf( fp, "# length: %d THOU\n", (int) length );
270 fprintf( fp, "# height: %d THOU\n", (int) height );
271
272 if( leaded )
273 {
274 fprintf( fp, "# wire dia: %d THOU\n", (int) wireDia );
275 fprintf( fp, "# pitch: %d THOU\n", (int) pitch );
276 }
277 else
278 {
279 fprintf( fp, "# chamfer: %d THOU\n", (int) chamfer );
280 }
281
282 fprintf( fp, ".ELECTRICAL\n" );
283 fprintf( fp, "\"RECT%sIN\" \"W%d_L%d_H%d", leaded ? "L" : "", (int) width, (int) length,
284 (int) height );
285
286 if( leaded )
287 fprintf( fp, "_D%d_P%d\" ", (int) wireDia, (int) pitch );
288 else
289 fprintf( fp, "_C%d\" ", (int) chamfer );
290
291 fprintf( fp, "THOU %d\n", (int) height );
292 }
293 else
294 {
295 fprintf( fp, "# width: %.3f mm\n", width );
296 fprintf( fp, "# length: %.3f mm\n", length );
297 fprintf( fp, "# height: %.3f mm\n", height );
298
299 if( leaded )
300 {
301 fprintf( fp, "# wire dia: %.3f mm\n", wireDia );
302 fprintf( fp, "# pitch: %.3f mm\n", pitch );
303 }
304 else
305 {
306 fprintf( fp, "# chamfer: %.3f mm\n", chamfer );
307 }
308
309 fprintf( fp, ".ELECTRICAL\n" );
310 fprintf( fp, "\"RECT%sMM\" \"W%.3f_L%.3f_H%.3f_", leaded ? "L" : "", width, length,
311 height );
312
313 if( leaded )
314 fprintf( fp, "D%.3f_P%.3f\" ", wireDia, pitch );
315 else
316 fprintf( fp, "C%.3f\" ", chamfer );
317
318 fprintf( fp, "MM %.3f\n", height );
319 }
320
321 if( leaded )
322 writeLeaded( fp, width, length, wireDia, pitch, inch );
323 else
324 writeLeadless( fp, width, length, chamfer, inch );
325
326 fprintf( fp, ".END_ELECTRICAL\n" );
327 fclose( fp );
328 }
329
330 setlocale( LC_ALL, "" );
331 return 0;
332 }
333
334
writeLeaded(FILE * fp,double width,double length,double wireDia,double pitch,bool inch)335 void writeLeaded( FILE* fp, double width, double length, double wireDia, double pitch, bool inch )
336 {
337 if( inch )
338 {
339 int x1, x2, x3;
340 int y1, y2;
341
342 x1 = static_cast<int>( pitch / 2.0 );
343 x2 = static_cast<int>( width / 2.0 - x1 );
344 x3 = static_cast<int>( x2 - width );
345
346 y1 = static_cast<int>( wireDia / 2.0 );
347 y2 = static_cast<int>( length / 2.0 );
348
349 fprintf( fp, "0 %d %d 0\n", x1, y1 );
350 fprintf( fp, "0 %d %d 0\n", x2, y1 );
351 fprintf( fp, "0 %d %d 0\n", x2, y2 );
352 fprintf( fp, "0 %d %d 0\n", x3, y2 );
353 fprintf( fp, "0 %d %d 0\n", x3, -y2 );
354 fprintf( fp, "0 %d %d 0\n", x2, -y2 );
355 fprintf( fp, "0 %d %d 0\n", x2, -y1 );
356 fprintf( fp, "0 %d %d 0\n", x1, -y1 );
357 fprintf( fp, "0 %d %d 180\n", x1, y1 );
358 }
359 else
360 {
361 double x1, x2, x3;
362 double y1, y2;
363
364 x1 = pitch / 2.0;
365 x2 = width / 2.0 - x1;
366 x3 = x2 - width;
367
368 y1 = wireDia / 2.0;
369 y2 = length / 2.0;
370
371 fprintf( fp, "0 %.3f %.3f 0\n", x1, y1 );
372 fprintf( fp, "0 %.3f %.3f 0\n", x2, y1 );
373 fprintf( fp, "0 %.3f %.3f 0\n", x2, y2 );
374 fprintf( fp, "0 %.3f %.3f 0\n", x3, y2 );
375 fprintf( fp, "0 %.3f %.3f 0\n", x3, -y2 );
376 fprintf( fp, "0 %.3f %.3f 0\n", x2, -y2 );
377 fprintf( fp, "0 %.3f %.3f 0\n", x2, -y1 );
378 fprintf( fp, "0 %.3f %.3f 0\n", x1, -y1 );
379 fprintf( fp, "0 %.3f %.3f 180\n", x1, y1 );
380 }
381 }
382
383
writeLeadless(FILE * fp,double width,double length,double chamfer,bool inch)384 void writeLeadless( FILE* fp, double width, double length, double chamfer, bool inch )
385 {
386 if( chamfer < 0.001 )
387 {
388 if( inch )
389 {
390 int x = static_cast<int>( width / 2.0 );
391 int y = static_cast<int>( length / 2.0 );
392
393 fprintf( fp, "0 %d %d 0\n", x, y );
394 fprintf( fp, "0 %d %d 0\n", -x, y );
395 fprintf( fp, "0 %d %d 0\n", -x, -y );
396 fprintf( fp, "0 %d %d 0\n", x, -y );
397 fprintf( fp, "0 %d %d 0\n", x, y );
398 }
399 else
400 {
401 double x = width / 2.0;
402 double y = length / 2.0;
403
404 fprintf( fp, "0 %.3f %.3f 0\n", x, y );
405 fprintf( fp, "0 %.3f %.3f 0\n", -x, y );
406 fprintf( fp, "0 %.3f %.3f 0\n", -x, -y );
407 fprintf( fp, "0 %.3f %.3f 0\n", x, -y );
408 fprintf( fp, "0 %.3f %.3f 0\n", x, y );
409 }
410
411 return;
412 }
413
414 if( inch )
415 {
416 int x = static_cast<int>( width / 2.0 );
417 int y = static_cast<int>( length / 2.0 );
418 int x1 = static_cast<int>( x - chamfer );
419 int y1 = static_cast<int>( y - chamfer );
420
421 fprintf( fp, "0 %d %d 0\n", x, y );
422 fprintf( fp, "0 %d %d 0\n", -x1, y );
423 fprintf( fp, "0 %d %d 0\n", -x, y1 );
424 fprintf( fp, "0 %d %d 0\n", -x, -y );
425 fprintf( fp, "0 %d %d 0\n", x, -y );
426 fprintf( fp, "0 %d %d 0\n", x, y );
427 }
428 else
429 {
430 double x = width / 2.0;
431 double y = length / 2.0;
432 double x1 = x - chamfer;
433 double y1 = y - chamfer;
434
435 fprintf( fp, "0 %.3f %.3f 0\n", x, y );
436 fprintf( fp, "0 %.3f %.3f 0\n", -x1, y );
437 fprintf( fp, "0 %.3f %.3f 0\n", -x, y1 );
438 fprintf( fp, "0 %.3f %.3f 0\n", -x, -y );
439 fprintf( fp, "0 %.3f %.3f 0\n", x, -y );
440 fprintf( fp, "0 %.3f %.3f 0\n", x, y );
441 }
442 }
443