You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

442 lines
12 KiB

  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 The 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. #include <iostream>
  25. #include <fstream>
  26. #include <string>
  27. #include <sstream>
  28. #include <cmath>
  29. #include <cstdio>
  30. #include <list>
  31. #include <utility>
  32. #include <clocale>
  33. using namespace std;
  34. void writeLeaded( FILE* fp, double width, double length, double wireDia, double pitch, bool inch );
  35. void writeLeadless( FILE* fp, double width, double length, double chamfer, bool inch );
  36. int main( int argc, char** argv )
  37. {
  38. // IDF implicitly requires the C locale
  39. setlocale( LC_ALL, "C" );
  40. if( argc == 1 )
  41. {
  42. cout << "idfrect: This program generates an outline for a rectangular component.\n";
  43. cout << " The component may have a single lead (axial) or a chamfer on the\n";
  44. cout << " upper left corner.\n";
  45. cout << "Input:\n";
  46. cout << " Unit: mm, in (millimeters or inches)\n";
  47. cout << " Width:\n";
  48. cout << " Length:\n";
  49. cout << " Height:\n";
  50. cout << " Chamfer: length of the 45 deg. chamfer\n";
  51. cout << " * Leaded: Y,N (lead is always to the right)\n";
  52. cout << " ** Wire diameter\n";
  53. cout << " ** Pitch\n";
  54. cout << " File name (must end in *.idf)\n\n";
  55. cout << " NOTES:\n";
  56. cout << " * only required if chamfer = 0\n\n";
  57. cout << " ** only required for leaded components\n\n";
  58. }
  59. bool inch = false; // default mm
  60. double width = 0.0;
  61. double length = 0.0;
  62. double height = 0.0;
  63. double wireDia = 0.0;
  64. double pitch = 0.0;
  65. double chamfer = 0.0;
  66. bool leaded = false;
  67. bool ok = false;
  68. stringstream tstr;
  69. string line;
  70. line.clear();
  71. while( line.compare( "mm" ) && line.compare( "in" ) )
  72. {
  73. cout << "* Units (mm,in): ";
  74. line.clear();
  75. std::getline( cin, line );
  76. }
  77. if( line.compare( "mm" ) )
  78. inch = true;
  79. ok = false;
  80. while( !ok )
  81. {
  82. cout << "* Width: ";
  83. line.clear();
  84. std::getline( cin, line );
  85. tstr.clear();
  86. tstr.str( line );
  87. tstr >> width;
  88. if( !tstr.fail() && width >= 0.001 )
  89. ok = true;
  90. }
  91. ok = false;
  92. while( !ok )
  93. {
  94. cout << "* Length: ";
  95. line.clear();
  96. std::getline( cin, line );
  97. tstr.clear();
  98. tstr.str( line );
  99. tstr >> length;
  100. if( !tstr.fail() && length > 0.0 )
  101. ok = true;
  102. }
  103. ok = false;
  104. while( !ok )
  105. {
  106. cout << "* Height: ";
  107. line.clear();
  108. std::getline( cin, line );
  109. tstr.clear();
  110. tstr.str( line );
  111. tstr >> height;
  112. if( !tstr.fail() && height >= 0.001 )
  113. ok = true;
  114. }
  115. ok = false;
  116. while( !ok )
  117. {
  118. cout << "* Chamfer (0 for none): ";
  119. line.clear();
  120. std::getline( cin, line );
  121. tstr.clear();
  122. tstr.str( line );
  123. tstr >> chamfer;
  124. if( !tstr.fail() && chamfer >= 0.0 )
  125. {
  126. if( chamfer > width / 3.0 || chamfer > length / 3.0 )
  127. cout << "* WARNING: chamfer must be <= MIN( width, length )/3\n";
  128. else
  129. ok = true;
  130. }
  131. }
  132. if( chamfer < 1e-6 )
  133. {
  134. ok = false;
  135. while( !ok )
  136. {
  137. cout << "* Leaded: Y, N: ";
  138. line.clear();
  139. std::getline( cin, line );
  140. if( !line.compare( "Y" ) || !line.compare( "y" ) )
  141. {
  142. leaded = true;
  143. ok = true;
  144. }
  145. else if( !line.compare( "N" ) || !line.compare( "n" ) )
  146. {
  147. leaded = false;
  148. ok = true;
  149. }
  150. }
  151. }
  152. ok = false;
  153. while( leaded && !ok )
  154. {
  155. cout << "* Wire dia.: ";
  156. line.clear();
  157. std::getline( cin, line );
  158. tstr.clear();
  159. tstr.str( line );
  160. tstr >> wireDia;
  161. if( !tstr.fail() && wireDia >= 0.001 )
  162. {
  163. if( wireDia >= length )
  164. cout << "* WARNING: wire diameter must be < length\n";
  165. else
  166. ok = true;
  167. }
  168. }
  169. ok = false;
  170. while( leaded && !ok )
  171. {
  172. cout << "* Pitch: ";
  173. line.clear();
  174. std::getline( cin, line );
  175. tstr.clear();
  176. tstr.str( line );
  177. tstr >> pitch;
  178. if( !tstr.fail() && pitch >= 0.001 )
  179. {
  180. if( pitch <= ( length + wireDia ) / 2.0 )
  181. cout << "* WARNING: pitch must be > (length + wireDia)/2\n";
  182. else
  183. ok = true;
  184. }
  185. }
  186. line.clear();
  187. while( line.empty() || line.find( ".idf" ) == string::npos )
  188. {
  189. cout << "* File name (*.idf): ";
  190. line.clear();
  191. std::getline( cin, line );
  192. }
  193. FILE* fp = fopen( line.c_str(), "w" );
  194. if( !fp )
  195. {
  196. cerr << "Could not open output file: " << line << "\n";
  197. }
  198. else
  199. {
  200. fprintf( fp, "# rectangular outline%s\n", leaded ? ", leaded" : "" );
  201. fprintf( fp, "# file: \"%s\"\n", line.c_str() );
  202. if( inch )
  203. {
  204. width *= 1000.0;
  205. length *= 1000.0;
  206. height *= 1000.0;
  207. wireDia *= 1000.0;
  208. pitch *= 1000.0;
  209. chamfer *= 1000.0;
  210. fprintf( fp, "# width: %d THOU\n", (int) width );
  211. fprintf( fp, "# length: %d THOU\n", (int) length );
  212. fprintf( fp, "# height: %d THOU\n", (int) height );
  213. if( leaded )
  214. {
  215. fprintf( fp, "# wire dia: %d THOU\n", (int) wireDia );
  216. fprintf( fp, "# pitch: %d THOU\n", (int) pitch );
  217. }
  218. else
  219. {
  220. fprintf( fp, "# chamfer: %d THOU\n", (int) chamfer );
  221. }
  222. fprintf( fp, ".ELECTRICAL\n" );
  223. fprintf( fp, "\"RECT%sIN\" \"W%d_L%d_H%d", leaded ? "L" : "", (int) width, (int) length,
  224. (int) height );
  225. if( leaded )
  226. fprintf( fp, "_D%d_P%d\" ", (int) wireDia, (int) pitch );
  227. else
  228. fprintf( fp, "_C%d\" ", (int) chamfer );
  229. fprintf( fp, "THOU %d\n", (int) height );
  230. }
  231. else
  232. {
  233. fprintf( fp, "# width: %.3f mm\n", width );
  234. fprintf( fp, "# length: %.3f mm\n", length );
  235. fprintf( fp, "# height: %.3f mm\n", height );
  236. if( leaded )
  237. {
  238. fprintf( fp, "# wire dia: %.3f mm\n", wireDia );
  239. fprintf( fp, "# pitch: %.3f mm\n", pitch );
  240. }
  241. else
  242. {
  243. fprintf( fp, "# chamfer: %.3f mm\n", chamfer );
  244. }
  245. fprintf( fp, ".ELECTRICAL\n" );
  246. fprintf( fp, "\"RECT%sMM\" \"W%.3f_L%.3f_H%.3f_", leaded ? "L" : "", width, length,
  247. height );
  248. if( leaded )
  249. fprintf( fp, "D%.3f_P%.3f\" ", wireDia, pitch );
  250. else
  251. fprintf( fp, "C%.3f\" ", chamfer );
  252. fprintf( fp, "MM %.3f\n", height );
  253. }
  254. if( leaded )
  255. writeLeaded( fp, width, length, wireDia, pitch, inch );
  256. else
  257. writeLeadless( fp, width, length, chamfer, inch );
  258. fprintf( fp, ".END_ELECTRICAL\n" );
  259. fclose( fp );
  260. }
  261. setlocale( LC_ALL, "" );
  262. return 0;
  263. }
  264. void writeLeaded( FILE* fp, double width, double length, double wireDia, double pitch, bool inch )
  265. {
  266. if( inch )
  267. {
  268. int x1, x2, x3;
  269. int y1, y2;
  270. x1 = static_cast<int>( pitch / 2.0 );
  271. x2 = static_cast<int>( width / 2.0 - x1 );
  272. x3 = static_cast<int>( x2 - width );
  273. y1 = static_cast<int>( wireDia / 2.0 );
  274. y2 = static_cast<int>( length / 2.0 );
  275. fprintf( fp, "0 %d %d 0\n", x1, y1 );
  276. fprintf( fp, "0 %d %d 0\n", x2, y1 );
  277. fprintf( fp, "0 %d %d 0\n", x2, y2 );
  278. fprintf( fp, "0 %d %d 0\n", x3, y2 );
  279. fprintf( fp, "0 %d %d 0\n", x3, -y2 );
  280. fprintf( fp, "0 %d %d 0\n", x2, -y2 );
  281. fprintf( fp, "0 %d %d 0\n", x2, -y1 );
  282. fprintf( fp, "0 %d %d 0\n", x1, -y1 );
  283. fprintf( fp, "0 %d %d 180\n", x1, y1 );
  284. }
  285. else
  286. {
  287. double x1, x2, x3;
  288. double y1, y2;
  289. x1 = pitch / 2.0;
  290. x2 = width / 2.0 - x1;
  291. x3 = x2 - width;
  292. y1 = wireDia / 2.0;
  293. y2 = length / 2.0;
  294. fprintf( fp, "0 %.3f %.3f 0\n", x1, y1 );
  295. fprintf( fp, "0 %.3f %.3f 0\n", x2, y1 );
  296. fprintf( fp, "0 %.3f %.3f 0\n", x2, y2 );
  297. fprintf( fp, "0 %.3f %.3f 0\n", x3, y2 );
  298. fprintf( fp, "0 %.3f %.3f 0\n", x3, -y2 );
  299. fprintf( fp, "0 %.3f %.3f 0\n", x2, -y2 );
  300. fprintf( fp, "0 %.3f %.3f 0\n", x2, -y1 );
  301. fprintf( fp, "0 %.3f %.3f 0\n", x1, -y1 );
  302. fprintf( fp, "0 %.3f %.3f 180\n", x1, y1 );
  303. }
  304. }
  305. void writeLeadless( FILE* fp, double width, double length, double chamfer, bool inch )
  306. {
  307. if( chamfer < 0.001 )
  308. {
  309. if( inch )
  310. {
  311. int x = static_cast<int>( width / 2.0 );
  312. int y = static_cast<int>( length / 2.0 );
  313. fprintf( fp, "0 %d %d 0\n", x, y );
  314. fprintf( fp, "0 %d %d 0\n", -x, y );
  315. fprintf( fp, "0 %d %d 0\n", -x, -y );
  316. fprintf( fp, "0 %d %d 0\n", x, -y );
  317. fprintf( fp, "0 %d %d 0\n", x, y );
  318. }
  319. else
  320. {
  321. double x = width / 2.0;
  322. double y = length / 2.0;
  323. fprintf( fp, "0 %.3f %.3f 0\n", x, y );
  324. fprintf( fp, "0 %.3f %.3f 0\n", -x, y );
  325. fprintf( fp, "0 %.3f %.3f 0\n", -x, -y );
  326. fprintf( fp, "0 %.3f %.3f 0\n", x, -y );
  327. fprintf( fp, "0 %.3f %.3f 0\n", x, y );
  328. }
  329. return;
  330. }
  331. if( inch )
  332. {
  333. int x = static_cast<int>( width / 2.0 );
  334. int y = static_cast<int>( length / 2.0 );
  335. int x1 = static_cast<int>( x - chamfer );
  336. int y1 = static_cast<int>( y - chamfer );
  337. fprintf( fp, "0 %d %d 0\n", x, y );
  338. fprintf( fp, "0 %d %d 0\n", -x1, y );
  339. fprintf( fp, "0 %d %d 0\n", -x, y1 );
  340. fprintf( fp, "0 %d %d 0\n", -x, -y );
  341. fprintf( fp, "0 %d %d 0\n", x, -y );
  342. fprintf( fp, "0 %d %d 0\n", x, y );
  343. }
  344. else
  345. {
  346. double x = width / 2.0;
  347. double y = length / 2.0;
  348. double x1 = x - chamfer;
  349. double y1 = y - chamfer;
  350. fprintf( fp, "0 %.3f %.3f 0\n", x, y );
  351. fprintf( fp, "0 %.3f %.3f 0\n", -x1, y );
  352. fprintf( fp, "0 %.3f %.3f 0\n", -x, y1 );
  353. fprintf( fp, "0 %.3f %.3f 0\n", -x, -y );
  354. fprintf( fp, "0 %.3f %.3f 0\n", x, -y );
  355. fprintf( fp, "0 %.3f %.3f 0\n", x, y );
  356. }
  357. }