plotboilerplate
Version:
A simple javascript plotting boilerplate for 2d stuff.
1,035 lines (1,022 loc) • 666 kB
JavaScript
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 30:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
/**
* @author Ikaros Kappler
* @date 2019-01-30
* @modified 2019-02-23 Added the toSVGString function, overriding Line.toSVGString.
* @modified 2019-03-20 Added JSDoc tags.
* @modified 2019-04-19 Added the clone function (overriding Line.clone()).
* @modified 2019-09-02 Added the Vector.perp() function.
* @modified 2019-09-02 Added the Vector.inverse() function.
* @modified 2019-12-04 Added the Vector.inv() function.
* @modified 2020-03-23 Ported to Typescript from JS.
* @modified 2021-01-20 Added UID.
* @modified 2022-02-02 Added the `destroy` method.
* @modified 2022-02-02 Cleared the `Vector.toSVGString` function (deprecated). Use `drawutilssvg` instead.
* @modified 2022-10-25 Added the `getOrthogonal` method.
* @modified 2025-04-14 Added the `Vector.rotate(number)` method.
* @version 1.6.0
*
* @file Vector
* @public
**/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Vector = void 0;
var VertTuple_1 = __webpack_require__(590);
var Vertex_1 = __webpack_require__(787);
/**
* @classdesc A vector (Vertex,Vertex) is a line with a visible direction.<br>
* <br>
* Vectors are drawn with an arrow at their end point.<br>
* <b>The Vector class extends the Line class.</b>
*
* @requires VertTuple
* @requires Vertex
**/
var Vector = /** @class */ (function (_super) {
__extends(Vector, _super);
/**
* The constructor.
*
* @constructor
* @name Vector
* @extends Line
* @param {Vertex} vertA - The start vertex of the vector.
* @param {Vertex} vertB - The end vertex of the vector.
**/
function Vector(vertA, vertB) {
var _this = _super.call(this, vertA, vertB, function (a, b) { return new Vector(a, b); }) || this;
/**
* Required to generate proper CSS classes and other class related IDs.
**/
_this.className = "Vector";
return _this;
}
/**
* Get the perpendicular of this vector which is located at a.
*
* @return {Vector} A new vector being the perpendicular of this vector sitting on a.
**/
Vector.prototype.perp = function () {
var v = this.clone();
v.sub(this.a);
v = new Vector(new Vertex_1.Vertex(), new Vertex_1.Vertex(-v.b.y, v.b.x));
v.a.add(this.a);
v.b.add(this.a);
return v;
};
/**
* The inverse of a vector is a vector with the same magnitude but oppose direction.
*
* Please not that the origin of this vector changes here: a->b becomes b->a.
*
* @return {Vector}
**/
Vector.prototype.inverse = function () {
var tmp = this.a;
this.a = this.b;
this.b = tmp;
return this;
};
/**
* This function computes the inverse of the vector, which means 'a' stays untouched.
*
* @return {Vector} this for chaining.
**/
Vector.prototype.inv = function () {
this.b.x = this.a.x - (this.b.x - this.a.x);
this.b.y = this.a.y - (this.b.y - this.a.y);
return this;
};
/**
* Get the intersection if this vector and the specified vector.
*
* @method intersection
* @param {Vector} line The second vector.
* @return {Vertex} The intersection (may lie outside the end-points).
* @instance
* @memberof Line
**/
Vector.prototype.intersection = function (line) {
var denominator = this.denominator(line);
if (denominator == 0)
return null;
var a = this.a.y - line.a.y;
var b = this.a.x - line.a.x;
var numerator1 = (line.b.x - line.a.x) * a - (line.b.y - line.a.y) * b;
var numerator2 = (this.b.x - this.a.x) * a - (this.b.y - this.a.y) * b;
a = numerator1 / denominator; // NaN if parallel lines
b = numerator2 / denominator;
// TODO:
// FOR A VECTOR THE LINE-INTERSECTION MUST BE ON BOTH VECTORS
// if we cast these lines infinitely in both directions, they intersect here:
return new Vertex_1.Vertex(this.a.x + a * (this.b.x - this.a.x), this.a.y + a * (this.b.y - this.a.y));
};
/**
* Get the orthogonal "vector" of this vector (rotated by 90° clockwise).
*
* @name getOrthogonal
* @method getOrthogonal
* @return {Vector} A new vector with the same length that stands on this vector's point a.
* @instance
* @memberof Vector
**/
Vector.prototype.getOrthogonal = function () {
// Orthogonal of vector (0,0)->(x,y) is (0,0)->(-y,x)
var linePoint = this.a.clone();
var startPoint = this.b.clone().sub(this.a);
var tmp = startPoint.x;
startPoint.x = -startPoint.y;
startPoint.y = tmp;
return new Vector(linePoint, startPoint.add(this.a));
};
/**
* Rotate this vector by the given angle around the first point `a`.
*
* @name rotate
* @method rotate
* @return {Vector} this - for chaining.
* @instance
* @memberof Vector
*/
Vector.prototype.rotate = function (angle) {
this.b.rotate(angle, this.a);
return this;
};
Vector.utils = {
/**
* Generate a four-point arrow head, starting at the vector end minus the
* arrow head length.
*
* The first vertex in the returned array is guaranteed to be the located
* at the vector line end minus the arrow head length.
*
*
* Due to performance all params are required.
*
* The params scaleX and scaleY are required for the case that the scaling is not uniform (x and y
* scaling different). Arrow heads should not look distored on non-uniform scaling.
*
* If unsure use 1.0 for scaleX and scaleY (=no distortion).
* For headlen use 8, it's a good arrow head size.
*
* Example:
* buildArrowHead( new Vertex(0,0), new Vertex(50,100), 8, 1.0, 1.0 )
*
* @param {XYCoords} zA - The start vertex of the vector to calculate the arrow head for.
* @param {XYCoords} zB - The end vertex of the vector.
* @param {number} headlen - The length of the arrow head (along the vector direction. A good value is 12).
* @param {number} scaleX - The horizontal scaling during draw.
* @param {number} scaleY - the vertical scaling during draw.
**/
buildArrowHead: function (zA, zB, headlen, scaleX, scaleY) {
var angle = Math.atan2((zB.y - zA.y) * scaleY, (zB.x - zA.x) * scaleX);
var vertices = [];
vertices.push(new Vertex_1.Vertex(zB.x * scaleX - headlen * Math.cos(angle), zB.y * scaleY - headlen * Math.sin(angle)));
vertices.push(new Vertex_1.Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle - Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle - Math.PI / 8)));
vertices.push(new Vertex_1.Vertex(zB.x * scaleX, zB.y * scaleY));
vertices.push(new Vertex_1.Vertex(zB.x * scaleX - headlen * 1.35 * Math.cos(angle + Math.PI / 8), zB.y * scaleY - headlen * 1.35 * Math.sin(angle + Math.PI / 8)));
return vertices;
}
};
return Vector;
}(VertTuple_1.VertTuple));
exports.Vector = Vector;
//# sourceMappingURL=Vector.js.map
/***/ }),
/***/ 39:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/**
* @author Ikaros Kappler
* @date 2018-04-22
* @modified 2018-08-16 Added the curve() function to draw cubic bézier curves.
* @modified 2018-10-23 Recognizing the offset param in the circle() function.
* @modified 2018-11-27 Added the diamondHandle() function.
* @modified 2018-11-28 Added the grid() function and the ellipse() function.
* @modified 2018-11-30 Renamed the text() function to label() as it is not scaling.
* @modified 2018-12-06 Added a test function for drawing arc in SVG style.
* @modified 2018-12-09 Added the dot(Vertex,color) function (copied from Feigenbaum-plot-script).
* @modified 2019-01-30 Added the arrow(Vertex,Vertex,color) function for drawing arrow heads.
* @modified 2019-01-30 Added the image(Image,Vertex,Vertex) function for drawing images.
* @modified 2019-04-27 Fixed a severe drawing bug in the arrow(...) function. Scaling arrows did not work properly.
* @modified 2019-04-28 Added Math.round to the dot() drawing parameters to really draw a singlt dot.
* @modified 2019-06-07 Fixed an issue in the cubicBezier() function. Paths were always closed.
* @modified 2019-10-03 Added the beginDrawCycle hook.
* @modified 2019-10-25 Polygons are no longer drawn with dashed lines (solid lines instead).
* @modified 2019-11-18 Added the polyline function.
* @modified 2019-11-22 Added a second workaround for th drawImage bug in Safari.
* @modified 2019-12-07 Added the 'lineWidth' param to the line(...) function.
* @modified 2019-12-07 Added the 'lineWidth' param to the cubicBezier(...) function.
* @modified 2019-12-11 Added the 'color' param to the label(...) function.
* @modified 2019-12-18 Added the quadraticBezier(...) function (for the sake of approximating Lissajous curves).
* @modified 2019-12-20 Added the 'lineWidth' param to the polyline(...) function.
* @modified 2020-01-09 Added the 'lineWidth' param to the ellipse(...) function.
* @modified 2020-03-25 Ported this class from vanilla-JS to Typescript.
* @modified 2020-05-05 Added the 'lineWidth' param to the circle(...) function.
* @modified 2020-05-12 Drawing any handles (square, circle, diamond) with lineWidth 1 now; this was not reset before.
* @modified 2020-06-22 Added a context.clearRect() call to the clear() function; clearing with alpha channel did not work as expected.
* @modified 2020-09-07 Added the circleArc(...) function to draw sections of circles.
* @modified 2020-10-06 Removed the .closePath() instruction from the circleArc function.
* @modified 2020-10-15 Re-added the text() function.
* @modified 2020-10-28 Added the path(Path2D) function.
* @modified 2020-12-28 Added the `singleSegment` mode (test).
* @modified 2021-01-05 Added the image-loaded/broken check.
* @modified 2021-01-24 Added the `setCurrentId` function from the `DrawLib` interface.
* @modified 2021-02-22 Added the `path` drawing function to draw SVG path data.
* @modified 2021-03-31 Added the `endDrawCycle` function from `DrawLib`.
* @modified 2021-05-31 Added the `setConfiguration` function from `DrawLib`.
* @modified 2021-11-12 Adding more parameters tot the `text()` function: fontSize, textAlign, fontFamily, lineHeight.
* @modified 2021-11-19 Added the `color` param to the `label(...)` function.
* @modified 2022-02-03 Added the `lineWidth` param to the `crosshair` function.
* @modified 2022-02-03 Added the `cross(...)` function.
* @modified 2022-03-27 Added the `texturedPoly` function.
* @modified 2022-06-01 Tweaked the `polyline` function; lineWidth now scales with scale.x.
* @modified 2022-07-26 Adding `alpha` to the `image(...)` function.
* @modified 2022-08-23 Fixed a type issue in the `polyline` function.
* @modified 2022-08-23 Fixed a type issue in the `setConfiguration` function.
* @modified 2022-08-23 Fixed a type issue in the `path` function.
* @modified 2023-02-10 The methods `setCurrentClassName` and `setCurrentId` also accept `null` now.
* @modified 2023-09-29 Removed unused method stub for texturedPoly helper function (cleanup).
* @modified 2023-09-29 Downgrading all `Vertex` param type to the more generic `XYCoords` type in these render functions: line, arrow, texturedPoly, cubicBezier, cubicBezierPath, handle, handleLine, dot, point, circle, circleArc, ellipse, grid, raster.
* @modified 2023-09-29 Added the `headLength` parameter to the 'DrawLib.arrow()` function.
* @modified 2023-09-29 Added the `arrowHead(...)` function to the 'DrawLib.arrow()` interface.
* @modified 2023-09-29 Added the `cubicBezierArrow(...)` function to the 'DrawLib.arrow()` interface.
* @modified 2023-09-29 Added the `lineDashes` attribute.
* @modified 2023-09-30 Adding `strokeOptions` param to these draw function: line, arrow, cubicBezierArrow, cubicBezier, cubicBezierPath, circle, circleArc, ellipse, square, rect, polygon, polyline.
* @modified 2023-10-07 Adding the optional `arrowHeadBasePositionBuffer` param to the arrowHead(...) method.
* @modified 2024-09-13 Remoed the scaling of `lineWidth` in the `polygon` and `polyline` methods. This makes no sense here and doesn't match up with the behavior of other line functions.
* @modified 2026-01-04 Adding `lineJoin` attribute to the `StrokeOptions`.
* @modified 2026-03-18 Adding `isOpen` parameter to `cubicBezierPath` draw method.
* @modified 2026-04-04 Added the method `bounds`.
* @modified 2026-04-04 Handling the `lineCap` attribute in the `StrokeOptions`.
* @version 1.15.0
**/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.drawutils = void 0;
var CubicBezierCurve_1 = __webpack_require__(973);
var Vertex_1 = __webpack_require__(787);
var drawutilssvg_1 = __webpack_require__(378);
var Vector_1 = __webpack_require__(30);
// Todo: rename this class to Drawutils?
/**
* @classdesc A wrapper class for basic drawing operations.
*
* @requires CubicBzierCurvce
* @requires Polygon
* @requires Vertex
* @requires XYCoords
*/
var drawutils = /** @class */ (function () {
/**
* The constructor.
*
* @constructor
* @name drawutils
* @param {anvasRenderingContext2D} context - The drawing context.
* @param {boolean} fillShaped - Indicates if the constructed drawutils should fill all drawn shapes (if possible).
**/
function drawutils(context, fillShapes) {
this.ctx = context;
// this.lineDash = [];
this.offset = new Vertex_1.Vertex(0, 0);
this.scale = new Vertex_1.Vertex(1, 1);
this.fillShapes = fillShapes;
}
/**
* A private helper method to apply stroke options to the current
* context.
* @param {StrokeOptions=} strokeOptions -
*/
drawutils.prototype.applyStrokeOpts = function (strokeOptions) {
var _this = this;
var _a, _b, _c, _d;
this.ctx.setLineDash(((_a = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.dashArray) !== null && _a !== void 0 ? _a : []).map(function (dashArrayElem) {
// Note assume scale.x === scale.y
// Invariant scale makes funny stuff anyway.
return dashArrayElem * _this.scale.x;
}));
this.ctx.lineDashOffset = ((_b = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.dashOffset) !== null && _b !== void 0 ? _b : 0) * this.scale.x;
this.ctx.lineJoin = (_c = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.lineJoin) !== null && _c !== void 0 ? _c : null;
this.ctx.lineCap = (_d = strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.lineCap) !== null && _d !== void 0 ? _d : null;
};
// +---------------------------------------------------------------------------------
// | This is the final helper function for drawing and filling stuff. It is not
// | intended to be used from the outside.
// |
// | When in draw mode it draws the current shape.
// | When in fill mode it fills the current shape.
// |
// | This function is usually only called internally.
// |
// | @param color A stroke/fill color to use.
// +-------------------------------
// TODO: convert this to a STATIC function.
drawutils.prototype._fillOrDraw = function (color) {
if (this.fillShapes) {
this.ctx.fillStyle = color;
this.ctx.fill();
}
else {
this.ctx.strokeStyle = color;
this.ctx.stroke();
}
};
/**
* Called before each draw cycle.
* @param {UID=} uid - (optional) A UID identifying the currently drawn element(s).
**/
drawutils.prototype.beginDrawCycle = function (renderTime) {
// NOOP
};
/**
* Called after each draw cycle.
*
* This is required for compatibility with other draw classes in the library (like drawgl).
*
* @name endDrawCycle
* @method
* @param {number} renderTime
* @instance
**/
drawutils.prototype.endDrawCycle = function (renderTime) {
// NOOP
};
/**
* Set the current drawlib configuration.
*
* @name setConfiguration
* @method
* @param {DrawLibConfiguration} configuration - The new configuration settings to use for the next render methods.
*/
drawutils.prototype.setConfiguration = function (configuration) {
this.ctx.globalCompositeOperation = configuration.blendMode || "source-over";
};
// /**
// * Set or clear the line-dash configuration. Pass `null` for un-dashed lines.
// *
// * See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
// * and https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
// * for how line dashes work.
// *
// * @method
// * @param {Array<number> lineDashes - The line-dash array configuration.
// * @returns {void}
// */
// setLineDash(lineDash: Array<number>) {
// this.lineDash = lineDash;
// }
/**
* This method shouled be called each time the currently drawn `Drawable` changes.
* It is used by some libraries for identifying elemente on re-renders.
*
* @name setCurrentId
* @method
* @param {UID|null} uid - A UID identifying the currently drawn element(s).
**/
drawutils.prototype.setCurrentId = function (uid) {
// NOOP
};
/**
* This method shouled be called each time the currently drawn `Drawable` changes.
* Determine the class name for further usage here.
*
* @name setCurrentClassName
* @method
* @param {string|null} className - A class name for further custom use cases.
**/
drawutils.prototype.setCurrentClassName = function (className) {
// NOOP
};
/**
* Draw the line between the given two points with the specified (CSS-) color.
*
* @method line
* @param {XYCoords} zA - The start point of the line.
* @param {XYCoords} zB - The end point of the line.
* @param {string} color - Any valid CSS color string.
* @param {number} lineWidth? - [optional] The line's width.
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
**/
drawutils.prototype.line = function (zA, zB, color, lineWidth, strokeOptions) {
this.ctx.save();
this.ctx.beginPath();
this.applyStrokeOpts(strokeOptions);
this.ctx.moveTo(this.offset.x + zA.x * this.scale.x, this.offset.y + zA.y * this.scale.y);
this.ctx.lineTo(this.offset.x + zB.x * this.scale.x, this.offset.y + zB.y * this.scale.y);
this.ctx.strokeStyle = color;
this.ctx.lineWidth = lineWidth || 1;
this.ctx.stroke();
this.ctx.restore();
};
/**
* Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.
*
* @method arrow
* @param {XYCoords} zA - The start point of the arrow-line.
* @param {XYCoords} zB - The end point of the arrow-line.
* @param {string} color - Any valid CSS color string.
* @param {number=} lineWidth - (optional) The line width to use; default is 1.
* @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
**/
drawutils.prototype.arrow = function (zA, zB, color, lineWidth, headLength, strokeOptions) {
if (headLength === void 0) { headLength = 8; }
var arrowHeadBasePosition = new Vertex_1.Vertex(0, 0);
this.arrowHead(zA, zB, color, lineWidth, headLength, undefined, arrowHeadBasePosition); // Will NOT use dash configuration
this.line(zA, arrowHeadBasePosition, color, lineWidth, strokeOptions); // Will use dash configuration
};
/**
* Draw a cubic Bézier curve and and an arrow at the end (endControlPoint) of the given line width the specified (CSS-) color and arrow size.
*
* @method cubicBezierArrow
* @param {XYCoords} startPoint - The start point of the cubic Bézier curve
* @param {XYCoords} endPoint - The end point the cubic Bézier curve.
* @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
* @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
* @param {string} color - The CSS color to draw the curve with.
* @param {number} lineWidth - (optional) The line width to use.
* @param {headLength=8} headLength - (optional) The length of the arrow head (default is 8 units).
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof DrawLib
*/
drawutils.prototype.cubicBezierArrow = function (startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, headLength, strokeOptions) {
var arrowHeadBasePosition = new Vertex_1.Vertex(0, 0);
// Will NOT use dash configuration
this.arrowHead(endControlPoint, endPoint, color, lineWidth, headLength, undefined, arrowHeadBasePosition);
var diff = arrowHeadBasePosition.difference(endPoint);
// Will use dash configuration
this.cubicBezier(startPoint, { x: endPoint.x - diff.x, y: endPoint.y - diff.y }, startControlPoint, { x: endControlPoint.x - diff.x, y: endControlPoint.y - diff.y }, color, lineWidth, strokeOptions);
};
/**
* Draw just an arrow head a the end of an imaginary line (zB) of the given line width the specified (CSS-) color and size.
*
* @method arrow
* @param {XYCoords} zA - The start point of the arrow-line.
* @param {XYCoords} zB - The end point of the arrow-line.
* @param {string} color - Any valid CSS color string.
* @param {number=1} lineWidth - (optional) The line width to use; default is 1.
* @param {number=8} headLength - (optional) The length of the arrow head (default is 8 pixels).
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
* @param {XYCoords=} arrowHeadBasePositionBuffer - (optional) If not null, then this position will contain the arrow head's start point (after execution). Some sort of OUT variable.
*
* @return {void}
* @instance
* @memberof DrawLib
**/
drawutils.prototype.arrowHead = function (zA, zB, color, lineWidth, headLength, strokeOptions, arrowHeadBasePositionBuffer) {
// var headLength: number = 8; // length of head in pixels
if (headLength === void 0) { headLength = 8; }
this.ctx.save();
this.ctx.beginPath();
this.applyStrokeOpts(strokeOptions);
var vertices = Vector_1.Vector.utils.buildArrowHead(zA, zB, headLength, this.scale.x, this.scale.y);
if (arrowHeadBasePositionBuffer) {
arrowHeadBasePositionBuffer.x = vertices[0].x / this.scale.x;
arrowHeadBasePositionBuffer.y = vertices[0].y / this.scale.y;
}
this.ctx.moveTo(this.offset.x + vertices[0].x, this.offset.y + vertices[0].y);
for (var i = 0; i < vertices.length; i++) {
this.ctx.lineTo(this.offset.x + vertices[i].x, this.offset.y + vertices[i].y);
}
this.ctx.lineTo(this.offset.x + vertices[0].x, this.offset.y + vertices[0].y);
this.ctx.lineWidth = lineWidth || 1;
this._fillOrDraw(color);
this.ctx.restore();
};
/**
* Draw an image at the given position with the given size.<br>
* <br>
* Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.
*
* @method image
* @param {Image} image - The image object to draw.
* @param {XYCoords} position - The position to draw the the upper left corner at.
* @param {XYCoords} size - The x/y-size to draw the image with.
* @param {number=0.0} alpha - (optional, default=0.0) The transparency (1.0=opaque, 0.0=transparent).
* @return {void}
* @instance
* @memberof drawutils
**/
drawutils.prototype.image = function (image, position, size, alpha) {
if (alpha === void 0) { alpha = 1.0; }
if (!image.complete || !image.naturalWidth) {
// Avoid drawing un-unloaded or broken images
return;
}
this.ctx.save();
this.ctx.globalAlpha = alpha;
// Note that there is a Safari bug with the 3 or 5 params variant.
// Only the 9-param varaint works.
this.ctx.drawImage(image, 0, 0, image.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)
image.naturalHeight - 1, // To avoid errors substract 1 here.
this.offset.x + position.x * this.scale.x, this.offset.y + position.y * this.scale.y, size.x * this.scale.x, size.y * this.scale.y);
this.ctx.restore();
};
/**
* Draw an image at the given position with the given size.<br>
* <br>
* Note: SVG images may have resizing issues at the moment.Draw a line and an arrow at the end (zB) of the given line with the specified (CSS-) color.
*
* @method texturedPoly
* @param {Image} textureImage - The image object to draw.
* @param {Bounds} textureSize - The texture size to use; these are the original bounds to map the polygon vertices to.
* @param {Polygon} polygon - The polygon to use as clip path.
* @param {XYCoords} polygonPosition - The polygon's position (relative), measured at the bounding box's center.
* @param {number} rotation - The rotation to use for the polygon (and for the texture).
* @param {XYCoords={x:0,y:0}} rotationCenter - (optional) The rotational center; default is center of bounding box.
* @return {void}
* @instance
* @memberof drawutils
**/
drawutils.prototype.texturedPoly = function (textureImage, textureSize, polygon, polygonPosition, rotation) {
var basePolygonBounds = polygon.getBounds();
// var targetCenterDifference = polygonPosition.clone().difference(basePolygonBounds.getCenter());
var targetCenterDifference = new Vertex_1.Vertex(polygonPosition.x, polygonPosition.y).difference(basePolygonBounds.getCenter());
// var tileCenter = basePolygonBounds.getCenter().sub(targetCenterDifference);
// Get the position offset of the polygon
var targetTextureSize = new Vertex_1.Vertex(textureSize.width, textureSize.height);
// var targetTextureOffset = new Vertex(-textureSize.width / 2, -textureSize.height / 2).sub(targetCenterDifference);
var targetTextureOffset = new Vertex_1.Vertex(textureSize.min.x, textureSize.min.y).sub(polygonPosition);
this.ctx.save();
// this.ctx.translate(this.offset.x + rotationCenter.x * this.scale.x, this.offset.y + rotationCenter.y * this.scale.y);
this.ctx.translate(this.offset.x + polygonPosition.x * this.scale.x, this.offset.y + polygonPosition.y * this.scale.y);
drawutils.helpers.clipPoly(this.ctx, {
x: -polygonPosition.x * this.scale.x,
y: -polygonPosition.y * this.scale.y
}, this.scale, polygon.vertices);
this.ctx.scale(this.scale.x, this.scale.y);
this.ctx.rotate(rotation);
this.ctx.drawImage(textureImage, 0, 0, textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)
textureImage.naturalHeight - 1, // To avoid errors substract 1 here.
targetTextureOffset.x, // * this.scale.x,
targetTextureOffset.y, // * this.scale.y,
targetTextureSize.x, // * this.scale.x,
targetTextureSize.y // * this.scale.y
);
this.ctx.restore();
};
/*
_texturedPoly(
textureImage: HTMLImageElement,
textureSize: Bounds,
polygon: Polygon,
polygonPosition: XYCoords,
rotation: number,
rotationCenter: XYCoords = { x: 0, y: 0 }
): void {
var basePolygonBounds = polygon.getBounds();
var targetCenterDifference = polygonPosition.clone().difference(basePolygonBounds.getCenter());
var rotationalOffset = rotationCenter ? polygonPosition.difference(rotationCenter) : { x: 0, y: 0 };
// var rotationalOffset = { x: 0, y: 0 };
var tileCenter = basePolygonBounds.getCenter().sub(targetCenterDifference);
// Get the position offset of the polygon
var targetTextureSize = new Vertex(textureSize.width, textureSize.height);
var targetTextureOffset = new Vertex(-textureSize.width / 2, -textureSize.height / 2).sub(targetCenterDifference);
this.ctx.save();
// this.ctx.translate(
// this.offset.x + (tileCenter.x - rotationalOffset.x * 0 + targetTextureOffset.x * 0.0) * this.scale.x,
// this.offset.y + (tileCenter.y - rotationalOffset.y * 0 + targetTextureOffset.y * 0.0) * this.scale.y
// );
this.ctx.translate(
this.offset.x + (tileCenter.x - rotationalOffset.x * 0 + targetTextureOffset.x * 0.0) * this.scale.x,
this.offset.y + (tileCenter.y - rotationalOffset.y * 0 + targetTextureOffset.y * 0.0) * this.scale.y
);
this.ctx.rotate(rotation);
drawutils.helpers.clipPoly(
this.ctx,
{
x: (-targetCenterDifference.x * 1 - tileCenter.x - rotationalOffset.x) * this.scale.x,
y: (-targetCenterDifference.y * 1 - tileCenter.y - rotationalOffset.y) * this.scale.y
},
this.scale,
polygon.vertices
);
this.ctx.drawImage(
textureImage,
0,
0,
textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)
textureImage.naturalHeight - 1, // To avoid errors substract 1 here.
(-polygonPosition.x + targetTextureOffset.x * 1 - rotationalOffset.x * 1) * this.scale.x,
(-polygonPosition.y + targetTextureOffset.y * 1 - rotationalOffset.y * 1) * this.scale.y,
targetTextureSize.x * this.scale.x,
targetTextureSize.y * this.scale.y
);
// const scaledTextureSize = new Bounds(
// new Vertex(
// -polygonPosition.x + targetTextureOffset.x - rotationalOffset.x,
// -polygonPosition.y + targetTextureOffset.y - rotationalOffset.y
// ).scaleXY(this.scale, rotationCenter),
// new Vertex(
// -polygonPosition.x + targetTextureOffset.x - rotationalOffset.x + targetTextureSize.x,
// -polygonPosition.y + targetTextureOffset.y - rotationalOffset.y + targetTextureSize.y
// ).scaleXY(this.scale, rotationCenter)
// );
// this.ctx.drawImage(
// textureImage,
// 0,
// 0,
// textureImage.naturalWidth - 1, // There is this horrible Safari bug (fixed in newer versions)
// textureImage.naturalHeight - 1, // To avoid errors substract 1 here.
// scaledTextureSize.min.x,
// scaledTextureSize.min.y,
// scaledTextureSize.width,
// scaledTextureSize.height
// );
this.ctx.restore();
}
*/
/**
* Draw a rectangle.
*
* @param {XYCoords} position - The upper left corner of the rectangle.
* @param {number} width - The width of the rectangle.
* @param {number} height - The height of the rectangle.
* @param {string} color - The color to use.
* @param {number=1} lineWidth - (optional) The line with to use (default is 1).
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
**/
drawutils.prototype.rect = function (position, width, height, color, lineWidth, strokeOptions) {
this.ctx.save();
this.ctx.beginPath();
this.applyStrokeOpts(strokeOptions);
this.ctx.moveTo(this.offset.x + position.x * this.scale.x, this.offset.y + position.y * this.scale.y);
this.ctx.lineTo(this.offset.x + (position.x + width) * this.scale.x, this.offset.y + position.y * this.scale.y);
this.ctx.lineTo(this.offset.x + (position.x + width) * this.scale.x, this.offset.y + (position.y + height) * this.scale.y);
this.ctx.lineTo(this.offset.x + position.x * this.scale.x, this.offset.y + (position.y + height) * this.scale.y);
// this.ctx.lineTo( this.offset.x+position.x*this.scale.x, this.offset.y+position.y*this.scale.y );
this.ctx.closePath();
this.ctx.lineWidth = lineWidth || 1;
this._fillOrDraw(color);
this.ctx.restore();
};
/**
* Draw a rectangle at the given bounds; and with the specified line width and (CSS-) color.<br>
*
* @method bounds
* @param {IBounds} bounds - The bounds rectangle to be drawn.
* @param {string} color - The CSS color to draw the rectangle with.
* @param {number=} lineWidth - (optional) The line width to use; default is 1.
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {R}
* @instance
* @memberof DrawLib
*/
drawutils.prototype.bounds = function (bounds, color, lineWidth, strokeOptions) {
this.rect(bounds.min, bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, color, lineWidth, strokeOptions);
};
/**
* Draw the given (cubic) bézier curve.
*
* @method cubicBezier
* @param {XYCoords} startPoint - The start point of the cubic Bézier curve
* @param {XYCoords} endPoint - The end point the cubic Bézier curve.
* @param {XYCoords} startControlPoint - The start control point the cubic Bézier curve.
* @param {XYCoords} endControlPoint - The end control point the cubic Bézier curve.
* @param {string} color - The CSS color to draw the curve with.
* @param {number} lineWidth - (optional) The line width to use.
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.cubicBezier = function (startPoint, endPoint, startControlPoint, endControlPoint, color, lineWidth, strokeOptions) {
if (startPoint instanceof CubicBezierCurve_1.CubicBezierCurve) {
this.cubicBezier(startPoint.startPoint, startPoint.endPoint, startPoint.startControlPoint, startPoint.endControlPoint, color, lineWidth);
return;
}
// Draw curve
this.ctx.save();
this.ctx.beginPath();
this.applyStrokeOpts(strokeOptions);
this.ctx.moveTo(this.offset.x + startPoint.x * this.scale.x, this.offset.y + startPoint.y * this.scale.y);
this.ctx.bezierCurveTo(this.offset.x + startControlPoint.x * this.scale.x, this.offset.y + startControlPoint.y * this.scale.y, this.offset.x + endControlPoint.x * this.scale.x, this.offset.y + endControlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);
//this.ctx.closePath();
this.ctx.lineWidth = lineWidth || 2;
this._fillOrDraw(color);
this.ctx.restore();
};
/**
* Draw the given (quadratic) bézier curve.
*
* @method quadraticBezier
* @param {XYCoords} startPoint - The start point of the cubic Bézier curve
* @param {XYCoords} controlPoint - The control point the cubic Bézier curve.
* @param {XYCoords} endPoint - The end control point the cubic Bézier curve.
* @param {string} color - The CSS color to draw the curve with.
* @param {number|string} lineWidth - (optional) The line width to use.
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.quadraticBezier = function (startPoint, controlPoint, endPoint, color, lineWidth, strokeOptions) {
// Draw curve
this.ctx.save();
this.ctx.beginPath();
this.applyStrokeOpts(strokeOptions);
this.ctx.moveTo(this.offset.x + startPoint.x * this.scale.x, this.offset.y + startPoint.y * this.scale.y);
this.ctx.quadraticCurveTo(this.offset.x + controlPoint.x * this.scale.x, this.offset.y + controlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);
this.ctx.lineWidth = lineWidth || 2;
this._fillOrDraw(color);
this.ctx.restore();
};
/**
* Draw the given (cubic) Bézier path.
*
* The given path must be an array with n*3+1 vertices, where n is the number of
* curves in the path:
* <pre> [ point1, point1_startControl, point2_endControl, point2, point2_startControl, point3_endControl, point3, ... pointN_endControl, pointN ]</pre>
*
* @method cubicBezierPath
* @param {XYCoords[]} path - The cubic bezier path as described above.
* @param {string} color - The CSS colot to draw the path with.
* @param {number=1} lineWidth - (optional) The line width to use.
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.cubicBezierPath = function (path, color, lineWidth, strokeOptions, isOpen) {
if (!path || path.length == 0) {
return;
}
// Draw curve
this.ctx.save();
this.ctx.beginPath();
var endPoint;
var startControlPoint;
var endControlPoint;
this.applyStrokeOpts(strokeOptions);
this.ctx.moveTo(this.offset.x + path[0].x * this.scale.x, this.offset.y + path[0].y * this.scale.y);
for (var i = 1; i < path.length; i += 3) {
startControlPoint = path[i];
endControlPoint = path[i + 1];
endPoint = path[i + 2];
this.ctx.bezierCurveTo(this.offset.x + startControlPoint.x * this.scale.x, this.offset.y + startControlPoint.y * this.scale.y, this.offset.x + endControlPoint.x * this.scale.x, this.offset.y + endControlPoint.y * this.scale.y, this.offset.x + endPoint.x * this.scale.x, this.offset.y + endPoint.y * this.scale.y);
}
if (!isOpen) {
this.ctx.closePath();
}
this.ctx.lineWidth = lineWidth || 1;
this._fillOrDraw(color);
this.ctx.restore();
};
/**
* Draw the given handle and handle point (used to draw interactive Bézier curves).
*
* The colors for this are fixed and cannot be specified.
*
* @method handle
* @param {XYCoords} startPoint - The start of the handle.
* @param {XYCoords} endPoint - The end point of the handle.
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.handle = function (startPoint, endPoint) {
// Draw handles
// (No need to save and restore here)
this.point(startPoint, "rgb(0,32,192)");
this.square(endPoint, 5, "rgba(0,128,192,0.5)");
};
/**
* Draw a handle line (with a light grey).
*
* @method handleLine
* @param {XYCoords} startPoint - The start point to draw the handle at.
* @param {XYCoords} endPoint - The end point to draw the handle at.
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.handleLine = function (startPoint, endPoint) {
// Draw handle lines
this.line(startPoint, endPoint, "rgba(128,128,128, 0.5)", undefined);
};
/**
* Draw a 1x1 dot with the specified (CSS-) color.
*
* @method dot
* @param {XYCoords} p - The position to draw the dot at.
* @param {string} color - The CSS color to draw the dot with.
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.dot = function (p, color) {
this.ctx.save();
this.ctx.beginPath();
this.ctx.setLineDash([]); // Clear line-dash settings
this.ctx.moveTo(Math.round(this.offset.x + this.scale.x * p.x), Math.round(this.offset.y + this.scale.y * p.y));
this.ctx.lineTo(Math.round(this.offset.x + this.scale.x * p.x + 1), Math.round(this.offset.y + this.scale.y * p.y + 1));
this.ctx.closePath();
this.ctx.lineWidth = 1;
this._fillOrDraw(color);
this.ctx.restore();
};
/**
* Draw the given point with the specified (CSS-) color and radius 3.
*
* @method point
* @param {XYCoords} p - The position to draw the point at.
* @param {string} color - The CSS color to draw the point with.
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.point = function (p, color) {
var radius = 3;
this.ctx.setLineDash([]); // Clear line-dash settings
this.ctx.beginPath();
this.ctx.arc(this.offset.x + p.x * this.scale.x, this.offset.y + p.y * this.scale.y, radius, 0, 2 * Math.PI, false);
this.ctx.closePath();
this.ctx.lineWidth = 1;
this._fillOrDraw(color);
};
/**
* Draw a circle with the specified (CSS-) color and radius.<br>
* <br>
* Note that if the x- and y- scales are different the result will be an ellipse rather than a circle.
*
* @method circle
* @param {XYCoords} center - The center of the circle.
* @param {number} radius - The radius of the circle.
* @param {string} color - The CSS color to draw the circle with.
* @param {number} lineWidth - The line width (optional, default=1).
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.circle = function (center, radius, color, lineWidth, strokeOptions) {
this.applyStrokeOpts(strokeOptions);
this.ctx.beginPath();
this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius * this.scale.x, radius * this.scale.y, 0.0, 0.0, Math.PI * 2);
this.ctx.closePath();
this.ctx.lineWidth = lineWidth || 1;
this._fillOrDraw(color);
};
/**
* Draw a circular arc (section of a circle) with the given CSS color.
*
* @method circleArc
* @param {XYCoords} center - The center of the circle.
* @param {number} radius - The radius of the circle.
* @param {number} startAngle - The angle to start at.
* @param {number} endAngle - The angle to end at.
* @param {string=#000000} color - The CSS color to draw the circle with.
* @param {number=1} lineWidth - The line width to use
* @param {boolean=false} options.asSegment - If `true` then no beginPath and no draw will be applied (as part of larger path).
* @param {number=} options.dashOffset - (optional) `See StrokeOptions`.
* @param {number=[]} options.dashArray - (optional) `See StrokeOptions`.
*
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.circleArc = function (center, radius, startAngle, endAngle, color, lineWidth, options) {
if (!options || !options.asSegment) {
this.ctx.beginPath();
}
this.applyStrokeOpts(options);
this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radius * this.scale.x, radius * this.scale.y, 0.0, startAngle, endAngle, false);
if (!options || !options.asSegment) {
// this.ctx.closePath();
this.ctx.lineWidth = lineWidth || 1;
this._fillOrDraw(color || "#000000");
}
};
/**
* Draw an ellipse with the specified (CSS-) color and thw two radii.
*
* @method ellipse
* @param {XYCoords} center - The center of the ellipse.
* @param {number} radiusX - The radius of the ellipse.
* @param {number} radiusY - The radius of the ellipse.
* @param {string} color - The CSS color to draw the ellipse with.
* @param {number} lineWidth=1 - An optional line width param (default is 1).
* @param {number=} rotation - (optional, default=0) The rotation of the ellipse.
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.ellipse = function (center, radiusX, radiusY, color, lineWidth, rotation, strokeOptions) {
if (typeof rotation === "undefined") {
rotation = 0.0;
}
this.applyStrokeOpts(strokeOptions);
this.ctx.beginPath();
this.ctx.ellipse(this.offset.x + center.x * this.scale.x, this.offset.y + center.y * this.scale.y, radiusX * this.scale.x, radiusY * this.scale.y, rotation, 0.0, Math.PI * 2);
this.ctx.closePath();
this.ctx.lineWidth = lineWidth || 1;
this._fillOrDraw(color);
};
/**
* Draw square at the given center, size and with the specified (CSS-) color.<br>
* <br>
* Note that if the x-scale and the y-scale are different the result will be a rectangle rather than a square.
*
* @method square
* @param {XYCoords} center - The center of the square.
* @param {number} size - The size of the square.
* @param {string} color - The CSS color to draw the square with.
* @param {number} lineWidth - The line with to use (optional, default is 1).
* @param {StrokeOptions=} strokeOptions - (optional) Stroke settings to use.
*
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.square = function (center, size, color, lineWidth, strokeOptions) {
this.applyStrokeOpts(strokeOptions);
this.ctx.beginPath();
this.ctx.rect(this.offset.x + (center.x - size / 2.0) * this.scale.x, this.offset.y + (center.y - size / 2.0) * this.scale.y, size * this.scale.x, size * this.scale.y);
this.ctx.closePath();
this.ctx.lineWidth = lineWidth || 1;
this._fillOrDraw(color);
};
/**
* Draw a grid of horizontal and vertical lines with the given (CSS-) color.
*
* @method grid
* @param {XYCoords} center - The center of the grid.
* @param {number} width - The total width of the grid (width/2 each to the left and to the right).
* @param {number} height - The total height of the grid (height/2 each to the top and to the bottom).
* @param {number} sizeX - The horizontal grid size.
* @param {number} sizeY - The vertical grid size.
* @param {string} color - The CSS color to draw the grid with.
* @return {void}
* @instance
* @memberof drawutils
*/
drawutils.prototype.grid = function (center, width, height, sizeX, sizeY, color) {
this.ctx.setLineDash([]); // Clear line-dash settings
this.ctx.beginPath();
var yMin = -Math.ceil((height * 0.5) / sizeY) * sizeY;
var yMax = height / 2;
for (var x = -Math.ceil((width * 0.5) / sizeX) * sizeX; x < width / 2; x += sizeX) {
this.ctx.moveTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + yMin) * this.scale.y);
this.ctx.lineTo(this.offset.x + (center.x + x) * this.scale.x, this.offset.y + (center.y + yMax) * this.scale.y);
}
var xMin = -Math.ceil((width * 0.5) / sizeX) * sizeX; // -Math.ceil((height*0.5)/sizeY)*sizeY;
var xMax = width / 2; // height/2;
for (var y = -Math.ceil((height * 0.5) / sizeY) * sizeY; y < height / 2; y += sizeY) {
this.ctx.moveTo(this.offset.x + (center.x + xMin) * this.scale.x - 4, this.offset.y + (center.y + y) * this.scale.y);
this.ctx.lineTo(this.offset.x + (center.x + xMax) * this.scale.x + 4, this.offset.y + (center.y + y) * this.scale.y);
}
this.ctx.strokeStyle = color;
this.ctx.lineWidth = 1.0;
this.ctx.stroke();
this.ctx.closePath();
};
/**
* Draw a raster of crosshairs in the given grid.<br>
*
* This works analogue to the grid() function
*
* @method raster
* @param {XYCoords} center - The center of the raster.
* @param {number} width - The total width of the raster (width/2 each to the left and to the right).
* @param {number} height - The total height of the raster (height/2 each to the top and to the bottom).
* @param {number} sizeX - The horizon