123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- import {RedBlackNode} from "./RedBlackTree";
- import {createCell} from "./Cell";
- import {attachCircle, detachCircle} from "./Circle";
- import {createEdge, setEdgeEnd} from "./Edge";
- import {beaches, epsilon} from "./Diagram";
- var beachPool = [];
- function Beach() {
- RedBlackNode(this);
- this.edge =
- this.site =
- this.circle = null;
- }
- function createBeach(site) {
- var beach = beachPool.pop() || new Beach;
- beach.site = site;
- return beach;
- }
- function detachBeach(beach) {
- detachCircle(beach);
- beaches.remove(beach);
- beachPool.push(beach);
- RedBlackNode(beach);
- }
- export function removeBeach(beach) {
- var circle = beach.circle,
- x = circle.x,
- y = circle.cy,
- vertex = [x, y],
- previous = beach.P,
- next = beach.N,
- disappearing = [beach];
- detachBeach(beach);
- var lArc = previous;
- while (lArc.circle
- && Math.abs(x - lArc.circle.x) < epsilon
- && Math.abs(y - lArc.circle.cy) < epsilon) {
- previous = lArc.P;
- disappearing.unshift(lArc);
- detachBeach(lArc);
- lArc = previous;
- }
- disappearing.unshift(lArc);
- detachCircle(lArc);
- var rArc = next;
- while (rArc.circle
- && Math.abs(x - rArc.circle.x) < epsilon
- && Math.abs(y - rArc.circle.cy) < epsilon) {
- next = rArc.N;
- disappearing.push(rArc);
- detachBeach(rArc);
- rArc = next;
- }
- disappearing.push(rArc);
- detachCircle(rArc);
- var nArcs = disappearing.length,
- iArc;
- for (iArc = 1; iArc < nArcs; ++iArc) {
- rArc = disappearing[iArc];
- lArc = disappearing[iArc - 1];
- setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
- }
- lArc = disappearing[0];
- rArc = disappearing[nArcs - 1];
- rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
- attachCircle(lArc);
- attachCircle(rArc);
- }
- export function addBeach(site) {
- var x = site[0],
- directrix = site[1],
- lArc,
- rArc,
- dxl,
- dxr,
- node = beaches._;
- while (node) {
- dxl = leftBreakPoint(node, directrix) - x;
- if (dxl > epsilon) node = node.L; else {
- dxr = x - rightBreakPoint(node, directrix);
- if (dxr > epsilon) {
- if (!node.R) {
- lArc = node;
- break;
- }
- node = node.R;
- } else {
- if (dxl > -epsilon) {
- lArc = node.P;
- rArc = node;
- } else if (dxr > -epsilon) {
- lArc = node;
- rArc = node.N;
- } else {
- lArc = rArc = node;
- }
- break;
- }
- }
- }
- createCell(site);
- var newArc = createBeach(site);
- beaches.insert(lArc, newArc);
- if (!lArc && !rArc) return;
- if (lArc === rArc) {
- detachCircle(lArc);
- rArc = createBeach(lArc.site);
- beaches.insert(newArc, rArc);
- newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
- attachCircle(lArc);
- attachCircle(rArc);
- return;
- }
- if (!rArc) { // && lArc
- newArc.edge = createEdge(lArc.site, newArc.site);
- return;
- }
- // else lArc !== rArc
- detachCircle(lArc);
- detachCircle(rArc);
- var lSite = lArc.site,
- ax = lSite[0],
- ay = lSite[1],
- bx = site[0] - ax,
- by = site[1] - ay,
- rSite = rArc.site,
- cx = rSite[0] - ax,
- cy = rSite[1] - ay,
- d = 2 * (bx * cy - by * cx),
- hb = bx * bx + by * by,
- hc = cx * cx + cy * cy,
- vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
- setEdgeEnd(rArc.edge, lSite, rSite, vertex);
- newArc.edge = createEdge(lSite, site, null, vertex);
- rArc.edge = createEdge(site, rSite, null, vertex);
- attachCircle(lArc);
- attachCircle(rArc);
- }
- function leftBreakPoint(arc, directrix) {
- var site = arc.site,
- rfocx = site[0],
- rfocy = site[1],
- pby2 = rfocy - directrix;
- if (!pby2) return rfocx;
- var lArc = arc.P;
- if (!lArc) return -Infinity;
- site = lArc.site;
- var lfocx = site[0],
- lfocy = site[1],
- plby2 = lfocy - directrix;
- if (!plby2) return lfocx;
- var hl = lfocx - rfocx,
- aby2 = 1 / pby2 - 1 / plby2,
- b = hl / plby2;
- if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
- return (rfocx + lfocx) / 2;
- }
- function rightBreakPoint(arc, directrix) {
- var rArc = arc.N;
- if (rArc) return leftBreakPoint(rArc, directrix);
- var site = arc.site;
- return site[1] === directrix ? site[0] : Infinity;
- }
|