|
@@ -1,3 +1,11 @@
|
|
|
+/*
|
|
|
+ * iGeom by LInE
|
|
|
+ * Geometric Object: Straight Line
|
|
|
+ * www.matematica.br/igeom
|
|
|
+ */
|
|
|
+
|
|
|
+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";
|
|
@@ -8,107 +16,177 @@ import { DrawerAggregator } from "../../../core/drawers/drawer-aggregator";
|
|
|
import { LineSegmentModel } from "../../line-segment-component/models/line-segment-model";
|
|
|
|
|
|
export class LineDrawer extends LineSegmentDrawer {
|
|
|
- constructor() {
|
|
|
+ constructor () {
|
|
|
super();
|
|
|
this.setElementClass(ELEMENTS_CLASS.LINE);
|
|
|
- }
|
|
|
- drawByStates(konvaObject) {
|
|
|
+ }
|
|
|
+
|
|
|
+ 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();
|
|
|
+ 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();
|
|
|
+ aggregator = aggregator != undefined ? aggregator : this.pointDrawer.drawPoint();
|
|
|
this.setAggregatorB(aggregator);
|
|
|
- this.drawByPoints(
|
|
|
- [this.pointA, this.pointB],
|
|
|
- [this.aggregatorA, this.aggregatorB]
|
|
|
- );
|
|
|
+ this.drawByPoints([this.pointA, this.pointB], [this.aggregatorA, this.aggregatorB]);
|
|
|
super.setState(LineDrawer.FIRST_POINT_STATE);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- drawByLineSegment(lineSegment) {
|
|
|
+ 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
|
|
|
- );
|
|
|
+ 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
|
|
|
- );
|
|
|
+ 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);
|
|
|
- SelectableDrawer.drawObject(this.konvaObject);
|
|
|
+
|
|
|
+ // 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);
|
|
|
- super.batchDraw();
|
|
|
- SelectableDrawer.setMaxIndex(aggregators[0].konvaObject);
|
|
|
- SelectableDrawer.setMaxIndex(aggregators[1].konvaObject);
|
|
|
- }
|
|
|
+ //leo super.batchDraw(); //D usar novo metodo para desenhar, aproveitar o proprio 'update' - REMOVER
|
|
|
+ this.update(aggregator,null);
|
|
|
|
|
|
- drawByPoints(points, aggregators) {
|
|
|
+ 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
|
|
|
- );
|
|
|
- this.drawByLineSegment(this.lineSegment);
|
|
|
+ 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(aggregator, e) {
|
|
|
+ // 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;
|
|
|
- const pointB = aggregator.genericObject.pointB;
|
|
|
+ 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 (Lg<Dg) ming = Dg;
|
|
|
+ else ming = Lg;
|
|
|
+ if (Rg>Ug) maxg = Ug;
|
|
|
+ else maxg = Rg;
|
|
|
+ }
|
|
|
+ else { // (2)
|
|
|
+ if (Lg>Ug) ming = Ug;
|
|
|
+ else ming = Lg;
|
|
|
+ if (Rg<Dg) maxg = Dg;
|
|
|
+ else maxg = Rg;
|
|
|
+ }
|
|
|
+ // Draw from minimum to maximum
|
|
|
+ Ix = Ax + ming * dx;
|
|
|
+ Iy = Ay + ming * dy; // left initial point of this line (Ix, Iy)
|
|
|
+ Ex = Ax + maxg * dx;
|
|
|
+ Ey = Ay + maxg * dy; // right end point of this line (Ex, Ey)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ix = Ax; Iy = H; Ex = Ax; Ey = 0;
|
|
|
+ const points = [Ix, Iy, Ex, Ey];
|
|
|
+ //D console.log("./app/components/line-component/drawers/line-drawer.js: update(aggregator, e):\nA=("+Ax+","+Ay+"), B=("+Bx+","+By+")"); //leo
|
|
|
+
|
|
|
+ // Update label line
|
|
|
const pos = aggregator.genericObject.getMiddlePoint();
|
|
|
aggregator.konvaObject.children[0].x(pos.posX);
|
|
|
aggregator.konvaObject.children[0].y(pos.posY - 20);
|
|
|
- const xA = pointA.posX,
|
|
|
- xB = pointB.posX,
|
|
|
- yA = pointA.posY,
|
|
|
- yB = pointB.posY;
|
|
|
-
|
|
|
- const slope = (yB - yA) / (xB - xA);
|
|
|
- const linearCoefficient = (yA * xB - yB * xA) / (xB - xA);
|
|
|
-
|
|
|
- const y = linearCoefficient;
|
|
|
- const x = -linearCoefficient / slope;
|
|
|
- const points = [x, 0, 0, y];
|
|
|
|
|
|
aggregator.konvaObject.children[1].points(points);
|
|
|
+
|
|
|
super.batchDraw();
|
|
|
- }
|
|
|
+ } // update(aggregator, e)
|
|
|
|
|
|
- static getKonvaLine(pointA, pointB, useLabel) {
|
|
|
|
|
|
- const xA = pointA.posX,
|
|
|
- xB = pointB.posX,
|
|
|
- yA = pointA.posY,
|
|
|
- yB = pointB.posY;
|
|
|
+ static getKonvaLine (pointA, pointB, useLabel) { //TODO: revisar, pois o codigo 'slope', 'linearCoefficient' so' funciona para quadrantes 1 e 3...
|
|
|
+ const xA = pointA.posX, xB = pointB.posX,
|
|
|
+ yA = pointA.posY, yB = pointB.posY;
|
|
|
|
|
|
const slope = (yB - yA) / (xB - xA);
|
|
|
const linearCoefficient = (yA * xB - yB * xA) / (xB - xA);
|
|
@@ -136,11 +214,11 @@ export class LineDrawer extends LineSegmentDrawer {
|
|
|
SelectableDrawer.setSelectableIfIntersectionChanged(line);
|
|
|
|
|
|
return line;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- static drawKonvaLine(pointA, pointB) {
|
|
|
+ static drawKonvaLine (pointA, pointB) {
|
|
|
const line = LineDrawer.getKonvaLine(pointA, pointB);
|
|
|
return line;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
-}
|
|
|
+ }
|