lot

File*
Docs
Download
What do I make?
log in to save
Machine control
/*
@title: Outer Space
@author: Loewe111
@snapshot: snapshot0.png
*/

bt.setRandSeed(1461);
const width = 200;
const height = 200;
const roughness = 5;
const detail = 3;
const size = 75;
const stars = 500;

setDocDimensions(width, height);

function drawPlanet(x, y, radius) {
let points = [];
let lines = [points];
for (let i=0; i<360; i+=Math.max(detail, 1)) {
let a = i * Math.PI / 180;
let r = radius + bt.randInRange(-0.1 * roughness, 0.1 * roughness);
let px = r * Math.sin(a);
let py = r * Math.cos(a);
points.push([px, py]);
}
points.push([points[0][0], points[0][1]]);
points = bt.catmullRom(points);
let islands = []
let num_islands = bt.randIntInRange(3 , 5);
for (let i=0; i<num_islands; i++) {
let px = bt.randInRange(-radius, radius);
let py = bt.randInRange(-radius, radius);
islands.push(bt.catmullRom(drawIsland(px, py, radius / 3, 0)))
}
islands = bt.cut(islands, [points]);

lines = lines.concat(islands)
bt.translate(lines, [x, y])
return lines
}

function drawIsland(x, y, size, angle) {
let points = [];
let radius = size;
while (angle < 360) {
angle += bt.randIntInRange(5, 20);
radius = bt.randInRange(radius - 2, radius + 2);
let px = radius * Math.sin(angle * Math.PI / 180);
let py = radius * Math.cos(angle * Math.PI / 180);
points.push([px, py]);
}
points.push([points[0][0], points[0][1]]);
bt.translate([points], [x, y])
return points
}

function star(x, y) {
const a = 0.5;
const b = 2;
const deltas = [
[-a, a], [0, b], [a, a], [b, 0], [a, -a], [0, -b], [-a, -a], [-b, 0], [-a, a]
];
var lines = deltas.map(([dx, dy]) => [x + dx, y + dy]);
lines = bt.rotate([lines], bt.randIntInRange(0, 90), [x, y])[0];

return bt.catmullRom(lines);
}

function getDistance(x1, y1, x2, y2) {
var a = x1 - x2;
var b = y1 - y2;
return Math.sqrt(a*a + b*b);
}

function drawStars() {
let points = [];
let lines = [];
for (let i=0; i<stars; i++) {
let px = bt.randIntInRange(0, width);
let py = bt.randIntInRange(0, height);
let c = false;
for (let j=0; j<points.length; j++) {
if (getDistance(px, py, points[j][0], points[j][1]) < 10) {
c = true
}
}
if (c) continue;
let s = star(px, py);
lines.push(s);
points.push([px, py]);
}
return lines
}

var planet = drawPlanet(width / 2, height / 2, size);
var stars_lines = drawStars();
stars_lines = bt.cover(stars_lines, planet);

drawLines(planet);
drawLines(stars_lines);

The Toolkit

This is a quick reference sheet. For full documentation refer to this.

For an introduction to Blot check out this guide.

Check out our 38 second trailer for a brief overview of the whole Blot project.

There are three names that provide functionality available in the Blot editor: setDocDimensions, drawLines, and blotToolkit (which can also be referenced as bt).

The first two affect the drawing environment itself, and the blotToolkit is used for creating line drawings.

Environment Affecting

setDocDimensions(width: number, height: number)
drawLines(polylines: [number, number][][])

Modify Polylines

Take and modify polylines in place returns first passed polylines.

These functions are available in the blotToolkit or bt object.

bt.iteratePoints(polylines, (pt, t) => { ... }) // return pt to modify, "BREAK" to split, "REMOVE" to filter out point
bt.scale(polylines, scale : scaleXY | [scaleX, scaleY], ?origin: [ x, y ]) 
bt.rotate(polylines, degrees, ?origin: [ x, y ]) 
bt.translate(polylines, [dx, dy], ?origin: [ x, y ]) 
bt.originate(polylines) // moves center to [0, 0] 
bt.resample(polylines, sampleRate) 
bt.simplify(polylines, tolerance) 
bt.trim(polylines, tStart, tEnd)
bt.merge(polylines)  
bt.join(polylines0, ...morePolylines) 
bt.copy(polylines)
bt.cut(polylines0, polylines1) 
bt.cover(polylines0, polylines1) 
bt.union(polylines0, polylines1)
bt.difference(polylines0, polylines1)
bt.intersection(polylines0, polylines1)
bt.xor(polylines0, polylines1)
bt.offset(polylines, delta, ?ops = { endType, joinType, miterLimit, arcTolerance })

Get Data From Polylines

These functions are available in the blotToolkit or bt object.

// take polylines return other
bt.getAngle(polylines, t: [0 to 1]) // returns angle in degrees
bt.getPoint(polylines, t: [0 to 1]) // returns point as [x, y]
bt.getNormal(polylines, t: [0 to 1]) // returns normal vector as [x, y]

bt.pointInside(polylines, pt)

bt.bounds(polylines) 
/*
returns { 
  xMin, xMax, 
  yMin, yMax, 
  lt, ct, rt, 
  lc, cc, rc,
  lb, cb, rb,
  width, height
}

l is left
c is center
r is right
t is top
b is bottom

they are arranged in this configuration around the bounding box of the polylines

lt--ct--rt
 |   |   |
lc--cc--rc
 |   |   | 
lb--cb--rb
*/

Generate Polylines

These functions are available in the blotToolkit or bt object.

const myTurtle = new bt.Turtle()
  .forward(distance: number)
  .arc(angle: number, radius: number)
  .goTo( [ x: number, y: number ] ) // move with up/down state
  .jump( [ x: number, y: number ] ) // move but don't draw
  .step( [ dx: number, dy: number ] ) // add delta to turtles current position
  .right(angle: number)
  .left(angle: number)
  .setAngle(angle: number)
  .up() // sets drawing to false
  .down() // sets drawing to true
  .copy()
  .applyToPath(fn) // takes (turtlePath) => { }
  .lines() // get copy of the Turtle's path

// data
const position = myTurtle.pos // [x: number, y: number]
const angle = myTurtle.angle // number
const path = myTurtle.path // is array of polylines [number, number][][]
const drawing = myTurtle.drawing // boolean
bt.catmullRom(points, ?steps = 1000) // returns polyline [number, number][]
bt.nurbs(points, ?ops = { steps: 100, degree: 2}) // returns polyline [number, number][]

Randomness

These functions are available in the blotToolkit or bt object.

bt.rand();

bt.randInRange(min: number, max: number);

bt.randIntInRange(min: number, max: number); 

bt.setRandSeed(seed: number);

bt.noise(
  number | [ x:number , ?y: number , ?z: number ], 
  { 
    octaves: number [0 to 8], 
    falloff: number [0 to 100] 
  }
);

Idioms

These are small useful code snippets.

function centerPolylines(polylines, documentWidth, documentHeight) {
  const cc = bt.bounds(polylines).cc;
  bt.translate(polylines, [documentWidth / 2, documentHeight / 2], cc);
}