Explode.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  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 Explode(guiAction) {
  22. Modify.call(this, guiAction);
  23. }
  24. Explode.prototype = new Modify();
  25. Explode.getPreferencesCategory = function() {
  26. return [qsTr("Modify"), qsTr("Explode")];
  27. };
  28. Explode.initPreferences = function(pageWidget, calledByPrefDialog, document) {
  29. var widgets = getWidgets(pageWidget);
  30. if (!RTextBasedData.hasProxy()) {
  31. // remove MultilineTextToSimpleText option:
  32. widgets["MultilineTextToSimpleText"].visible = false;
  33. }
  34. if (!RSpline.hasProxy()) {
  35. widgets["SplineTolerance"].visible = false;
  36. widgets["SplineTolerance_Label"].visible = false;
  37. widgets["SplinesToLineSegments"].visible = false;
  38. destr(widgets["Indent"]);
  39. pageWidget.findChild("GridLayout").addWidget(widgets["SplineSegments_Label"], 2, 0, 1, 2);
  40. }
  41. else {
  42. widgets["SplinesToLineSegments"].toggled.connect(function(state) {
  43. widgets["SplineSegments"].enabled = state;
  44. widgets["SplineSegments_Label"].enabled = state;
  45. });
  46. widgets["SplineSegments"].enabled = widgets["SplinesToLineSegments"].checked;
  47. widgets["SplineSegments_Label"].enabled = widgets["SplinesToLineSegments"].checked;
  48. }
  49. };
  50. Explode.prototype.beginEvent = function() {
  51. Modify.prototype.beginEvent.call(this);
  52. var di = this.getDocumentInterface();
  53. Explode.explodeSelection(di, this.getToolTitle());
  54. this.terminate();
  55. };
  56. /**
  57. * Explodes all selected entities.
  58. * \param di Document interface
  59. * \param toolTitle Tool title used for undo/redo information.
  60. */
  61. Explode.explodeSelection = function(di, toolTitle) {
  62. var document = di.getDocument();
  63. var storage = document.getStorage();
  64. var ids = document.querySelectedEntities();
  65. var i, k, e, n;
  66. var polyline, shapes;
  67. var options = {};
  68. options["splineTolerance"] = RSettings.getDoubleValue("Explode/SplineTolerance", 0.01);
  69. options["splineSegments"] = RSettings.getIntValue("Explode/SplineSegments", 64);
  70. options["ellipseSegments"] = RSettings.getIntValue("Explode/EllipseSegments", 32);
  71. options["splinesToLineSegments"] = RSettings.getBoolValue("Explode/SplinesToLineSegments", false);
  72. options["textToPolylines"] = RSettings.getBoolValue("Explode/TextToPolylines", true);
  73. options["textSplineToLineOrArc"] = RSettings.getBoolValue("Explode/TextSplineToLineOrArc", true);
  74. options["multilineTextToSimpleText"] = RSettings.getBoolValue("Explode/MultilineTextToSimpleText", true);
  75. options["circlesToPolylines"] = RSettings.getBoolValue("Explode/CirclesToPolylines", true);
  76. var op = new RAddObjectsOperation();
  77. if (!isNull(toolTitle)) {
  78. op.setText(toolTitle);
  79. }
  80. // map old block reference IDs to block reference entities:
  81. var blockReferenceMap = {};
  82. // list of attribute entities:
  83. var attributeEntities = [];
  84. for (i=0; i<ids.length; i++) {
  85. var id = ids[i];
  86. var entity = document.queryEntity(id);
  87. if (isNull(entity)) {
  88. debugger;
  89. }
  90. //var newShapes = [];
  91. //var newEntities = [];
  92. var news = Explode.explodeEntity(entity, options);
  93. if (isNull(news)) {
  94. // do nothing:
  95. continue;
  96. }
  97. // add explosion result and delete original:
  98. if (news.length!==0) {
  99. // add entities based on shapes that resulted from the explosion:
  100. for (k=0; k<news.length; k++) {
  101. if (isEntity(news[k])) {
  102. var newEntity = news[k];
  103. // add entities based on entities that resulted from the explosion:
  104. op.addObject(newEntity, false, true);
  105. if (isBlockReferenceEntity(newEntity)) {
  106. qDebug("old block ref id: ", newEntity.getId());
  107. blockReferenceMap[newEntity.getId()] = newEntity;
  108. }
  109. else if (isAttributeEntity(newEntity)) {
  110. attributeEntities.push(newEntity);
  111. }
  112. }
  113. else {
  114. var newShape = news[k];
  115. e = shapeToEntity(entity.getDocument(), newShape);
  116. if (!isNull(e)) {
  117. e.setSelected(true);
  118. e.copyAttributesFrom(getPtr(entity));
  119. if (!isNull(newShape.color)) {
  120. e.setColor(new RColor(newShape.color));
  121. }
  122. op.addObject(e, false);
  123. }
  124. }
  125. }
  126. // delete original entity:
  127. op.deleteObject(entity);
  128. }
  129. else {
  130. // delete original entity:
  131. op.deleteObject(entity);
  132. }
  133. }
  134. di.applyOperation(op);
  135. // update block reference attributes:
  136. if (attributeEntities.length>0) {
  137. op = new RAddObjectsOperation();
  138. //op.setTransactionGroup(doc.getTransactionGroup());
  139. if (!isNull(toolTitle)) {
  140. op.setText(toolTitle);
  141. }
  142. // fix attribute links to block references:
  143. for (i=0; i<attributeEntities.length; i++) {
  144. var attributeEntity = attributeEntities[i].clone();
  145. // find parent entity of attribute:
  146. var blockReferenceEntity = blockReferenceMap[attributeEntity.getParentId()];
  147. if (!isNull(blockReferenceEntity)) {
  148. // update parent ID:
  149. storage.setEntityParentId(attributeEntity, blockReferenceEntity.getId());
  150. op.addObject(attributeEntity, false);
  151. }
  152. }
  153. di.applyOperation(op);
  154. }
  155. };
  156. /**
  157. * \return Array of new shapes and entities or undefined to do nothing.
  158. */
  159. Explode.explodeEntity = function(entity, options) {
  160. var ret = [];
  161. if (isNull(options)) {
  162. options = {};
  163. }
  164. // these entity types are not explodable:
  165. if (isPointEntity(entity) ||
  166. isLineEntity(entity) ||
  167. isXLineEntity(entity) ||
  168. isRayEntity(entity) ||
  169. isImageEntity(entity) ||
  170. isArcEntity(entity) ||
  171. isViewportEntity(entity)) {
  172. return undefined;
  173. }
  174. var k, e, n, d;
  175. var col, row;
  176. var painterPaths;
  177. var document = entity.getDocument();
  178. var storage = document.getStorage();
  179. var splineTolerance = options["splineTolerance"];
  180. var splineSegments = options["splineSegments"];
  181. var ellipseSegments = options["ellipseSegments"];
  182. var splinesToLineSegments = options["splinesToLineSegments"];
  183. var textToPolylines = options["textToPolylines"];
  184. var textSplineToLineOrArc = options["textSplineToLineOrArc"];
  185. var multilineTextToSimpleText = options["multilineTextToSimpleText"];
  186. var circlesToPolylines = options["circlesToPolylines"];
  187. if (isNull(splineTolerance)) {
  188. splineTolerance = RSettings.getDoubleValue("Explode/SplineTolerance", 0.01);
  189. }
  190. if (isNull(splineSegments)) {
  191. splineSegments = RSettings.getIntValue("Explode/SplineSegments", 64);
  192. }
  193. if (isNull(ellipseSegments)) {
  194. ellipseSegments = RSettings.getIntValue("Explode/EllipseSegments", 32);
  195. }
  196. if (isNull(splinesToLineSegments)) {
  197. splinesToLineSegments = RSettings.getBoolValue("Explode/SplinesToLineSegments", false);
  198. }
  199. if (isNull(textToPolylines)) {
  200. textToPolylines = RSettings.getBoolValue("Explode/TextToPolylines", true);
  201. }
  202. if (isNull(textSplineToLineOrArc)) {
  203. textSplineToLineOrArc = RSettings.getBoolValue("Explode/TextSplineToLineOrArc", true);
  204. }
  205. if (isNull(multilineTextToSimpleText)) {
  206. multilineTextToSimpleText = RSettings.getBoolValue("Explode/MultilineTextToSimpleText", true);
  207. }
  208. if (isNull(circlesToPolylines)) {
  209. circlesToPolylines = RSettings.getBoolValue("Explode/CirclesToPolylines", true);
  210. }
  211. // explode ellipse into polyline with arc segments:
  212. if (isEllipseEntity(entity)) {
  213. if (REllipse.hasProxy()) {
  214. var ellipse = entity.getData().castToShape();
  215. var polyline = ellipse.approximateWithArcs(ellipseSegments);
  216. if (!polyline.isEmpty()) {
  217. ret.push(polyline);
  218. }
  219. }
  220. else {
  221. return undefined;
  222. }
  223. }
  224. // explode circle into polyline with two arc segments:
  225. else if (isCircleEntity(entity)) {
  226. if (circlesToPolylines) {
  227. var circle = entity.getData().castToShape();
  228. polyline = new RPolyline();
  229. polyline.appendShape(new RArc(circle.getCenter(), circle.getRadius(), 0.0, Math.PI, false));
  230. polyline.appendShape(new RArc(circle.getCenter(), circle.getRadius(), Math.PI, 2*Math.PI, false));
  231. polyline.autoClose();
  232. ret.push(polyline);
  233. }
  234. else {
  235. return undefined;
  236. }
  237. }
  238. // explode polyline into line and arc segments:
  239. else if (isPolylineEntity(entity)) {
  240. polyline = entity.getData().castToShape();
  241. // explode polyline with segment widths:
  242. if (RPolyline.hasProxy() && polyline.hasWidths()) {
  243. // list of polyline pairs (left / right):
  244. var pls;
  245. if (RSettings.getQtVersion() >= 0x060000) {
  246. pls = [];
  247. var plsLeft = polyline.getLeftOutline();
  248. var plsRight = polyline.getRightOutline();
  249. for (var i=0; i<plsLeft.length && i<plsRight.length; i++) {
  250. pls.push([plsLeft[i], plsRight[i]]);
  251. }
  252. }
  253. else {
  254. pls = polyline.getLeftRightOutline();
  255. }
  256. var first = true;
  257. var lastSegment = undefined;
  258. var prevLeftPl = undefined;
  259. var prevRightPl = undefined;
  260. for (k=0; k<pls.length; k++) {
  261. if (pls[k].length!==2) {
  262. qWarning("invalid result from RPolyline::getLeftRightOutline");
  263. continue;
  264. }
  265. var leftPl = pls[k][0];
  266. var rightPl = pls[k][1];
  267. if (leftPl.countSegments()===1 && rightPl.countSegments()===1) {
  268. if (first) {
  269. // add orthogonal segment at start of this sequence:
  270. //ret.push(pls[k].getSegmentAt(3));
  271. if (isNull(prevLeftPl) || isNull(prevRightPl)) {
  272. ret.push(new RLine(leftPl.getStartPoint(), rightPl.getStartPoint()));
  273. }
  274. else {
  275. var dirLeft = prevLeftPl.getDirection2() + Math.PI;
  276. var dirRight = prevRightPl.getDirection2() + Math.PI;
  277. //qDebug("dirLeft:", dirLeft);
  278. //qDebug("new dir:", leftPl.getDirection1());
  279. if (!RMath.fuzzyAngleCompare(dirLeft, leftPl.getDirection1(), 0.01) ||
  280. !RMath.fuzzyAngleCompare(dirRight, rightPl.getDirection1(), 0.01)) {
  281. ret.push(new RLine(leftPl.getStartPoint(), rightPl.getStartPoint()));
  282. }
  283. }
  284. }
  285. // add left segment:
  286. ret.push(leftPl);
  287. // add right segment:
  288. ret.push(rightPl);
  289. lastSegment = new RLine(leftPl.getEndPoint(), rightPl.getEndPoint());
  290. prevLeftPl = leftPl;
  291. prevRightPl = rightPl;
  292. }
  293. //else if (leftPl.countSegments()>1 || rightPl.countSegments()>1) {
  294. else if (!leftPl.isEmpty()) {
  295. //ret.push(pls[k]);
  296. if (!rightPl.isEmpty()) {
  297. ret.push(new RLine(leftPl.getStartPoint(), rightPl.getStartPoint()));
  298. }
  299. ret.push(leftPl);
  300. if (!rightPl.isEmpty()) {
  301. ret.push(rightPl);
  302. ret.push(new RLine(leftPl.getEndPoint(), rightPl.getEndPoint()));
  303. }
  304. first = true;
  305. if (!isNull(lastSegment)) {
  306. ret.push(lastSegment);
  307. lastSegment = undefined;
  308. prevLeftPl = undefined;
  309. prevRightPl = undefined;
  310. }
  311. continue;
  312. }
  313. }
  314. if (!isNull(lastSegment)) {
  315. ret.push(lastSegment);
  316. }
  317. }
  318. else {
  319. var polySegments = polyline.getExploded();
  320. if (polySegments.length>0) {
  321. for (k=0; k<polySegments.length; k++) {
  322. var shape = getPtr(polySegments[k]);
  323. // last shape might have zero length if polyline is closed geometrically and logically:
  324. if (k===polySegments.length-1) {
  325. if (shape.getLength()<1.0e-5) {
  326. break;
  327. }
  328. }
  329. ret.push(shape.clone());
  330. }
  331. }
  332. }
  333. }
  334. // explode spline into polyline with arc or line segments:
  335. else if (isSplineEntity(entity)) {
  336. var spline = entity.getData().castToShape();
  337. var pl;
  338. if (RSpline.hasProxy() && !splinesToLineSegments) {
  339. pl = spline.approximateWithArcs(splineTolerance);
  340. }
  341. else {
  342. pl = spline.toPolyline(splineSegments);
  343. }
  344. pl.simplify();
  345. ret.push(pl);
  346. }
  347. // explode hatch into lines / solid fill into boundary:
  348. else if (isHatchEntity(entity)) {
  349. if (entity.isSolid()) {
  350. for (k=0; k<entity.getLoopCount(); k++) {
  351. var shapes = entity.getLoopBoundary(k);
  352. for (n=0; n<shapes.length; n++) {
  353. shape = shapes[n];
  354. ret.push(shape.clone());
  355. }
  356. }
  357. }
  358. else {
  359. painterPaths = entity.getPainterPaths(false);
  360. for (k=0; k<painterPaths.length; k++) {
  361. shapes = painterPaths[k].getShapes();
  362. for (n=0; n<shapes.length; n++) {
  363. shape = getPtr(shapes[n]);
  364. if (isSplineShape(shape)) {
  365. shape = ShapeAlgorithms.splineToLineOrArc(shape, 0.01);
  366. }
  367. ret.push(shape.clone());
  368. }
  369. }
  370. }
  371. }
  372. // explode dimension into lines, solids (triangles) and a text entity:
  373. else if (isDimensionEntity(entity)) {
  374. shapes = entity.getShapes();
  375. for (k=0; k<shapes.length; k++) {
  376. if (shapes[k].isValid()) {
  377. ret.push(getPtr(shapes[k]));
  378. }
  379. }
  380. var textData = entity.getData().getTextData();
  381. e = new RTextEntity(entity.getDocument(), textData);
  382. e.setSelected(true);
  383. e.copyAttributesFrom(getPtr(entity));
  384. var textColor = document.getKnownVariable(RS.DIMCLRT, new RColor(RColor.ByBlock));
  385. e.setColor(textColor);
  386. ret.push(e);
  387. }
  388. // explode leaders into lines and solids (triangles):
  389. else if (isLeaderEntity(entity)) {
  390. shapes = entity.getShapes();
  391. for (k=0; k<shapes.length; k++) {
  392. shape = getPtr(shapes[k]);
  393. ret.push(shape.clone());
  394. }
  395. }
  396. // explode tolerances into lines and texts:
  397. else if (isToleranceEntity(entity)) {
  398. shapes = entity.getFrame();
  399. for (k=0; k<shapes.length; k++) {
  400. shape = shapes[k];
  401. ret.push(shape.clone());
  402. }
  403. var textDatas = entity.getTextLabels();
  404. for (k=0; k<textDatas.length; k++) {
  405. var d = textDatas[k];
  406. e = new RTextEntity(document, new RTextData(d))
  407. e.setSelected(true);
  408. e.copyAttributesFrom(getPtr(entity));
  409. if (e.getColor()!==d.getColor()) {
  410. e.setColor(d.getColor());
  411. }
  412. ret.push(e);
  413. }
  414. }
  415. // explode solids into polylines:
  416. else if (isSolidEntity(entity)) {
  417. shapes = entity.getShapes();
  418. for (k=0; k<shapes.length; k++) {
  419. shape = getPtr(shapes[k]);
  420. if (shape.countVertices()===4) {
  421. var v3 = shape.getVertexAt(3);
  422. shape.setVertexAt(3, shape.getVertexAt(2));
  423. shape.setVertexAt(2, v3);
  424. }
  425. ret.push(shape.clone());
  426. }
  427. }
  428. // explode faces into polylines:
  429. else if (isFaceEntity(entity)) {
  430. shapes = entity.getShapes();
  431. for (k=0; k<shapes.length; k++) {
  432. shape = getPtr(shapes[k]);
  433. ret.push(shape.clone());
  434. }
  435. }
  436. // explode text entities into text blocks or lines, arcs and splines:
  437. else if (isTextEntity(entity)) {
  438. // explode multi-block text into simple text entities:
  439. // each text block with the same format is converted into one individual simple text entity:
  440. if (!entity.isSimple() && multilineTextToSimpleText && RTextBasedData.hasProxy()) {
  441. var textDatas = entity.getSimpleTextBlocks();
  442. for (k=0; k<textDatas.length; k++) {
  443. var d = textDatas[k];
  444. e = new RTextEntity(document, new RTextData(d))
  445. e.setSelected(true);
  446. e.copyAttributesFrom(getPtr(entity));
  447. if (e.getColor()!==d.getColor()) {
  448. e.setColor(d.getColor());
  449. }
  450. ret.push(e);
  451. }
  452. }
  453. else {
  454. painterPaths = entity.getPainterPaths();
  455. for (k=0; k<painterPaths.length; k++) {
  456. var p = painterPaths[k].getPen();
  457. var b = painterPaths[k].getBrush();
  458. var col = undefined;
  459. if (p.style()!==Qt.NoPen) {
  460. if (p.color().isValid()) {
  461. col = p.color().name();
  462. }
  463. }
  464. else if (b.style()!==Qt.NoBrush) {
  465. if (b.color().isValid()) {
  466. col = b.color().name();
  467. }
  468. }
  469. // ignore text bounding box, used only to display instead of
  470. // text at small zoom factors:
  471. if (painterPaths[k].getFeatureSize()<0) {
  472. continue;
  473. }
  474. var plText = undefined;
  475. shapes = painterPaths[k].getShapes();
  476. for (n=0; n<shapes.length; n++) {
  477. shape = shapes[n];
  478. if (isSplineShape(shape)) {
  479. // spline to arc or line or spline:
  480. if (textSplineToLineOrArc) {
  481. shape = ShapeAlgorithms.splineToLineOrArc(shape, splineTolerance);
  482. }
  483. if (textToPolylines) {
  484. // spline to polyline with arcs:
  485. if (isSplineShape(shape)) {
  486. if (RSpline.hasProxy() && !splinesToLineSegments) {
  487. shape = shape.approximateWithArcs(splineTolerance);
  488. }
  489. else {
  490. shape = shape.toPolyline(splineSegments);
  491. }
  492. }
  493. }
  494. }
  495. if (!isNull(shape)) {
  496. var sc = shape.clone();
  497. sc.color = col;
  498. if (textToPolylines) {
  499. // explode to polylines:
  500. if (!isNull(plText) && plText.getEndPoint().equalsFuzzy(shape.getStartPoint())) {
  501. plText.appendShape(sc);
  502. }
  503. else {
  504. if (!isNull(plText)) {
  505. plText.toLogicallyClosed();
  506. }
  507. plText = new RPolyline();
  508. ret.push(plText);
  509. plText.appendShape(sc);
  510. }
  511. }
  512. else {
  513. // explode to lines, arcs, polylines:
  514. ret.push(sc);
  515. }
  516. }
  517. }
  518. if (textToPolylines) {
  519. if (!isNull(plText)) {
  520. plText.toLogicallyClosed();
  521. }
  522. }
  523. }
  524. }
  525. }
  526. // explode attribute entities into texts:
  527. else if (isAttributeEntity(entity)) {
  528. // create text data from attribute data:
  529. d = new RTextData(entity.getData());
  530. // unlink from parent (block ref):
  531. d.setParentId(RObject.INVALID_ID);
  532. e = new RTextEntity(document, d);
  533. e.setSelected(true);
  534. if (isFunction(entity.data)) {
  535. e.copyAttributesFrom(getPtr(entity));
  536. }
  537. else {
  538. e.copyAttributesFrom(entity);
  539. }
  540. ret.push(e);
  541. }
  542. // explode block reference or block reference array:
  543. else if (isBlockReferenceEntity(entity)) {
  544. var data = entity.getData();
  545. var pos = entity.getPosition();
  546. var uniform = RMath.fuzzyCompare(entity.getScaleFactors().x, entity.getScaleFactors().y);
  547. // explode array into multiple block references:
  548. if (data.getColumnCount()>1 || data.getRowCount()>1) {
  549. for (col=0; col<data.getColumnCount(); col++) {
  550. for (row=0; row<data.getRowCount(); row++) {
  551. var offset = data.getColumnRowOffset(col, row, true);
  552. e = entity.clone();
  553. e.setRowCount(1);
  554. e.setColumnCount(1);
  555. e.setPosition(pos.operator_add(offset));
  556. storage.setObjectId(e, RObject.INVALID_ID);
  557. e.setSelected(true);
  558. ret.push(e);
  559. }
  560. }
  561. }
  562. // explode block reference into contained entities:
  563. else {
  564. var subIds = document.queryBlockEntities(data.getReferencedBlockId());
  565. for (k=0; k<subIds.length; k++) {
  566. var subEntity = data.queryEntity(subIds[k], true);
  567. if (isNull(subEntity)) {
  568. continue;
  569. }
  570. if (!isBlockReferenceEntity(subEntity)) {
  571. subEntity.scaleVisualProperties(data.getScaleFactors().x);
  572. }
  573. // ignore attribute definitions:
  574. if (isAttributeDefinitionEntity(subEntity)) {
  575. continue;
  576. }
  577. // ignore hatch in non-uniformly scaled block reference:
  578. if (!uniform && isHatchEntity(subEntity)) {
  579. EAction.handleUserWarning(qsTr("Ignored hatch in block reference with non-uniform scale factors"));
  580. continue;
  581. }
  582. e = subEntity.clone();
  583. //data.applyColumnRowOffsetTo(e, col, row);
  584. // we need the old ID to update attribute parent IDs:
  585. //storage.setObjectId(e, RObject.INVALID_ID);
  586. e.setBlockId(document.getCurrentBlockId());
  587. e.setSelected(true);
  588. ret.push(e);
  589. }
  590. }
  591. }
  592. return ret;
  593. };