plotboilerplate
Version:
A simple javascript plotting boilerplate for 2d stuff.
257 lines (237 loc) • 10.2 kB
JavaScript
/**
* @date 2018-10-23
* @modified 2021-01-04 Placed into a function.
* @modified 2024-05-19 Adding circle sectors helpers.
*/
/**
* @param {PlotBoilerplate} pb
* @param {string} imagePath
* @param {function} drawCallback
*/
function createDemoDrawables(pb, imagePath, drawCallback) {
// +---------------------------------------------------------------------------------
// | Add some elements to draw (demo).
// +-------------------------------
var diameter = Math.min(pb.canvasSize.width, pb.canvasSize.height) / 4.5;
var radius = diameter * 0.5;
var hypo = Math.sqrt(radius * radius * 2);
var D2R = Math.PI / 180.0;
var drawables = [];
// +---------------------------------------------------------------------------------
// | Add an image.
// +-------------------------------
// var img = new Image(50,50);
var img = new PBImage(new Image(50, 50), new Vertex(-25, -25), new Vertex(25, 25));
drawables.push(img);
// +---------------------------------------------------------------------------------
// | Add some Lines.
// +-------------------------------
drawables.push(new Line(new Vertex(-diameter, -diameter), new Vertex(-hypo, -hypo)));
drawables.push(new Line(new Vertex(-diameter, diameter), new Vertex(-hypo, hypo)));
drawables.push(new Line(new Vertex(diameter, -diameter), new Vertex(hypo, -hypo)));
drawables.push(new Line(new Vertex(diameter, diameter), new Vertex(hypo, hypo)));
// +---------------------------------------------------------------------------------
// | Add some Vectors.
// +-------------------------------
drawables.push(new Vector(new Vertex(-diameter * 1.6, 0), new Vertex(-diameter * 1.2, 0)));
drawables.push(new Vector(new Vertex(diameter * 1.6, 0), new Vertex(diameter * 1.2, 0)));
drawables.push(new Vector(new Vertex(0, -diameter * 1.6), new Vertex(0, -diameter * 1.2)));
drawables.push(new Vector(new Vertex(0, diameter * 1.6), new Vertex(0, diameter * 1.2)));
// +---------------------------------------------------------------------------------
// | Add polygon (here a hexagon).
// +-------------------------------
let n = 6;
var polygonRadius = radius;
var polygonVerts = [];
for (var i = 0; i < n; i++) {
let vert = new Vertex(polygonRadius, 0).rotate(((Math.PI * 2) / n) * i);
vert.attr.draggable = vert.attr.selectable = false;
polygonVerts.push(vert);
}
var polygon = new Polygon(polygonVerts);
drawables.push(polygon);
// +---------------------------------------------------------------------------------
// | Add an ellipse, intitially drawn as circle.
// +-------------------------------
var ellipse = new VEllipse(new Vertex(0, 0), new Vertex(radius, radius));
drawables.push(ellipse);
// +---------------------------------------------------------------------------------
// | Add a circle.
// +-------------------------------
var circle = new Circle(new Vertex(0, 0), diameter);
drawables.push(circle);
// +---------------------------------------------------------------------------------
// | Add four circle sectors.
// +-------------------------------
var csectorA = new CircleSector(new Circle(new Vertex(diameter * 0.8, 0), diameter), -20 * D2R, 20 * D2R);
var csectorB = new CircleSector(new Circle(new Vertex(0, diameter * 0.8), diameter), (90 - 25) * D2R, (90 + 25) * D2R);
var csectorC = new CircleSector(new Circle(new Vertex(-diameter * 0.8, 0), diameter), (180 - 20) * D2R, (180 + 20) * D2R);
var csectorD = new CircleSector(new Circle(new Vertex(0, -diameter * 0.8), diameter), (270 - 25) * D2R, (270 + 25) * D2R);
drawables.push(csectorA);
drawables.push(csectorB);
drawables.push(csectorC);
drawables.push(csectorD);
var installCircleSectorHelper = function (circleSector) {
// Further: add a circle sector helper to edit angles and radius manually (mouse or touch)
var controlPointA = circleSector.circle.vertAt(circleSector.startAngle);
var controlPointB = circleSector.circle.vertAt(circleSector.endAngle);
new CircleSectorHelper(circleSector, controlPointA, controlPointB, pb);
pb.add(controlPointA);
pb.add(controlPointB);
};
installCircleSectorHelper(csectorA);
installCircleSectorHelper(csectorB);
installCircleSectorHelper(csectorC);
installCircleSectorHelper(csectorD);
// +---------------------------------------------------------------------------------
// | Add a circular connected bezier path.
// +-------------------------------
var fract = 0.5;
var bpath = [];
bpath[0] = [
new Vertex(0, -diameter),
new Vertex(diameter, 0),
new Vertex(diameter * fract, -diameter),
new Vertex(diameter * fract, 0)
];
bpath[1] = [
bpath[0][1], // Use same reference
new Vertex(0, diameter),
new Vertex(diameter, diameter * fract),
new Vertex(0, diameter * fract)
];
bpath[2] = [
bpath[1][1], // Use same reference
new Vertex(-diameter, 0),
new Vertex(-diameter * fract, diameter),
new Vertex(-diameter * fract, 0)
];
bpath[3] = [
bpath[2][1], // Use same reference
bpath[0][0], // Use same reference
new Vertex(-diameter, -diameter * fract),
new Vertex(0, -diameter * fract)
];
// Construct
var path = BezierPath.fromArray(bpath);
path.adjustCircular = true;
drawables.push(path);
// +---------------------------------------------------------------------------------
// | Add four equilateral triangles.
// +-------------------------------
let triangles = [
new Triangle(
new Vertex(-hypo * 1.5, -diameter * 1.45),
new Vertex(-diameter * 1.45, -hypo * 1.5),
new Vertex(-diameter * 1.6, -diameter * 1.6)
),
new Triangle(
new Vertex(diameter * 1.45, -hypo * 1.5),
new Vertex(hypo * 1.5, -diameter * 1.45),
new Vertex(diameter * 1.6, -diameter * 1.6)
),
new Triangle(
new Vertex(-diameter * 1.45, hypo * 1.5),
new Vertex(-hypo * 1.5, diameter * 1.45),
new Vertex(-diameter * 1.6, diameter * 1.6)
),
new Triangle(
new Vertex(hypo * 1.5, diameter * 1.45),
new Vertex(diameter * 1.45, hypo * 1.5),
new Vertex(diameter * 1.6, diameter * 1.6)
)
];
var setEquilateral = function (triangle) {
const vec = new Vector(triangle.a, triangle.b);
const mid = vec.vertAt(0.5);
const perp = vec.perp().add(mid).sub(vec.a);
perp.setLength((vec.length() * Math.sqrt(3)) / 2); // The height of a equilateral triangle
triangle.c.set(perp.b);
};
for (var i in triangles) {
let tri = triangles[i];
tri.c.attr.draggable = tri.c.attr.selectable = false;
tri.a.listeners.addDragListener(function (e) {
setEquilateral(tri);
});
tri.b.listeners.addDragListener(function (e) {
setEquilateral(tri);
});
}
// drawables.push( triangles );
for (var i = 0; i < triangles.length; i++) {
drawables.push(triangles[i]);
}
// +---------------------------------------------------------------------------------
// | Add an auto-adjusting bezier path.
// +-------------------------------
var bpath2 = [];
fract *= 0.66;
bpath2[0] = [
new Vertex(0, -diameter),
new Vertex(diameter, 0),
new Vertex(diameter * fract, -diameter),
new Vertex(diameter, -diameter * fract)
];
bpath2[1] = [
bpath2[0][1], // Use same reference
new Vertex(0, diameter),
new Vertex(diameter, diameter * fract),
new Vertex(diameter * fract, diameter)
];
bpath2[2] = [
bpath2[1][1], // Use same reference
new Vertex(-diameter, -0),
new Vertex(-diameter * fract, diameter),
new Vertex(-diameter, diameter * fract)
];
bpath2[3] = [
bpath2[2][1], // Use same reference
bpath2[0][0], // Use same reference
new Vertex(-diameter, -diameter * fract),
new Vertex(-diameter * fract, -diameter)
];
// Construct
var path2 = BezierPath.fromArray(bpath2);
path2.adjustCircular = true;
path2.scale(new Vertex(0, 0), 1.6);
path2.rotate(Math.PI / 4);
for (var i in path2.bezierCurves) {
path2.bezierCurves[i].startPoint.attr.bezierAutoAdjust = true;
path2.bezierCurves[i].endPoint.attr.bezierAutoAdjust = true;
}
// pb.add( path2 );
drawables.push(path2);
// +---------------------------------------------------------------------------------
// | Add elliptic sectors.
// +-------------------------------
var verticalBaseEllipse = new VEllipse(new Vertex(0, 0), new Vertex(radius * 4, radius * 0.8));
var horizontalBaseEllipse = new VEllipse(new Vertex(0, 0), new Vertex(radius * 0.8, radius * 4));
var ellipticSectorA = new VEllipseSector(verticalBaseEllipse, Math.PI - Math.PI / 4, Math.PI + Math.PI / 4);
var ellipticSectorB = new VEllipseSector(verticalBaseEllipse, -Math.PI / 4, Math.PI / 4);
var ellipticSectorC = new VEllipseSector(horizontalBaseEllipse, Math.PI / 4, Math.PI - Math.PI / 4);
var ellipticSectorD = new VEllipseSector(horizontalBaseEllipse, Math.PI + Math.PI / 4, -Math.PI / 4);
drawables.push(ellipticSectorA);
drawables.push(ellipticSectorB);
drawables.push(ellipticSectorC);
drawables.push(ellipticSectorD);
var addEllipticSectorHelper = function (ellipticSector) {
var startControlPoint = ellipticSector.ellipse.vertAt(ellipticSector.startAngle);
var endControlPoint = ellipticSector.ellipse.vertAt(ellipticSector.endAngle);
var rotationControlPoint = ellipticSector.ellipse.vertAt(ellipticSector.rotation).scale(1.2, ellipticSector.ellipse.center);
new VEllipseSectorHelper(ellipticSector, startControlPoint, endControlPoint, rotationControlPoint);
pb.add(startControlPoint);
pb.add(endControlPoint);
pb.add(rotationControlPoint);
};
addEllipticSectorHelper(ellipticSectorA);
addEllipticSectorHelper(ellipticSectorB);
addEllipticSectorHelper(ellipticSectorC);
addEllipticSectorHelper(ellipticSectorD);
// +---------------------------------------------------------------------------------
// | Finally load an image.
// +-------------------------------
img.image.addEventListener("load", drawCallback);
img.image.src = imagePath; // 'example-image.png';
return drawables;
}