@cantoo/pdf-lib
Version:
Create and modify PDF files with JavaScript
87 lines • 3.37 kB
JavaScript
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