Published
Edited
Sep 16, 2019
Importers
1 star
Insert cell
Insert cell
{
const width = 300, height = 300
let ctx = DOM.context2d(width, width);
s.setStroke("red")
s.setStrokeWeight(3)
console.log("S", s)
s.draw(ctx)
return ctx.canvas;
}
Insert cell
s = new Shape([[0, 0], [100, 50], [90, 280], [70, 280]])
Insert cell
{
const width = 300, height = 300
let ctx = DOM.context2d(width, width);
s.setStroke("black")
s.setStrokeWeight(1)
s.draw(ctx)
const s2 = s.offset(-8)
s2.setStroke("red")
s2.setStrokeDash([5, 5])
s2.draw(ctx)
return ctx.canvas;
}


Insert cell
getOffset = function(line, offset = 10) {
const alpha = Math.atan2(-(line[0][0] - line[1][0]), - (line[1][1] - line[0][1]))
const line2 = [[
line[0][0] + offset*Math.cos(alpha),
line[0][1] + offset*Math.sin(alpha)
], [
line[1][0] + offset*Math.cos(alpha),
line[1][1] + offset*Math.sin(alpha)
]]
return line2
}
Insert cell
class Shape {
constructor(pts) {
this.pts = pts;
this.stroke = () => "black"
this.strokeWeight = () => 1
this.fill = () => null
this.lineDash = () => []
this.x = p => p[0]
this.y = p => p[1]
}
setStrokeWeight(_) {
return arguments.length ? (this.strokeWeight = typeof _ === "function" ? _ : () => _) : this.strokeWeight
}
setStrokeDash(_) {
return arguments.length ? (this.lineDash = typeof _ === "function" ? _ : () => _) : this.lineDash
}
getCenter() {
const mx = d3.mean(this.pts.map(d => this.x(d)))
const my = d3.mean(this.pts.map(d => this.y(d)))
return [mx, my]
}
offset(p) {
return new Shape(inflatePolygon(this.pts, p))
}
scale(s) {
const center = this.getCenter()
const newPts = this.pts.map(pt => {
return d3.interpolate(center, pt)(s)
})
return new Shape(newPts)
}
setFill(_) {
return arguments.length ? (this.fill = typeof _ === "function" ? _ : () => _) : this.fill
}
setStroke(_) {
return arguments.length ? (this.stroke = typeof _ === "function" ? _ : () => _) : this.stroke
}
x(_) {
return arguments.length ? (this.x = typeof _ === "function" ? _ : () => _) : this.x
};

y(_) {
return arguments.length ? (this.y = typeof _ === "function" ? _ : () => _) : this.y
};

getBoundingRect() {
const minX = d3.min(this.pts.map(d => this.x(d)))
const maxX = d3.max(this.pts.map(d => this.x(d)))
const minY = d3.min(this.pts.map(d => this.y(d)))
const maxY = d3.max(this.pts.map(d => this.y(d)))
return [minX, maxX, minY, maxY]
}
draw(ctx, offsetX=0, offsetY=0) {
ctx.save()
ctx.beginPath()
ctx.setLineDash(this.lineDash());
ctx.fillStyle = this.fill();
ctx.strokeStyle = this.stroke();
ctx.lineWidth = this.strokeWeight();
ctx.moveTo(this.x(this.pts[0]) + offsetX, this.y(this.pts[0]) + offsetY)
this.pts.slice(1).forEach(pt => ctx.lineTo(this.x(pt) + offsetX, this.y(pt) + offsetY))
ctx.closePath()
if (this.stroke()) ctx.stroke()
if (this.fill()) ctx.fill();
ctx.restore()
}
}
Insert cell
function inflatePolygon(poly, spacing)
{
var geoInput = vectorCoordinates2JTS(poly);
geoInput.push(geoInput[0]);

var geometryFactory = new jsts.geom.GeometryFactory();

var shell = geometryFactory.createPolygon(geoInput);
var polygon = shell.buffer(spacing, jsts.operation.buffer.BufferParameters.CAP_FLAT);

var inflatedCoordinates = [];
var oCoordinates;
oCoordinates = polygon.shell.points.coordinates;
for (let i = 0; i < oCoordinates.length; i++) {
var oItem;
oItem = oCoordinates[i];
inflatedCoordinates.push([Math.ceil(oItem.x), Math.ceil(oItem.y)]);
}
return inflatedCoordinates;
}
Insert cell
function vectorCoordinates2JTS (polygon) {
var coordinates = [];

for (var i = 0; i < polygon.length; i++) {
coordinates.push(new jsts.geom.Coordinate(polygon[i][0], polygon[i][1]));
}
return coordinates;
}
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more