Files
rough/bin/fillers/filler-utils.js
Preet Shihn 2fa4ec3c65 dot filler
2018-06-19 00:30:19 -07:00

102 lines
3.9 KiB
JavaScript

import { Segment } from '../geometry';
import { HachureIterator } from '../utils/hachure';
export function lineLength(line) {
const p1 = line[0];
const p2 = line[1];
return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2));
}
export function getIntersectingLines(line, points) {
const intersections = [];
const s1 = new Segment([line[0], line[1]], [line[2], line[3]]);
for (let i = 0; i < points.length; i++) {
const s2 = new Segment(points[i], points[(i + 1) % points.length]);
if (s1.intersects(s2)) {
intersections.push([s1.xi, s1.yi]);
}
}
return intersections;
}
export function affine(x, y, cx, cy, sinAnglePrime, cosAnglePrime, R) {
const A = -cx * cosAnglePrime - cy * sinAnglePrime + cx;
const B = R * (cx * sinAnglePrime - cy * cosAnglePrime) + cy;
const C = cosAnglePrime;
const D = sinAnglePrime;
const E = -R * sinAnglePrime;
const F = R * cosAnglePrime;
return [
A + C * x + D * y,
B + E * x + F * y
];
}
export function hachureLinesForPolygon(points, o) {
const ret = [];
if (points && points.length) {
let left = points[0][0];
let right = points[0][0];
let top = points[0][1];
let bottom = points[0][1];
for (let i = 1; i < points.length; i++) {
left = Math.min(left, points[i][0]);
right = Math.max(right, points[i][0]);
top = Math.min(top, points[i][1]);
bottom = Math.max(bottom, points[i][1]);
}
const angle = o.hachureAngle;
let gap = o.hachureGap;
if (gap < 0) {
gap = o.strokeWidth * 4;
}
gap = Math.max(gap, 0.1);
const radPerDeg = Math.PI / 180;
const hachureAngle = (angle % 180) * radPerDeg;
const cosAngle = Math.cos(hachureAngle);
const sinAngle = Math.sin(hachureAngle);
const tanAngle = Math.tan(hachureAngle);
const it = new HachureIterator(top - 1, bottom + 1, left - 1, right + 1, gap, sinAngle, cosAngle, tanAngle);
let rect;
while ((rect = it.nextLine()) != null) {
const lines = getIntersectingLines(rect, points);
for (let i = 0; i < lines.length; i++) {
if (i < (lines.length - 1)) {
const p1 = lines[i];
const p2 = lines[i + 1];
ret.push([p1, p2]);
}
}
}
}
return ret;
}
export function hachureLinesForEllipse(cx, cy, width, height, o, renderer) {
const ret = [];
let rx = Math.abs(width / 2);
let ry = Math.abs(height / 2);
rx += renderer.getOffset(-rx * 0.05, rx * 0.05, o);
ry += renderer.getOffset(-ry * 0.05, ry * 0.05, o);
const angle = o.hachureAngle;
let gap = o.hachureGap;
if (gap <= 0) {
gap = o.strokeWidth * 4;
}
let fweight = o.fillWeight;
if (fweight < 0) {
fweight = o.strokeWidth / 2;
}
const radPerDeg = Math.PI / 180;
const hachureAngle = (angle % 180) * radPerDeg;
const tanAngle = Math.tan(hachureAngle);
const aspectRatio = ry / rx;
const hyp = Math.sqrt(aspectRatio * tanAngle * aspectRatio * tanAngle + 1);
const sinAnglePrime = aspectRatio * tanAngle / hyp;
const cosAnglePrime = 1 / hyp;
const gapPrime = gap / ((rx * ry / Math.sqrt((ry * cosAnglePrime) * (ry * cosAnglePrime) + (rx * sinAnglePrime) * (rx * sinAnglePrime))) / rx);
let halfLen = Math.sqrt((rx * rx) - (cx - rx + gapPrime) * (cx - rx + gapPrime));
for (let xPos = cx - rx + gapPrime; xPos < cx + rx; xPos += gapPrime) {
halfLen = Math.sqrt((rx * rx) - (cx - xPos) * (cx - xPos));
const p1 = affine(xPos, cy - halfLen, cx, cy, sinAnglePrime, cosAnglePrime, aspectRatio);
const p2 = affine(xPos, cy + halfLen, cx, cy, sinAnglePrime, cosAnglePrime, aspectRatio);
ret.push([p1, p2]);
}
return ret;
}