simple_modify.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /**
  2. * Simple Modification API, mainly designed for use in the ECMAScript console.
  3. */
  4. /**
  5. * Pastes the given document into the current document or into the second given document.
  6. * \ingroup ecma_simple
  7. *
  8. * \param docSource RDocument to paste
  9. * \param diDestination RDocumentInterface to paste into (or undefined for current document)
  10. * \param offset Offset RVector or [x,y] array
  11. * \param scale Scale factor
  12. * \param rotation Rotation angle in degrees
  13. * \param flipHorizontal True to flip horizontally
  14. * \param flipVertial True to flip vertically
  15. * \param toCurrentLayer Paste all entities to the current layer of the target document
  16. * \param overwriteLayers Overwrite existing layers in the target document with layers
  17. * from the source document
  18. * \param overwriteBlocks Overwrite existing blocks in the target document with blocks
  19. * from the source document
  20. */
  21. function paste(docSource, diDestination, offset, scale, rotation, flipHorizontal, flipVertical, toCurrentLayer, overwriteLayers, overwriteBlocks) {
  22. if (isArray(offset)) {
  23. return paste(docSource, diDestination, new RVector(offset), scale, rotation, flipHorizontal, flipVertical, toCurrentLayer, overwriteLayers, overwriteBlocks);
  24. }
  25. var op = new RPasteOperation(docSource);
  26. op.setOffset(offset);
  27. op.setScale(scale);
  28. op.setRotation(deg2rad(rotation));
  29. op.setFlipHorizontal(flipHorizontal);
  30. op.setFlipVertical(flipVertical);
  31. op.setToCurrentLayer(toCurrentLayer);
  32. op.setOverwriteLayers(overwriteLayers);
  33. op.setOverwriteBlocks(overwriteBlocks);
  34. if (isNull(diDestination)) {
  35. diDestination = getDocumentInterface();
  36. }
  37. diDestination.applyOperation(op);
  38. }
  39. /**
  40. * Moves the given entity or shape by the given offset.
  41. * \ingroup ecma_simple
  42. *
  43. * \param e Entity, entity ID or shape.
  44. *
  45. * \code
  46. * move(entity, x,y)
  47. * move(entity, [x,y])
  48. * move(entity, new RVector(x,y))
  49. * \endcode
  50. */
  51. function move(e, offset) {
  52. if (arguments.length===3) {
  53. return move(arguments[0], new RVector(arguments[1], arguments[2]));
  54. }
  55. if (isArray(offset)) {
  56. return move(e, new RVector(offset));
  57. }
  58. if (isEntity(e)) {
  59. return move(e.getId(), offset);
  60. }
  61. if (isShape(e)) {
  62. e.move(offset);
  63. return undefined;
  64. }
  65. if (isNumber(e)) {
  66. var doc = getTransactionDocument();
  67. if (isNull(doc)) {
  68. return undefined;
  69. }
  70. var entity = doc.queryEntity(e);
  71. entity.move(offset);
  72. return addEntity(entity);
  73. }
  74. return undefined;
  75. }
  76. /**
  77. * Rotates the given entity or shape by the given angle around the given center.
  78. * \ingroup ecma_simple
  79. *
  80. * \param e Entity, entity ID or shape.
  81. *
  82. * \code
  83. * rotate(entity, angle, cx,cy)
  84. * rotate(entity, angle, [cx,cy])
  85. * rotate(entity, angle, new RVector(cx,cy))
  86. * \endcode
  87. */
  88. function rotate(e, angle, center) {
  89. if (arguments.length===4) {
  90. return rotate(arguments[0], arguments[1], new RVector(arguments[2], arguments[3]));
  91. }
  92. if (isArray(center)) {
  93. return rotate(e, angle, new RVector(center));
  94. }
  95. if (isEntity(e)) {
  96. return rotate(e.getId(), angle, center);
  97. }
  98. if (isShape(e)) {
  99. e.rotate(angle, center);
  100. return undefined;
  101. }
  102. if (isNumber(e)) {
  103. var doc = getTransactionDocument();
  104. if (isNull(doc)) {
  105. return undefined;
  106. }
  107. var entity = doc.queryEntity(e);
  108. if (isNull(center)) {
  109. entity.rotate(deg2rad(angle));
  110. }
  111. else {
  112. entity.rotate(deg2rad(angle), center);
  113. }
  114. return addEntity(entity);
  115. }
  116. return undefined;
  117. }
  118. /**
  119. * Scales the given entity or shape by the given factor with the given focus point.
  120. * \ingroup ecma_simple
  121. *
  122. * \param e Entity, entity ID or shape.
  123. *
  124. * \code
  125. * scale(entity, factor, cx,cy)
  126. * scale(entity, factor, [cx,cy])
  127. * scale(entity, factor, new RVector(cx,cy))
  128. * \endcode
  129. */
  130. function scale(e, factor, focusPoint) {
  131. if (arguments.length===4) {
  132. return scale(arguments[0], arguments[1], new RVector(arguments[2], arguments[3]));
  133. }
  134. if (isNumber(focusPoint)) {
  135. return scale(e, factor, new RVector(focusPoint));
  136. }
  137. if (isEntity(e)) {
  138. return scale(e.getId(), factor, focusPoint);
  139. }
  140. if (isShape(e)) {
  141. e.scale(factor, focusPoint);
  142. return undefined;
  143. }
  144. if (isNumber(e)) {
  145. var doc = getTransactionDocument();
  146. if (isNull(doc)) {
  147. return undefined;
  148. }
  149. var entity = doc.queryEntity(e);
  150. if (isNull(focusPoint)) {
  151. entity.scale(factor);
  152. }
  153. else {
  154. entity.scale(factor, focusPoint);
  155. }
  156. return addEntity(entity);
  157. }
  158. return undefined;
  159. }
  160. /**
  161. * Mirrors the given entity or shape at the given axis.
  162. * \ingroup ecma_simple
  163. *
  164. * \param e Entity, entity ID or shape.
  165. *
  166. * \code
  167. * mirror(entity, x1,y1, x2,y2)
  168. * mirror(entity, [x1,y1], [x2,y2])
  169. * mirror(entity, new RVector(x1,y1), new RVector(x2,y2))
  170. * mirror(entity, new RLine(x1,y1, x2, y2))
  171. * mirror(entity, [new RVector(x1,y1), new RVector(x2,y2)])
  172. * mirror(entity, [[x1,y1], [x2,y2]])
  173. * \endcode
  174. */
  175. function mirror(e, axis) {
  176. if (arguments.length===5) {
  177. return mirror(arguments[0], new RLine(arguments[1], arguments[2], arguments[3], arguments[4]));
  178. }
  179. if (arguments.length===3) {
  180. var p1 = arguments[1];
  181. if (isArray(p1)) {
  182. p1 = new RVector(p1);
  183. }
  184. var p2 = arguments[1];
  185. if (isArray(p2)) {
  186. p2 = new RVector(p2);
  187. }
  188. return mirror(arguments[0], new RLine(p1, p2));
  189. }
  190. if (isArray(axis)) {
  191. if (isVector(axis[0])) {
  192. return mirror(e, new RLine(axis[0], axis[1]));
  193. }
  194. return mirror(e, new RLine(new RVector(axis[0]), new RVector(axis[1])));
  195. }
  196. if (isEntity(e)) {
  197. return mirror(e.getId(), axis);
  198. }
  199. if (isShape(e)) {
  200. e.mirror(axis);
  201. return undefined;
  202. }
  203. if (isNumber(e)) {
  204. var doc = getTransactionDocument();
  205. if (isNull(doc)) {
  206. return undefined;
  207. }
  208. var entity = doc.queryEntity(e);
  209. entity.mirror(axis);
  210. return addEntity(entity);
  211. }
  212. return undefined;
  213. }
  214. /**
  215. * Trims the given entity / entities or shape(s).
  216. * \ingroup ecma_simple
  217. *
  218. * \param trimEntity Entity, entity ID or shape to trim
  219. * \param trimClickPos Position clicked when choosing trim entity.
  220. * \param limitingEntity Entity, entity ID or shape that limits the trimming.
  221. * \param limitingClickPos Position clicked when choosing limiting entity.
  222. * \param trimBoth True to trim both entities.
  223. *
  224. * \return RTransaction created by operation if no operation is given. If op is given, undefined is returned.
  225. *
  226. * \code
  227. * trim(trimEntity, x1,y1, limitingEntity, x2,y2, trimBoth)
  228. * trim(trimEntity, [x1,y1], limitingEntity, [x2,y2], trimBoth)
  229. * trim(trimEntity, new RVector(x1,y1), limitingEntity, new RVector(x2,y2), trimBoth)
  230. * \endcode
  231. */
  232. function trim(trimEntity, trimClickPos, limitingEntity, limitingClickPos, trimBoth) {
  233. if (arguments.length===7) {
  234. return trim(arguments[0], new RVector(arguments[1], arguments[2]), arguments[3], new RVector(arguments[4], arguments[5]), arguments[6]);
  235. }
  236. var trimShape, limitingShape;
  237. var doc = getTransactionDocument();
  238. if (isNull(doc)) {
  239. return undefined;
  240. }
  241. if (isNumber(trimEntity)) {
  242. trimEntity = doc.queryEntity(trimEntity);
  243. }
  244. if (isNumber(limitingEntity)) {
  245. limitingEntity = doc.queryEntity(limitingEntity);
  246. }
  247. if (isShape(trimEntity) && isShape(limitingShape)) {
  248. trimShape = trimEntity;
  249. limitingShape = limitingEntity;
  250. }
  251. else {
  252. trimShape = trimEntity.castToShape();
  253. limitingShape = limitingEntity.castToShape();
  254. if (isNull(limitingShape)) {
  255. limitingShape = limitingEntity.getClosestSimpleShape(limitingClickPos);
  256. if (!isNull(limitingShape)) {
  257. limitingShape = limitingShape.data();
  258. }
  259. }
  260. }
  261. if (isNull(trimShape) || isNull(limitingShape)) {
  262. return undefined;
  263. }
  264. var samePolyline = (limitingEntity.getId()===trimEntity.getId() && isPolylineEntity(limitingEntity));
  265. if (samePolyline) {
  266. if (!trimBoth) {
  267. // TODO: fix trimming one segment within same polyline:
  268. return undefined;
  269. }
  270. }
  271. var newShapes = RShape.trim(trimShape, trimClickPos, limitingShape, limitingClickPos, trimBoth, samePolyline);
  272. if (newShapes.length===0) {
  273. return undefined;
  274. }
  275. var op = getOperation();
  276. if (!modifyEntity(op, trimEntity.clone(), newShapes[0].data())) {
  277. if (trimBoth) {
  278. warning(qsTr("First entity cannot be trimmed."));
  279. }
  280. else {
  281. warning(qsTr("Entity cannot be trimmed."));
  282. }
  283. }
  284. if (newShapes.length===1) {
  285. // trimming was within same polyline
  286. }
  287. else {
  288. if (trimBoth) {
  289. if (!modifyEntity(op, limitingEntity.clone(), newShapes[1].data())) {
  290. warning(qsTr("Second entity cannot be trimmed."));
  291. }
  292. }
  293. }
  294. if (!__simpleUseOp) {
  295. var di = getDocumentInterface();
  296. return di.applyOperation(op);
  297. }
  298. }
  299. /**
  300. * Lengthens of shortens the given entity or shape.
  301. * \ingroup ecma_simple
  302. *
  303. * \param entity Entity, entity ID or shape to lengthen
  304. * \param start True to extend at start point, false for end point
  305. * \param amount Amount to lengthen or negative value to shorten
  306. */
  307. function lengthen(entity, start, amount) {
  308. var doc = getTransactionDocument();
  309. if (isNull(doc)) {
  310. return undefined;
  311. }
  312. if (isNumber(entity)) {
  313. entity = doc.queryEntity(entity);
  314. }
  315. else {
  316. entity = entity.clone();
  317. }
  318. var from = RS.FromStart;
  319. if (!start) {
  320. from = RS.FromEnd;
  321. }
  322. var pts = entity.getPointsWithDistanceToEnd(-amount, from);
  323. if (pts.length===1) {
  324. if (start) {
  325. entity.trimStartPoint(pts[0], pts[0], true);
  326. }
  327. else {
  328. entity.trimEndPoint(pts[0], pts[0], true);
  329. }
  330. }
  331. return addEntity(entity);
  332. }