UNPKG

@cantoo/pdf-lib

Version:

Create and modify PDF files with JavaScript

87 lines 3.37 kB
import { angle, distance, isEqual, orientation, orthogonal, times, unitVector, vector, } from '../maths.js'; import GraphElement from './GraphElement.js'; import Point from './Point.js'; import Segment from './Segment.js'; export default class Ellipse extends GraphElement { constructor(A = new Point(), B = new Point(), C = new Point()) { super(); this.A = A; this.B = B; this.C = C; } center() { const center = this.axis().middle(); return center; } axis() { const axis = new Segment(this.A, this.B); return axis; } a() { const axis = this.axis(); return Math.max(axis.length() / 2, axis.distance(this.C)); } b() { const axis = this.axis(); return Math.min(axis.length() / 2, axis.distance(this.C)); } rotation() { const axis = this.axis(); return axis.length() / 2 > axis.distance(this.C) ? orientation(axis.dirVect()) : orientation(orthogonal(axis.dirVect())); } getSize() { return { width: 2 * this.a(), height: 2 * this.b() }; } isEqual(element) { if (!(element instanceof Ellipse)) return false; const a = this.a(); const b = this.b(); const rotation = this.rotation(); const eltA = element.a(); const eltB = element.b(); const eltRotation = element.rotation(); // If the main axis is the same on both ellipse if (eltA < eltB === a < b) { // The rotation is equivalent module PI as the element is symetrical return (isEqual(eltA, a) && isEqual(eltB, b) && isEqual(rotation + (Math.PI % Math.PI), eltRotation + (Math.PI % Math.PI))); } // If the small axis is different else { // We add a rotation of PI / 2 to emulate the fact that the main axis are actually orthogonal return (isEqual(eltA, b) && isEqual(eltB, a) && isEqual(rotation + (Math.PI % Math.PI), eltRotation + (((3 * Math.PI) / 2) % Math.PI))); } } includes(P) { const { x, y } = P.toCoords(); const { x: cx, y: cy } = this.center().toCoords(); const teta = this.rotation(); return isEqual(Math.pow(((x - cx) * Math.cos(teta) + (y - cy) * Math.sin(teta)) / this.a(), 2) + Math.pow(((x - cx) * Math.sin(teta) - (y - cy) * Math.cos(teta)) / this.b(), 2), 1); } orthoProjection(P) { // We will consider that the parametric projection is a correct approximation of the distance for the current case, even if it is not orthogonal const C = this.center(); const axis = this.axis(); const CP = vector(C, P); const teta = angle(axis.dirVect(), vector(C, P)); const ray = this.polarRay(teta); if (distance(P, this.center()) < ray) return P; const vect = times(unitVector(CP), ray); return new Point(this.center().plus(vect).toCoords()); } polarRay(teta) { const a = this.a(); const b = this.b(); const excentricity = Math.sqrt(Math.abs(a * a - b * b)) / Math.max(a, b); return (Math.min(a, b) / Math.sqrt(1 - Math.pow(excentricity * Math.cos(teta), 2))); } } //# sourceMappingURL=Ellipse.js.map