Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: wires autolayout #191

Merged
merged 7 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions ArduinoFrontend/src/app/Libs/CircuitElement.ts
@@ -1,6 +1,7 @@
import { Point } from './Point';
import { Wire } from './Wire';
import { isNull } from 'util';
import { BoundingBox } from './Geometry';

/**
* Abstract Class Circuit Elements
Expand Down Expand Up @@ -110,6 +111,14 @@ export abstract class CircuitElement {
});
}
}

/**
* Returns bounding box of the circuit element
*/
getBoundingBox(): BoundingBox {
return BoundingBox.loadFromRaphaelBbox(this.elements.getBBox());
}

/**
* Draws circuit nodes
* @param canvas Raphael Canvas
Expand Down
29 changes: 29 additions & 0 deletions ArduinoFrontend/src/app/Libs/Geometry.ts
@@ -0,0 +1,29 @@
import _ from 'lodash';

export class BoundingBox {
x: number;
y: number;
height: number;
width: number;

constructor(x: number, y: number, width: number, height: number) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}

static loadFromRaphaelBbox(bBox) {
return new BoundingBox(bBox.x, bBox.y, bBox.width, bBox.height);
}

static getCombinedBBox(bBoxes: BoundingBox[]) {
const minX = _.minBy(bBoxes, box => box.x).x;
const maxX = _.maxBy(bBoxes, box => box.x).x;
const minY = _.minBy(bBoxes, box => box.y).y;
const maxY = _.maxBy(bBoxes, box => box.y).y;
return new BoundingBox(
minX, minY, maxX - minX, maxY - minY
);
}
}
8 changes: 8 additions & 0 deletions ArduinoFrontend/src/app/Libs/Point.ts
@@ -1,6 +1,7 @@
import { Wire } from './Wire';
import { CircuitElement } from './CircuitElement';
import { isNull } from 'util';
import { BoundingBox } from './Geometry';

/**
* Declare window so that custom created function don't throw error
Expand Down Expand Up @@ -221,6 +222,13 @@ export class Point {
return wire;
}

/**
* Returns the bounding box of the point
*/
getBoundingBox(): BoundingBox {
return BoundingBox.loadFromRaphaelBbox(this.body.getBBox());
}

/**
* Set Hover and Hover close Callback
* @param callback Hover Callback
Expand Down
100 changes: 69 additions & 31 deletions ArduinoFrontend/src/app/Libs/Wire.ts
Expand Up @@ -97,7 +97,7 @@ export class Wire {
* @param y y-coordinate of cursor
* @param isPerpendicular is the point to be drawn perpendicular
*/
addPoint(x: number, y: number, isPerpendicular = false) {
addPoint(x: number, y: number, isPerpendicular = false, index?) {
let newX = x;
let newY = y;

Expand All @@ -107,7 +107,7 @@ export class Wire {
[newX, newY] = this.getPerpendicularXY(x, y, previousX, previousY);
}

this.add(newX, newY);
this.add(newX, newY, index);

// draw the line from the previous point to cursor's current position
if (isPerpendicular) {
Expand All @@ -117,6 +117,16 @@ export class Wire {
}
}

/**
* Removes all the intermediate points from the wire path
*/
removeAllMiddlePoints() {
for (let i = this.points.length; i > 0; i--) {
this.removeJoint(i);
}
this.points = [this.points[0], this.points[this.points.length - 1]];
}

/**
* Makes the current temporary line perpendicular depending on current x and y
* @param toggle: true to draw perpendicular line upto current cursor's position
Expand Down Expand Up @@ -217,8 +227,15 @@ export class Wire {
* @param x x position
* @param y y position
*/
private add(x: number, y: number) {
this.points.push([x, y]);
private add(x: number, y: number, index?) {
if (index) {
// insert the point [x, y] at the index and create joint
this.points.splice(index, 0, [x, y]);
this.createJoint(index, true);
} else {
// else, insert at the end
this.points.push([x, y]);
}
}
/**
* Handle click on Wire
Expand Down Expand Up @@ -307,36 +324,59 @@ export class Wire {
// For each point in the wire except first and last
for (let i = 1; i < this.points.length - 1; ++i) {
// Create a Joint
const joint = this.canvas.circle(this.points[i][0], this.points[i][1], 6);
joint.attr({ fill: this.color, stroke: this.color }); // Give the joint a Color
// Variables used while dragging joints
let tmpx;
let tmpy;
// set drag listener
joint.drag((dx, dy) => {
// Update joints position
joint.attr({ cx: tmpx + dx, cy: tmpy + dy });
// Update repective Point
this.points[i] = [tmpx + dx, tmpy + dy];
// Update the wire
this.update();
}, () => {
// Get the Joints center
const xx = joint.attr();
tmpx = xx.cx;
tmpy = xx.cy;
}, () => {
});
this.joints.push(joint);
// Hide joint if required
if (hideJoint) {
joint.hide();
}
this.createJoint(i, hideJoint);
}
}
// Update Wire
this.update();
}

/**
* Removes joint present at the point at index `pointIndex`
* @param pointIndex: index of the point whose joint needs to be removed
*/
removeJoint(pointIndex: number) {
const jointIndex = pointIndex - 1;
const joint = this.joints[jointIndex];
if (joint) {
joint.remove();
this.joints.splice(jointIndex, 1);
}
}

/**
* Creates joint at the index `pointIndex`
* @param pointIndex index of the point
* @param hideJoint hide the joint?
*/
createJoint(pointIndex: number, hideJoint: boolean = false) {
const joint = this.canvas.circle(this.points[pointIndex][0], this.points[pointIndex][1], 6);
joint.attr({ fill: this.color, stroke: this.color }); // Give the joint a Color
// Variables used while dragging joints
let tmpx;
let tmpy;
// set drag listener
joint.drag((dx, dy) => {
// Update joints position
joint.attr({ cx: tmpx + dx, cy: tmpy + dy });
// Update repective Point
this.points[pointIndex] = [tmpx + dx, tmpy + dy];
// Update the wire
this.update();
}, () => {
// Get the Joints center
const jointAttr = joint.attr();
tmpx = jointAttr.cx;
tmpy = jointAttr.cy;
}, () => {
});
this.joints.push(joint);
// Hide joint if required
if (hideJoint) {
joint.hide();
}
}

/**
* Returns true if both end of wire is connected
*/
Expand Down Expand Up @@ -422,10 +462,8 @@ export class Wire {
// Remove Glow
this.removeGlows();
// Clear Joints
this.joints = [];
this.joints = null;
// Clear Points
this.points = [];
this.points = null;
// Remove element from dom
this.element.remove();
Expand Down
12 changes: 12 additions & 0 deletions ArduinoFrontend/src/app/Libs/outputs/Display.ts
Expand Up @@ -11,6 +11,7 @@ import { LCDCharacterPanel } from './LCD/LCDPanel';
import { DDRAM, CGROM, CGRAM, RAM } from './LCD/MemorySchema';
import { MathUtils } from '../MathUtils';
import { ArduinoUno } from './Arduino';
import { BoundingBox } from '../Geometry';
import { Point } from '../Point';
import { BreadBoard } from '../General';

Expand Down Expand Up @@ -191,6 +192,17 @@ export class LCD16X2 extends CircuitElement {
};
}

/**
* Returns the bounding box for the LCD
*/
getBoundingBox(): BoundingBox {
const lcdImageElement = this.elements.items.find(el => el.type === 'image')[0];
const lcdBBox = lcdImageElement.getBBox();
lcdBBox.x += this.tx;
lcdBBox.y += this.ty;
return BoundingBox.loadFromRaphaelBbox(lcdBBox);
}

/**
* Turns on/off the display
* @param isDisplayOn true for switching on, false for off
Expand Down
7 changes: 7 additions & 0 deletions ArduinoFrontend/src/app/Libs/outputs/LCD/LCDPanel.ts
@@ -1,6 +1,7 @@
import { LCDUtils } from './LCDUtils';
import chroma from 'chroma-js';
import LRU from 'lru-cache';
import { BoundingBox } from '../../Geometry';

const COLOR_SCALING_MAP = new LRU({
max: 5000,
Expand Down Expand Up @@ -435,6 +436,12 @@ export class LCDCharacterPanel {
this.shiftPixels(distance);
}

getBoundingBox(): BoundingBox {
const width = (this.pixelWidth + this.intraSpacing) * this.N_ROW - this.intraSpacing;
const height = (this.pixelHeight + this.intraSpacing) * this.N_COLUMN - this.intraSpacing;
return new BoundingBox(this.posX, this.posY, width, height);
}

/**
* Shift the children pixels by distance `distance`
* @param distance distance by which to move the children pixels
Expand Down