xxxxxxxxxx
283
// Gautam Bose
// This sketch generates code that can be used to create animations
// For Adafruits 14-segment alpha-numaric displays.
// The first seven segment positions were taken from Dan Schiffmans Coding Train
// https://thecodingtrain.com/CodingChallenges/117-seven-segment.html
//same as Segment class, can be rotated for italic / diagonal segment
class RotatedSegment {
//takes x, y, w, h, radius, rotation angle,
constructor(x, y, w, h, r1, r2, deg, fb) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.r1 = r1;
this.r2 = r2;
this.deg = deg;
this.isSelected = false;
this.corners = this.getCorners([this.x, this.y], [this.w, this.h], this.deg);
this.rectArea = this.w * this.h;
this.fb = fb;
}
distance(p1, p2) {
return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2));
}
triangleArea(d1, d2, d3) {
// See https://en.wikipedia.org/wiki/Heron's_formula
var s = (d1 + d2 + d3) / 2;
return Math.sqrt(s * (s - d1) * (s - d2) * (s - d3));
}
getCorners(position, size, degrees) {
var left = position[0];
var right = position[0] + size[0];
var top = position[1];
var bottom = position[1] + size[1];
//modified center to reflect p5's rotation function
var center = [0, 0];
var LT = [left, top];
var RT = [right, top];
var RB = [right, bottom];
var LB = [left, bottom];
return {
LT: this.rotatePoint(LT, center, degrees),
RT: this.rotatePoint(RT, center, degrees),
RB: this.rotatePoint(RB, center, degrees),
LB: this.rotatePoint(LB, center, degrees)
};
}
rotatePoint(point, rotationCenterPoint, degrees) {
// Using radians for this formula
var radians = degrees * Math.PI / 180;
// Translate the plane on which rotation is occurring.
// We want to rotate around 0,0. We'll add these back later.
point[0] -= rotationCenterPoint[0];
point[1] -= rotationCenterPoint[1];
// Perform the rotation
var newPoint = [];
newPoint[0] = point[0] * Math.cos(radians) - point[1] * Math.sin(radians);
newPoint[1] = point[0] * Math.sin(radians) + point[1] * Math.cos(radians);
// Translate the plane back to where it was.
newPoint[0] += rotationCenterPoint[0];
newPoint[1] += rotationCenterPoint[1];
return newPoint;
}
checkClick(mX, mY) {
//no need to perform complicated calculations if its not rotated.
if (this.deg === 0) {
if ((mX >= this.x && mX <= this.x + this.w) &&
(mY >= this.y && mY <= this.y + this.h)) {
this.isSelected = !this.isSelected;
}
} else {
//Original reference for this function and all helper functions:
//https://joshuawoehlke.com/detecting-clicks-rotated-rectangles/
const click = [mX, mY];
//create an array of floats that are the areas of the triangles
let triAreas = [
//each float is calculated by finding the tirangle and feeding into
//Herron's forrmula.
this.triangleArea(
this.distance(click, this.corners.LT),
this.distance(this.corners.LT, this.corners.RT),
this.distance(this.corners.RT, click)
),
this.triangleArea(
this.distance(click, this.corners.RT),
this.distance(this.corners.RT, this.corners.RB),
this.distance(this.corners.RB, click)
),
this.triangleArea(
this.distance(click, this.corners.RB),
this.distance(this.corners.RB, this.corners.LB),
this.distance(this.corners.LB, click)
),
this.triangleArea(
this.distance(click, this.corners.LB),
this.distance(this.corners.LB, this.corners.LT),
this.distance(this.corners.LT, click)
),
];
let triArea = Math.round(triAreas.reduce((a, b) => a + b), 0);
if (triArea <= this.rectArea) {
this.isSelected = !this.isSelected;
}
}
}
display() {
if (!this.isSelected) {
this.fb.fill(120);
} else {
this.fb.fill(255, 0, 0);
}
this.fb.push();
this.fb.rotate(this.deg);
this.fb.translate(this.x, this.y);
// image(this.fb, this.x, this.y);
this.fb.rect(0, 0, this.w, this.h, this.r1, this.r2);
this.fb.pop();
//could be a cool visualziation of Josua's algo
// fill(0, 244, 0);
// stroke(255);
// strokeWeight(2);
// line(this.corners.LT[0], this.corners.LT[1], mouseX, mouseY);
// ellipse(this.corners.LT[0], this.corners.LT[1], 10, 10);
// ellipse(this.corners.LB[0], this.corners.LB[1], 10, 10);
// ellipse(this.corners.RT[0], this.corners.RT[1], 10, 10);
// ellipse(this.corners.RB[0], this.corners.RB[1], 10, 10);
}
}
//class for a single alphanumeric display (1 set of 14-segments);
class AlphaNumeric {
constructor(x, y) {
this.x = x;
this.y = y;
this.fb = createGraphics(180, 255); //create the buffer segments will draw to
this.fb.angleMode(DEGREES);
this.fb.noStroke();
//top segment
this.a = new RotatedSegment(51, 20, 78, 18, 10, 10, 0, this.fb);
//right legs
this.b = new RotatedSegment(130, 25, 18, 84, 10, 10, 5, this.fb);
this.c = new RotatedSegment(130, 121, 18, 84, 10, 10, 5, this.fb);
//bottom segment
this.d = new RotatedSegment(40, 217, 78, 18, 10, 10, 0, this.fb);
//left legs
this.e = new RotatedSegment(43, 130, 18, 84, 10, 10, 5, this.fb);
this.f = new RotatedSegment(43, 35, 18, 84, 10, 10, 5, this.fb);
//horizontal dashes
this.g1 = new RotatedSegment(45, 120, 39, 16, 10, 10, 0, this.fb);
this.g2 = new RotatedSegment(85, 120, 39, 16, 10, 10, 0, this.fb);
//top internal segments from left to right
this.h = new RotatedSegment(57, -57, 85, 14, 10, 10, 75, this.fb);
this.j = new RotatedSegment(87, 32, 18, 80, 10, 10, 5, this.fb);
this.k = new RotatedSegment(-82, 122, 85, 14, 10, 10, -68, this.fb);
//bottom internal segments from left to right
this.l = new RotatedSegment(-177, 120, 85, 14, 10, 10, -68, this.fb);
this.m = new RotatedSegment(87, 128, 18, 80, 10, 10, 5, this.fb);
this.n = new RotatedSegment(150, -57, 85, 14, 10, 10, 75, this.fb);
//decimal point
this.dp = new RotatedSegment(130, 217, 15, 15, 10, 10, 0, this.fb);
this.segments = [];
this.segments.push(this.a, this.b, this.c, this.d, this.e, this.f,
this.g1, this.g2, this.h, this.j, this.k, this.l, this.m, this.n, this.dp);
}
getBits() {
let retVal = 1 << 15; //sets MSB to 1 (null bit in display)
for (let i = 0; i < this.segments.length; i++) {
let currSegment = this.segments[i];
if (currSegment.isSelected) {
retVal = retVal | (0x1 << i);
}
}
console.log(retVal.toString(16));
return retVal.toString(16);
}
setBits(hexString) {
}
checkClick(mX, mY) {
this.segments.forEach(segment => segment.checkClick(mX, mY));
this.getBits();
}
display() {
this.fb.background(0);
// console.log(this.segments);
this.segments.forEach(segment => segment.display());
//display g1 and g2 last again so they go on top of everything else
this.segments[7].display();
this.segments[6].display();
return(this.fb);
}
}
// class for a set of 4 alphanumeric displays (as in adafruits 14-segment display backpack)
class AlphaNumericBackPack {
constructor() {
this.displays = [
new AlphaNumeric(),
new AlphaNumeric(),
new AlphaNumeric(),
new AlphaNumeric()
];
}
checkClick(mX, mY) {
this.displays.forEach((disp, i) => disp.checkClick(mX, mY));
}
display() {
for (let i = 0; i < this.displays.length; i++) {
image(this.displays[i].display(), 180 * i, 0);
}
}
}
let seg_display;
function setup() {
createCanvas(720, 255);
frameRate(60);
seg_display = new AlphaNumericBackPack();
angleMode(DEGREES);
}
function draw() {
background(255);
seg_display.display();
// testSegmentA.render();
}
function mousePressed() {
seg_display.checkClick(mouseX, mouseY);
}
// function mouseDragged() {
// seg_display.checkClick(mouseX, mouseY);
// }