/* * iGeom by LInE * Geometric Object: Straight Line * www.matematica.br/igeom * ./app/components/line-component/drawers/line-drawer.js * Draw the Straight Line */ import { stageManager } from "../../../core/application/stage-manager"; // to get Canvas size 'stageManager.getSize();' import { ELEMENTS_CLASS } from "../../../core/enums/elements-class-enum"; import { label as Label } from "../../../component-registry/label"; import { LineModel } from "../models/line-model"; import { objects as Objects } from "../../../core/application/objects"; import { SelectableDrawer } from "../../../core/drawers/selectable-drawer"; import { LineSegmentDrawer } from "../../line-segment-component/drawers/line-segment-drawer"; import { DrawerAggregator } from "../../../core/drawers/drawer-aggregator"; import { LineSegmentModel } from "../../line-segment-component/models/line-segment-model"; export class LineDrawer extends LineSegmentDrawer { constructor () { super(); this.setElementClass(ELEMENTS_CLASS.LINE); } drawByStates (konvaObject) { let aggregator = undefined; if (konvaObject != undefined) { aggregator = Objects.getByKonvaObject(konvaObject)[0]; } if (this.state == undefined) { super.setState(LineDrawer.FIRST_POINT_STATE); } else if (this.state == LineDrawer.FIRST_POINT_STATE) { aggregator = aggregator != undefined ? aggregator : this.pointDrawer.drawPoint(); this.setAggregatorA(aggregator); super.setState(LineDrawer.SECOND_POINT_STATE); } else if (this.state == LineDrawer.SECOND_POINT_STATE) { aggregator = aggregator != undefined ? aggregator : this.pointDrawer.drawPoint(); this.setAggregatorB(aggregator); this.drawByPoints([this.pointA, this.pointB], [this.aggregatorA, this.aggregatorB]); super.setState(LineDrawer.FIRST_POINT_STATE); } } drawByLineSegment (lineSegment) { //TODO Nome adequado? Nao seria 'drawLine(lineSegment)'? this.lineSegment = lineSegment; const group = SelectableDrawer.getKonvaGroup(false); const text = LineDrawer.getKonvaText(lineSegment, lineSegment.label); group.add(text); const konvaObject = LineDrawer.getKonvaLine(lineSegment.pointA, lineSegment.pointB); group.add(konvaObject); super.setKonvaObject(group); const aggregator = new DrawerAggregator(this, this.lineSegment, group, ELEMENTS_CLASS.LINE); super.addAggregator(aggregator); const aggregators = this.resolveAggregators([this.lineSegment.pointA, this.lineSegment.pointB], undefined); aggregators[1].addAggregator(aggregator); aggregators[0].addAggregator(aggregator); // Sequence of calls: // ./app/core/drawers/drawer.js: static drawObject(object): DrawerManager.draw(object); // ./app/core/drawers/drawer-manager.js: draw(object): this.currentStage.draw(object); SelectableDrawer.drawObject(this.konvaObject); // in ./app/core/drawers/drawer.js: static drawObject(object): DrawerManager.draw(object); this.konvaObject.zIndex(1); //leo super.batchDraw(); //D usar novo metodo para desenhar, aproveitar o proprio 'update' - REMOVER this.update(aggregator,null); SelectableDrawer.setMaxIndex(aggregators[0].konvaObject); // mark object 1: A SelectableDrawer.setMaxIndex(aggregators[1].konvaObject); // mark object 2: B } // Draw Straight Line by its points drawByPoints (points, aggregators) { if (points == undefined || points.length < 1) return; this.setPointA(points[0]); this.setPointB(points[1]); aggregators = this.resolveAggregators(points, aggregators, true); this.label = Label.draw(true); this.lineSegment = new LineModel(this.pointA, this.pointB, this.label); // ./app/components/line-segment-component/drawers/line-segment-drawer.js // Use: ./app/components/line-segment-component/drawers/line-segment-drawer.js: drawByLineSegment(lineSegment) // Use: ./app/components/core/drawers/selectable-drawer this.drawByLineSegment(this.lineSegment); // here, makes: SelectableDrawer.drawObject(this.konvaObject); this.reset(); } // Update straight line (Line) // Whenever points A=(ax,ay) or B=(bx,by), was moved // Let d=B-A, i.e., d=(dx,dy) where: dx=bx-ax, dy=by-ay // If necessary semi-space: build the vector "o" (ortogonal to the segment AB), with // "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) // // Model under Canvas: r(.) parametric equation of the straight line // // Possible configurations to be considered: // +----------+----------+----------+----------+ // | A x | x B | B x | x A | // | x B | A x | x A | B x | // | (1) | (2) | (3) | (4) | // +----------+----------+----------+----------+ // Straight line defined by points A,B (parametric equation by 'g'): // P(g) = A + g * (B-A) = A + g * d // Given W=canvas width and H=canvas height, find intersections with borders, i.e., find values of "g" such that: // 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) // Ug // (0,0) +-------------+ (W,0) Lg: 0 = r(g).x = A.x + g.x * d.x => g.x = -A.x / d.x // | | Rg: W = r(g).x = A.x + g.x * d.x => g.x = (W-A.x) / d.x // Lg | | Rg // | | Ug: 0 = r(g).y = A.y + g.y * d.y => g.y = -A.y / d.y // (0,H) +-------------+ (W,a) Dg: H = r(g).y = A.y + g.y * d.y => g.y = (H-A.y) / d.y // Dg // // (1) Ug (2) Dg // (0,0) +------------o------------------+--> (0,0) +------------o------------------+--> // | o B Q | | o A Q | // Lg |P o A | Rg Rg | o B | Lg // +-o-----------------------------+ +-o-----------------------------+ // \|/ Dg Ug update (aggregator, e) { if (!aggregator.visible) return; const pointA = aggregator.genericObject.pointA; // A const pointB = aggregator.genericObject.pointB; // B const Ax = pointA.posX, Ay = pointA.posY, Bx = pointB.posX, By = pointB.posY; // A=(Ax,Ay) and B=(Bx,By) const dx = Bx-Ax, dy = By-Ay; // direction d=B-A const size = stageManager.getSize(); // From: ../../../core/application/stage-manager const W = size.w; // canvas width const H = size.h; // canvas height var Ix, Iy, Ex, Ey; // Point I will be left-bottom one and E will be the top-right one var Lg, Rg, Ug, Dg; // Line perpendicular to axis "x" (dx = 0) if (dx === 0) { // Calculates parameters Ug, Dg: Ug = -Ay / dy; // -A.y / d.y Dg = (H-Ay) / dy; // (H-A.y) / d.y // Find the situation (1), (2), (3) or (4) calculating "ming" the smallest "g" and "maxg" the greatest "g" const ming = Math.min(Ug, Dg); // minimum const maxg = Math.max(Ug, Dg); // maximum // Draw from minimum to maximum Ix = Ax; Lg = 0; Iy = Ay + ming * dy; // left initial point of this line (Ix, Iy) Ex = Ax; Rg = 0; Ey = Ay + maxg * dy; // right end point of this line (Ex, Ey) } else { // Calculates parameters Lg, Rg, Ug, Dg: Lg = -Ax / dx; // -A.x / d.x Rg = (W-Ax) / dx; // (W-A.x) / d.x Ug = -Ay / dy; // -A.y / d.y Dg = (H-Ay) / dy; // (H-A.y) / d.y // Find the situation (1), (2), (3) or (4) calculating "ming" the smallest "g" and "maxg" the greatest "g" var ming, maxg; // calculate extreme points (intercepted with the Canvas frame) if (dx>0) { // (1) if (LgUg) maxg = Ug; else maxg = Rg; } else { // (2) if (Lg>Ug) ming = Ug; else ming = Lg; if (Rg