BreakOutManual.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. include("scripts/Modify/Modify.js");
  20. include("scripts/ShapeAlgorithms.js");
  21. function BreakOutManual(guiAction) {
  22. Modify.call(this, guiAction);
  23. this.entity = undefined;
  24. this.shape = undefined;
  25. this.ceids = [];
  26. this.point1 = undefined;
  27. this.point2 = undefined;
  28. this.point3 = undefined;
  29. this.point4 = undefined;
  30. this.removeSegment = true;
  31. this.setUiOptions("BreakOutManual.ui");
  32. }
  33. BreakOutManual.prototype = new Modify();
  34. BreakOutManual.State = {
  35. SettingShape : 0,
  36. SettingPoint1 : 1,
  37. SettingPoint2 : 2,
  38. SelectCircleEllipsePart : 3
  39. };
  40. BreakOutManual.prototype.beginEvent = function() {
  41. Modify.prototype.beginEvent.call(this);
  42. this.setState(BreakOutManual.State.SettingShape);
  43. };
  44. BreakOutManual.prototype.escapeEvent = function() {
  45. switch (this.state) {
  46. case BreakOutManual.State.SettingShape:
  47. EAction.prototype.escapeEvent.call(this);
  48. return;
  49. case BreakOutManual.State.SettingPoint1:
  50. this.setState(BreakOutManual.State.SettingShape);
  51. break;
  52. case BreakOutManual.State.SettingPoint2:
  53. this.setState(BreakOutManual.State.SettingPoint1);
  54. break;
  55. case BreakOutManual.State.SelectCircleEllipsePart:
  56. this.setState(BreakOutManual.State.SettingShape);
  57. break;
  58. }
  59. };
  60. BreakOutManual.prototype.setState = function(state) {
  61. Modify.prototype.setState.call(this, state);
  62. var di = this.getDocumentInterface();
  63. var appWin = RMainWindowQt.getMainWindow();
  64. switch (this.state) {
  65. case BreakOutManual.State.SettingShape:
  66. di.setClickMode(RAction.PickEntity);
  67. var trFirstPoint;
  68. if (RSpline.hasProxy() && RPolyline.hasProxy()) {
  69. trFirstPoint = qsTr("Choose line, arc, circle, ellipse, spline or polyline to break up");
  70. }
  71. else {
  72. trFirstPoint = qsTr("Choose line, arc, circle or ellipse to break up");
  73. }
  74. this.setCommandPrompt(trFirstPoint);
  75. this.setLeftMouseTip(trFirstPoint);
  76. this.setRightMouseTip(EAction.trCancel);
  77. this.ceids = [];
  78. break;
  79. case BreakOutManual.State.SettingPoint1:
  80. this.point2 = undefined;
  81. di.setClickMode(RAction.PickCoordinate);
  82. var trSecondPoint = qsTr("First break point");
  83. this.setCommandPrompt(trSecondPoint);
  84. this.setLeftMouseTip(trSecondPoint);
  85. this.setRightMouseTip(EAction.trDone);
  86. break;
  87. case BreakOutManual.State.SettingPoint2:
  88. this.point4 = undefined;
  89. di.setClickMode(RAction.PickCoordinate);
  90. var trThirdPoint = qsTr("Second break point");
  91. this.setCommandPrompt(trThirdPoint);
  92. this.setLeftMouseTip(trThirdPoint);
  93. this.setRightMouseTip(EAction.trDone);
  94. break;
  95. case BreakOutManual.State.SelectCircleEllipsePart:
  96. di.setClickMode(RAction.PickEntity);
  97. var cepos = qsTr("Click the part of the circle or ellipse to remove");
  98. this.setCommandPrompt(cepos);
  99. this.setLeftMouseTip(cepos);
  100. this.setRightMouseTip(EAction.trDone);
  101. break;
  102. }
  103. this.setCrosshairCursor();
  104. EAction.showSnapTools();
  105. };
  106. BreakOutManual.prototype.pickEntity = function(event, preview) {
  107. var di = this.getDocumentInterface();
  108. var doc = this.getDocument();
  109. var entityId = this.getEntityId(event, preview);
  110. var entity = doc.queryEntity(entityId);
  111. var pos = event.getModelPosition();
  112. if (isNull(entity)) {
  113. return;
  114. }
  115. this.entity = entity;
  116. switch (this.state) {
  117. case BreakOutManual.State.SettingShape:
  118. var cond = isLineBasedEntity(entity) ||
  119. isArcEntity(entity) ||
  120. isCircleEntity(entity) ||
  121. isEllipseEntity(entity) ||
  122. (RSpline.hasProxy() && isSplineEntity(entity)) ||
  123. (RPolyline.hasProxy() && isPolylineEntity(entity));
  124. if (!cond) {
  125. if (!preview) {
  126. if (RSpline.hasProxy() && RPolyline.hasProxy()) {
  127. EAction.warnNotLineArcCircleEllipseSplinePolyline();
  128. }
  129. else {
  130. EAction.warnNotLineArcCircleEllipse();
  131. }
  132. }
  133. break;
  134. }
  135. else {
  136. di.highlightEntity(this.entity.getId());
  137. }
  138. if (!EAction.assertEditable(entity, preview)) {
  139. break;
  140. }
  141. if (!preview) {
  142. this.shape = entity.getClosestShape(pos);
  143. this.setState(BreakOutManual.State.SettingPoint1);
  144. }
  145. break;
  146. case BreakOutManual.State.SelectCircleEllipsePart:
  147. di.highlightEntity(this.entity.getId());
  148. if (!preview) {
  149. if (this.ceids.indexOf(this.entity.getId())!==-1) {
  150. var op = new RDeleteObjectOperation(this.entity);
  151. op.setTransactionGroup(doc.getTransactionGroup());
  152. if (!isNull(op)) {
  153. di.applyOperation(op);
  154. }
  155. }
  156. this.setState(BreakOutManual.State.SettingShape);
  157. }
  158. break;
  159. }
  160. };
  161. BreakOutManual.prototype.pickCoordinate = function(event, preview) {
  162. var di = this.getDocumentInterface();
  163. var doc = this.getDocument();
  164. var line;
  165. var op;
  166. if (isNull(this.shape)) {
  167. return;
  168. }
  169. switch (this.state) {
  170. case BreakOutManual.State.SettingPoint1:
  171. this.point1 = event.getModelPosition();
  172. if (!isValidVector(this.point1)) {
  173. return;
  174. }
  175. this.point2 = this.shape.getClosestPointOnShape(this.point1, true);
  176. if (!isValidVector(this.point2)) {
  177. if (this.point1.getDistanceTo(this.entity.getStartPoint()) <= this.point1.getDistanceTo(this.entity.getEndPoint())) {
  178. this.point2 = this.entity.getStartPoint();
  179. } else {
  180. this.point2 = this.entity.getEndPoint();
  181. }
  182. //return;
  183. }
  184. di.highlightEntity(this.entity.getId());
  185. if (preview) {
  186. line = new RLine(this.point1, this.point2);
  187. di.addAuxShapeToPreview(line);
  188. } else {
  189. this.setState(BreakOutManual.State.SettingPoint2);
  190. }
  191. break;
  192. case BreakOutManual.State.SettingPoint2:
  193. this.point3 = event.getModelPosition();
  194. if (!isValidVector(this.point3)) {
  195. return;
  196. }
  197. this.point4 = this.shape.getClosestPointOnShape(this.point3, true);
  198. if (!isValidVector(this.point4)) {
  199. if (this.point3.getDistanceTo(this.entity.getStartPoint()) <= this.point3.getDistanceTo(this.entity.getEndPoint())) {
  200. this.point4 = this.entity.getStartPoint();
  201. } else {
  202. this.point4 = this.entity.getEndPoint();
  203. }
  204. //return;
  205. }
  206. di.highlightEntity(this.entity.getId());
  207. if (preview) {
  208. line = new RLine(this.point3, this.point4);
  209. di.addAuxShapeToPreview(line);
  210. } else {
  211. op = this.getOperation(false);
  212. if (!isNull(op)) {
  213. doc.startTransactionGroup();
  214. op.setTransactionGroup(doc.getTransactionGroup());
  215. var t = di.applyOperation(op);
  216. if ((isCircleEntity(this.entity) || isFullEllipseEntity(this.entity)) && this.removeSegment) {
  217. if (this.point2.equalsFuzzy(this.point4)) {
  218. this.setState(BreakOutManual.State.SettingShape);
  219. } else {
  220. // remember IDs of added entities from transaction:
  221. // used to make sure user cannot delete another entity:
  222. this.ceids = t.getAffectedObjects();
  223. this.setState(BreakOutManual.State.SelectCircleEllipsePart);
  224. }
  225. } else {
  226. this.setState(BreakOutManual.State.SettingShape);
  227. }
  228. }
  229. }
  230. break;
  231. }
  232. };
  233. BreakOutManual.prototype.getOperation = function(preview) {
  234. //var newSegments = BreakOutManual.autoTrim(this.shape, this.point2, this.point4);
  235. var newSegments = ShapeAlgorithms.autoSplitManual(this.shape, undefined, undefined, this.point2, this.point4, RVector.getAverage(this.point2, this.point4));
  236. if (isNull(newSegments)) {
  237. return undefined;
  238. }
  239. var op = new RAddObjectsOperation();
  240. op.setText(this.getToolTitle());
  241. var e;
  242. // replace circle with arc:
  243. if (isCircleEntity(this.entity) || isFullEllipseEntity(this.entity)) {
  244. op.deleteObject(this.entity);
  245. if (!isNull(newSegments[2])) {
  246. e = shapeToEntity(this.entity.getDocument(), newSegments[2]);
  247. if (!isNull(e)) {
  248. e.copyAttributesFrom(getPtr(this.entity));
  249. op.addObject(e, false);
  250. }
  251. }
  252. }
  253. // change existing entity into segment if we keep the segment,
  254. // otherwise delete existing entity
  255. else {
  256. if (this.removeSegment) {
  257. // delete entity completely:
  258. op.deleteObject(this.entity);
  259. }
  260. else {
  261. this.entity.setShape(newSegments[2]);
  262. op.addObject(this.entity, false);
  263. }
  264. }
  265. if (!isNull(newSegments[0])) {
  266. e = shapeToEntity(this.entity.getDocument(), newSegments[0]);
  267. if (!isNull(e)) {
  268. e.copyAttributesFrom(getPtr(this.entity));
  269. op.addObject(e, false);
  270. }
  271. }
  272. if (!isNull(newSegments[1])) {
  273. e = shapeToEntity(this.entity.getDocument(), newSegments[1])
  274. if (!isNull(e)) {
  275. e.copyAttributesFrom(getPtr(this.entity));
  276. op.addObject(e, false);
  277. }
  278. }
  279. return op;
  280. };
  281. BreakOutManual.prototype.slotRemoveSegmentChanged = function(value) {
  282. this.removeSegment = value;
  283. };