You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
4.0 KiB
127 lines
4.0 KiB
1 year ago
|
import {createBorderEdge} from "./Edge";
|
||
|
import {cells, edges, epsilon} from "./Diagram";
|
||
|
|
||
|
export function createCell(site) {
|
||
|
return cells[site.index] = {
|
||
|
site: site,
|
||
|
halfedges: []
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function cellHalfedgeAngle(cell, edge) {
|
||
|
var site = cell.site,
|
||
|
va = edge.left,
|
||
|
vb = edge.right;
|
||
|
if (site === vb) vb = va, va = site;
|
||
|
if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
|
||
|
if (site === va) va = edge[1], vb = edge[0];
|
||
|
else va = edge[0], vb = edge[1];
|
||
|
return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
|
||
|
}
|
||
|
|
||
|
export function cellHalfedgeStart(cell, edge) {
|
||
|
return edge[+(edge.left !== cell.site)];
|
||
|
}
|
||
|
|
||
|
export function cellHalfedgeEnd(cell, edge) {
|
||
|
return edge[+(edge.left === cell.site)];
|
||
|
}
|
||
|
|
||
|
export function sortCellHalfedges() {
|
||
|
for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
|
||
|
if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
|
||
|
var index = new Array(m),
|
||
|
array = new Array(m);
|
||
|
for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
|
||
|
index.sort(function(i, j) { return array[j] - array[i]; });
|
||
|
for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
|
||
|
for (j = 0; j < m; ++j) halfedges[j] = array[j];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function clipCells(x0, y0, x1, y1) {
|
||
|
var nCells = cells.length,
|
||
|
iCell,
|
||
|
cell,
|
||
|
site,
|
||
|
iHalfedge,
|
||
|
halfedges,
|
||
|
nHalfedges,
|
||
|
start,
|
||
|
startX,
|
||
|
startY,
|
||
|
end,
|
||
|
endX,
|
||
|
endY,
|
||
|
cover = true;
|
||
|
|
||
|
for (iCell = 0; iCell < nCells; ++iCell) {
|
||
|
if (cell = cells[iCell]) {
|
||
|
site = cell.site;
|
||
|
halfedges = cell.halfedges;
|
||
|
iHalfedge = halfedges.length;
|
||
|
|
||
|
// Remove any dangling clipped edges.
|
||
|
while (iHalfedge--) {
|
||
|
if (!edges[halfedges[iHalfedge]]) {
|
||
|
halfedges.splice(iHalfedge, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Insert any border edges as necessary.
|
||
|
iHalfedge = 0, nHalfedges = halfedges.length;
|
||
|
while (iHalfedge < nHalfedges) {
|
||
|
end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
|
||
|
start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
|
||
|
if (Math.abs(endX - startX) > epsilon || Math.abs(endY - startY) > epsilon) {
|
||
|
halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
|
||
|
Math.abs(endX - x0) < epsilon && y1 - endY > epsilon ? [x0, Math.abs(startX - x0) < epsilon ? startY : y1]
|
||
|
: Math.abs(endY - y1) < epsilon && x1 - endX > epsilon ? [Math.abs(startY - y1) < epsilon ? startX : x1, y1]
|
||
|
: Math.abs(endX - x1) < epsilon && endY - y0 > epsilon ? [x1, Math.abs(startX - x1) < epsilon ? startY : y0]
|
||
|
: Math.abs(endY - y0) < epsilon && endX - x0 > epsilon ? [Math.abs(startY - y0) < epsilon ? startX : x0, y0]
|
||
|
: null)) - 1);
|
||
|
++nHalfedges;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (nHalfedges) cover = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If there weren’t any edges, have the closest site cover the extent.
|
||
|
// It doesn’t matter which corner of the extent we measure!
|
||
|
if (cover) {
|
||
|
var dx, dy, d2, dc = Infinity;
|
||
|
|
||
|
for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
|
||
|
if (cell = cells[iCell]) {
|
||
|
site = cell.site;
|
||
|
dx = site[0] - x0;
|
||
|
dy = site[1] - y0;
|
||
|
d2 = dx * dx + dy * dy;
|
||
|
if (d2 < dc) dc = d2, cover = cell;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cover) {
|
||
|
var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
|
||
|
cover.halfedges.push(
|
||
|
edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
|
||
|
edges.push(createBorderEdge(site, v01, v11)) - 1,
|
||
|
edges.push(createBorderEdge(site, v11, v10)) - 1,
|
||
|
edges.push(createBorderEdge(site, v10, v00)) - 1
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Lastly delete any cells with no edges; these were entirely clipped.
|
||
|
for (iCell = 0; iCell < nCells; ++iCell) {
|
||
|
if (cell = cells[iCell]) {
|
||
|
if (!cell.halfedges.length) {
|
||
|
delete cells[iCell];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|