@eclipse-scout/chart
Version:
Eclipse Scout chart
108 lines (88 loc) • 3.08 kB
text/typescript
/*
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
import {VennCircle} from '../index';
export class VennCircleHelper {
distR: number;
maxR: number;
minR: number;
total: number;
constructor(distR: number, maxR: number, minR: number, total: number) {
this.distR = distR;
this.maxR = maxR;
this.minR = minR;
this.total = total;
}
findBalance2(venn1: VennCircle, venn2: VennCircle) {
// find center
let midX = (venn1.r * venn1.x + venn2.r * venn2.x) / (venn1.r + venn2.r);
let midY = (venn1.r * venn1.y + venn2.r * venn2.y) / (venn1.r + venn2.r);
// move to center
venn1.x = venn1.x - midX;
venn2.x = venn2.x - midX;
venn1.y = venn1.y - midY;
venn2.y = venn2.y - midY;
}
findBalance3(venn1: VennCircle, venn2: VennCircle, venn3: VennCircle) {
// find center
let midX = (venn1.r * venn1.x + venn2.r * venn2.x + venn3.r * venn3.x) / (venn1.r + venn2.r + venn3.r);
let midY = (venn1.r * venn1.y + venn2.r * venn2.y + venn3.r * venn3.y) / (venn1.r + venn2.r + venn3.r);
// move to center
venn1.x = venn1.x - midX;
venn2.x = venn2.x - midX;
venn3.x = venn3.x - midX;
venn1.y = venn1.y - midY;
venn2.y = venn2.y - midY;
venn3.y = venn3.y - midY;
}
calcR(count: number, factorMax: number): number {
if (count === -1) {
return this.maxR * factorMax;
}
return Math.max(this.minR, Math.sqrt(count / this.total) * this.maxR * factorMax);
}
calcD(venn1: VennCircle, venn2: VennCircle, u: number, v: number, uv: number, changeR: boolean): number {
let ret: number;
if (uv === 0) {
// separated circles
ret = venn1.r + venn2.r + this.distR * 2;
} else if (u === 0 && v === 0) {
// same circle
ret = 0;
} else if (u === 0) {
// a part of b
ret = Math.max(0, venn2.r - venn1.r - this.distR);
// check if inner circle is to large
if (ret < 1.5 * this.distR && changeR) {
ret = 1.5 * this.distR;
venn1.r = venn2.r - ret;
}
} else if (v === 0) {
// b part of a
ret = Math.max(0, venn1.r - venn2.r - this.distR);
// check if inner circle is to large
if (ret < 1.5 * this.distR && changeR) {
ret = 1.5 * this.distR;
venn2.r = venn1.r - ret;
}
} else {
// this is pure magic ;) please do not touch!
let ri = Math.min(venn1.r, venn2.r);
let ra = Math.max(venn1.r, venn2.r);
let q = Math.min(u, v) / (Math.min(u, v) + uv);
// unfortunately, there is no closed solution for cricles, so handle as squares
ret = 2 * q * ri - ri + ra;
// check and fix
ret = Math.max(3 * this.distR, ret);
ret = Math.min(ri + ra - 3 * this.distR, ret);
ret = Math.max(ra - ri + 3 * this.distR, ret);
}
return ret;
}
}