MergeDrawings.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**
  2. * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
  3. *
  4. * This file is part of the QCAD project.
  5. *
  6. * QCAD is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * QCAD is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with QCAD.
  18. */
  19. /**
  20. * Command line tool.
  21. * Merges multiple drawing files (DWG, DXF) into one.
  22. */
  23. include("scripts/Tools/arguments.js");
  24. function printHelp() {
  25. print("Usage: " + args[1] + " [OPTIONS]... <XML config file>");
  26. print();
  27. print("Merges multiple drawing files (DWG, DXF, ...) into one.");
  28. print();
  29. print(" -f, -force Overwrite existing output file");
  30. print(" -h, -help Display this help");
  31. print(" -t TYPE, -type=TYPE Set file type to TYPE ");
  32. print(" (e.g. R12...R27 or 2000...2013)");
  33. print(" -o FILE, -outfile=FILE Set output file to FILE");
  34. print(" default is same path and base name as input file");
  35. printGenericUsage();
  36. print();
  37. print("XML format:");
  38. print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  39. print("<merge xmlns=\"http://qcad.org/merge/elements/1.0/\" unit=\"Millimeter\">");
  40. print(" <item src=\"file1.dxf\">");
  41. print(" <insert x=\"10\" y=\"0\" angle=\"30\" flipx=\"false\" flipy=\"false\" />");
  42. print(" </item>");
  43. print("</merge>");
  44. print();
  45. }
  46. function main() {
  47. if (testArgument(args, "-h", "-help")) {
  48. printHelp();
  49. return;
  50. }
  51. if (args.length < 3) {
  52. print("No input file given. Try -h for help.");
  53. return;
  54. }
  55. qApp.organizationName = "QCAD";
  56. qApp.organizationDomain = "QCAD.org";
  57. qApp.applicationVersion = RSettings.getVersionString();
  58. qApp.applicationName = "QCAD";
  59. RSettings.setApplicationNameOverride("QCAD3");
  60. var xmlFile = args[args.length - 1];
  61. if (xmlFile.indexOf("-") === 0) {
  62. print("No input file. Try -h for help.");
  63. return;
  64. }
  65. include("scripts/ImportExport/SvgImporter/SvgImporterInit.js");
  66. RFileImporterRegistry.registerFileImporter(new SvgImporterFactory());
  67. var fi = new QFileInfo(xmlFile);
  68. if (!fi.isAbsolute()) {
  69. xmlFile = RSettings.getLaunchPath() + QDir.separator + xmlFile;
  70. fi = new QFileInfo(xmlFile);
  71. }
  72. var outputFile = getArgument(args, "-o", "-outfile");
  73. if (outputFile!==undefined) {
  74. if (!new QFileInfo(outputFile).isAbsolute()) {
  75. outputFile = RSettings.getLaunchPath() + QDir.separator + outputFile;
  76. }
  77. }
  78. else {
  79. outputFile = fi.absolutePath() + QDir.separator + fi.completeBaseName() + ".dxf";
  80. }
  81. if (new QFileInfo(outputFile).exists() && !testArgument(args, "-f", "-force")) {
  82. print("Output file exists already, not overwriting: ", outputFile);
  83. print("Use -f to force overwrite");
  84. return;
  85. }
  86. var type = getArgument(args, "-t", "-type");
  87. if (type===undefined) {
  88. type = "";
  89. }
  90. // parse XML into array:
  91. //var file = new QFile(xmlFile);
  92. //var xmlReader = new QXmlSimpleReader();
  93. //var source = new QXmlInputSource(file);
  94. var handler = new XmlHandler();
  95. //xmlReader.setContentHandler(handler);
  96. //var ok = xmlReader.parse(source, false);
  97. parseXml(xmlFile, handler);
  98. //file.close();
  99. // target document:
  100. var docDest = new RDocument(new RMemoryStorage(), new RSpatialIndexSimple());
  101. docDest.setUnit(handler.outputUnit);
  102. var diDest = new RDocumentInterface(docDest);
  103. for (var i=0; i<handler.items.length; i++) {
  104. var item = handler.items[i];
  105. for (var k=0; k<item.inserts.length; k++) {
  106. var insert = item.inserts[k];
  107. qDebug("insert: ", item.src, insert.x);
  108. var doc = new RDocument(new RMemoryStorage(), new RSpatialIndexSimple());
  109. var di = new RDocumentInterface(doc);
  110. var src;
  111. if (!new QFileInfo(item.src).isAbsolute()) {
  112. src = fi.absolutePath() + QDir.separator + item.src;
  113. }
  114. else {
  115. src = item.src;
  116. }
  117. if (di.importFile(src) !== RDocumentInterface.IoErrorNoError) {
  118. qWarning("cannot import file: ", src);
  119. }
  120. // input files without units are assumed to be in output unit:
  121. // if (doc.getUnit()===RS.None) {
  122. // qDebug("adjusting unit of unitless input file '%1' to '%2'.".arg(src).arg(RUnit.unitToName(handler.outputUnit)));
  123. // doc.setUnit(handler.outputUnit);
  124. // }
  125. var op = new RPasteOperation(doc);
  126. op.setOffset(new RVector(insert.x, insert.y));
  127. op.setRotation(insert.angle);
  128. op.setScale(insert.scale);
  129. op.setFlipHorizontal(insert.flipX);
  130. op.setFlipVertical(insert.flipY);
  131. op.setBlockName(new QFileInfo(src).completeBaseName());
  132. diDest.applyOperation(op);
  133. destr(di);
  134. }
  135. }
  136. diDest.exportFile(outputFile, type);
  137. print("Converting");
  138. print(" from: " + xmlFile);
  139. print(" to : " + outputFile);
  140. destr(diDest);
  141. }
  142. /**
  143. * SAX style XML handler.
  144. */
  145. function XmlHandler() {
  146. QXmlDefaultHandler.call(this);
  147. this.items = [];
  148. this.item = undefined;
  149. this.outputUnit = RS.Millimeter;
  150. }
  151. XmlHandler.prototype = new QXmlDefaultHandler();
  152. /**
  153. * Handle element (tag).
  154. */
  155. XmlHandler.prototype.startElement = function(namespaceURI, localName, qName, atts) {
  156. if (localName==="merge") {
  157. this.outputUnit = this.getUnitAttribute(atts, "unit", RS.Millimeter);
  158. }
  159. if (localName==="item") {
  160. this.item = {};
  161. this.item.src = atts.value("src");
  162. this.item.inserts = [];
  163. this.items.push(this.item);
  164. }
  165. if (localName==="insert") {
  166. if (this.item===undefined) {
  167. qWarning("insert element found outside of the scope of an item element");
  168. return false;
  169. }
  170. var insert = {};
  171. insert.x = this.getDoubleAttribute(atts, "x", 0);
  172. insert.y = this.getDoubleAttribute(atts, "y", 0);
  173. insert.angle = RMath.deg2rad(this.getDoubleAttribute(atts, "angle", 0));
  174. insert.scale = this.getDoubleAttribute(atts, "scale", 1.0);
  175. insert.flipX = this.getBoolAttribute(atts, "flipx", false);
  176. insert.flipY = this.getBoolAttribute(atts, "flipy", false);
  177. this.item.inserts.push(insert);
  178. }
  179. return true;
  180. };
  181. XmlHandler.prototype.getDoubleAttribute = function(atts, name, defaultValue) {
  182. var str = atts.value(name);
  183. if (str.length===0) {
  184. return defaultValue;
  185. }
  186. return parseFloat(str);
  187. };
  188. XmlHandler.prototype.getBoolAttribute = function(atts, name, defaultValue) {
  189. var str = atts.value(name).toLowerCase();
  190. if (str.length===0) {
  191. return defaultValue;
  192. }
  193. return str==="true" || str==="1";
  194. };
  195. XmlHandler.prototype.getUnitAttribute = function(atts, name, defaultValue) {
  196. var str = atts.value(name).toLowerCase();
  197. if (str.length===0) {
  198. return defaultValue;
  199. }
  200. return RUnit.parseUnit(str);
  201. };
  202. if (typeof(including)=='undefined' || including===false) {
  203. main();
  204. }