intersection-drawer.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * iGeom by LInE
  3. * Provides intersetion point to Geometric Objects (GO)
  4. * www.matematica.br/igeom
  5. * ./app/components/intersection-component/drawers/intersection-drawer.js
  6. * @calledby
  7. * @version 2020/11/02: Implemented Line instersection.
  8. */
  9. import { PointDrawer } from "../../point-component/drawers/point-drawer";
  10. import { ELEMENTS_CLASS } from "../../../core/enums/elements-class-enum";
  11. import { Drawer } from "../../../core/drawers/drawer";
  12. import { app as App } from "../../../app";
  13. import { objects } from "../../../core/application/objects";
  14. import { DrawerAggregator } from "../../../core/drawers/drawer-aggregator";
  15. import { intersectionService } from "../services/intersection-service";
  16. export class IntersectionDrawer extends Drawer {
  17. static FIRST_OBJECT_STATE () {
  18. return "FIRST_OBJECT";
  19. }
  20. static SECOND_OBJECT_STATE () {
  21. return "SECOND_OBJECTf";
  22. }
  23. constructor () {
  24. super();
  25. this.aggregatorA;
  26. this.aggregatorB;
  27. this.label;
  28. this.states = [IntersectionDrawer.FIRST_OBJECT_STATE, IntersectionDrawer.SECOND_OBJECT_STATE];
  29. this.intersections = [];
  30. this.pointDrawer = new PointDrawer();
  31. super.setElementClass(ELEMENTS_CLASS.INTERSECTION_POINT);
  32. }
  33. // @calledby ./app/core/drawers/stage.js! draw (e): this.drawer.draw(e);
  34. draw (e) {
  35. var auxE = "", aux = "debug - uncomment 'aux' = "; //D console.log("intersection-drawer.js!draw(e): inicio");
  36. var aux4 = "";
  37. try {
  38. if (e != undefined && e.attrs != undefined) { //D
  39. auxE += "1, "; //D
  40. this.aggregatorA = this.getObjectAggregatorByGenericObject(e.attrs.genericObject.og1);
  41. this.aggregatorB = this.getObjectAggregatorByGenericObject(e.attrs.genericObject.og2);
  42. this.drawByIntersectionPoints([e.attrs.genericObject]);
  43. var aux2 = "this.aggregatorA.id=" + (this.aggregatorA!=undefined?this.aggregatorA.id:"<>");
  44. aux2 += ", this.aggregatorB.id=" + (this.aggregatorB!=undefined?this.aggregatorB.id:"<>");
  45. console.log("intersection-drawer.js!draw(e): final 1 - " + aux2);
  46. return;
  47. } //D
  48. auxE += "2, "; //D
  49. if (e == undefined || !this.isValidObject(e.target)) {
  50. var aux3 = (e==undefined? " e==undefined" : (e.target==undefined? "e.target==undefined?" : (e.target.attrs==undefined ? "e.target.attrs==undefined" : undefined)) );
  51. console.log("intersection-drawer.js!draw(e): final 2, e : " + aux3);
  52. return;
  53. } //D
  54. auxE += "3, "; //D
  55. const selectedTool = App.getSelectedTool();
  56. if (selectedTool != undefined && selectedTool.drawer != undefined && selectedTool.drawer.elementClass == ELEMENTS_CLASS.INTERSECTION_POINT) {
  57. //D
  58. auxE += "4, ";
  59. if (this.state == undefined || this.state == IntersectionDrawer.FIRST_OBJECT_STATE) { //D
  60. auxE += "5, ";
  61. try {
  62. aux4 = "setFirstObject: this.aggregatorA.id = " + (e.target==undefined ? "<>" : JSON.stringify(Object.keys(e.target))); // this.getObjectAggregator(e.target).id);
  63. // intersection-drawer.js!draw(e): final 3, setFirstObject: error in this.getObjectAggregator(e.target) TypeError: this.getObjectAggregator(...) is undefined
  64. // aux4 += ", e.target=" + JSON.stringify(e.target);
  65. } catch (error) { aux4 = "setFirstObject: error in this.getObjectAggregator(" + JSON.stringify(Object.keys(e.target)) + ") " + error; };
  66. auxE += "6, ";
  67. this.setFirstObject(e.target); // this.aggregatorA = this.getObjectAggregator(e.target)
  68. this.setState(IntersectionDrawer.SECOND_OBJECT_STATE);
  69. auxE += "7, ";
  70. }
  71. else if (this.state == IntersectionDrawer.SECOND_OBJECT_STATE) { //D
  72. auxE += "8, ";
  73. aux4 = "setSecondObject: this.aggregatorB.id = " + (e.target==undefined ? "<>" : this.getObjectAggregator(e.target).id);
  74. this.setSecondObject(e.target); // this.aggregatorB = this.getObjectAggregator(e.target)
  75. this.drawPoint();
  76. aux += "9, ";
  77. this.reset();
  78. aux += "10, ";
  79. // this.clear();
  80. }
  81. }
  82. } catch (error) { console.log("intersection-drawer.js!draw(e): " + error + " " + auxE + "\n * " + aux); }
  83. console.log("intersection-drawer.js!draw(e): final 3, " + aux4);
  84. } // draw(e)
  85. setFirstObject (konvaObject) {
  86. var aggregator = null;
  87. var auxE = "";
  88. try {
  89. aggregator = this.getObjectAggregator(konvaObject); auxE = " (after aggregator)";
  90. this.aggregatorA = aggregator;
  91. } catch (error) { console.log("intersection-drawer.js!setFirstObject(konvaObject): " + error + auxE); }
  92. }
  93. setSecondObject (konvaObject) {
  94. var aggregator = null;
  95. var auxE = "";
  96. try {
  97. aggregator = this.getObjectAggregator(konvaObject); auxE = " (after aggregator)";
  98. this.aggregatorB = aggregator;
  99. } catch (error) { console.log("intersection-drawer.js!setSecondObject(konvaObject): " + error + auxE); }
  100. }
  101. static count = 0;
  102. getObjectAggregator (konvaObject) {
  103. const answer = objects.getByKonvaObject(konvaObject); // app/core/application/objects.js: getByKonvaObject(konvaObject)
  104. IntersectionDrawer.count++; // D console.trace();
  105. console.log("intersection-drawer.js!getObjectAggregator(konvaObject): " + IntersectionDrawer.count +
  106. " objects.getByKonvaObject(konvaObject) = " + JSON.stringify(Object.keys(answer))); // Object.keys to avoid "TypeError: cyclic object value"
  107. return answer[0];
  108. }
  109. getObjectAggregatorByGenericObject (genericObject) {
  110. return objects.getByGenericObject(genericObject)[0];
  111. }
  112. // Avoid to create intersection between lines/segments when some defining point is the intersection
  113. // Return true <=> need a new point
  114. alreadyHasIntersection (og1, og2, str_a1, str_a2) {
  115. // app/core/enums/elements-class-enum.js : ELEMENTS_CLASS.LINE, ELEMENTS_CLASS.LINE_SEGMENT, ELEMENTS_CLASS.CIRCUMFERENCE
  116. // Avoid duplicate intersection between line/segment with line/segment
  117. if ((og1.elementClass==ELEMENTS_CLASS.LINE || og1.elementClass==ELEMENTS_CLASS.LINE_SEGMENT) &&
  118. (og2.elementClass==ELEMENTS_CLASS.LINE || og2.elementClass==ELEMENTS_CLASS.LINE_SEGMENT)) {
  119. // Try to avoid redundant point
  120. if (og1.pointA==og2.pointA || og1.pointA==og2.pointB || og1.pointB==og2.pointA || og1.pointB==og2.pointB) {
  121. var aux2 = " "+og1.pointA+","+og1.pointB+";"+og2.pointA+","+og2.pointB+" ";
  122. console.log("intersection-drawer.js!alreadyHasIntersection(): existing intersection, nothing to be done: " + str_a1 + " , " + str_a2 + ", " + aux2);
  123. //TODO need to become visible? "og1.visible = true;" or "og2.visible = true;"
  124. return true;
  125. }
  126. }
  127. // Avoid duplicate intersection between line/segment with circumference
  128. var ogLine = null, ogCirc = null;
  129. if (og1.elementClass==ELEMENTS_CLASS.LINE || og1.elementClass==ELEMENTS_CLASS.LINE_SEGMENT) ogLine = og1;
  130. else if (og1.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE || og1.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE) ogCirc = og1;
  131. if (og2.elementClass==ELEMENTS_CLASS.LINE || og2.elementClass==ELEMENTS_CLASS.LINE_SEGMENT) ogLine = og2;
  132. else if (og2.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE || og2.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE) ogCirc = og2;
  133. if (ogLine!=null && ogCirc!=null) { // is Line/Segment and Circumference
  134. // Try to avoid redundant point
  135. if (ogLine.pointA==ogCirc.radius || ogLine.pointB==ogCirc.radius) {
  136. var aux2 = " Line/Segment with (A,B)=("+ogLine.pointA + "," + ogLine.pointB + "); Circ.=" + ogCirc.radius + " ";
  137. console.log("intersection-drawer.js!alreadyHasIntersection(): existing intersection, nothing to be done: " + str_a1 + " , " + str_a2 + ", " + aux2);
  138. //TODO need to become visible? "ogLine.visible = true;" or "ogCirc.visible = true;"
  139. return false; // let "app/components/line-segment-component/models/line-segment-model.js!getIntersectionWithCircumference(.)" treat this case!
  140. // return true;
  141. }
  142. }
  143. return false;
  144. }
  145. // Used to create new intersection point
  146. //@calledby this.draw()
  147. drawPoint () {
  148. var og1, og2, str_a1, str_a2;
  149. if (this.aggregatorA==undefined || this.aggregatorB==undefined) {
  150. if (this.aggregatorA==undefined)
  151. this.aggregatorA = this.aggregatorB;
  152. console.log("intersection-drawer.js!drawPoint(): error undefined: this.aggregatorA=" + this.aggregatorA + " or this.aggregatorB=" + this.aggregatorB);
  153. return;
  154. }
  155. og1 = this.aggregatorA.genericObject, og2 = this.aggregatorB.genericObject;
  156. str_a1 = "og1=(" + og1.elementClass + ",id=" + og1.id + ")"; //D genericObject
  157. str_a2 = "og2=(" + og2.elementClass + ",id=" + og2.id + ")"; //D
  158. if (this.alreadyHasIntersection(og1,og2,str_a1,str_a2))
  159. return; // intersection already defined by line/segment.pointA or pointB
  160. console.log("intersection-drawer.js!drawPoint(): create intersection between " + str_a1 + " , " + str_a2); //D //leo
  161. // Really create the intersection: line-segment-model.js!getIntersectionByLine(.); getIntersectionWithCircumference(.)
  162. // app/components/: line-component/models/line-model.js; line-segment-component/models/line-segment-model.js; circumference-component/models/circumference-model.js
  163. const intersectionOg1Og2 = og1.getIntersection(og2); // get [ṔA, PB], but perhaps PA or PB is Point, NOT IntersectionPoint!
  164. // app/components/intersection-component/services/intersection-service.js
  165. const intersectionPoints = intersectionService.addIntersections(intersectionOg1Og2, og1, og2);
  166. this.drawByIntersectionPoints(intersectionPoints);
  167. }
  168. drawByIntersectionPoints (intersectionPoints) {
  169. for (let index = 0; index < intersectionPoints.length; index++) {
  170. const intersectionPoint = intersectionPoints[index];
  171. if (intersectionPoint.og1 == undefined) {
  172. //D console.log("intersection-drawer.js!drawByIntersectionPoints(.): " + index + ": intersectionPoint.id=" + intersectionPoint.id + " og1 undefined");
  173. continue; // this point already exists!
  174. }
  175. //D else console.log("intersection-drawer.js!drawByIntersectionPoints(.): " + index + ": intersectionPoint.id=" + intersectionPoint.id + "");
  176. intersectionPoint.update();
  177. // if (!intersectionPoint.visible) return;
  178. const point = PointDrawer.drawPoint(intersectionPoint, true, false, true);
  179. const aggregator = new DrawerAggregator(this, intersectionPoint, point.konvaObject, ELEMENTS_CLASS.INTERSECTION_POINT);
  180. super.addAggregator(aggregator);
  181. this.aggregatorB.addAggregator(aggregator);
  182. this.aggregatorA.addAggregator(aggregator);
  183. }
  184. }
  185. isValidObject (konvaObject) {
  186. switch (konvaObject.attrs.class) {
  187. case ELEMENTS_CLASS.LINE:
  188. return true;
  189. case ELEMENTS_CLASS.LINE_SEGMENT:
  190. return true;
  191. case ELEMENTS_CLASS.CIRCUMFERENCE:
  192. return true;
  193. case ELEMENTS_CLASS.MIDDLE_POINT:
  194. return true;
  195. default:
  196. return false;
  197. }
  198. }
  199. update (aggregator, e) {
  200. aggregator.genericObject.update(aggregator, e);
  201. if (!aggregator.genericObject.visible || aggregator.genericObject.posX == Number.MAX_SAFE_INTEGER) {
  202. if (aggregator.visible) {
  203. aggregator.konvaObject.hide();
  204. aggregator.aggregators.forEach(a => {
  205. a.visible = false;
  206. a.konvaObject.hide();
  207. });
  208. this.batchDraw();
  209. }
  210. aggregator.visible = false;
  211. return;
  212. }
  213. //todo: konva objects
  214. aggregator.konvaObject.children[0].x(aggregator.genericObject.posX + 10);
  215. aggregator.konvaObject.children[0].y(aggregator.genericObject.posY - 10);
  216. aggregator.konvaObject.children[1].x(aggregator.genericObject.posX);
  217. aggregator.konvaObject.children[1].y(aggregator.genericObject.posY);
  218. if (!aggregator.visible || aggregator.genericObject.posX == Number.MAX_SAFE_INTEGER) {
  219. aggregator.genericObject.visible = true;
  220. aggregator.konvaObject.show();
  221. aggregator.aggregators.forEach(a => {
  222. a.visible = true;
  223. a.konvaObject.show();
  224. });
  225. aggregator.visible = true;
  226. }
  227. this.batchDraw();
  228. }
  229. reset () {
  230. this.aggregatorA = undefined;
  231. this.aggregatorB = undefined;
  232. this.setState(undefined);
  233. }
  234. } // export class IntersectionDrawer extends Drawer