LineDove.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /**
  2. * Copyright (c) 2017 by Christian Aigner, inspired by Matthias Melcher's LineDove script. All rights reserved.
  3. *
  4. * This file is an extension of the QCAD project.
  5. *
  6. * LineDove 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. * LineDove 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. include("scripts/EAction.js");
  20. /**
  21. * \class LineDove
  22. * \brief Dovetail joint line between two points.
  23. * \ingroup ecma_misc_draw
  24. */
  25. function LineDove(guiAction) {
  26. EAction.call(this, guiAction);
  27. this.corner1 = undefined;
  28. this.corner2 = undefined;
  29. this.dovetailNumber = undefined;
  30. this.dovetailHeight = undefined;
  31. this.dovetailGradient = undefined;
  32. this.pinRatio = undefined;
  33. this.setUiOptions("LineDove.ui");
  34. }
  35. LineDove.prototype = new EAction();
  36. LineDove.State = {
  37. SettingCorner1 : 0,
  38. SettingCorner2 : 1
  39. };
  40. LineDove.prototype.beginEvent = function() {
  41. EAction.prototype.beginEvent.call(this);
  42. this.setState(LineDove.State.SettingCorner1);
  43. };
  44. LineDove.prototype.setState = function(state) {
  45. EAction.prototype.setState.call(this, state);
  46. this.getDocumentInterface().setClickMode(RAction.PickCoordinate);
  47. this.setCrosshairCursor();
  48. var appWin = RMainWindowQt.getMainWindow();
  49. switch (this.state) {
  50. case LineDove.State.SettingCorner1:
  51. var trCorner1 = qsTr("First point");
  52. this.setCommandPrompt(trCorner1);
  53. this.setLeftMouseTip(trCorner1);
  54. this.setRightMouseTip(EAction.trCancel);
  55. break;
  56. case LineDove.State.SettingCorner2:
  57. var trCorner2 = qsTr("Second point");
  58. this.setCommandPrompt(trCorner2);
  59. this.setLeftMouseTip(trCorner2);
  60. this.setRightMouseTip(EAction.trDone);
  61. break;
  62. }
  63. EAction.showSnapTools();
  64. };
  65. LineDove.prototype.escapeEvent = function() {
  66. switch (this.state) {
  67. case LineDove.State.SettingCorner1:
  68. EAction.prototype.escapeEvent.call(this);
  69. break;
  70. case LineDove.State.SettingCorner2:
  71. this.setState(LineDove.State.SettingCorner1);
  72. break;
  73. }
  74. };
  75. LineDove.prototype.pickCoordinate = function(event, preview) {
  76. var di = this.getDocumentInterface();
  77. switch (this.state) {
  78. case LineDove.State.SettingCorner1:
  79. this.corner1 = event.getModelPosition();
  80. if (!preview) {
  81. di.setRelativeZero(this.corner1);
  82. //di.repaintViews();
  83. this.setState(LineDove.State.SettingCorner2);
  84. }
  85. break;
  86. case LineDove.State.SettingCorner2:
  87. this.corner2 = event.getModelPosition();
  88. if (preview) {
  89. this.updatePreview();
  90. }
  91. else {
  92. var op = this.getOperation(false);
  93. if (!isNull(op)) {
  94. di.applyOperation(op);
  95. di.setRelativeZero(this.corner2);
  96. this.setState(LineDove.State.SettingCorner1);
  97. }
  98. }
  99. break;
  100. }
  101. };
  102. LineDove.prototype.getOperation = function(preview) {
  103. if (isNull(this.corner1) || isNull(this.corner2)) {
  104. return undefined;
  105. }
  106. var c1 = this.corner1;
  107. var c2 = this.corner2;
  108. // get values from UI
  109. var nDovetails = this.dovetailNumber;
  110. var hDovetail = this.dovetailHeight;
  111. var gradient = this.dovetailGradient;
  112. var ratio = this.pinRatio;
  113. /*
  114. qDebug("nDovetails", nDovetails);
  115. qDebug("hDovetail", hDovetail);
  116. qDebug("gradient", gradient);
  117. qDebug("ratio", ratio);
  118. qDebug("-------------------------------------------------------");
  119. */
  120. // distance and angle between start and end point
  121. var boardwidth = this.corner1.getDistanceTo(this.corner2);
  122. var angle = this.corner1.getAngleTo(this.corner2);
  123. // distance from start of one dovetail to the next dovetail
  124. var period = boardwidth/nDovetails;
  125. // length under dovetail slope
  126. var lUnderDovetailSlope = hDovetail/gradient;
  127. // length of dovetail top
  128. var lDovetailTop = (period+2*lUnderDovetailSlope)/(1+1/ratio);
  129. // length of pin bottom
  130. var lPinBottom = lDovetailTop/ratio;
  131. // length of pin top
  132. var lPinTop = lPinBottom-2*lUnderDovetailSlope;
  133. // distance from Dovetail Bottom to Border
  134. var ldovetailBottomToBorder = lPinBottom/2;
  135. // distance from Dovetail Top to Border
  136. var ldovetailTopToBorder = ldovetailBottomToBorder-lUnderDovetailSlope;
  137. // length of dovetail slope
  138. var lDovetailSlope = Math.sqrt(hDovetail*hDovetail + lUnderDovetailSlope*lUnderDovetailSlope);
  139. /*
  140. qDebug("boardwidth = ", boardwidth);
  141. qDebug("period = ", period);
  142. qDebug("lUnderDovetailSlope = ", lUnderDovetailSlope);
  143. qDebug("lDovetailTop = ", lDovetailTop);
  144. qDebug("lPinBottom = ", lPinBottom);
  145. qDebug("lPinTop = ", lPinTop);
  146. qDebug("ldovetailBottomToBorder = ", ldovetailBottomToBorder);
  147. qDebug("ldovetailTopToBorder = ", ldovetailTopToBorder);
  148. qDebug("lDovetailSlope = ", lDovetailSlope);
  149. qDebug("=========================================================");
  150. */
  151. // Some sanity check
  152. if (Math.abs(period-(lDovetailTop+lPinTop)) > 0.001) {
  153. // something is wrong with the calculation
  154. qDebug("=== WARNING Calculation Error ===");
  155. qDebug("period = ", period);
  156. qDebug("lDovetailTop+lPinTop = ", lDovetailTop+lPinTop);
  157. qDebug("=================================");
  158. return undefined;
  159. }
  160. /*
  161. * Prepare the vectors for all edges of the dovetail...
  162. */
  163. var dovetailBottomToBorderEdge = new RVector();
  164. dovetailBottomToBorderEdge.setPolar(ldovetailBottomToBorder, angle);
  165. var dovetailSlopeLeft = new RVector();
  166. dovetailSlopeLeft.setPolar(lDovetailSlope, angle+Math.atan(1/gradient)+Math.PI/2.0);
  167. var dovetailTop = new RVector();
  168. dovetailTop.setPolar(lDovetailTop, angle);
  169. var dovetailSlopeRight = new RVector();
  170. dovetailSlopeRight.setPolar(lDovetailSlope, angle-Math.atan(1/gradient)-Math.PI/2.0);
  171. var dovetailPinBottom = new RVector();
  172. dovetailPinBottom.setPolar(lPinBottom, angle);
  173. // let's draw some dovetails...
  174. var op = new RAddObjectsOperation();
  175. // First draw lead-in
  176. c2 = c1.operator_add(dovetailBottomToBorderEdge);
  177. op.addObject(new RLineEntity(this.getDocument(), new RLineData(c1, c2)));
  178. // now draw all dovetails
  179. for (var i=nDovetails; i>0; i--) {
  180. c1 = c2;
  181. c2 = c2.operator_add(dovetailSlopeLeft);
  182. op.addObject(new RLineEntity(this.getDocument(), new RLineData(c1, c2)));
  183. c1 = c2;
  184. c2 = c2.operator_add(dovetailTop);
  185. op.addObject(new RLineEntity(this.getDocument(), new RLineData(c1, c2)));
  186. c1 = c2;
  187. c2 = c2.operator_add(dovetailSlopeRight);
  188. op.addObject(new RLineEntity(this.getDocument(), new RLineData(c1, c2)));
  189. if (i>1) {
  190. c1 = c2;
  191. c2 = c2.operator_add(dovetailPinBottom);
  192. op.addObject(new RLineEntity(this.getDocument(), new RLineData(c1, c2)));
  193. }
  194. }
  195. // Lastly draw lead-out
  196. c1 = c2;
  197. c2 = c2.operator_add(dovetailBottomToBorderEdge);
  198. op.addObject(new RLineEntity(this.getDocument(), new RLineData(c1, c2)));
  199. return op;
  200. };
  201. LineDove.prototype.slotDovetailNumberChanged = function(value) {
  202. this.dovetailNumber = value;
  203. this.updatePreview(true);
  204. };
  205. LineDove.prototype.slotDovetailHeightChanged = function(value) {
  206. this.dovetailHeight = value;
  207. this.updatePreview(true);
  208. };
  209. LineDove.prototype.slotDovetailGradientChanged = function(value) {
  210. this.dovetailGradient = value;
  211. this.updatePreview(true);
  212. };
  213. LineDove.prototype.slotPinRatioChanged = function(value) {
  214. this.pinRatio = value;
  215. this.updatePreview(true);
  216. };