Skip to content

Commit

Permalink
Merge branch 'master' into 98-ellipse-collision-not-detecting
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Oswald authored Oct 9, 2023
2 parents 982cd31 + 71eff51 commit 7e67c20
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 27 deletions.
8 changes: 4 additions & 4 deletions src/AEG/AtomNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ export class AtomNode {
* @param rect The rectangle to be set as the boundary box of this node.
* @param val The value of the proposition represented by this node.
*/
public constructor(val: string, origin: Point, rect: Rectangle) {
this.rect = rect;
this.identifier = val;
this.origin = origin;
public constructor(val?: string, origin?: Point, rect?: Rectangle) {
this.rect = rect ?? new Rectangle();
this.identifier = val ?? "";
this.origin = origin ?? new Point();
}

/**
Expand Down
11 changes: 11 additions & 0 deletions src/AEG/Point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ export class Point {
this.y = coordY;
}

/**
* Returns the distance between this Point and the other.
* @param otherPoint the other Point
* @returns the distance between the two
*/
public distance(otherPoint: Point): number {
const dx = this.x - otherPoint.x;
const dy = this.y - otherPoint.y;
return Math.sqrt(dx * dx + dy * dy);
}

/**
* Method that returns a string representation of the point.
* @returns The coordinates of the point.
Expand Down
8 changes: 4 additions & 4 deletions src/AEG/Rectangle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ export class Rectangle {
* @param w The width of the rectangle.
* @param h The height of the rectangle.
*/
public constructor(vertex: Point, w: number, h: number) {
this.startVertex = vertex;
this.width = w;
this.height = h;
public constructor(vertex?: Point, w?: number, h?: number) {
this.startVertex = vertex ?? new Point();
this.width = w ?? 0;
this.height = h ?? 0;
}

/**
Expand Down
108 changes: 108 additions & 0 deletions src/AtomMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import {Point} from "./AEG/Point";
import {AtomNode} from "./AEG/AtomNode";
import {redrawCut, tree} from "./index";
import {Rectangle} from "./AEG/Rectangle";

const canvas: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("canvas");
const res: CanvasRenderingContext2D | null = canvas.getContext("2d");
if (res === null) {
throw Error("2d rendering context not supported");
}
const ctx: CanvasRenderingContext2D = res;
let atomMetrics: TextMetrics;

let hasMouseDown: Boolean = false;
let hasAtom: Boolean = false;
let currentAtom: AtomNode = new AtomNode();

/**
* Will compare the event given with all possible events it could be.
* keypress checks to see if the key was a letter and if yes sets it to that letter.
* mousedown sets the atom down, calculates the bounding box, and checks for what color.
* mousemove will alter the origin position and the starting vertex of the bounding box.
* mouseup will add the atom to the tree if it is in a valid location.
* mosueout will end drawing early.
* @param event The event that will be used
* @param event the event that will be used
*/
export function atomHandler(event: Event) {
if (event.type === "keypress") {
const thisEvent: KeyboardEvent = <KeyboardEvent>event;
const regex = new RegExp(/^[A-Za-z]$/);
if (regex.test(thisEvent.key)) {
currentAtom.identifier = thisEvent.key;
hasAtom = true;
}
} else if (event.type === "mousedown" && hasAtom) {
const thisEvent: MouseEvent = <MouseEvent>event;
atomMetrics = ctx.measureText(currentAtom.identifier);
const startVertex: Point = new Point(
thisEvent.clientX,
thisEvent.clientY - atomMetrics.actualBoundingBoxAscent
);
currentAtom.rect = new Rectangle(
startVertex,
atomMetrics.width,
atomMetrics.fontBoundingBoxDescent + atomMetrics.actualBoundingBoxAscent
);
currentAtom.origin = new Point(thisEvent.clientX, thisEvent.clientY);

ctx.clearRect(0, 0, canvas.width, canvas.height);
redrawCut(tree.sheet);
if (tree.canInsert(currentAtom)) {
drawAtom(currentAtom, "#00FF00");
} else {
drawAtom(currentAtom, "#6600ff");
}
hasMouseDown = true;
} else if (event.type === "mousemove" && hasMouseDown) {
const thisEvent: MouseEvent = <MouseEvent>event;
currentAtom.origin = new Point(thisEvent.clientX, thisEvent.clientY);
currentAtom.rect.startVertex = new Point(
thisEvent.clientX,
thisEvent.clientY - atomMetrics.actualBoundingBoxAscent
);

ctx.clearRect(0, 0, canvas.width, canvas.height);
redrawCut(tree.sheet);
if (tree.canInsert(currentAtom)) {
drawAtom(currentAtom, "#00FF00");
} else {
drawAtom(currentAtom, "#FF0000");
}
} else if (event.type === "mouseup" && hasMouseDown) {
if (tree.canInsert(currentAtom)) {
tree.insert(currentAtom);
}
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);
ctx.clearRect(0, 0, canvas.width, canvas.height);
redrawCut(tree.sheet);
}
}

/**
* Draws the given atomNode with the given color.
* @param thisAtom the atomnode to be drawn.
* @param color the color of the atom.
*/
function drawAtom(thisAtom: AtomNode, color: string) {
ctx.fillStyle = color;
ctx.strokeStyle = color;
const displayBox = thisAtom.rect;
ctx.beginPath();
ctx.fillText(thisAtom.identifier, thisAtom.origin.x, thisAtom.origin.y);
ctx.rect(
displayBox.startVertex.x,
displayBox.startVertex.y,
displayBox.width,
displayBox.height
);
ctx.stroke();
}
116 changes: 116 additions & 0 deletions src/CutMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import {Point} from "./AEG/Point";
import {CutNode} from "./AEG/CutNode";
import {Ellipse} from "./AEG/Ellipse";
import {redrawCut} from "./index";
import {tree} from "./index";

const canvas: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("canvas");
const res: CanvasRenderingContext2D | null = canvas.getContext("2d");
const showRectElm: HTMLInputElement = <HTMLInputElement>document.getElementById("showRect");
const modeElm: HTMLSelectElement = <HTMLSelectElement>document.getElementById("mode");
if (res === null) {
throw Error("2d rendering context not supported");
}
const ctx: CanvasRenderingContext2D = res;

let hasMouseDown: Boolean = false;
let currentEllipse: Ellipse = new Ellipse();
let startingPoint: Point = new Point();

/**
* Will compare the event given with all possible events it could be.
* mousedown events will allocate the starting point and allow the later events to take place
* mousemove will call createEllipse starting and current points, if invalid place will color it.
* mouseup will add the cut to the tree if it is in a valid place, and set hasmousedown to false.
* mosueout will end drawing early.
* @param event The event that will be used
*/
export function cutHandler(event: MouseEvent) {
let newCut: CutNode = new CutNode();
const currentPoint: Point = new Point();

if (event.type === "mousedown") {
hasMouseDown = true;
startingPoint.x = event.clientX;
startingPoint.y = event.clientY;
} else if (event.type === "mousemove" && hasMouseDown) {
currentPoint.x = event.clientX;
currentPoint.y = event.clientY;
ctx.clearRect(0, 0, canvas.width, canvas.height);
redrawCut(tree.sheet);
currentEllipse = createEllipse(startingPoint, currentPoint);
newCut.ellipse = currentEllipse;

if (tree.canInsert(newCut) && currentEllipse.radiusX > 15 && currentEllipse.radiusY > 15) {
drawEllipse(newCut, "#00FF00");
} else {
drawEllipse(newCut, "#FF0000");
}
} else if (event.type === "mouseup" && hasMouseDown) {
newCut = new CutNode(currentEllipse);
if (tree.canInsert(newCut) && currentEllipse.radiusX > 15 && currentEllipse.radiusY > 15) {
tree.insert(newCut);
}
hasMouseDown = false;
startingPoint = new Point();
ctx.clearRect(0, 0, canvas.width, canvas.height);
redrawCut(tree.sheet);
console.log(tree.toString());
} else if (event.type === "mouseout" && hasMouseDown) {
hasMouseDown = false;
startingPoint = new Point();
ctx.clearRect(0, 0, canvas.width, canvas.height);
redrawCut(tree.sheet);
}
}

/**
* A function to draw an ellipse between two points designated by the user.
* @param original the point where the user originally clicked
* @param current the point where the user's mouse is currently located
*/
export function createEllipse(original: Point, current: Point): Ellipse {
const center: Point = new Point(
(current.x - original.x) / 2 + original.x,
(current.y - original.y) / 2 + original.y
);

const sdx = original.x - current.x;
const sdy = original.y - current.y;
const dx = Math.abs(sdx);
const dy = Math.abs(sdy);
let rx, ry: number;

if (modeElm.value === "circumscribed") {
//This inscribed ellipse solution is inspired by the discussion of radius ratios in
//https://stackoverflow.com/a/433426/6342516
const rv: number = Math.floor(center.distance(current));
ry = Math.floor(rv * (dy / dx));
rx = Math.floor(rv * (dx / dy));
} else {
rx = dx / 2;
ry = dy / 2;
}

if (showRectElm.checked) {
ctx.beginPath();
ctx.rect(original.x, original.y, -sdx, -sdy);
ctx.stroke();
}

return new Ellipse(center, rx, ry);
}

/**
* Draws the given cut onto the canvas.
* @param thisCut The cut containing the ellipse to be drawn
* @param color the line color of the ellipse
*/
function drawEllipse(thisCut: CutNode, color: string) {
ctx.strokeStyle = color;
const ellipse: 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);
ctx.stroke();
}
6 changes: 6 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,9 @@ p {
left: 0px;
z-index: -1;
}
.no-highlight{
user-select: none;
-moz-user-select: none;
-webkit-text-select: none;
-webkit-user-select: none;
}
8 changes: 4 additions & 4 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</head>
<body>
<header id="header">
<p>Peirce My Heart</p>
<p class="no-highlight">Peirce My Heart</p>
</header>
<div id="sidebar">
<div class="row">
Expand All @@ -32,13 +32,13 @@
<div id="toolbar">
<div id="cutTools">
<div class="toolSetting">
<p>Show Guidelines:</p>
<p class="no-highlight">Show Guidelines:</p>
</div>
<div class="toolSetting">
<input id="showRect" type="checkbox" title="Show Rect"/>
</div>
<div class="toolSetting">
<p>Cut Mode:</p>
<p class="no-highlight">Cut Mode:</p>
</div>
<div class="toolSetting">
<select id="mode" name="guideSelector">
Expand All @@ -47,7 +47,7 @@
</select>
</div>
<div class="toolSetting">
<p id="graphString"></p>
<p class="no-highlight" id="graphString"></p>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 7e67c20

Please sign in to comment.