/* * iGeom by LInE * Provides intersetion point to Geometric Objects (GO) * www.matematica.br/igeom * ./app/components/intersection-component/drawers/intersection-drawer.js * @calledby * @version 2020/11/02: Implemented Line instersection. */ import { PointDrawer } from "../../point-component/drawers/point-drawer"; import { ELEMENTS_CLASS } from "../../../core/enums/elements-class-enum"; import { Drawer } from "../../../core/drawers/drawer"; import { app as App } from "../../../app"; import { objects } from "../../../core/application/objects"; import { DrawerAggregator } from "../../../core/drawers/drawer-aggregator"; import { intersectionService } from "../services/intersection-service"; export class IntersectionDrawer extends Drawer { static FIRST_OBJECT_STATE () { return "FIRST_OBJECT"; } static SECOND_OBJECT_STATE () { return "SECOND_OBJECTf"; } constructor () { super(); this.aggregatorA; this.aggregatorB; this.label; this.states = [IntersectionDrawer.FIRST_OBJECT_STATE, IntersectionDrawer.SECOND_OBJECT_STATE]; this.intersections = []; this.pointDrawer = new PointDrawer(); super.setElementClass(ELEMENTS_CLASS.INTERSECTION_POINT); } // @calledby ./app/core/drawers/stage.js! draw (e): this.drawer.draw(e); draw (e) { var auxE = "", aux = "debug - uncomment 'aux' = "; //D console.log("intersection-drawer.js!draw(e): inicio"); var aux4 = ""; try { if (e != undefined && e.attrs != undefined) { //D auxE += "1, "; //D this.aggregatorA = this.getObjectAggregatorByGenericObject(e.attrs.genericObject.og1); this.aggregatorB = this.getObjectAggregatorByGenericObject(e.attrs.genericObject.og2); this.drawByIntersectionPoints([e.attrs.genericObject]); var aux2 = "this.aggregatorA.id=" + (this.aggregatorA!=undefined?this.aggregatorA.id:"<>"); aux2 += ", this.aggregatorB.id=" + (this.aggregatorB!=undefined?this.aggregatorB.id:"<>"); console.log("intersection-drawer.js!draw(e): final 1 - " + aux2); return; } //D auxE += "2, "; //D if (e == undefined || !this.isValidObject(e.target)) { var aux3 = (e==undefined? " e==undefined" : (e.target==undefined? "e.target==undefined?" : (e.target.attrs==undefined ? "e.target.attrs==undefined" : undefined)) ); console.log("intersection-drawer.js!draw(e): final 2, e : " + aux3); return; } //D auxE += "3, "; //D const selectedTool = App.getSelectedTool(); if (selectedTool != undefined && selectedTool.drawer != undefined && selectedTool.drawer.elementClass == ELEMENTS_CLASS.INTERSECTION_POINT) { //D auxE += "4, "; if (this.state == undefined || this.state == IntersectionDrawer.FIRST_OBJECT_STATE) { //D auxE += "5, "; try { aux4 = "setFirstObject: this.aggregatorA.id = " + (e.target==undefined ? "<>" : JSON.stringify(Object.keys(e.target))); // this.getObjectAggregator(e.target).id); // intersection-drawer.js!draw(e): final 3, setFirstObject: error in this.getObjectAggregator(e.target) TypeError: this.getObjectAggregator(...) is undefined // aux4 += ", e.target=" + JSON.stringify(e.target); } catch (error) { aux4 = "setFirstObject: error in this.getObjectAggregator(" + JSON.stringify(Object.keys(e.target)) + ") " + error; }; auxE += "6, "; this.setFirstObject(e.target); // this.aggregatorA = this.getObjectAggregator(e.target) this.setState(IntersectionDrawer.SECOND_OBJECT_STATE); auxE += "7, "; } else if (this.state == IntersectionDrawer.SECOND_OBJECT_STATE) { //D auxE += "8, "; aux4 = "setSecondObject: this.aggregatorB.id = " + (e.target==undefined ? "<>" : this.getObjectAggregator(e.target).id); this.setSecondObject(e.target); // this.aggregatorB = this.getObjectAggregator(e.target) this.drawPoint(); aux += "9, "; this.reset(); aux += "10, "; // this.clear(); } } } catch (error) { console.log("intersection-drawer.js!draw(e): " + error + " " + auxE + "\n * " + aux); } console.log("intersection-drawer.js!draw(e): final 3, " + aux4); } // draw(e) setFirstObject (konvaObject) { var aggregator = null; var auxE = ""; try { aggregator = this.getObjectAggregator(konvaObject); auxE = " (after aggregator)"; this.aggregatorA = aggregator; } catch (error) { console.log("intersection-drawer.js!setFirstObject(konvaObject): " + error + auxE); } } setSecondObject (konvaObject) { var aggregator = null; var auxE = ""; try { aggregator = this.getObjectAggregator(konvaObject); auxE = " (after aggregator)"; this.aggregatorB = aggregator; } catch (error) { console.log("intersection-drawer.js!setSecondObject(konvaObject): " + error + auxE); } } static count = 0; getObjectAggregator (konvaObject) { const answer = objects.getByKonvaObject(konvaObject); // app/core/application/objects.js: getByKonvaObject(konvaObject) IntersectionDrawer.count++; // D console.trace(); console.log("intersection-drawer.js!getObjectAggregator(konvaObject): " + IntersectionDrawer.count + " objects.getByKonvaObject(konvaObject) = " + JSON.stringify(Object.keys(answer))); // Object.keys to avoid "TypeError: cyclic object value" return answer[0]; } getObjectAggregatorByGenericObject (genericObject) { return objects.getByGenericObject(genericObject)[0]; } // Avoid to create intersection between lines/segments when some defining point is the intersection // Return true <=> need a new point alreadyHasIntersection (og1, og2, str_a1, str_a2) { // app/core/enums/elements-class-enum.js : ELEMENTS_CLASS.LINE, ELEMENTS_CLASS.LINE_SEGMENT, ELEMENTS_CLASS.CIRCUMFERENCE // Avoid duplicate intersection between line/segment with line/segment if ((og1.elementClass==ELEMENTS_CLASS.LINE || og1.elementClass==ELEMENTS_CLASS.LINE_SEGMENT) && (og2.elementClass==ELEMENTS_CLASS.LINE || og2.elementClass==ELEMENTS_CLASS.LINE_SEGMENT)) { // Try to avoid redundant point if (og1.pointA==og2.pointA || og1.pointA==og2.pointB || og1.pointB==og2.pointA || og1.pointB==og2.pointB) { var aux2 = " "+og1.pointA+","+og1.pointB+";"+og2.pointA+","+og2.pointB+" "; console.log("intersection-drawer.js!alreadyHasIntersection(): existing intersection, nothing to be done: " + str_a1 + " , " + str_a2 + ", " + aux2); //TODO need to become visible? "og1.visible = true;" or "og2.visible = true;" return true; } } // Avoid duplicate intersection between line/segment with circumference var ogLine = null, ogCirc = null; if (og1.elementClass==ELEMENTS_CLASS.LINE || og1.elementClass==ELEMENTS_CLASS.LINE_SEGMENT) ogLine = og1; else if (og1.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE || og1.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE) ogCirc = og1; if (og2.elementClass==ELEMENTS_CLASS.LINE || og2.elementClass==ELEMENTS_CLASS.LINE_SEGMENT) ogLine = og2; else if (og2.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE || og2.elementClass==ELEMENTS_CLASS.CIRCUMFERENCE) ogCirc = og2; if (ogLine!=null && ogCirc!=null) { // is Line/Segment and Circumference // Try to avoid redundant point if (ogLine.pointA==ogCirc.radius || ogLine.pointB==ogCirc.radius) { var aux2 = " Line/Segment with (A,B)=("+ogLine.pointA + "," + ogLine.pointB + "); Circ.=" + ogCirc.radius + " "; console.log("intersection-drawer.js!alreadyHasIntersection(): existing intersection, nothing to be done: " + str_a1 + " , " + str_a2 + ", " + aux2); //TODO need to become visible? "ogLine.visible = true;" or "ogCirc.visible = true;" return false; // let "app/components/line-segment-component/models/line-segment-model.js!getIntersectionWithCircumference(.)" treat this case! // return true; } } return false; } // Used to create new intersection point //@calledby this.draw() drawPoint () { var og1, og2, str_a1, str_a2; if (this.aggregatorA==undefined || this.aggregatorB==undefined) { if (this.aggregatorA==undefined) this.aggregatorA = this.aggregatorB; console.log("intersection-drawer.js!drawPoint(): error undefined: this.aggregatorA=" + this.aggregatorA + " or this.aggregatorB=" + this.aggregatorB); return; } og1 = this.aggregatorA.genericObject, og2 = this.aggregatorB.genericObject; str_a1 = "og1=(" + og1.elementClass + ",id=" + og1.id + ")"; //D genericObject str_a2 = "og2=(" + og2.elementClass + ",id=" + og2.id + ")"; //D if (this.alreadyHasIntersection(og1,og2,str_a1,str_a2)) return; // intersection already defined by line/segment.pointA or pointB console.log("intersection-drawer.js!drawPoint(): create intersection between " + str_a1 + " , " + str_a2); //D //leo // Really create the intersection: line-segment-model.js!getIntersectionByLine(.); getIntersectionWithCircumference(.) // app/components/: line-component/models/line-model.js; line-segment-component/models/line-segment-model.js; circumference-component/models/circumference-model.js const intersectionOg1Og2 = og1.getIntersection(og2); // get [ṔA, PB], but perhaps PA or PB is Point, NOT IntersectionPoint! // app/components/intersection-component/services/intersection-service.js const intersectionPoints = intersectionService.addIntersections(intersectionOg1Og2, og1, og2); this.drawByIntersectionPoints(intersectionPoints); } drawByIntersectionPoints (intersectionPoints) { for (let index = 0; index < intersectionPoints.length; index++) { const intersectionPoint = intersectionPoints[index]; if (intersectionPoint.og1 == undefined) { //D console.log("intersection-drawer.js!drawByIntersectionPoints(.): " + index + ": intersectionPoint.id=" + intersectionPoint.id + " og1 undefined"); continue; // this point already exists! } //D else console.log("intersection-drawer.js!drawByIntersectionPoints(.): " + index + ": intersectionPoint.id=" + intersectionPoint.id + ""); intersectionPoint.update(); // if (!intersectionPoint.visible) return; const point = PointDrawer.drawPoint(intersectionPoint, true, false, true); const aggregator = new DrawerAggregator(this, intersectionPoint, point.konvaObject, ELEMENTS_CLASS.INTERSECTION_POINT); super.addAggregator(aggregator); this.aggregatorB.addAggregator(aggregator); this.aggregatorA.addAggregator(aggregator); } } isValidObject (konvaObject) { switch (konvaObject.attrs.class) { case ELEMENTS_CLASS.LINE: return true; case ELEMENTS_CLASS.LINE_SEGMENT: return true; case ELEMENTS_CLASS.CIRCUMFERENCE: return true; case ELEMENTS_CLASS.MIDDLE_POINT: return true; default: return false; } } update (aggregator, e) { aggregator.genericObject.update(aggregator, e); if (!aggregator.genericObject.visible || aggregator.genericObject.posX == Number.MAX_SAFE_INTEGER) { if (aggregator.visible) { aggregator.konvaObject.hide(); aggregator.aggregators.forEach(a => { a.visible = false; a.konvaObject.hide(); }); this.batchDraw(); } aggregator.visible = false; return; } //todo: konva objects aggregator.konvaObject.children[0].x(aggregator.genericObject.posX + 10); aggregator.konvaObject.children[0].y(aggregator.genericObject.posY - 10); aggregator.konvaObject.children[1].x(aggregator.genericObject.posX); aggregator.konvaObject.children[1].y(aggregator.genericObject.posY); if (!aggregator.visible || aggregator.genericObject.posX == Number.MAX_SAFE_INTEGER) { aggregator.genericObject.visible = true; aggregator.konvaObject.show(); aggregator.aggregators.forEach(a => { a.visible = true; a.konvaObject.show(); }); aggregator.visible = true; } this.batchDraw(); } reset () { this.aggregatorA = undefined; this.aggregatorB = undefined; this.setState(undefined); } } // export class IntersectionDrawer extends Drawer