From 336fc054b6b1cdd3ee05e1af4268483f241d69f8 Mon Sep 17 00:00:00 2001 From: Dawn <93628226+DawnTheWitch@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:57:30 -0400 Subject: [PATCH 1/6] Issue #59 Atom Selected --- src/AtomMode.ts | 3 +++ src/index.html | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/AtomMode.ts b/src/AtomMode.ts index 276d6294..95e8cad0 100644 --- a/src/AtomMode.ts +++ b/src/AtomMode.ts @@ -9,11 +9,13 @@ if (res === null) { throw Error("2d rendering context not supported"); } const ctx: CanvasRenderingContext2D = res; +const atomDisplay = document.getElementById("atomDisplay"); let atomMetrics: TextMetrics; let hasMouseDown: Boolean = false; let hasAtom: Boolean = false; let currentAtom: AtomNode = new AtomNode("a"); //MAKING a THE DEFAULT IDENTIFIER FOR ATOMS +atomDisplay.innerHTML = currentAtom.Identifier; /** * Will compare the event given with all possible events it could be. @@ -31,6 +33,7 @@ export function atomHandler(event: Event) { const regex = new RegExp(/^[A-Za-z]$/); if (regex.test(thisEvent.key)) { currentAtom.Identifier = thisEvent.key; + atomDisplay.innerHTML = currentAtom.Identifier; hasAtom = true; } } else if (event.type === "mousedown" && hasAtom) { diff --git a/src/index.html b/src/index.html index bb253d6e..d2f63bf0 100644 --- a/src/index.html +++ b/src/index.html @@ -49,6 +49,12 @@

+
+

Current Atom:

+
+
+

+
From b49725fe4cf2110db1adb5b25e9c5e88edd8bc3b Mon Sep 17 00:00:00 2001 From: Dawn <93628226+DawnTheWitch@users.noreply.github.com> Date: Tue, 10 Oct 2023 22:59:01 -0400 Subject: [PATCH 2/6] Issue #60 --- src/index.css | 179 +++++++++++++++++++++++++++---------------------- src/index.html | 12 +++- src/index.ts | 6 ++ 3 files changed, 113 insertions(+), 84 deletions(-) diff --git a/src/index.css b/src/index.css index 86ef95c8..83f33d0a 100644 --- a/src/index.css +++ b/src/index.css @@ -1,82 +1,99 @@ - -body, html{ - margin: 0; - width: 100vw; - height: 100vh; - overflow: hidden; - display:contents; -} - -p { - margin: 0px; -} - -#header { - background-color: white; - border: 2px solid black; - height: 3vw; - width: 100vw; - text-align: center; - padding-top: 1vw; - box-sizing: border-box; -} - -#application { - display: flex; - flex-grow: 1; - height: 100%; - width: auto; -} - -.row { - display: flex; -} - -.modeButton { - width: 2vw; - height: 2vw; - border: 2px solid black; - margin: 3px; -} - -#content { - width: 100%; - height: auto; -} - -#toolbar { - border: 2px solid black; - width: 95vw; - float: right; - height: 2vw; - box-sizing: border-box; - background-color: white; -} - -.toolSetting { - margin: 0.1vw; - display: inline-flex; - margin: 5px; -} - -#sidebar { - box-sizing: border-box; - border: 2px solid black; - background-color: white; - height: 100vh; - float: left; - width: 5vw; -} - -#canvas { - position: absolute; - top: 0px; - left: 0px; - z-index: -1; -} -.no-highlight{ - user-select: none; - -moz-user-select: none; - -webkit-text-select: none; - -webkit-user-select: none; + +body, html{ + margin: 0; + width: 100vw; + height: 100vh; + overflow: hidden; + display:contents; +} + +p { + margin: 0px; +} + +#header { + background-color: white; + border: 2px solid black; + height: 3vw; + width: 100vw; + text-align: center; + padding-top: 1vw; + box-sizing: border-box; +} + +#application { + display: flex; + flex-grow: 1; + height: 100%; + width: auto; +} + +.row { + display: flex; +} + +.modeButton { + width: 2vw; + height: 2vw; + border: 2px solid black; + margin: 3px; +} + +#content { + width: 100%; + height: auto; +} + +#toolbar { + border: 2px solid black; + width: 95vw; + float: right; + height: 2vw; + box-sizing: border-box; + background-color: white; +} + +#subBar { + border: 2px solid black; + width: 95vw; + float: right; + height: 2vw; + box-sizing: border-box; + background-color: white; +} + +#cutTools { + display: none +} + +#atomTools { + display: none +} + +.toolSetting { + margin: 0.1vw; + display: inline-flex; + margin: 5px; +} + +#sidebar { + box-sizing: border-box; + border: 2px solid black; + background-color: white; + height: 100vh; + float: left; + width: 5vw; +} + +#canvas { + position: absolute; + top: 0px; + left: 0px; + z-index: -1; +} +.no-highlight{ + user-select: none; + -moz-user-select: none; + -webkit-text-select: none; + -webkit-user-select: none; } \ No newline at end of file diff --git a/src/index.html b/src/index.html index d2f63bf0..18ef9fb2 100644 --- a/src/index.html +++ b/src/index.html @@ -30,6 +30,13 @@
+
+
+

+
+
+
+

Show Guidelines:

@@ -46,9 +53,8 @@
-
-

-
+
+

Current Atom:

diff --git a/src/index.ts b/src/index.ts index f44d9012..0fea436b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,6 +32,8 @@ ctx.font = "35pt arial"; //Global State const cutDisplay = document.getElementById("graphString"); +const cutTools = document.getElementById("cutTools"); +const atomTools = document.getElementById("atomTools"); let modeState: string; export const tree: AEGTree = new AEGTree(); @@ -53,7 +55,9 @@ function ellipseMode() { if (modeState !== "ellipseMode") { removeListeners(); modeState = "ellipseMode"; + atomTools.style.display = "none"; } + cutTools.style.display = "block"; canvas.addEventListener("mousedown", cutHandler); canvas.addEventListener("mousemove", cutHandler); canvas.addEventListener("mouseup", cutHandler); @@ -68,7 +72,9 @@ function atomMode() { if (modeState !== "atomMode") { removeListeners(); modeState = "atomMode"; + cutTools.style.display = "none"; } + atomTools.style.display = "block"; window.addEventListener("keypress", atomHandler); canvas.addEventListener("mousedown", atomHandler); canvas.addEventListener("mousemove", atomHandler); From 9ed197051849dfc7159c75537b183aa7e58d8963 Mon Sep 17 00:00:00 2001 From: AnushaTiwari5 Date: Tue, 10 Oct 2023 23:47:39 -0400 Subject: [PATCH 3/6] finished all 105 comments except simplify edge overlap --- src/AEG/AEGTree.ts | 46 +++++++++++++++--------------- src/AEG/AEGUtils.ts | 53 +++++++++++++++++------------------ src/AEG/AtomNode.ts | 46 +++++++++++++++--------------- src/AEG/CutNode.ts | 66 ++++++++++++++++++++++---------------------- src/AEG/Ellipse.ts | 6 ++-- src/AEG/Rectangle.ts | 4 +-- src/AtomMode.ts | 24 ++++++++-------- src/CutMode.ts | 4 +-- src/index.ts | 22 +++++++-------- 9 files changed, 135 insertions(+), 136 deletions(-) diff --git a/src/AEG/AEGTree.ts b/src/AEG/AEGTree.ts index c32b2c14..6153c447 100644 --- a/src/AEG/AEGTree.ts +++ b/src/AEG/AEGTree.ts @@ -2,6 +2,7 @@ import {AtomNode} from "./AtomNode"; import {CutNode} from "./CutNode"; import {Point} from "./Point"; import {Ellipse} from "./Ellipse"; +import {shapesOverlap} from "./AEGUtils"; export class AEGTree { sheet: CutNode; @@ -28,24 +29,24 @@ export class AEGTree { * @returns True, if the structure is structurally consistent. Else, false. */ private verifyAEG(currentCut: CutNode): boolean { - for (let i = 0; i < currentCut.Children.length; i++) { + for (let i = 0; i < currentCut.children.length; i++) { //Check that all children, in this level, are in currentCut - if (!currentCut.containsNode(currentCut.Children[i])) { + if (!currentCut.containsNode(currentCut.children[i])) { return false; } //Check for overlaps on the same level - for (let j = i + 1; j < currentCut.Children.length; j++) { - if (this.overlaps(currentCut.Children[i], currentCut.Children[j])) { + for (let j = i + 1; j < currentCut.children.length; j++) { + if (this.overlaps(currentCut.children[i], currentCut.children[j])) { return false; } } } - for (let i = 0; i < currentCut.Children.length; i++) { + for (let i = 0; i < currentCut.children.length; i++) { //Check one level deeper if the child is a CutNode. Recursive case if ( - currentCut.Children[i] instanceof CutNode && - !this.verifyAEG(currentCut.Children[i] as CutNode) + currentCut.children[i] instanceof CutNode && + !this.verifyAEG(currentCut.children[i] as CutNode) ) { return false; } @@ -61,8 +62,8 @@ export class AEGTree { */ public canInsert(incomingNode: AtomNode | CutNode): boolean { const currentCut: CutNode = this.sheet.getCurrentCut(incomingNode); - for (let i = 0; i < currentCut.Children.length; i++) { - if (this.overlaps(incomingNode, currentCut.Children[i])) { + for (let i = 0; i < currentCut.children.length; i++) { + if (this.overlaps(incomingNode, currentCut.children[i])) { return false; } } @@ -80,14 +81,14 @@ export class AEGTree { } const currentCut: CutNode = this.sheet.getCurrentCut(incomingNode); - const originalChildren: (AtomNode | CutNode)[] = [...currentCut.Children]; - currentCut.Child = incomingNode; + const originalChildren: (AtomNode | CutNode)[] = [...currentCut.children]; + currentCut.child = incomingNode; if (incomingNode instanceof CutNode) { for (let i = 0; i < originalChildren.length; i++) { if (incomingNode.containsNode(originalChildren[i])) { - incomingNode.Child = originalChildren[i]; - currentCut.Children.splice(i, 1); + incomingNode.child = originalChildren[i]; + currentCut.children.splice(i, 1); } } } @@ -114,24 +115,25 @@ export class AEGTree { if (incomingNode instanceof AtomNode) { if (otherNode instanceof AtomNode) { - return (incomingNode as AtomNode).Rectangle.overlaps( - (otherNode as AtomNode).Rectangle + return shapesOverlap( + (incomingNode as AtomNode).rectangle, + (otherNode as AtomNode).rectangle ); } else { //the case where otherNode is the sheet is handled in canInsert() //and all child.ellipse[i] will never be null. this is the reason for ! below - ellipse1 = (otherNode as CutNode).Ellipse!; - return (incomingNode as AtomNode).Rectangle.overlaps(ellipse1); + ellipse1 = (otherNode as CutNode).ellipse!; + return shapesOverlap((incomingNode as AtomNode).rectangle, ellipse1); } } else { if (otherNode instanceof AtomNode) { - ellipse1 = (incomingNode as CutNode).Ellipse!; - return ellipse1.overlaps((otherNode as AtomNode).Rectangle); + ellipse1 = (incomingNode as CutNode).ellipse!; + return shapesOverlap(ellipse1, (otherNode as AtomNode).rectangle); } else { - ellipse1 = (incomingNode as CutNode).Ellipse!; - ellipse2 = (otherNode as CutNode).Ellipse!; - return ellipse1.overlaps(ellipse2); + ellipse1 = (incomingNode as CutNode).ellipse!; + ellipse2 = (otherNode as CutNode).ellipse!; + return shapesOverlap(ellipse1, ellipse2); } } } diff --git a/src/AEG/AEGUtils.ts b/src/AEG/AEGUtils.ts index 8a581ba8..82538fa7 100644 --- a/src/AEG/AEGUtils.ts +++ b/src/AEG/AEGUtils.ts @@ -8,7 +8,7 @@ import {Rectangle} from "./Rectangle"; * @param existingShape The existing shape * @returns True, if the new shape overlaps the existing shape. Else, false */ -export function shapesOverlaps( +export function shapesOverlap( newShape: Rectangle | Ellipse, existingShape: Rectangle | Ellipse ): boolean { @@ -17,32 +17,16 @@ export function shapesOverlaps( //For rectangle-rectangle, check if their edges intersect return edgesIntersect(newShape, existingShape); } else { - //For ellipse-rectangle collision, check if points on the ellipse are - //within the rectangle - const points: Point[] = getEllipsePoints(existingShape as Ellipse, 64); - for (let i = 0; i < points.length; i++) { - if (pointInRect(newShape as Rectangle, points[i])) { - return true; - } - } - return false; + return ellipseRectangleCollision(existingShape as Ellipse, newShape as Rectangle); } } else { if (existingShape instanceof Rectangle) { - //For ellipse-rectangle collision, check if points on the ellipse are - //within the rectangle - const points: Point[] = getEllipsePoints(newShape as Ellipse, 64); - for (let i = 0; i < points.length; i++) { - if (pointInRect(existingShape as Rectangle, points[i])) { - return true; - } - } - return false; + return ellipseRectangleCollision(newShape as Ellipse, existingShape as Rectangle); } else { //For ellipse-ellipse collision, check if the rectangular bounding boxes intersect. //If they do, check if points of the new ellipse are within the current ellipse if ( - shapesOverlaps( + shapesOverlap( (newShape as Ellipse).boundingBox, (existingShape as Ellipse).boundingBox ) || @@ -54,9 +38,9 @@ export function shapesOverlaps( //if there is an overlap, check if points along the ellipse curve overlap //this can be done by checking if points along the curve of this ellipse //are within the other ellipse - const points: Point[] = getEllipsePoints(newShape, 64); + const points: Point[] = getEllipsePoints(newShape); for (let i = 0; i < points.length; i++) { - if (pointInELlipse(existingShape as Ellipse, points[i])) { + if (pointInEllipse(existingShape as Ellipse, points[i])) { return true; } } @@ -66,6 +50,18 @@ export function shapesOverlaps( } } +function ellipseRectangleCollision(ellipse: Ellipse, rectangle: Rectangle): boolean { + //For ellipse-rectangle collision, check if points on the ellipse are + //within the rectangle + const points: Point[] = getEllipsePoints(ellipse); + for (let i = 0; i < points.length; i++) { + if (pointInRect(rectangle, points[i])) { + return true; + } + } + return false; +} + /** * Method that checks whether a shape is contained within another * @param outerShape The outer shape @@ -104,7 +100,7 @@ export function shapeContains( //the ellipse const innerCorners = (innerShape as Rectangle).getCorners(); for (let i = 0; i < 4; i++) { - if (!pointInELlipse(outerShape as Ellipse, innerCorners[i])) { + if (!pointInEllipse(outerShape as Ellipse, innerCorners[i])) { return false; } } @@ -112,10 +108,10 @@ export function shapeContains( } else { //An ellipse contains an ellipse if all the widest coordinates of the inner ellipse //are within the outer ellipse - const innerCoords: Point[] = getEllipsePoints(innerShape as Ellipse, 64); + const innerCoords: Point[] = getEllipsePoints(innerShape as Ellipse); //= getWidestCoordinates(innerShape as Ellipse); for (let i = 0; i < innerCoords.length; i++) { - if (!pointInELlipse(outerShape as Ellipse, innerCoords[i])) { + if (!pointInEllipse(outerShape as Ellipse, innerCoords[i])) { return false; } } @@ -286,7 +282,7 @@ export function pointInRect(rect: Rectangle, point: Point): boolean { * @param otherPoint The point that might be inside the given ellipse. * @returns True, if the point is inside the given ellipse. Else, false */ -export function pointInELlipse(ellipse: Ellipse, point: Point): boolean { +export function pointInEllipse(ellipse: Ellipse, point: Point): boolean { //(x-h)^2/rx^2 + (y-k)^2/ry^2 <= 1 //(x, y) = new point //(h, k) = center @@ -324,7 +320,8 @@ function getWidestCoordinates(ellipse: Ellipse): Point[] { * @param ellipse The given ellipse * @returns An array of points along the bounding curve of the ellipse */ -function getEllipsePoints(ellipse: Ellipse, amount: number): Point[] { +export function getEllipsePoints(ellipse: Ellipse): Point[] { + const amount = 400; const points: Point[] = []; const pointDist = ellipse.radiusX / (amount / 4); @@ -333,7 +330,7 @@ function getEllipsePoints(ellipse: Ellipse, amount: number): Point[] { let y: number; for (let i = 1; i < amount; i++) { - if (i < amount / 2 + 1) { + if (i <= amount / 2) { x = points[i - 1].x + pointDist; y = getCurvePoint(ellipse, x, 1); } else { diff --git a/src/AEG/AtomNode.ts b/src/AEG/AtomNode.ts index 848977e6..efac190e 100644 --- a/src/AEG/AtomNode.ts +++ b/src/AEG/AtomNode.ts @@ -12,17 +12,17 @@ export class AtomNode { /** * The rectangle signifying the boundary box of this node. */ - private rect: Rectangle; + private internalRectangle: Rectangle; /** * The string value of the proposition represented by this node. */ - private identifier: string; + private internalIdentifier: string; /** * The point the atom is initially placed. */ - private origin: Point; + private internalOrigin: Point; /** * Construct an atom node with given boundary box and proposition. @@ -30,54 +30,54 @@ export class AtomNode { * @param val (Required) The value of the proposition represented by this node. */ public constructor(val: string, origin?: Point, rect?: Rectangle) { - this.rect = rect ?? new Rectangle(); - this.identifier = val; - this.origin = origin ?? new Point(); + this.internalRectangle = rect ?? new Rectangle(); + this.internalIdentifier = val; + this.internalOrigin = origin ?? new Point(); } /** * Accessor to get the bounding rectangle of the Atom Node. * @returns The bounding rectangle of this Atom Node */ - public get Rectangle(): Rectangle { - return this.rect; + public get rectangle(): Rectangle { + return this.internalRectangle; } /** * Modifier to set the bounding rectangle of the Atom Node. */ - public set Rectangle(rect: Rectangle) { - this.rect = rect; + public set rectangle(rect: Rectangle) { + this.internalRectangle = rect; } /** * Accessor to get the identifier of the Atom Node. * @returns The identifier of this Atom Node */ - public get Identifier(): string { - return this.identifier; + public get identifier(): string { + return this.internalIdentifier; } /** * Modifier to set the identifier of the Atom Node */ - public set Identifier(identifier: string) { - this.identifier = identifier; + public set identifier(identifier: string) { + this.internalIdentifier = identifier; } /** * Accessor to get the origin (top left) vertex of the bounding rectangle of the Atom Node. * @returns The origin of the bounding rectangle */ - public get Origin(): Point { - return this.origin; + public get origin(): Point { + return this.internalOrigin; } /** * Modifier to set the origin (top left) vertex of the bounding rectangle of the Atom Node. */ - public set Origin(point: Point) { - this.origin = point; + public set origin(point: Point) { + this.internalOrigin = point; } /** @@ -86,7 +86,7 @@ export class AtomNode { * @returns True, if the point is within this node. Else, false. */ public containsPoint(otherPoint: Point): boolean { - return this.rect.containsPoint(otherPoint); + return this.internalRectangle.containsPoint(otherPoint); } /** @@ -96,9 +96,9 @@ export class AtomNode { */ public containsNode(otherNode: AtomNode | CutNode): boolean { if (otherNode instanceof AtomNode) { - return this.rect.contains((otherNode as AtomNode).Rectangle); + return this.internalRectangle.contains((otherNode as AtomNode).rectangle); } else { - return this.rect.contains((otherNode as CutNode).Ellipse as Ellipse); + return this.internalRectangle.contains((otherNode as CutNode).ellipse as Ellipse); } } @@ -109,10 +109,10 @@ export class AtomNode { public toString(): string { return ( "An atom representing the proposition: " + - this.identifier + + this.internalIdentifier + " and " + "Boundary box of: " + - this.rect.toString() + this.internalRectangle.toString() ); } } diff --git a/src/AEG/CutNode.ts b/src/AEG/CutNode.ts index 85dbde64..4f759ede 100644 --- a/src/AEG/CutNode.ts +++ b/src/AEG/CutNode.ts @@ -12,12 +12,12 @@ export class CutNode { /** * The boundary of this node. */ - private ellipse: Ellipse | null; //Null for sheet of assertion + private internalEllipse: Ellipse | null; //Null for sheet of assertion /** * Contains the list of child nodes nested within this node. */ - private children: (AtomNode | CutNode)[]; + private internalChildren: (AtomNode | CutNode)[]; /** * Constructs a CutNode with the incoming Ellipse as its boundary box. @@ -27,8 +27,8 @@ export class CutNode { * If not passed, defaults to an empty array. */ public constructor(ellipse: Ellipse | null, childList?: (AtomNode | CutNode)[]) { - this.ellipse = ellipse; - this.children = childList ?? []; + this.internalEllipse = ellipse; + this.internalChildren = childList ?? []; } /** @@ -36,39 +36,39 @@ export class CutNode { * @returns The bounding ellipse of this Cut Node * Returns null for Sheet of Assertion */ - public get Ellipse(): Ellipse | null { - return this.ellipse; + public get ellipse(): Ellipse | null { + return this.internalEllipse; } /** * Modifier to set the bounding ellipse of this Cut Node */ - public set Ellipse(ellipse: Ellipse) { - this.ellipse = ellipse; + public set ellipse(ellipse: Ellipse) { + this.internalEllipse = ellipse; } /** * Accessor to get the children (array of nodes nested within) of the Cut Node. * @returns The children of the Cut Node */ - public get Children(): (AtomNode | CutNode)[] { - return this.children; + public get children(): (AtomNode | CutNode)[] { + return this.internalChildren; } /** * Modifier that sets the children of the Cut Node. * @param list The list of nodes to be added as the children of the Cut Node */ - public set Children(list: (AtomNode | CutNode)[]) { - this.children = list; + public set children(list: (AtomNode | CutNode)[]) { + this.internalChildren = list; } /** * Modifier that adds a child to the Cut Node. * @param child The node to be added as a child of the Cut Node */ - public set Child(child: AtomNode | CutNode) { - this.children.push(child); + public set child(child: AtomNode | CutNode) { + this.internalChildren.push(child); } /** @@ -77,8 +77,8 @@ export class CutNode { * @returns the deepest valid CutNode in which newNode can fit */ public getCurrentCut(newNode: CutNode | AtomNode): CutNode { - for (let i = 0; i < this.children.length; i++) { - const child: CutNode | AtomNode = this.children[i]; + for (let i = 0; i < this.internalChildren.length; i++) { + const child: CutNode | AtomNode = this.internalChildren[i]; if (child instanceof CutNode && child.containsNode(newNode)) { //newNode can be placed at least one layer deeper return child.getCurrentCut(newNode); @@ -93,13 +93,13 @@ export class CutNode { * @returns True, if the point is within this node. Else, false. */ public containsPoint(otherPoint: Point): boolean { - if (this.ellipse === null) { + if (this.internalEllipse === null) { //This CutNode represents the sheet. //Everything is within the sheet. return true; } - return this.ellipse.containsPoint(otherPoint); + return this.internalEllipse.containsPoint(otherPoint); } /** @@ -108,16 +108,16 @@ export class CutNode { * @returns True, otherNode it is within this CutNode. Else, false. */ public containsNode(otherNode: AtomNode | CutNode): boolean { - if (this.ellipse === null) { + if (this.internalEllipse === null) { //This CutNode represents the sheet. //Everything is within the sheet. return true; } if (otherNode instanceof AtomNode) { - return this.ellipse.contains(otherNode.Rectangle); + return this.internalEllipse.contains(otherNode.rectangle); } else { - return this.ellipse.contains(otherNode.Ellipse as Ellipse); + return this.internalEllipse.contains(otherNode.ellipse as Ellipse); } } @@ -130,17 +130,17 @@ export class CutNode { if (this.containsPoint(incomingPoint)) { let isSmallest = true; - for (let i = 0; i < this.children.length; i++) { + for (let i = 0; i < this.internalChildren.length; i++) { //Check if the point is within a child - if (this.children[i].containsPoint(incomingPoint)) { + if (this.internalChildren[i].containsPoint(incomingPoint)) { isSmallest = false; - if (this.children[i] instanceof CutNode) { + if (this.internalChildren[i] instanceof CutNode) { //If the point is within a cut node, check its children - return (this.children[i] as CutNode).remove(incomingPoint); + return (this.internalChildren[i] as CutNode).remove(incomingPoint); } else { //If the point is within an atom node, remove it - this.children = this.children.splice(i, 1); + this.internalChildren = this.internalChildren.splice(i, 1); return true; } } @@ -162,30 +162,30 @@ export class CutNode { public toString(): string { let str: string; - if (this.ellipse === null) { + if (this.internalEllipse === null) { str = "Sheet of Assertion of the AEG Tree"; } else { - str = "A cut node with boundary box of \n" + this.ellipse.toString(); + str = "A cut node with boundary box of \n" + this.internalEllipse.toString(); } - if (this.children.length > 0) { - str += ", \n" + "With nested nodes: " + this.children.toString(); + if (this.internalChildren.length > 0) { + str += ", \n" + "With nested nodes: " + this.internalChildren.toString(); } return str; } public toFormulaString(): string { let formulaString = ""; - for (const child of this.children) { + for (const child of this.internalChildren) { if (child instanceof AtomNode) { - formulaString += child.Identifier; + formulaString += child.identifier; } else if (child instanceof CutNode) { formulaString += child.toFormulaString(); } formulaString += " "; } formulaString = formulaString.slice(0, -1); - if (this.ellipse === null) { + if (this.internalEllipse === null) { formulaString = "[" + formulaString + "]"; } else { formulaString = "(" + formulaString + ")"; diff --git a/src/AEG/Ellipse.ts b/src/AEG/Ellipse.ts index 3300b1fb..b3a4bfe4 100644 --- a/src/AEG/Ellipse.ts +++ b/src/AEG/Ellipse.ts @@ -1,6 +1,6 @@ import {Point} from "./Point"; import {Rectangle} from "./Rectangle"; -import {shapesOverlaps, shapeContains, pointInELlipse} from "./AEGUtils"; +import {shapesOverlap, shapeContains, pointInEllipse} from "./AEGUtils"; /** * Class that defines an Ellipse. @@ -73,7 +73,7 @@ export class Ellipse { * @returns True, if the point is inside this ellipse. Else, false */ public containsPoint(point: Point): boolean { - return pointInELlipse(this, point); + return pointInEllipse(this, point); } /** @@ -82,7 +82,7 @@ export class Ellipse { * @returns True, if there is an overlap. Else, false. */ public overlaps(otherShape: Rectangle | Ellipse): boolean { - return shapesOverlaps(this, otherShape); + return shapesOverlap(this, otherShape); } /** diff --git a/src/AEG/Rectangle.ts b/src/AEG/Rectangle.ts index 395be8db..aa04d47a 100644 --- a/src/AEG/Rectangle.ts +++ b/src/AEG/Rectangle.ts @@ -1,6 +1,6 @@ import {Ellipse} from "./Ellipse"; import {Point} from "./Point"; -import {shapesOverlaps, shapeContains, pointInRect} from "./AEGUtils"; +import {shapesOverlap, shapeContains, pointInRect} from "./AEGUtils"; /** * Class that defines a Rectangle. @@ -72,7 +72,7 @@ export class Rectangle { * @returns True, if there is an overlap. Else, false. */ public overlaps(otherShape: Rectangle | Ellipse): boolean { - return shapesOverlaps(this, otherShape); + return shapesOverlap(this, otherShape); } /** diff --git a/src/AtomMode.ts b/src/AtomMode.ts index 95e8cad0..08e739dc 100644 --- a/src/AtomMode.ts +++ b/src/AtomMode.ts @@ -15,7 +15,7 @@ let atomMetrics: TextMetrics; let hasMouseDown: Boolean = false; let hasAtom: Boolean = false; let currentAtom: AtomNode = new AtomNode("a"); //MAKING a THE DEFAULT IDENTIFIER FOR ATOMS -atomDisplay.innerHTML = currentAtom.Identifier; +atomDisplay.innerHTML = currentAtom.identifier; /** * Will compare the event given with all possible events it could be. @@ -32,23 +32,23 @@ export function atomHandler(event: Event) { const thisEvent: KeyboardEvent = event; const regex = new RegExp(/^[A-Za-z]$/); if (regex.test(thisEvent.key)) { - currentAtom.Identifier = thisEvent.key; - atomDisplay.innerHTML = currentAtom.Identifier; + currentAtom.identifier = thisEvent.key; + atomDisplay.innerHTML = currentAtom.identifier; hasAtom = true; } } else if (event.type === "mousedown" && hasAtom) { const thisEvent: MouseEvent = event; - atomMetrics = ctx.measureText(currentAtom.Identifier); + atomMetrics = ctx.measureText(currentAtom.identifier); const startVertex: Point = new Point( thisEvent.clientX, thisEvent.clientY - atomMetrics.actualBoundingBoxAscent ); - currentAtom.Rectangle = new Rectangle( + currentAtom.rectangle = new Rectangle( startVertex, atomMetrics.width, atomMetrics.fontBoundingBoxDescent + atomMetrics.actualBoundingBoxAscent ); - currentAtom.Origin = new Point(thisEvent.clientX, thisEvent.clientY); + currentAtom.origin = new Point(thisEvent.clientX, thisEvent.clientY); ctx.clearRect(0, 0, canvas.width, canvas.height); redrawCut(tree.sheet); @@ -60,8 +60,8 @@ export function atomHandler(event: Event) { hasMouseDown = true; } else if (event.type === "mousemove" && hasMouseDown) { const thisEvent: MouseEvent = event; - currentAtom.Origin = new Point(thisEvent.clientX, thisEvent.clientY); - currentAtom.Rectangle.startVertex = new Point( + currentAtom.origin = new Point(thisEvent.clientX, thisEvent.clientY); + currentAtom.rectangle.startVertex = new Point( thisEvent.clientX, thisEvent.clientY - atomMetrics.actualBoundingBoxAscent ); @@ -77,14 +77,14 @@ export function atomHandler(event: Event) { if (tree.canInsert(currentAtom)) { tree.insert(currentAtom); } - currentAtom = new AtomNode(currentAtom.Identifier); + currentAtom = new AtomNode(currentAtom.identifier); ctx.clearRect(0, 0, canvas.width, canvas.height); redrawCut(tree.sheet); hasMouseDown = false; console.log(tree.toString()); } else if (event.type === "mouseout" && hasMouseDown) { hasMouseDown = false; - currentAtom = new AtomNode(currentAtom.Identifier); + currentAtom = new AtomNode(currentAtom.identifier); ctx.clearRect(0, 0, canvas.width, canvas.height); redrawCut(tree.sheet); } @@ -98,9 +98,9 @@ export function atomHandler(event: Event) { function drawAtom(thisAtom: AtomNode, color: string) { ctx.fillStyle = color; ctx.strokeStyle = color; - const displayBox = thisAtom.Rectangle; + const displayBox = thisAtom.rectangle; ctx.beginPath(); - ctx.fillText(thisAtom.Identifier, thisAtom.Origin.x, thisAtom.Origin.y); + ctx.fillText(thisAtom.identifier, thisAtom.origin.x, thisAtom.origin.y); ctx.rect( displayBox.startVertex.x, displayBox.startVertex.y, diff --git a/src/CutMode.ts b/src/CutMode.ts index ac57965e..6f26900c 100644 --- a/src/CutMode.ts +++ b/src/CutMode.ts @@ -39,7 +39,7 @@ export function cutHandler(event: MouseEvent) { ctx.clearRect(0, 0, canvas.width, canvas.height); redrawCut(tree.sheet); currentEllipse = createEllipse(startingPoint, currentPoint); - newCut.Ellipse = currentEllipse; + newCut.ellipse = currentEllipse; if (tree.canInsert(newCut) && currentEllipse.radiusX > 15 && currentEllipse.radiusY > 15) { drawEllipse(newCut, "#00FF00"); @@ -108,7 +108,7 @@ export function createEllipse(original: Point, current: Point): Ellipse { */ function drawEllipse(thisCut: CutNode, color: string) { ctx.strokeStyle = color; - const ellipse: Ellipse = thisCut.Ellipse; + const ellipse: Ellipse = thisCut.ellipse; const center: Point = ellipse.center; ctx.beginPath(); ctx.ellipse(center.x, center.y, ellipse.radiusX, ellipse.radiusY, 0, 0, 2 * Math.PI); diff --git a/src/index.ts b/src/index.ts index f44d9012..e2b56d4a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -101,21 +101,21 @@ function removeListeners() { */ export function redrawCut(incomingNode: CutNode) { cutDisplay.innerHTML = tree.toString(); - for (let i = 0; incomingNode.Children.length > i; i++) { - if (incomingNode.Children[i] instanceof AtomNode) { - redrawAtom(incomingNode.Children[i]); + for (let i = 0; incomingNode.children.length > i; i++) { + if (incomingNode.children[i] instanceof AtomNode) { + redrawAtom(incomingNode.children[i]); } else { - redrawCut(incomingNode.Children[i]); + redrawCut(incomingNode.children[i]); } } - if (incomingNode.Ellipse instanceof Ellipse) { + if (incomingNode.ellipse instanceof Ellipse) { ctx.strokeStyle = "#000000"; ctx.beginPath(); ctx.ellipse( - incomingNode.Ellipse.center.x, - incomingNode.Ellipse.center.y, - incomingNode.Ellipse.radiusX, - incomingNode.Ellipse.radiusY, + incomingNode.ellipse.center.x, + incomingNode.ellipse.center.y, + incomingNode.ellipse.radiusX, + incomingNode.ellipse.radiusY, 0, 0, 2 * Math.PI @@ -129,7 +129,7 @@ export function redrawCut(incomingNode: CutNode) { * @param incomingNode The Atom Node to be redrawn */ function redrawAtom(incomingNode: AtomNode) { - const displayBox = incomingNode.Rectangle; + const displayBox = incomingNode.rectangle; ctx.strokeStyle = "#000000"; ctx.fillStyle = "#000000"; ctx.beginPath(); @@ -139,6 +139,6 @@ function redrawAtom(incomingNode: AtomNode) { displayBox.width, displayBox.height ); - ctx.fillText(incomingNode.Identifier, incomingNode.Origin.x, incomingNode.Origin.y); + ctx.fillText(incomingNode.identifier, incomingNode.origin.x, incomingNode.origin.y); ctx.stroke(); } From dd9ef58c8b4abe3ace0bd8e5b71ece760a8ffb0d Mon Sep 17 00:00:00 2001 From: AnushaTiwari5 Date: Wed, 11 Oct 2023 22:09:32 -0400 Subject: [PATCH 4/6] simplied edge intersection --- src/AEG/AEGUtils.ts | 151 ++++++-------------------------------------- 1 file changed, 18 insertions(+), 133 deletions(-) diff --git a/src/AEG/AEGUtils.ts b/src/AEG/AEGUtils.ts index 82538fa7..d597cb07 100644 --- a/src/AEG/AEGUtils.ts +++ b/src/AEG/AEGUtils.ts @@ -15,7 +15,7 @@ export function shapesOverlap( if (newShape instanceof Rectangle) { if (existingShape instanceof Rectangle) { //For rectangle-rectangle, check if their edges intersect - return edgesIntersect(newShape, existingShape); + return edgesWithin(newShape, existingShape) || edgesWithin(existingShape, newShape); } else { return ellipseRectangleCollision(existingShape as Ellipse, newShape as Rectangle); } @@ -121,139 +121,24 @@ export function shapeContains( } /** - * Method that checks if any edges of this rectangle overlap with the other rectangle. - * @param otherRect The other rectangle to be checked. + * Method that checks if any edges of a rectangle are within the other rectangle. + * @param rect1 The incoming rectangle. + * @param rect2 The existing rectangle. * @returns True, if edges overlap. Else, false. - * @todo This algo can and should be simplified to be less than 10 lines of code. -James-Oswald */ -function edgesIntersect(shape1: Rectangle, shape2: Rectangle): boolean { - const thisCorners = shape1.getCorners(); - const otherCorners = shape2.getCorners(); - - if (thisCorners[0].y <= otherCorners[0].y && thisCorners[2].y >= otherCorners[0].y) { - //The top edge of the other rectangle is within the horizontal boundaries - //of this rectangle - if (thisCorners[0].x <= otherCorners[0].x && thisCorners[1].x >= otherCorners[0].x) { - //The left edge of the other rectangle is within the vertical boundaries - //of this rectangle - return true; - } else if ( - //The left edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[0].x && - otherCorners[1].x >= thisCorners[0].x - ) { - return true; - } else if ( - //The right edge of the other rectangle is within the vertical boundaries - //of this rectangle - thisCorners[0].x <= otherCorners[1].x && - thisCorners[1].x >= otherCorners[1].x - ) { - return true; - } else if ( - //The right edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[1].x && - otherCorners[1].x >= thisCorners[1].x - ) { - return true; - } - - return false; - } else if (otherCorners[0].y <= thisCorners[0].y && otherCorners[2].y >= thisCorners[0].y) { - //The top edge of this rectangle is within the horizontal boundaries - //of the other rectangle - if (thisCorners[0].x <= otherCorners[0].x && thisCorners[1].x >= otherCorners[0].x) { - //The left edge of the other rectangle is within the vertical boundaries - //of this rectangle - return true; - } else if ( - //The left edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[0].x && - otherCorners[1].x >= thisCorners[0].x - ) { - return true; - } else if ( - //The right edge of the other rectangle is within the vertical boundaries - //of this rectangle - thisCorners[0].x <= otherCorners[1].x && - thisCorners[1].x >= otherCorners[1].x - ) { - return true; - } else if ( - //The right edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[1].x && - otherCorners[1].x >= thisCorners[1].x - ) { - return true; - } - - return false; - } else if (thisCorners[0].y <= otherCorners[2].y && thisCorners[2].y >= otherCorners[2].y) { - //The bottom edge of the other rectangle is within the horizontal boundaries - //of this rectangle - if (thisCorners[0].x <= otherCorners[0].x && thisCorners[1].x >= otherCorners[0].x) { - //The left edge of the other rectangle is within the vertical boundaries - //of this rectangle - return true; - } else if ( - //The left edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[0].x && - otherCorners[1].x >= thisCorners[0].x - ) { - return true; - } else if ( - //The right edge of the other rectangle is within the vertical boundaries - //of this rectangle - thisCorners[0].x <= otherCorners[1].x && - thisCorners[1].x >= otherCorners[1].x - ) { - return true; - } else if ( - //The right edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[1].x && - otherCorners[1].x >= thisCorners[1].x - ) { - return true; - } - - return false; - } else if (otherCorners[0].y <= thisCorners[2].y && otherCorners[2].y >= thisCorners[2].y) { - //The bottom edge of this rectangle is within the horizontal boundaries - //of the other rectangle - if (thisCorners[0].x <= otherCorners[0].x && thisCorners[1].x >= otherCorners[0].x) { - //The left edge of the other rectangle is within the vertical boundaries - //of this rectangle - return true; - } else if ( - //The left edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[0].x && - otherCorners[1].x >= thisCorners[0].x - ) { - return true; - } else if ( - //The right edge of the other rectangle is within the vertical boundaries - //of this rectangle - thisCorners[0].x <= otherCorners[1].x && - thisCorners[1].x >= otherCorners[1].x - ) { - return true; - } else if ( - //The right edge of this rectangle is within the vertical boundaries - //of the other rectangle - otherCorners[0].x <= thisCorners[1].x && - otherCorners[1].x >= thisCorners[1].x - ) { - return true; - } - - return false; +function edgesWithin(rect1: Rectangle, rect2: Rectangle): boolean { + const corners1 = rect1.getCorners(); + const corners2 = rect2.getCorners(); + + if ( + //Check if the horizontal edges are within + ((corners1[0].y <= corners2[0].y && corners1[2].y >= corners2[0].y) || + (corners1[0].y <= corners2[2].y && corners1[2].y >= corners2[2].y)) && + //Check if the vertical edges are within + ((corners1[0].x <= corners2[0].x && corners1[1].x >= corners2[0].x) || + (corners1[0].x <= corners2[1].x && corners1[1].x >= corners2[1].x)) + ) { + return true; } return false; @@ -292,7 +177,7 @@ export function pointInEllipse(ellipse: Ellipse, point: Point): boolean { Math.pow(point.y - ellipse.center.y, 2) / Math.pow(ellipse.radiusY, 2); //); - return p < 1; + return p <= 1; } /** From 34abcbf2c9605ee4a767861894613f6ae7772c15 Mon Sep 17 00:00:00 2001 From: AnushaTiwari5 Date: Wed, 11 Oct 2023 22:18:29 -0400 Subject: [PATCH 5/6] duh --- src/AEG/AEGUtils.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/AEG/AEGUtils.ts b/src/AEG/AEGUtils.ts index d597cb07..a0ee6a6f 100644 --- a/src/AEG/AEGUtils.ts +++ b/src/AEG/AEGUtils.ts @@ -130,18 +130,14 @@ function edgesWithin(rect1: Rectangle, rect2: Rectangle): boolean { const corners1 = rect1.getCorners(); const corners2 = rect2.getCorners(); - if ( + return ( //Check if the horizontal edges are within ((corners1[0].y <= corners2[0].y && corners1[2].y >= corners2[0].y) || (corners1[0].y <= corners2[2].y && corners1[2].y >= corners2[2].y)) && //Check if the vertical edges are within ((corners1[0].x <= corners2[0].x && corners1[1].x >= corners2[0].x) || (corners1[0].x <= corners2[1].x && corners1[1].x >= corners2[1].x)) - ) { - return true; - } - - return false; + ); } /** From 5eb335fce98a6567183279e9989db9e03a152190 Mon Sep 17 00:00:00 2001 From: AnushaTiwari5 Date: Wed, 11 Oct 2023 22:33:12 -0400 Subject: [PATCH 6/6] no executions on my watch --- src/AEG/AEGTree.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AEG/AEGTree.ts b/src/AEG/AEGTree.ts index 6153c447..9fef23a4 100644 --- a/src/AEG/AEGTree.ts +++ b/src/AEG/AEGTree.ts @@ -85,7 +85,7 @@ export class AEGTree { currentCut.child = incomingNode; if (incomingNode instanceof CutNode) { - for (let i = 0; i < originalChildren.length; i++) { + for (let i = originalChildren.length - 1; i >= 0; i--) { if (incomingNode.containsNode(originalChildren[i])) { incomingNode.child = originalChildren[i]; currentCut.children.splice(i, 1);