Skip to content

Instantly share code, notes, and snippets.

@harunpehlivan
Created May 30, 2021 13:31
Show Gist options
  • Save harunpehlivan/643217ef8b2c8b36b45e10fe796171e4 to your computer and use it in GitHub Desktop.
Save harunpehlivan/643217ef8b2c8b36b45e10fe796171e4 to your computer and use it in GitHub Desktop.
Travelling Salesman Sketches: Radial Search
<div>
<canvas id="cvs1" height="800" width="800"></canvas>
<canvas id="cvs2" height="800" width="800"></canvas>
</div>
console.clear();
const PI = Math.PI;
const PI2 = PI * 2;
class Point {
constructor() {
this.x = Math.random();
this.y = Math.random();
}
}
class Canvas {
constructor() {
this.element1 = document.querySelector("#cvs1");
this.context1 = this.element1.getContext("2d");
this.element2 = document.querySelector("#cvs2");
this.context2 = this.element2.getContext("2d");
this.diameter = this.element1.width;
this.hypot = Math.hypot(-0.5, -0.5);
this.gutter = this.hypot * this.diameter - this.diameter / 2;
this.switchContext(0);
}
clear(which) {
if (which !== undefined) {
[
this.context1,
this.context2
][which].clearRect(0, 0, this.diameter, this.diameter);
} else {
this.context1.clearRect(0, 0, this.diameter, this.diameter);
this.context2.clearRect(0, 0, this.diameter, this.diameter);
}
}
switchContext(idx) {
this.context = [this.context1, this.context2][idx];
}
grid() {
this.switchContext(0);
this.rect(0, 0, 1, 1, "#444");
this.circ(0.5, 0.5, this.hypot, "#444");
}
dToR(deg) {
return deg * PI / 180;
}
text(x, y, text, offset = 1) {
this.context.textAlign = "center";
this.context.textBaseline = "middle";
let fontSize = 14;
let offsetY = y > 0.5
? fontSize * (offset * 1.5)
: fontSize * (offset * -1.5);
this.context.fillStyle = "white";
this.context.font = `${fontSize}px Helvetica`;
this.context.fillText(text, this.rel(x), this.rel(y) + offsetY);
}
point(x, y, fill = "red") {
this.context.fillStyle = fill;
this.context.beginPath();
this.context.arc(this.rel(x), this.rel(y), 2, 0, PI2);
this.context.fill();
}
path(x1, y1, x2, y2, stroke = "red") {
this.context.strokeStyle = stroke;
this.context.lineWidth = 2;
this.context.beginPath();
this.context.moveTo(this.rel(x1), this.rel(y1));
this.context.lineTo(this.rel(x2), this.rel(y2));
this.context.stroke();
}
arc(x, y, rad, sDeg, eDeg, ccwise, stroke, fill) {
x = x === null ? 0.5 : x;
y = y === null ? 0.5 : y;
rad = rad === null ? this.hypot : rad;
this.context.fillStyle = fill;
this.context.strokeStyle = stroke;
this.context.lineWidth = 1;
this.context.beginPath();
this.context.moveTo(this.rel(x), this.rel(y));
this.context.arc(
this.rel(x),
this.rel(y),
this.relS(rad),
this.dToR(sDeg),
this.dToR(eDeg),
ccwise
);
this.context.lineTo(this.rel(x), this.rel(y));
this.context.closePath();
this.context.fill();
this.context.stroke();
}
cone(deg, rad, ratio, stroke, fill) {
let x = this.rel(0.5);
let y = this.rel(0.5);
let off = ratio * 45;
let relrad = this.relS(rad);
this.context.fillStyle = fill;
this.context.lineJoin = "round";
this.context.strokeStyle = stroke;
this.context.lineWidth = 1;
let srad = this.dToR(90 + deg);
let erad = this.dToR(-90 + deg);
let mrad = this.dToR(deg);
let mrad1 = this.dToR(deg - off);
let mrad2 = this.dToR(deg + off);
let mrad3 = this.dToR(90 + deg - off);
let mrad4 = this.dToR(-90 + deg + off);
let ax = rad * Math.cos(erad) + 0.5;
let ay = rad * Math.sin(erad) + 0.5;
let bx = rad * Math.cos(srad) + 0.5;
let by = rad * Math.sin(srad) + 0.5;
let cx = this.hypot * Math.cos(mrad1) + 0.5;
let cy = this.hypot * Math.sin(mrad1) + 0.5;
let dx = this.hypot * Math.cos(mrad2) + 0.5;
let dy = this.hypot * Math.sin(mrad2) + 0.5;
let ex = rad * Math.cos(mrad3) + 0.5;
let ey = rad * Math.sin(mrad3) + 0.5;
let fx = rad * Math.cos(mrad4) + 0.5;
let fy = rad * Math.sin(mrad4) + 0.5;
let mx = this.hypot * Math.cos(mrad) + 0.5;
let my = this.hypot * Math.sin(mrad) + 0.5;
this.context.beginPath();
this.context.arc(x, y, relrad, srad, erad, false);
this.context.lineTo(this.rel(ax), this.rel(ay));
this.context.lineTo(this.rel(cx), this.rel(cy));
this.context.arc(
this.rel(0.5), this.rel(0.5),
this.relS(this.hypot), mrad1, mrad2, false
);
// this.context.lineTo(this.rel(dx), this.rel(dy));
this.context.lineTo(this.rel(bx), this.rel(by));
this.context.closePath();
this.context.fill();
this.context.stroke();
this.context.beginPath();
this.context.moveTo(this.rel(ex), this.rel(ey));
this.context.lineTo(this.rel(mx), this.rel(my));
this.context.lineTo(this.rel(fx), this.rel(fy));
this.context.stroke();
this.context.beginPath();
this.context.arc(x, y, relrad, this.dToR(0), this.dToR(360), false);
this.context.stroke();
}
circ(x, y, rad, stroke = "red") {
this.context.strokeStyle = stroke;
this.context.beginPath();
this.context.arc(this.rel(x), this.rel(y), this.relS(rad), 0, PI2);
this.context.stroke();
}
rect(x, y, w, h, stroke = "red") {
this.context.strokeStyle = stroke;
this.context.lineWidth = 2;
this.context.strokeRect(
this.rel(x),
this.rel(y),
this.relS(w),
this.relS(h)
);
}
get relativeS() {
return this.diameter - this.gutter * 2;
}
relS(size) {
return size * this.relativeS;
}
rel(plot) {
return this.relS(plot) + this.gutter;
}
}
class Radar {
constructor(points) {
this.canvas = new Canvas();
this.canvas.switchContext(0);
this.canvas.grid();
this.draw(points);
this.canvas.switchContext(1);
this.ticker = 0;
this.step = 1;
this.tick()
}
draw(points) {
points.forEach(({ x, y }) => {
this.canvas.point(x, y, 'white');
});
}
tick() {
let offset = 270;
let deg = (this.ticker % 360) + offset;
let rotations = 4;
let outof = rotations * 360;
let rat = Math.pow((this.ticker % outof) / outof, PI);
let rad = rat * 0.5;
// console.log(deg, rad)
this.canvas.clear(1);
let c1 = 'hsla(70,100%,40%,1)';
let c2 = 'hsla(70,100%,60%,0.5)';
this.canvas.cone(deg, rad, rat, c1, c2);
this.ticker += this.step;
window.requestAnimationFrame(() => this.tick());
}
}
let points = [];
for (let i = 0; i < 10; i++) {
points.push(new Point());
}
let radar = new Radar(points);
body {
background: #121212;
}
header {
text-align: center;
margin: 1rem 0;
}
div {
position: relative;
margin: 1rem auto;
width: 95%;
max-width: 600px;
canvas {
&:first-child {
background: black;
}
position: absolute;
top: 0; left: 50%;
transform: translateX(-50%);
width: 100%;
height: auto;
}
}

Travelling Salesman Sketches: Radial Search

A concept for how to connect vectors radially and proximally using vector grouping. These groups would be determined at the vector level by doing calculations on the vector's radial position.

A Pen by HARUN PEHLİVAN on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment