middle-point-drawer.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * iGeom by LInE
  3. * Geometric Object: Segment
  4. * Drawer to Segment
  5. * www.usp.br/line
  6. * www.matematica.br/igeom
  7. * ./app/components/middle-point/drawers/middle-point-drawer.js
  8. *
  9. * @version 2024/09/28: fixed import bug (now coord. of MidPoint is effectively updated in movements)
  10. * @version 2020/11/02: indentation
  11. */
  12. import { ELEMENTS_CLASS } from "../../../core/enums/elements-class-enum";
  13. import { label as Label } from "../../../component-registry/label";
  14. import { DrawerAggregator } from "../../../core/drawers/drawer-aggregator";
  15. import { selector as Selector } from "../../../core/application/selector";
  16. import { PointDrawer } from "../../point-component/drawers/point-drawer";
  17. import { objects as Objects } from "../../../core/application/objects";
  18. import { SelectableDrawer } from "../../../core/drawers/selectable-drawer";
  19. import { PointModel } from "../../point-component/models/point-model";
  20. import { MiddlePointModel } from "../models/middle-point-model";
  21. // MiddlePointDrawer extends PointDrawer (app/components/point-component/drawers/point-drawer.js)
  22. export class MiddlePointDrawer extends PointDrawer {
  23. static count2debug = 1; //DEBUG
  24. static FIRST_POINT_STATE () {
  25. return "FIRST_POINT";
  26. }
  27. static SECOND_POINT_STATE () {
  28. return "SECOND_POINT";
  29. }
  30. // A single instace of "MiddlePointDrawer" is created
  31. constructor () { // constructor of any MidPoint (called once at the begining
  32. super();
  33. this.id = MiddlePointDrawer.count2debug++; //DEBUG
  34. //D console.log("middle-point-drawer.js: constructor(): this.id=" + this.id);
  35. this.pointA; // origin
  36. this.pointB; // end point
  37. this.aggregatorA;
  38. this.aggregatorB;
  39. this.label;
  40. this.states = [MiddlePointDrawer.FIRST_POINT_STATE, MiddlePointDrawer.SECOND_POINT_STATE];
  41. this.middlePoint; // also MidPoint? (missing the segment!)
  42. this.pointDrawer = new PointDrawer();
  43. super.setElementClass(ELEMENTS_CLASS.MIDDLE_POINT);
  44. }
  45. setPointA (point) {
  46. this.pointA = point;
  47. console.log("middle-point-drawer.js: setPointA(point): point.id=" + point.id);
  48. }
  49. setPointB(point) {
  50. this.pointB = point;
  51. console.log("middle-point-drawer.js: setPointB(point): point.id=" + point.id);
  52. }
  53. setPointC(point) { //REMOVER
  54. this.pointC = point;
  55. console.log("middle-point-drawer.js: setPointC(point): point.id=" + point.id);
  56. }
  57. // @calledby this.drawByStates(konvaObject): this.setAggregatorA(aggregator);
  58. setAggregatorA (aggregator) {
  59. this.aggregatorA = aggregator;
  60. this.setPointA(aggregator.genericObject);
  61. // console.trace(); //D detectar erro aggregatorA.id=3 mas aggregatorA.genericObject.id=2!
  62. console.log("middle-point-drawer.js: setAggregatorA(aggregator): aggregatorA.id=" + aggregator.id + ", aggregatorA.genericObject.id=" + aggregator.genericObject.id);
  63. }
  64. setAggregatorB (aggregator) {
  65. this.aggregatorB = aggregator;
  66. this.setPointB(aggregator.genericObject);
  67. console.log("middle-point-drawer.js: setAggregatorB(aggregator): aggregatorB.id=" + aggregator.id + ", aggregatorB.genericObject.id=" + aggregator.genericObject.id);
  68. }
  69. setAggregatorC (aggregator) { //REMOVER
  70. this.aggregatorC = aggregator;
  71. this.setPointC(aggregator.genericObject);
  72. console.log("middle-point-drawer.js: setAggregatorC(aggregator): aggregator.genericObject.id=" + aggregator.genericObject.id);
  73. }
  74. //DEBUG print coordinates of point
  75. pp (point) { var px="",py="";
  76. try { //D //leo
  77. px=""+point.id+":"+point.posX; py=""+point.posY; var aux1="", aux2="";
  78. var items = px.split("."); if (items && items.length>1) aux1 = "." + items[1].substr(0,3); px = items[0] + aux1; // pegar apenas 3 digitos
  79. var items = py.split("."); if (items && items.length>1) aux2 = "." + items[1].substr(0,3); py = items[0] + aux2; // pegar apenas 3 digitos
  80. } catch (e) {
  81. console.log("pp(.): erro! " + e); }
  82. return "(" + px + "," + py + ")";
  83. }
  84. // @calledby app/core/models/components/component.js: draw(e): this.drawer.draw(e);
  85. draw (e) { // First "click" on MidlePoint icon reache this point
  86. console.log("middle-point-drawer.js!draw(e)");
  87. if (e != undefined) { //
  88. if (e.target != undefined && e.target.attrs.class != undefined &&
  89. (e.target.attrs.class == ELEMENTS_CLASS.POINT || e.target.attrs.class == ELEMENTS_CLASS.INTERSECTION_POINT)) {
  90. console.log(" * 4. b, e.target.attrs=" + JSON.stringify(e.target.attrs)); // first and second point already exists
  91. this.drawByStates(e.target); // create the final point defining this MidPoint
  92. return;
  93. }
  94. else if (e.attrs != undefined && e.attrs.genericObject != undefined) {
  95. console.log(" * 5. c");
  96. this.drawByMiddlePoint(e.attrs.genericObject)
  97. return;
  98. }
  99. }
  100. // Selected MidPoint constructor
  101. const points = Selector.getSelectedPoints();
  102. if (points == undefined || points.length == 0) {
  103. this.drawByStates(); // create this MidPoint
  104. var aux1 = (this.middlePoint && this.middlePoint.id ? this.middlePoint.id : "<>");
  105. console.log(" * 6. apos 'this.drawByStates()' this.middlePoint.id=" + aux1 + "; points=0"); //D //leo
  106. return;
  107. }
  108. console.log(" * 7. this.middlePoint.id="+(this.middlePoint&&this.middlePoint.id?this.middlePoint.id:"<>") + " #points=" + points.length + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx "); //D //leo
  109. if (points.length >= 2)
  110. this.drawByPoints(points); // necessary to crate new MidPoint from 2 already existing point (mode "selection + action")
  111. } // draw(e)
  112. drawByStates (konvaObject) {
  113. let aggregator = undefined;
  114. var aux = "";
  115. if (konvaObject != undefined) {
  116. aggregator = Objects.getByKonvaObject(konvaObject)[0];
  117. aux += " (1) aggregator.id=" + (aggregator!=undefined ? aggregator.id : "<>") + "; ";
  118. }
  119. if (this.state == undefined) {
  120. super.setState(MiddlePointDrawer.FIRST_POINT_STATE);
  121. console.log("middle-point-drawer.js!drawByStates(konvaObject): " + aux + " (2) FIRST_POINT_STATE; ");
  122. }
  123. else if (this.state == MiddlePointDrawer.FIRST_POINT_STATE) { // second "click" after initial Point => creates final Point
  124. try {
  125. // aggregator=["id","drawer","genericObject","konvaObject","aggregators","visible","elementClass"]
  126. // var aux2 = ", aggregator=" + JSON.stringify(Object.keys(aggregator)); // JSON.stringify(aggregator) => "TypeError: cyclic object value"
  127. // aggregator[id, genericObject.id, #aggregators, elementClass]=[3, 2, 0, 13]
  128. var aux2 = (aggregator!=undefined ? ", aggregator[id, genericObject.id, #aggregators, elementClass]=[" + aggregator.id + ", " + aggregator.genericObject.id
  129. + ", " + aggregator.aggregators.length + ", " + aggregator.elementClass + "]" : "<>");
  130. aggregator = aggregator != undefined ? aggregator : this.pointDrawer.drawPoint(); // drawPoint() provides "point" to "this.pointA"
  131. this.setAggregatorA(aggregator); // will associate "this.pointA" with "aggregator.genericObject"
  132. console.log("middle-point-drawer.js!drawByStates(konvaObject): aggregatorA.id=" + aggregator.id + aux2);
  133. } catch (e) { console.log("middle-point-drawer.js!drawByStates(.): 4 - erro " + e); }
  134. console.log("middle-point-drawer.js!drawByStates(konvaObject): aggregatorA.id=" + aggregator.id + ", this.pointA.id=" + this.pointA.id);
  135. super.setState(MiddlePointDrawer.SECOND_POINT_STATE);
  136. }
  137. else if (this.state == MiddlePointDrawer.SECOND_POINT_STATE) { // second "click" after final Point => creates MidPoint
  138. console.log("middle-point-drawer.js!drawByStates(.): 5");
  139. aggregator = aggregator != undefined ? aggregator : this.pointDrawer.drawPoint(); // drawPoint() provides "point" to "this.pointB"
  140. this.setAggregatorB(aggregator); // will associate "this.pointB" with "aggregator.genericObject"
  141. var aux = ", A=" + this.pp(this.pointA) + ", B=" + this.pp(this.pointB) + ": ";
  142. console.log("middle-point-drawer.js!drawByStates(konvaObject): aggregatorB.id=" + aggregator.id + ", this.pointB.id=" + this.pointB.id + aux); //D//leo
  143. this.draggable = false; //novo
  144. const coord = MiddlePointModel.getMiddlePointPos(this.pointA, this.pointB); // get coord. of defining points
  145. this.posX = coord.posX; this.posY = coord.posY;
  146. this.drawByPoints([this.pointA, this.pointB], [this.aggregatorA, this.aggregatorB]); //x origem do 2o MidPoint!
  147. super.setState(MiddlePointDrawer.FIRST_POINT_STATE); // return to the state initial
  148. }
  149. } // drawByStates(konvaObject)
  150. drawByPoints (points, aggregators) { // create 2 midpoint with the points A and B already created
  151. console.log("middle-point-drawer.js!drawByPoints(.): #points=" + points.length); //D var aux = "";
  152. if (points == undefined || points.length < 1) return;
  153. try { // Considering this as C=MidPoint(A,B)
  154. this.setPointA(points[0]); // get source point A
  155. this.setPointB(points[1]); // get source point B
  156. aggregators = this.resolveAggregators(points, aggregators, true); // get the lists of dependents of point A and point B
  157. this.label = Label.draw(false); // app/component-registry/label.js : draw(lower = false) => this.pushUpper();
  158. // this.middlePoint = new MiddlePointModel(this.pointA, this.pointB, this.label, -1); // now create Segment - 'drawByStates(konvaObject)' already created the MidPoint pointC
  159. // Now create this MidPoint
  160. this.middlePoint = new MiddlePointModel(this.pointA, this.pointB, this.label); // now create Segment - 'drawByStates(konvaObject)' already created the MidPoint pointC
  161. this.drawByMiddlePoint(this.middlePoint);
  162. this.reset();
  163. } catch (error) { console.log("middle-point-drawer.js!drawByPoints(.): " + error); }
  164. console.log("middle-point-drawer.js!drawByPoints(.): final");
  165. } // drawByPoints(points, aggregators)
  166. drawByMiddlePoint (middlePoint, draggable, selectable) {
  167. try {
  168. this.middlePoint = middlePoint;
  169. this.middlePoint.backgroundColor = "#f54260";
  170. const group = SelectableDrawer.getKonvaGroup(false);
  171. const text = MiddlePointDrawer.getKonvaText(middlePoint, middlePoint.label); // app/component-registry/label.js :
  172. // const midpoint = MiddlePointDrawer.getKonvaCircle(middlePoint);
  173. const midpoint = MiddlePointDrawer.getKonvaCircle(middlePoint, draggable, selectable); // apos introd. param. ", draggable, selectable"
  174. midpoint.selectable = true;
  175. // const circle = PointDrawer.getKonvaCircle(point, draggable, selectable);
  176. group.add(text);
  177. group.add(midpoint);
  178. super.setKonvaObject(group);
  179. const aggregator = new DrawerAggregator(
  180. this, this.middlePoint,
  181. group, ELEMENTS_CLASS.MIDDLE_POINT
  182. );
  183. console.log("middle-point-drawer.js!drawByMiddlePoint(.): insert this C=MidPoint(A,B) in the list of dependents of A or of B"); //DEBUG
  184. try { // Insert this MidPoint C=MidPoint(A,B) in the list of drawers dependents of A and of B (in app/core/drawers/drawer.js)
  185. //D "C:=MidPoint(A,B); D:=MidPoint(C,B);" could launch error "TypeError: cyclic object value", try/catch allow running with no error
  186. super.addAggregator(aggregator); // PointDrawer (app/components/point-component/drawers/point-drawer.js) extends SelectableDrawer
  187. } catch (error) { console.log("middle-point-drawer.js!drawByMiddlePoint(.): error in 'super.addAggregator(aggregator): " + error); }
  188. const aggregators = this.resolveAggregators([this.middlePoint.pointA, this.middlePoint.pointB], undefined);
  189. aggregators[1].addAggregator(aggregator); // Insert this MidPoint C in the list of dependents of point A
  190. aggregators[0].addAggregator(aggregator); // Insert this MidPoint C in the list of dependents of point B
  191. //D console.log("app/components/middle-point/drawers/middle-point-drawer.js: drawByMiddlePoint"); //leo
  192. SelectableDrawer.drawObject(this.konvaObject); //
  193. this.konvaObject.zIndex(1);
  194. super.batchDraw(); // ../../../core/drawers/drawer-aggregator.js
  195. SelectableDrawer.setMaxIndex(aggregators[0].konvaObject);
  196. SelectableDrawer.setMaxIndex(aggregators[1].konvaObject);
  197. } catch (error) { console.log("middle-point-drawer.js!drawByMiddlePoint(middlePoint): " + error); }
  198. } // drawByMiddlePoint(middlePoint)
  199. resolveAggregators (points, aggregators, selected) {
  200. this.pointA = points[0];
  201. this.pointB = points[1];
  202. if (aggregators == undefined && selected == true)
  203. aggregators = Selector.getSelectedPointsAggregators();
  204. else {
  205. aggregators = [
  206. Objects.getByGenericObject(this.pointA)[0],
  207. Objects.getByGenericObject(this.pointB)[0],
  208. ];
  209. }
  210. return aggregators;
  211. }
  212. //DEBUG
  213. distancePointMouseclick (midPoint, e) {
  214. var distX = midPoint.posX-e.evt.offsetX, distY = midPoint.posY-e.evt.offsetY;
  215. return ((distX*distX + distY*distY)); // this MidPoint only small distance!
  216. }
  217. // Update MidPoint after any movement of one point that impact this MidPoint
  218. // @calledby ./src/app/core/drawers/drawer-aggregator.js!updateAggregators(aggregators,e): aggregator.drawer.update(aggregator, e);
  219. update (aggregator, e) {
  220. //D if (MiddlePointDrawer.count2debug==2) { //D
  221. //D console.log(" * middle-point-drawer!update(.): aggregator.id="+(aggregator!=undefined ? aggregator.id : "<>")+", count2debug="+MiddlePointDrawer.count2debug);
  222. //D console.trace();
  223. //D } //D
  224. if (!aggregator.visible) {
  225. console.log(" * middle-point-drawer!update(.): aggregator.id=" + (aggregator!=undefined ? aggregator.id : "<>") + " with !aggregator.visible"); //D
  226. return;
  227. }
  228. var aux = "\n[1], ", aux2; //D
  229. try {
  230. const pointA = aggregator.genericObject.pointA; // initial point that define MidPoint
  231. const pointB = aggregator.genericObject.pointB; // final point
  232. aux += "[2], "; //D
  233. const coord = aggregator.genericObject.getMiddlePoint(); // app/components/middle-point/models/middle-point-model.js
  234. aux += "[3], "; //D
  235. // console.log(" * middle-point-drawer!update(.): A.id=" + pointA.id + "=" + this.pointA.id + ", B.id=" + pointB.id + ", C.id="+pointC.id+", : " + aux);
  236. aggregator.konvaObject.children[0].x(coord.posX); // Konva.Text : used to the MidPoint label X coord.
  237. aggregator.konvaObject.children[0].y(coord.posY - 20); // used to the MidPoint label Y coord.
  238. var point = aggregator.konvaObject.children[1]; // Konva.Circle : used to draw the point
  239. //D aux2 = point.attrs; // atributes of KonvaObject
  240. //D aux += "[4], children[1]=(" + aux2.x + "," + aux2.y + "), " + point.className; // JSON.stringify(point); //D
  241. // Now update the coordinates of this midpoint: need to use KonvaObject (type Point) functions "point.x(.)" and "point.y(.)"
  242. //this.posX = coord.posX; // xxx no effect!
  243. //this.posY = coord.posY; // xxx no effect!
  244. point.x(coord.posX); // update X coord. of the label of this MidPoint
  245. point.y(coord.posY); // update Y coord. of the label of this MidPoint
  246. aggregator.genericObject.posX = coord.posX; // really update internal X coord. of this MidPoint
  247. aggregator.genericObject.posY = coord.posY; // really update internal Y coord. of this MidPoint
  248. //D console.log("middle-point-drawer.js!update(aggregator, e): this.id=" + this.id + ", aggregator.genericObject.id=" + aggregator.genericObject.id + " : MP=MidPoint[" + this.pp(aggregator.genericObject) + "], A=" + this.pp(pointA) + ", B=" + this.pp(pointB) + ""); // + aux
  249. } catch (error) {
  250. console.log("middle-point-drawer.js!update(.): error = " + error + "\n" + aux);
  251. }
  252. super.batchDraw(); // app/core/drawers/drawer.js: batchDraw(): Drawer.stageBatchDraw(); | static stageBatchDraw(): DrawerManager.batchDraw();
  253. // app/core/drawers/drawer-manager.js: batchDraw()
  254. }
  255. insertPoint (aggregator) { //REMOVER
  256. const pointA = aggregator.genericObject.pointA;
  257. const pointB = aggregator.genericObject.pointB;
  258. const pointCAggregator = this.pointDrawer.drawPoint();
  259. aggregator.konvaObject.points([
  260. pointA.posX, pointA.posY,
  261. pointB.posX, pointB.posY
  262. ]);
  263. super.batchDraw();
  264. }
  265. static getKonvaText (MiddlePoint, label) {
  266. const pos = MiddlePoint.getMiddlePoint();
  267. return new Konva.Text({
  268. x: pos.posX,
  269. y: pos.posY - 20,
  270. text: label,
  271. fontSize: 14,
  272. fontFamily: "Calibri",
  273. fill: "#434a45",
  274. stroke: "#ffffff",
  275. strokeWidth: 0.2,
  276. draggable: false,
  277. resizeEnabled: false,
  278. transformEnabled: false,
  279. selectable: false
  280. });
  281. }
  282. static getKonvaLine (pointA, pointB, useLabel) {
  283. const points = [pointA.posX, pointA.posY, pointB.posX, pointB.posY];
  284. const line = new Konva.Line({
  285. points: points,
  286. stroke: "grey",
  287. strokeWidth: 2,
  288. lineJoin: "round",
  289. draggable: false,
  290. strokeScaleEnabled: false,
  291. class: ELEMENTS_CLASS.LINE_SEGMENT,
  292. connections: [],
  293. index: 1,
  294. selectable: false,
  295. draggable: false,
  296. style: { stroke: "grey", fill: "grey" }
  297. });
  298. SelectableDrawer.setSelectableIfIntersectionChanged(line);
  299. return line;
  300. }
  301. static drawKonvaLine(pointA, pointB) {
  302. const line = MiddlePointDrawer.getKonvaLine(pointA, pointB);
  303. return line;
  304. }
  305. }