UNPKG

@rws-framework/client

Version:

This package provides the core client-side framework for Realtime Web Suit (RWS), enabling modular, asynchronous web components, state management, and integration with backend services. It is located in `.dev/client`.

374 lines (311 loc) 12.3 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.hull = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ function _cross(o, a, b) { return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]); } function _upperTangent(pointset) { const lower = []; for (let l = 0; l < pointset.length; l++) { while (lower.length >= 2 && (_cross(lower[lower.length - 2], lower[lower.length - 1], pointset[l]) <= 0)) { lower.pop(); } lower.push(pointset[l]); } lower.pop(); return lower; } function _lowerTangent(pointset) { const reversed = pointset.reverse(), upper = []; for (let u = 0; u < reversed.length; u++) { while (upper.length >= 2 && (_cross(upper[upper.length - 2], upper[upper.length - 1], reversed[u]) <= 0)) { upper.pop(); } upper.push(reversed[u]); } upper.pop(); return upper; } // pointset has to be sorted by X function convex(pointset) { const upper = _upperTangent(pointset), lower = _lowerTangent(pointset); const convex = lower.concat(upper); convex.push(pointset[0]); return convex; } module.exports = convex; },{}],2:[function(require,module,exports){ module.exports = { toXy: function(pointset, format) { if (format === undefined) { return pointset.slice(); } return pointset.map(function(pt) { /*jslint evil: true */ const _getXY = new Function('pt', 'return [pt' + format[0] + ',' + 'pt' + format[1] + '];'); return _getXY(pt); }); }, fromXy: function(pointset, format) { if (format === undefined) { return pointset.slice(); } return pointset.map(function(pt) { /*jslint evil: true */ const _getObj = new Function('pt', 'const o = {}; o' + format[0] + '= pt[0]; o' + format[1] + '= pt[1]; return o;'); return _getObj(pt); }); } } },{}],3:[function(require,module,exports){ function Grid(points, cellSize) { this._cells = []; this._cellSize = cellSize; this._reverseCellSize = 1 / cellSize; for (let i = 0; i < points.length; i++) { const point = points[i]; const x = this.coordToCellNum(point[0]); const y = this.coordToCellNum(point[1]); if (!this._cells[x]) { const array = []; array[y] = [point]; this._cells[x] = array; } else if (!this._cells[x][y]) { this._cells[x][y] = [point]; } else { this._cells[x][y].push(point); } } } Grid.prototype = { cellPoints: function(x, y) { // (Number, Number) -> Array return (this._cells[x] !== undefined && this._cells[x][y] !== undefined) ? this._cells[x][y] : []; }, rangePoints: function(bbox) { // (Array) -> Array const tlCellX = this.coordToCellNum(bbox[0]); const tlCellY = this.coordToCellNum(bbox[1]); const brCellX = this.coordToCellNum(bbox[2]); const brCellY = this.coordToCellNum(bbox[3]); const points = []; for (let x = tlCellX; x <= brCellX; x++) { for (let y = tlCellY; y <= brCellY; y++) { // replaced Array.prototype.push.apply to avoid hitting stack size limit on larger arrays. for (let i = 0; i < this.cellPoints(x, y).length; i++) { points.push(this.cellPoints(x, y)[i]); } } } return points; }, removePoint: function(point) { // (Array) -> Array const cellX = this.coordToCellNum(point[0]); const cellY = this.coordToCellNum(point[1]); const cell = this._cells[cellX][cellY]; let pointIdxInCell; for (let i = 0; i < cell.length; i++) { if (cell[i][0] === point[0] && cell[i][1] === point[1]) { pointIdxInCell = i; break; } } cell.splice(pointIdxInCell, 1); return cell; }, trunc: Math.trunc || function(val) { // (number) -> number return val - val % 1; }, coordToCellNum: function(x) { // (number) -> number return this.trunc(x * this._reverseCellSize); }, extendBbox: function(bbox, scaleFactor) { // (Array, Number) -> Array return [ bbox[0] - (scaleFactor * this._cellSize), bbox[1] - (scaleFactor * this._cellSize), bbox[2] + (scaleFactor * this._cellSize), bbox[3] + (scaleFactor * this._cellSize) ]; } }; function grid(points, cellSize) { return new Grid(points, cellSize); } module.exports = grid; },{}],4:[function(require,module,exports){ /* (c) 2014-2020, Andrii Heonia Hull.js, a JavaScript library for concave hull generation by set of points. https://github.com/AndriiHeonia/hull */ 'use strict'; const intersect = require('./intersect.js'); const grid = require('./grid.js'); const formatUtil = require('./format.js'); const convexHull = require('./convex.js'); function _filterDuplicates(pointset) { const unique = [pointset[0]]; let lastPoint = pointset[0]; for (let i = 1; i < pointset.length; i++) { const currentPoint = pointset[i]; if (lastPoint[0] !== currentPoint[0] || lastPoint[1] !== currentPoint[1]) { unique.push(currentPoint); } lastPoint = currentPoint; } return unique; } function _sortByX(pointset) { return pointset.sort(function(a, b) { return (a[0] - b[0]) || (a[1] - b[1]); }); } function _sqLength(a, b) { return Math.pow(b[0] - a[0], 2) + Math.pow(b[1] - a[1], 2); } function _cos(o, a, b) { const aShifted = [a[0] - o[0], a[1] - o[1]], bShifted = [b[0] - o[0], b[1] - o[1]], sqALen = _sqLength(o, a), sqBLen = _sqLength(o, b), dot = aShifted[0] * bShifted[0] + aShifted[1] * bShifted[1]; return dot / Math.sqrt(sqALen * sqBLen); } function _intersect(segment, pointset) { for (let i = 0; i < pointset.length - 1; i++) { const seg = [pointset[i], pointset[i + 1]]; if (segment[0][0] === seg[0][0] && segment[0][1] === seg[0][1] || segment[0][0] === seg[1][0] && segment[0][1] === seg[1][1]) { continue; } if (intersect(segment, seg)) { return true; } } return false; } function _occupiedArea(pointset) { let minX = Infinity; let minY = Infinity; let maxX = -Infinity; let maxY = -Infinity; for (let i = pointset.length - 1; i >= 0; i--) { if (pointset[i][0] < minX) { minX = pointset[i][0]; } if (pointset[i][1] < minY) { minY = pointset[i][1]; } if (pointset[i][0] > maxX) { maxX = pointset[i][0]; } if (pointset[i][1] > maxY) { maxY = pointset[i][1]; } } return [ maxX - minX, // width maxY - minY // height ]; } function _bBoxAround(edge) { return [ Math.min(edge[0][0], edge[1][0]), // left Math.min(edge[0][1], edge[1][1]), // top Math.max(edge[0][0], edge[1][0]), // right Math.max(edge[0][1], edge[1][1]) // bottom ]; } function _midPoint(edge, innerPoints, convex) { let point = null, angle1Cos = MAX_CONCAVE_ANGLE_COS, angle2Cos = MAX_CONCAVE_ANGLE_COS, a1Cos, a2Cos; for (let i = 0; i < innerPoints.length; i++) { a1Cos = _cos(edge[0], edge[1], innerPoints[i]); a2Cos = _cos(edge[1], edge[0], innerPoints[i]); if (a1Cos > angle1Cos && a2Cos > angle2Cos && !_intersect([edge[0], innerPoints[i]], convex) && !_intersect([edge[1], innerPoints[i]], convex)) { angle1Cos = a1Cos; angle2Cos = a2Cos; point = innerPoints[i]; } } return point; } function _concave(convex, maxSqEdgeLen, maxSearchArea, grid, edgeSkipList) { let midPointInserted = false; for (let i = 0; i < convex.length - 1; i++) { const edge = [convex[i], convex[i + 1]]; // generate a key in the format X0,Y0,X1,Y1 const keyInSkipList = edge[0][0] + ',' + edge[0][1] + ',' + edge[1][0] + ',' + edge[1][1]; if (_sqLength(edge[0], edge[1]) < maxSqEdgeLen || edgeSkipList.has(keyInSkipList)) { continue; } let scaleFactor = 0; let bBoxAround = _bBoxAround(edge); let bBoxWidth; let bBoxHeight; let midPoint; do { bBoxAround = grid.extendBbox(bBoxAround, scaleFactor); bBoxWidth = bBoxAround[2] - bBoxAround[0]; bBoxHeight = bBoxAround[3] - bBoxAround[1]; midPoint = _midPoint(edge, grid.rangePoints(bBoxAround), convex); scaleFactor++; } while (midPoint === null && (maxSearchArea[0] > bBoxWidth || maxSearchArea[1] > bBoxHeight)); if (bBoxWidth >= maxSearchArea[0] && bBoxHeight >= maxSearchArea[1]) { edgeSkipList.add(keyInSkipList); } if (midPoint !== null) { convex.splice(i + 1, 0, midPoint); grid.removePoint(midPoint); midPointInserted = true; } } if (midPointInserted) { return _concave(convex, maxSqEdgeLen, maxSearchArea, grid, edgeSkipList); } return convex; } function hull(pointset, concavity, format) { let maxEdgeLen = concavity || 20; const points = _filterDuplicates(_sortByX(formatUtil.toXy(pointset, format))); if (points.length < 4) { return points.concat([points[0]]); } const occupiedArea = _occupiedArea(points); const maxSearchArea = [ occupiedArea[0] * MAX_SEARCH_BBOX_SIZE_PERCENT, occupiedArea[1] * MAX_SEARCH_BBOX_SIZE_PERCENT ]; const convex = convexHull(points); const innerPoints = points.filter(function(pt) { return convex.indexOf(pt) < 0; }); const cellSize = Math.ceil(1 / (points.length / (occupiedArea[0] * occupiedArea[1]))); const concave = _concave( convex, Math.pow(maxEdgeLen, 2), maxSearchArea, grid(innerPoints, cellSize), new Set()); if (format) { return formatUtil.fromXy(concave, format); } else { return concave; } } const MAX_CONCAVE_ANGLE_COS = Math.cos(90 / (180 / Math.PI)); // angle = 90 deg const MAX_SEARCH_BBOX_SIZE_PERCENT = 0.6; module.exports = hull; },{"./convex.js":1,"./format.js":2,"./grid.js":3,"./intersect.js":5}],5:[function(require,module,exports){ function ccw(x1, y1, x2, y2, x3, y3) { const cw = ((y3 - y1) * (x2 - x1)) - ((y2 - y1) * (x3 - x1)); return cw > 0 ? true : cw < 0 ? false : true; // colinear } function intersect(seg1, seg2) { const x1 = seg1[0][0], y1 = seg1[0][1], x2 = seg1[1][0], y2 = seg1[1][1], x3 = seg2[0][0], y3 = seg2[0][1], x4 = seg2[1][0], y4 = seg2[1][1]; return ccw(x1, y1, x3, y3, x4, y4) !== ccw(x2, y2, x3, y3, x4, y4) && ccw(x1, y1, x2, y2, x3, y3) !== ccw(x1, y1, x2, y2, x4, y4); } module.exports = intersect; },{}]},{},[4])(4) });