Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/npm_and_yarn/types/node-20.10.0
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanR712 authored Nov 27, 2023
2 parents 8f63acd + 71583a7 commit a8c567b
Show file tree
Hide file tree
Showing 18 changed files with 965 additions and 207 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"Anusha",
"atomnode",
"buttonface",
"Deiterate",
"Deiteration",
"hasmousedown",
"Huda",
Expand Down
1 change: 1 addition & 0 deletions src/DrawModes/DeleteMultiTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,5 @@ export function deleteMultiMouseUp(event: MouseEvent) {
export function deleteMultiMouseOut() {
currentNode = null;
legalNode = false;
redrawTree(treeContext.tree);
}
38 changes: 38 additions & 0 deletions src/DrawModes/DrawUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,41 @@ export function highlightNode(child: AtomNode | CutNode, color: string) {
}
}
}

/**
* Determines which widest points the current point is closest to so that the resize
* can move in that direction.
* widestPoints[0] = leftmost widest point of the ellipse
* widestPoints[1] = topmost widest point of the ellipse
* widestPoints[2] = rightmost widest point of the ellipse
* widestPoints[3] = bottommost widest point of the ellipse
* @returns The new direction for x and y
*/
export function determineDirection(currentNode: CutNode, startingPoint: Point): Point {
const newDirection = new Point(1, 1);
if (currentNode instanceof CutNode && (currentNode as CutNode).ellipse !== null) {
const currentEllipse: Ellipse = currentNode.ellipse as Ellipse;
const widestPoints: Point[] = [
new Point(currentEllipse.center.x - currentEllipse.radiusX, currentEllipse.center.y),
new Point(currentEllipse.center.x, currentEllipse.center.y - currentEllipse.radiusY),
new Point(currentEllipse.center.x + currentEllipse.radiusX, currentEllipse.center.y),
new Point(currentEllipse.center.x, currentEllipse.center.y + currentEllipse.radiusY),
];

//If the current point is closer to the top or equal the direction is positive and going down
if (widestPoints[0].distance(startingPoint) >= widestPoints[2].distance(startingPoint)) {
newDirection.x = 1;
} else {
newDirection.x = -1;
}

//If the current point is closer to the left or equal the direction is positive and going right
if (widestPoints[1].distance(startingPoint) >= widestPoints[3].distance(startingPoint)) {
newDirection.y = 1;
} else {
newDirection.y = -1;
}
}

return newDirection;
}
62 changes: 62 additions & 0 deletions src/DrawModes/EditModeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,43 @@ export function alterCut(originalCut: CutNode, difference: Point): CutNode {
}
}

/**
* Takes a cut and makes a copy of it with the center changed by the given difference.
* Creates a new array of children and alters those by the same distance acting recursively if needed.
* @param originalCut The cut we want to change the center of
* @param difference The distance the cut will be shifted
* @returns The new cut node with all of it's children altered
*/
export function alterCutChildren(originalCut: CutNode, difference: Point): CutNode {
if (originalCut.ellipse !== null) {
const alteredChildren: (CutNode | AtomNode)[] = [];

for (let i = 0; i < originalCut.children.length; i++) {
if (originalCut.children[i] instanceof CutNode) {
alteredChildren.push(
alterCutChildren(originalCut.children[i] as CutNode, difference)
);
} else if (originalCut.children[i] instanceof AtomNode) {
alteredChildren.push(alterAtom(originalCut.children[i] as AtomNode, difference));
}
}

return new CutNode(
new Ellipse(
new Point(
originalCut.ellipse.center.x + difference.x - offset.x,
originalCut.ellipse.center.y + difference.y - offset.y
),
originalCut.ellipse.radiusX,
originalCut.ellipse.radiusY
),
alteredChildren
);
} else {
throw new Error("Cannot alter the position of a cut without an ellipse.");
}
}

/**
* Takes an atom object and changes the origin point by the difference.
* @param originalAtom The Atom to be altered
Expand Down Expand Up @@ -169,3 +206,28 @@ export function highlightChildren(child: AtomNode | CutNode, color: string) {
}
}
}

/**
* Makes a copy of original cut and changes the center and radii by the difference given.
* Alters the change to the center based on the direction that is being moved to.
* @param originalCut The original cut that will be copied and altered
* @param difference The change for the new cut
* @param direction the direction the radius will be expanding towards
* @returns The new altered cut
*/
export function resizeCut(originalCut: CutNode, difference: Point, direction: Point) {
if (originalCut.ellipse !== null) {
return new CutNode(
new Ellipse(
new Point(
originalCut.ellipse.center.x + difference.x,
originalCut.ellipse.center.y + difference.y
),
originalCut.ellipse.radiusX + difference.x * direction.x,
originalCut.ellipse.radiusY + difference.y * direction.y
)
);
} else {
throw new Error("Cannot alter the position of a cut without an ellipse.");
}
}
71 changes: 7 additions & 64 deletions src/DrawModes/ResizeTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
*/

import {Point} from "../AEG/Point";
import {Ellipse} from "../AEG/Ellipse";
import {determineDirection} from "./DrawUtils";
import {resizeCut} from "./EditModeUtils";
import {AtomNode} from "../AEG/AtomNode";
import {CutNode} from "../AEG/CutNode";
import {treeContext} from "../treeContext";
Expand All @@ -23,7 +24,7 @@ let legalNode: boolean;

//The direction the cut will move in. For x 1 means going to the right and -1 means left.
//For y 1 means going down and -1 means going up.
const direction: Point = new Point(1, 1);
let direction: Point = new Point(1, 1);

/**
* Takes the point the user clicked and stores that for later use. If the lowest node containing
Expand All @@ -34,7 +35,7 @@ const direction: Point = new Point(1, 1);
export function resizeMouseDown(event: MouseEvent) {
startingPoint = new Point(event.x - offset.x, event.y - offset.y);
currentNode = treeContext.tree.getLowestNode(startingPoint);
if (currentNode !== treeContext.tree.sheet && currentNode instanceof CutNode) {
if (currentNode instanceof CutNode && currentNode.ellipse !== null) {
legalNode = true;
const currentParent = treeContext.tree.getLowestParent(startingPoint);
if (currentParent !== null) {
Expand All @@ -44,7 +45,7 @@ export function resizeMouseDown(event: MouseEvent) {
for (let i = 0; i < currentNode.children.length; i++) {
treeContext.tree.insert(currentNode.children[i]);
}
determineDirection();
direction = determineDirection(currentNode, startingPoint);
currentNode.children = [];
}
}
Expand All @@ -62,7 +63,7 @@ export function resizeMouseMove(event: MouseEvent) {
);

if (currentNode instanceof CutNode) {
const tempCut: CutNode = resizeCut(currentNode, moveDifference);
const tempCut: CutNode = resizeCut(currentNode, moveDifference, direction);
//This is just to make the lint stop yelling
if (tempCut.ellipse !== null) {
redrawTree(treeContext.tree);
Expand All @@ -88,7 +89,7 @@ export function resizeMouseUp(event: MouseEvent) {
);

if (currentNode instanceof CutNode) {
const tempCut: CutNode = resizeCut(currentNode, moveDifference);
const tempCut: CutNode = resizeCut(currentNode, moveDifference, direction);
//This is just to make the lint stop yelling
if (tempCut.ellipse !== null) {
if (treeContext.tree.canInsert(tempCut) && ellipseLargeEnough(tempCut.ellipse)) {
Expand All @@ -113,61 +114,3 @@ export function resizeMouseOut() {
legalNode = false;
redrawTree(treeContext.tree);
}

/**
* Makes a copy of original cut and changes the center and radii by the difference given.
* Alters the change to the center based on the direction that is being moved to.
* @param originalCut The original cut that will be copied and altered
* @param difference The change for the new cut
* @returns The new altered cut
*/
function resizeCut(originalCut: CutNode, difference: Point) {
if (originalCut.ellipse !== null) {
return new CutNode(
new Ellipse(
new Point(
originalCut.ellipse.center.x + difference.x,
originalCut.ellipse.center.y + difference.y
),
originalCut.ellipse.radiusX + difference.x * direction.x,
originalCut.ellipse.radiusY + difference.y * direction.y
)
);
} else {
throw new Error("Cannot alter the position of a cut without an ellipse.");
}
}

/**
* Determines which widest points the current point is closest to so that the resize
* can move in that direction.
* widestPoints[0] = leftmost widest point of the ellipse
* widestPoints[1] = topmost widest point of the ellipse
* widestPoints[2] = rightmost widest point of the ellipse
* widestPoints[3] = bottommost widest point of the ellipse
*/
function determineDirection() {
if (currentNode instanceof CutNode && (currentNode as CutNode).ellipse !== null) {
const currentEllipse: Ellipse = currentNode.ellipse as Ellipse;
const widestPoints: Point[] = [
new Point(currentEllipse.center.x - currentEllipse.radiusX, currentEllipse.center.y),
new Point(currentEllipse.center.x, currentEllipse.center.y - currentEllipse.radiusY),
new Point(currentEllipse.center.x + currentEllipse.radiusX, currentEllipse.center.y),
new Point(currentEllipse.center.x, currentEllipse.center.y + currentEllipse.radiusY),
];

//If the current point is closer to the top or equal the direction is positive and going down
if (widestPoints[0].distance(startingPoint) >= widestPoints[2].distance(startingPoint)) {
direction.x = 1;
} else {
direction.x = -1;
}

//If the current point is closer to the left or equal the direction is positive and going right
if (widestPoints[1].distance(startingPoint) >= widestPoints[3].distance(startingPoint)) {
direction.y = 1;
} else {
direction.y = -1;
}
}
}
147 changes: 147 additions & 0 deletions src/ProofTools/DeiterationTool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* Tool to be used during proof mode to perform deiteration on subgraphs on an AEG
* @author Dawn Moore
*/

import {Point} from "../AEG/Point";
import {AtomNode} from "../AEG/AtomNode";
import {CutNode} from "../AEG/CutNode";
import {redrawProof} from "../DrawModes/DrawUtils";
import {treeContext} from "../treeContext";
import {illegalColor} from "../Themes";
import {offset} from "../DrawModes/DragTool";
import {ProofNode} from "../AEG/ProofNode";
import {AEGTree} from "../AEG/AEGTree";
import {highlightChildren} from "../DrawModes/EditModeUtils";

//The node selected with the user mouse down.
let currentNode: CutNode | AtomNode | null = null;

//Whether or not the node is allowed to be moved (not the sheet).
let legalNode: boolean;

//The current tree in the proof chain
let currentProofTree: AEGTree;

/**
* Determines the lowest node containing the current point and if that is not the sheet is is
* considered a legal node. If it can also deiterate highlight it and all of it's children.
* @param event A Mouse up event while using the deiteration tool
*/
export function deiterationMouseDown(event: MouseEvent) {
const currentPoint: Point = new Point(event.x - offset.x, event.y - offset.y);
currentProofTree = new AEGTree(treeContext.getLastProofStep().tree.sheet);
currentNode = currentProofTree.getLowestNode(currentPoint);

setLegal();
}

/**
* Determines the lowest node containing the current point and if that is not the sheet it is
* considered a legal node and will be highlighted.
* @param event A mouse move event while using deiteration tool
*/
export function deiterationMouseMove(event: MouseEvent) {
const currentPoint: Point = new Point(event.x - offset.x, event.y - offset.y);
currentNode = currentProofTree.getLowestNode(currentPoint);
redrawProof();

setLegal();
}

/**
* If the node we currently have is legal, find it's parent and remove the current node from it.
* Push the new version of the tree onto the proof history array.
* @param event A mouse up event while using deiteration tool
*/
export function deiterationMouseUp(event: MouseEvent) {
if (legalNode) {
const currentPoint: Point = new Point(event.x - offset.x, event.y - offset.y);
if (
currentNode !== null &&
canDeiterate(currentProofTree.sheet, currentProofTree.getLevel(currentNode))
) {
const currentParent: CutNode | null = currentProofTree.getLowestParent(currentPoint);
if (currentParent instanceof CutNode) {
currentParent.remove(currentPoint);
}
treeContext.proofHistory.push(new ProofNode(currentProofTree, "Deiteration"));
}
}

legalNode = false;
redrawProof();
}

/**
* Helper function to determine if the currently selected node is a legal node and highlight it.
*/
function setLegal() {
if (
currentNode !== null &&
!(currentNode instanceof CutNode && currentNode.ellipse === null) &&
canDeiterate(currentProofTree.sheet, currentProofTree.getLevel(currentNode))
) {
highlightChildren(currentNode, illegalColor());
legalNode = true;
} else {
legalNode = false;
}
}

/**
* Reset the current null and make this node illegal until it's selected again, redraws the screen.
*/
export function deiterationMouseOut() {
legalNode = false;
currentNode = null;
redrawProof();
}

/**
* Searches the tree for an equal match to the node we're attempting to delete/deiterate that is
* not itself. It cannot go to a level lower than itself and it cannot search any cuts it is not
* contained by. The Node we search for is the currently selected no currentNode.
* @param currentParent The current node we are searching the children of
* @param level The level the node we're searching for is located
* @returns Whether or not this is a valid deiteration
*/
function canDeiterate(currentParent: CutNode, level: number): boolean {
let potentialParent: CutNode | null = null;
for (let i = 0; i < currentParent.children.length; i++) {
//If both nodes are cuts, and they are equal then we have found a copy higher on the tree
if (
currentParent.children[i] instanceof CutNode &&
currentNode instanceof CutNode &&
currentNode.isEqualTo(currentParent.children[i] as CutNode) &&
currentNode.ellipse !== (currentParent.children[i] as CutNode).ellipse
) {
return true;
} //If both nodes are atoms, and they both have the same identifier then they are equal
else if (
currentParent.children[i] instanceof AtomNode &&
currentNode instanceof AtomNode &&
(currentParent.children[i] as AtomNode).identifier === currentNode.identifier &&
currentParent.children[i].toString() !== currentNode.toString()
) {
return true;
} //If this cut has the node we're looking for we want to recurse towards it, however
//We want to still check the rest of this level so we do it afterwards.
else if (
currentParent.children[i] instanceof CutNode &&
(currentParent.children[i] as CutNode).containsNode(currentNode!) &&
currentProofTree.getLevel(currentParent.children[i]) < level
) {
potentialParent = currentParent.children[i] as CutNode;
}
}

//If we did find the parent of the node we're trying to find an equal of, we look at the next
//closest node.
if (potentialParent !== null) {
return canDeiterate(potentialParent, level);
}

//If there was no equal found then we cannot deiterate.
return false;
}
Loading

0 comments on commit a8c567b

Please sign in to comment.