Skip to content

Commit

Permalink
Change NodeGeometry to match EdgeGeometry
Browse files Browse the repository at this point in the history
  • Loading branch information
antonvolkoff committed Jun 29, 2020
1 parent e3ae160 commit bc4c24d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 104 deletions.
17 changes: 16 additions & 1 deletion src/canvas/geometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,19 @@ export function midPoint(line: Line): Point {
const y3 = midRatio * y2 + (1 - midRatio) * y1;

return { x: x3, y: y3 };
}
}

/**
* Checks if a given point `p` is inside of a rectangle `r`.
*/
export const within = (r: Rect, p: Point): boolean => {
const left = r.x;
const right = r.x + r.width;
const top = r.y;
const bottom = r.y + r.height;

return (
p.x > left && p.x < right &&
p.y < bottom && p.y > top
);
};
122 changes: 53 additions & 69 deletions src/canvas/node_geometry.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import * as p5 from "p5";
import { Point, Rect } from "./geometry";
import { Point, Rect, within } from "./geometry";

interface NodeGeometry {
export interface NodeGeometry {
center: Point;
border: Rect;
text: Point;
drag: Point[];
dragPoints: Point[];
value: string;
draw(s: p5, selected: boolean): void;
isWithin(mouse: Point): boolean;
isWithinDragArea(mouse: Point): boolean;
}

const buildNodeGeometry = (atom: any): NodeGeometry => {
Expand All @@ -28,7 +31,7 @@ const buildNodeGeometry = (atom: any): NodeGeometry => {
center,
border: { x: atom.x - 20, y: atom.y - 14, width, height },
text: { x: atom.x + 2, y: atom.y - 7.5 },
drag: [
dragPoints: [
{ x: atom.x - 12, y: atom.y - 7 },
{ x: atom.x - 7, y: atom.y - 7 },
{ x: atom.x - 12, y: atom.y },
Expand All @@ -37,71 +40,52 @@ const buildNodeGeometry = (atom: any): NodeGeometry => {
{ x: atom.x - 7, y: atom.y + 7 },
],
value: atom.value,
};
};

const drawNode = (s: p5, geometry: NodeGeometry, selected: boolean) => {
const fillColor = "#ffffff";
const unselectedColor = "#999999";
const selectedColor = "#79B8FF";
const strokeWeight = 1.5;
const borderRadius = 6;

const strokeColor = selected ? selectedColor : unselectedColor;

s.push();
s.fill(s.color(fillColor));
s.strokeWeight(strokeWeight);
s.stroke(s.color(strokeColor));

const border = geometry.border;
s.rect(border.x, border.y, border.width, border.height, borderRadius);
s.pop();

if (selected) {
s.push();
s.fill(s.color(fillColor));
s.stroke(s.color(strokeColor));
geometry.drag.forEach((p) => s.circle(p.x, p.y, 2));
s.pop();
}

s.push();
s.fill(50);
s.strokeWeight(0);
s.textAlign(s.LEFT, s.TOP);
s.textFont("monospace", 14);
s.textLeading(17);
s.text(geometry.value, geometry.text.x, geometry.text.y);
s.pop();
};

const within = (mouse: Point, geometry: NodeGeometry): boolean => {
const leftBoundary = geometry.border.x;
const rightBoundary = geometry.border.x + geometry.border.width;
const topBoundary = geometry.border.y;
const bottomBoundary = geometry.border.y + geometry.border.height;

return (
mouse.x > leftBoundary &&
mouse.x < rightBoundary &&
mouse.y < bottomBoundary &&
mouse.y > topBoundary
);
};

const withinDragArea = (mouse: Point, geometry: NodeGeometry): boolean => {
const leftBoundary = geometry.border.x;
const rightBoundary = geometry.border.x + 20;
const topBoundary = geometry.border.y;
const bottomBoundary = geometry.border.y + 20;

return (
mouse.x > leftBoundary &&
mouse.x < rightBoundary &&
mouse.y < bottomBoundary &&
mouse.y > topBoundary
);
draw(s, selected) {
const fillColor = "#ffffff";
const unselectedColor = "#999999";
const selectedColor = "#79B8FF";
const strokeWeight = 1.5;
const borderRadius = 6;

const strokeColor = selected ? selectedColor : unselectedColor;

s.push();
s.fill(s.color(fillColor));
s.strokeWeight(strokeWeight);
s.stroke(s.color(strokeColor));

const border = this.border;
s.rect(border.x, border.y, border.width, border.height, borderRadius);
s.pop();

if (selected) {
s.push();
s.fill(s.color(fillColor));
s.stroke(s.color(strokeColor));
this.dragPoints.forEach((p) => s.circle(p.x, p.y, 2));
s.pop();
}

s.push();
s.fill(50);
s.strokeWeight(0);
s.textAlign(s.LEFT, s.TOP);
s.textFont("monospace", 14);
s.textLeading(17);
s.text(this.value, this.text.x, this.text.y);
s.pop();
},

isWithin(mouse) {
return within(this.border, mouse);
},

isWithinDragArea(mouse) {
const dragArea: Rect = { x: this.border.x, y: this.border.y, width: 20, height: 20 };
return within(dragArea, mouse);
},
};
};

export { buildNodeGeometry, drawNode, within, withinDragArea };
export { buildNodeGeometry };
50 changes: 16 additions & 34 deletions src/canvas/sketch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as p5 from "p5";
import { Store } from "redux";

import { Point } from "./geometry";
import { within, buildNodeGeometry, drawNode, withinDragArea } from "./node_geometry";
import { buildNodeGeometry, NodeGeometry } from "./node_geometry";
import { buildEdgeGeometry } from "./edge_geometry";
import * as Legend from "./legend";
import { gridPoints, gridTiles } from "./grid";
Expand Down Expand Up @@ -45,42 +45,24 @@ export default function Sketch(store: Store<ApplicationState>) {
const backgroundColor = p.color("#FDFDFD");
let bg: p5.Graphics = null;

const createClickPayload = (): Click => {
const mouse = { x: p.mouseX, y: p.mouseY };
const atomId = null;
const dragArea = false;
return { mouse, atomId, dragArea };
}
const createClickPayload = (x: number, y: number): Click => {
const clickedOn = (mouse) => (candidate) => buildNodeGeometry(candidate).isWithin(mouse);

const processClick = (payload: Click): Click => {
// Convert coordinates
payload.mouse = ViewField.toGlobalCoordinates(viewField, payload.mouse);

// Detect click
const withinAtom = (candidate) => within(payload.mouse, buildNodeGeometry(candidate));
const atom = Object.values(atoms).find(withinAtom);
if (atom) {
payload.atomId = atom.id;
payload.dragArea = withinDragArea(payload.mouse, buildNodeGeometry(atom));
payload.clickOffset = {
deltaX: atom.x - payload.mouse.x,
deltaY: atom.y - payload.mouse.y,
};
}
const mouse = ViewField.toGlobalCoordinates(viewField, { x, y });
const atom = Object.values(atoms).find(clickedOn(mouse));
const atomId = atom?.id;
const dragArea = atom ? buildNodeGeometry(atom).isWithinDragArea(mouse) : false;
const clickOffset = atom ? { deltaX: atom.x - mouse.x, deltaY: atom.y - mouse.y } : null;

return payload;
}
return { mouse, atomId, dragArea, clickOffset };
};

function drawEdges() {
edges.forEach(e => buildEdgeGeometry(e).draw(p, e.selected));
edges.forEach((edge) => buildEdgeGeometry(edge).draw(p, edge.selected));
}

function drawAtoms() {
p.push();
atoms.forEach(atom => {
drawNode(p, buildNodeGeometry(atom), atom.selected);
});
p.pop();
atoms.forEach((node) => buildNodeGeometry(node).draw(p, node.selected));
}

function drawBackground(s: p5, bg: p5.Graphics, color: p5.Color) {
Expand Down Expand Up @@ -166,12 +148,12 @@ export default function Sketch(store: Store<ApplicationState>) {
const tagName = (event.srcElement as HTMLElement).tagName;
if (tagName !== "CANVAS" && tagName !== "INPUT") return;

const payload = processClick(createClickPayload());
const payload = createClickPayload(p.mouseX, p.mouseY);
store.dispatch(actions.mousePressed(payload));
}

p.mouseClicked = () => {
const payload = processClick(createClickPayload());
const payload = createClickPayload(p.mouseX, p.mouseY);
store.dispatch(actions.clicked(payload));

if (payload.atomId) return;
Expand All @@ -186,7 +168,7 @@ export default function Sketch(store: Store<ApplicationState>) {
}

p.doubleClicked = () => {
const payload = processClick(createClickPayload());
const payload = createClickPayload(p.mouseX, p.mouseY);
store.dispatch(actions.doubleClicked(payload));
}

Expand All @@ -197,7 +179,7 @@ export default function Sketch(store: Store<ApplicationState>) {
}

p.mouseDragged = () => {
const payload = processClick(createClickPayload());
const payload = createClickPayload(p.mouseX, p.mouseY);
store.dispatch(actions.mouseDragged(payload));
}

Expand Down

0 comments on commit bc4c24d

Please sign in to comment.