line-drawer.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * iGeom by LInE
  3. * Geometric Object: Straight Line
  4. * www.matematica.br/igeom
  5. * ./app/components/line-component/drawers/line-drawer.js
  6. * Draw the Straight Line
  7. */
  8. import { stageManager } from "../../../core/application/stage-manager"; // to get Canvas size 'stageManager.getSize();'
  9. import { ELEMENTS_CLASS } from "../../../core/enums/elements-class-enum";
  10. import { label as Label } from "../../../component-registry/label";
  11. import { LineModel } from "../models/line-model";
  12. import { objects as Objects } from "../../../core/application/objects";
  13. import { SelectableDrawer } from "../../../core/drawers/selectable-drawer";
  14. import { LineSegmentDrawer } from "../../line-segment-component/drawers/line-segment-drawer";
  15. import { DrawerAggregator } from "../../../core/drawers/drawer-aggregator";
  16. import { LineSegmentModel } from "../../line-segment-component/models/line-segment-model";
  17. export class LineDrawer extends LineSegmentDrawer {
  18. constructor () {
  19. super();
  20. this.setElementClass(ELEMENTS_CLASS.LINE);
  21. }
  22. drawByStates (konvaObject) {
  23. let aggregator = undefined;
  24. if (konvaObject != undefined) {
  25. aggregator = Objects.getByKonvaObject(konvaObject)[0];
  26. }
  27. if (this.state == undefined) {
  28. super.setState(LineDrawer.FIRST_POINT_STATE);
  29. } else if (this.state == LineDrawer.FIRST_POINT_STATE) {
  30. aggregator = aggregator != undefined ? aggregator : this.pointDrawer.drawPoint();
  31. this.setAggregatorA(aggregator);
  32. super.setState(LineDrawer.SECOND_POINT_STATE);
  33. } else if (this.state == LineDrawer.SECOND_POINT_STATE) {
  34. aggregator = aggregator != undefined ? aggregator : this.pointDrawer.drawPoint();
  35. this.setAggregatorB(aggregator);
  36. this.drawByPoints([this.pointA, this.pointB], [this.aggregatorA, this.aggregatorB]);
  37. super.setState(LineDrawer.FIRST_POINT_STATE);
  38. }
  39. }
  40. drawByLineSegment (lineSegment) { //TODO Nome adequado? Nao seria 'drawLine(lineSegment)'?
  41. this.lineSegment = lineSegment;
  42. const group = SelectableDrawer.getKonvaGroup(false);
  43. const text = LineDrawer.getKonvaText(lineSegment, lineSegment.label);
  44. group.add(text);
  45. const konvaObject = LineDrawer.getKonvaLine(lineSegment.pointA, lineSegment.pointB);
  46. group.add(konvaObject);
  47. super.setKonvaObject(group);
  48. const aggregator = new DrawerAggregator(this, this.lineSegment, group, ELEMENTS_CLASS.LINE);
  49. super.addAggregator(aggregator);
  50. const aggregators = this.resolveAggregators([this.lineSegment.pointA, this.lineSegment.pointB], undefined);
  51. aggregators[1].addAggregator(aggregator);
  52. aggregators[0].addAggregator(aggregator);
  53. // Sequence of calls:
  54. // ./app/core/drawers/drawer.js: static drawObject(object): DrawerManager.draw(object);
  55. // ./app/core/drawers/drawer-manager.js: draw(object): this.currentStage.draw(object);
  56. SelectableDrawer.drawObject(this.konvaObject); // in ./app/core/drawers/drawer.js: static drawObject(object): DrawerManager.draw(object);
  57. this.konvaObject.zIndex(1);
  58. //leo super.batchDraw(); //D usar novo metodo para desenhar, aproveitar o proprio 'update' - REMOVER
  59. this.update(aggregator,null);
  60. SelectableDrawer.setMaxIndex(aggregators[0].konvaObject); // mark object 1: A
  61. SelectableDrawer.setMaxIndex(aggregators[1].konvaObject); // mark object 2: B
  62. }
  63. // Draw Straight Line by its points
  64. drawByPoints (points, aggregators) {
  65. if (points == undefined || points.length < 1) return;
  66. this.setPointA(points[0]);
  67. this.setPointB(points[1]);
  68. aggregators = this.resolveAggregators(points, aggregators, true);
  69. this.label = Label.draw(true);
  70. this.lineSegment = new LineModel(this.pointA, this.pointB, this.label);
  71. // ./app/components/line-segment-component/drawers/line-segment-drawer.js
  72. // Use: ./app/components/line-segment-component/drawers/line-segment-drawer.js: drawByLineSegment(lineSegment)
  73. // Use: ./app/components/core/drawers/selectable-drawer
  74. this.drawByLineSegment(this.lineSegment); // here, makes: SelectableDrawer.drawObject(this.konvaObject);
  75. this.reset();
  76. }
  77. // Update straight line (Line)
  78. // Whenever points A=(ax,ay) or B=(bx,by), was moved
  79. // Let d=B-A, i.e., d=(dx,dy) where: dx=bx-ax, dy=by-ay
  80. // If necessary semi-space: build the vector "o" (ortogonal to the segment AB), with
  81. // "o"=(ox,oy) with ox = -dy, oy = dx (then the scalar product "o" by d is: o'd = ox*dx+oy*dy = -dy*dx+dx*dy = -dy*dx+dy*dx = 0 CQD)
  82. //
  83. // Model under Canvas: r(.) parametric equation of the straight line
  84. //
  85. // Possible configurations to be considered:
  86. // +----------+----------+----------+----------+
  87. // | A x | x B | B x | x A |
  88. // | x B | A x | x A | B x |
  89. // | (1) | (2) | (3) | (4) |
  90. // +----------+----------+----------+----------+
  91. // Straight line defined by points A,B (parametric equation by 'g'):
  92. // P(g) = A + g * (B-A) = A + g * d
  93. // Given W=canvas width and H=canvas height, find intersections with borders, i.e., find values of "g" such that:
  94. // r(g).x=0 or r(g).x=W or r(g).y=0 or r(g).y=H (call this "g" respectively as Lg, Rg, Ug, and Dg - these are dependent of A and B positions)
  95. // Ug
  96. // (0,0) +-------------+ (W,0) Lg: 0 = r(g).x = A.x + g.x * d.x => g.x = -A.x / d.x
  97. // | | Rg: W = r(g).x = A.x + g.x * d.x => g.x = (W-A.x) / d.x
  98. // Lg | | Rg
  99. // | | Ug: 0 = r(g).y = A.y + g.y * d.y => g.y = -A.y / d.y
  100. // (0,H) +-------------+ (W,a) Dg: H = r(g).y = A.y + g.y * d.y => g.y = (H-A.y) / d.y
  101. // Dg
  102. //
  103. // (1) Ug (2) Dg
  104. // (0,0) +------------o------------------+--> (0,0) +------------o------------------+-->
  105. // | o B Q | | o A Q |
  106. // Lg |P o A | Rg Rg | o B | Lg
  107. // +-o-----------------------------+ +-o-----------------------------+
  108. // \|/ Dg Ug
  109. update (aggregator, e) {
  110. if (!aggregator.visible) return;
  111. const pointA = aggregator.genericObject.pointA; // A
  112. const pointB = aggregator.genericObject.pointB; // B
  113. const Ax = pointA.posX, Ay = pointA.posY, Bx = pointB.posX, By = pointB.posY; // A=(Ax,Ay) and B=(Bx,By)
  114. const dx = Bx-Ax, dy = By-Ay; // direction d=B-A
  115. const size = stageManager.getSize(); // From: ../../../core/application/stage-manager
  116. const W = size.w; // canvas width
  117. const H = size.h; // canvas height
  118. var Ix, Iy, Ex, Ey; // Point I will be left-bottom one and E will be the top-right one
  119. var Lg, Rg, Ug, Dg;
  120. // Line perpendicular to axis "x" (dx = 0)
  121. if (dx === 0) {
  122. // Calculates parameters Ug, Dg:
  123. Ug = -Ay / dy; // -A.y / d.y
  124. Dg = (H-Ay) / dy; // (H-A.y) / d.y
  125. // Find the situation (1), (2), (3) or (4) calculating "ming" the smallest "g" and "maxg" the greatest "g"
  126. const ming = Math.min(Ug, Dg); // minimum
  127. const maxg = Math.max(Ug, Dg); // maximum
  128. // Draw from minimum to maximum
  129. Ix = Ax; Lg = 0;
  130. Iy = Ay + ming * dy; // left initial point of this line (Ix, Iy)
  131. Ex = Ax; Rg = 0;
  132. Ey = Ay + maxg * dy; // right end point of this line (Ex, Ey)
  133. }
  134. else {
  135. // Calculates parameters Lg, Rg, Ug, Dg:
  136. Lg = -Ax / dx; // -A.x / d.x
  137. Rg = (W-Ax) / dx; // (W-A.x) / d.x
  138. Ug = -Ay / dy; // -A.y / d.y
  139. Dg = (H-Ay) / dy; // (H-A.y) / d.y
  140. // Find the situation (1), (2), (3) or (4) calculating "ming" the smallest "g" and "maxg" the greatest "g"
  141. var ming, maxg; // calculate extreme points (intercepted with the Canvas frame)
  142. if (dx>0) { // (1)
  143. if (Lg<Dg) ming = Dg;
  144. else ming = Lg;
  145. if (Rg>Ug) maxg = Ug;
  146. else maxg = Rg;
  147. }
  148. else { // (2)
  149. if (Lg>Ug) ming = Ug;
  150. else ming = Lg;
  151. if (Rg<Dg) maxg = Dg;
  152. else maxg = Rg;
  153. }
  154. // Draw from minimum to maximum
  155. Ix = Ax + ming * dx;
  156. Iy = Ay + ming * dy; // left initial point of this line (Ix, Iy)
  157. Ex = Ax + maxg * dx;
  158. Ey = Ay + maxg * dy; // right end point of this line (Ex, Ey)
  159. }
  160. // Ix = Ax; Iy = H; Ex = Ax; Ey = 0;
  161. const points = [Ix, Iy, Ex, Ey];
  162. //D console.log("./app/components/line-component/drawers/line-drawer.js: update(aggregator, e):\nA=("+Ax+","+Ay+"), B=("+Bx+","+By+")"); //leo
  163. // Update label line
  164. const pos = aggregator.genericObject.getMiddlePoint();
  165. aggregator.konvaObject.children[0].x(pos.posX);
  166. aggregator.konvaObject.children[0].y(pos.posY - 20);
  167. aggregator.konvaObject.children[1].points(points);
  168. super.batchDraw();
  169. } // update(aggregator, e)
  170. static getKonvaLine (pointA, pointB, useLabel) { //TODO: revisar, pois o codigo 'slope', 'linearCoefficient' so' funciona para quadrantes 1 e 3...
  171. const xA = pointA.posX, xB = pointB.posX,
  172. yA = pointA.posY, yB = pointB.posY;
  173. const slope = (yB - yA) / (xB - xA);
  174. const linearCoefficient = (yA * xB - yB * xA) / (xB - xA);
  175. const y = linearCoefficient;
  176. const x = -linearCoefficient / slope;
  177. const points = [x, 0, 0, y];
  178. const line = new Konva.Line({
  179. points: points,
  180. stroke: "grey",
  181. strokeWidth: 2,
  182. lineJoin: "round",
  183. draggable: false,
  184. strokeScaleEnabled: false,
  185. class: ELEMENTS_CLASS.LINE,
  186. connections: [],
  187. index: 1,
  188. selectable: false,
  189. draggable: false,
  190. style: { stroke: "grey", fill: "grey" }
  191. });
  192. SelectableDrawer.setSelectableIfIntersectionChanged(line);
  193. return line;
  194. }
  195. static drawKonvaLine (pointA, pointB) {
  196. const line = LineDrawer.getKonvaLine(pointA, pointB);
  197. return line;
  198. }
  199. }