rapid-spreadjs 1.0.143 → 1.0.145

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -1377,6 +1377,231 @@ const BusinessUtils = {
1377
1377
  * @returns 返回所有需要显示和隐藏的行索引结果对象,格式如:{hasValueIndex: [1, 2, 3], noValueIndex: [4, 5, 6]},hasValueIndex代表所有显示的行索引,noValueIndex代表所有隐藏的行索引
1378
1378
  */
1379
1379
  dynamicLoadRows: (GC, spread, dynamicLoadRangeJson, headerRangeHeight, footerRangeHeight, remainingHeight = 500, pageDir = 1, blankRowCellValue = '空白') => {
1380
+ const sheet = spread.getActiveSheet();
1381
+ // 暂停绘制
1382
+ sheet.suspendPaint();
1383
+ // 获取所有单元格对象
1384
+ const cells = SheetUtils.getAllCellObjsByRanges(sheet, dynamicLoadRangeJson);
1385
+ // 设置所有行可见,原因是:如果再次执行的时候,第一次隐藏的行没有还原
1386
+ cells.forEach((item, index) => {
1387
+ sheet.setRowVisible(item.row, true);
1388
+ });
1389
+ // 获取按照row分组后的数据,格式如:{"1":[{row: 1, col: 43, rowCount: 1, colCount: 24}]}
1390
+ const cellsGroupByRow = rapidUtils.groupByJson(cells, 'row');
1391
+ // 获取序号列的跨列数
1392
+ let seqColSpanCount = null;
1393
+ // 最终行索引Key对应的单元格对象集合(跨行的索引)
1394
+ let rowCells = [];
1395
+ rapidUtils.forEachJson(cellsGroupByRow, (cellItems, rowIndexKey, source) => {
1396
+ if (seqColSpanCount == null) {
1397
+ const seqSpans = sheet.getSpans(sheet.getCell(parseInt(rowIndexKey), 1));
1398
+ seqColSpanCount = seqSpans[0].colCount;
1399
+ }
1400
+ // 得到序号列的跨行单元格对象
1401
+ const seqColSpanObj = sheet.getSpans({ row: parseInt(rowIndexKey), col: 1, rowCount: cellItems[0].rowCount, colCount: seqColSpanCount })[0];
1402
+ // 当前序号跨行单元格对应的所有单元格中是否有值
1403
+ let curRowHasValue = false;
1404
+ // 当前所有行索引
1405
+ let curRowIndexs = [];
1406
+ for (let i = 0; i < cellItems.length; i++) {
1407
+ // 获取当前单元格对象
1408
+ const cell = cellItems[i];
1409
+ for (let j = cell.row; j < cell.row + cell.rowCount; j++) {
1410
+ if (!curRowIndexs.some((x) => x == j)) {
1411
+ curRowIndexs.push(j);
1412
+ }
1413
+ }
1414
+ // 获取当前单元格的值
1415
+ const cellValue = sheet.getValue(cell.row, cell.col);
1416
+ // 验证是否有值
1417
+ if (cellValue !== null &&
1418
+ cellValue !== undefined &&
1419
+ cellValue !== '' &&
1420
+ cellValue !== '/' &&
1421
+ !(cellValue instanceof GC.Spread.CalcEngine.CalcError)) {
1422
+ curRowHasValue = true;
1423
+ break;
1424
+ }
1425
+ }
1426
+ let rowObjs = { row: parseInt(rowIndexKey), rows: curRowIndexs, cells: cellItems, hasValue: curRowHasValue };
1427
+ if (!rowCells.some((x) => x.rowSpan == seqColSpanObj.row)) {
1428
+ let rowIndexs = [];
1429
+ const seqColSpanRowSpan = sheet.getSpans({ row: seqColSpanObj.row, col: 1, rowCount: 1, colCount: 1 })[0];
1430
+ for (let i = 0; i < seqColSpanRowSpan.rowCount; i++) {
1431
+ rowIndexs.push(seqColSpanObj.row + i);
1432
+ }
1433
+ rowCells.push({
1434
+ rowSpan: seqColSpanObj.row,
1435
+ rowIndexs: rowIndexs,
1436
+ rows: [rowObjs],
1437
+ });
1438
+ }
1439
+ else {
1440
+ let curRow = rowCells.find((x) => x.rowSpan == seqColSpanObj.row);
1441
+ curRow.rows.push(rowObjs);
1442
+ }
1443
+ });
1444
+ // 有值和没有值的行索引集合
1445
+ let hasValueRows = [], noValueRows = [];
1446
+ // 有值的行索引(序号列使用)
1447
+ let hasValueRowsSer = [];
1448
+ rowCells.forEach((rowObj, index) => {
1449
+ if (rowObj.rows.some((x) => x.hasValue) && !hasValueRowsSer.some((x) => x == rowObj.rowSpan)) {
1450
+ hasValueRowsSer.push(rowObj.rowSpan);
1451
+ }
1452
+ if (rowObj.rows.some((x) => x.hasValue)) {
1453
+ // rowObj.rows.forEach(x => {
1454
+ // x.rows.forEach(rowIndex => {
1455
+ // if (!hasValueRows.some(hItem => hItem == rowIndex)) {
1456
+ // hasValueRows.push(rowIndex);
1457
+ // }
1458
+ // });
1459
+ // });
1460
+ rowObj.rowIndexs.forEach((rowIndex) => {
1461
+ if (!hasValueRows.some((hItem) => hItem == rowIndex)) {
1462
+ hasValueRows.push(rowIndex);
1463
+ }
1464
+ });
1465
+ }
1466
+ else {
1467
+ // rowObj.rows.forEach(x => {
1468
+ // x.rows.forEach(rowIndex => {
1469
+ // if (!noValueRows.some(hItem => hItem == rowIndex)) {
1470
+ // noValueRows.push(rowIndex);
1471
+ // }
1472
+ // });
1473
+ // });
1474
+ rowObj.rowIndexs.forEach((rowIndex) => {
1475
+ if (!noValueRows.some((hItem) => hItem == rowIndex)) {
1476
+ noValueRows.push(rowIndex);
1477
+ }
1478
+ });
1479
+ }
1480
+ });
1481
+ let serNum = 0;
1482
+ hasValueRowsSer.forEach((rowIndex, index) => {
1483
+ const curVal = sheet.getValue(rowIndex, 1);
1484
+ // 检查第一个单元格的值是否包含非数字字符,有非数字字符的时候代表不填充序号
1485
+ if (!/^(?!\d+$)[\u4e00-\u9fa5a-zA-Z0-9!@#$%^&*()_+[\]{};':",.\/?\\|-]+$/.test(curVal)) {
1486
+ serNum++;
1487
+ // 设置序号列单元格的值(1、2、3...的格式)
1488
+ sheet.setValue(rowIndex, 1, serNum);
1489
+ }
1490
+ });
1491
+ hasValueRows.forEach((rowIndex, index) => {
1492
+ // 设置行可见
1493
+ sheet.setRowVisible(rowIndex, true);
1494
+ });
1495
+ noValueRows.forEach((rowIndex) => {
1496
+ // 设置行不可见
1497
+ sheet.setRowVisible(rowIndex, false);
1498
+ });
1499
+ /** 创建空白行单元格 */
1500
+ const createBlackRowCell = () => {
1501
+ // 工作表总高度
1502
+ const sheetTotalHeight = pageDir == 1 ? 1055 : 615;
1503
+ // 之前已经创建的空白行索引
1504
+ let createBlackRowIndex = -1;
1505
+ // 获取所有可见行的总高度
1506
+ let allRowHeight = 0;
1507
+ for (let i = 0; i < sheet.getRowCount(); i++) {
1508
+ const curRowVisible = sheet.getRowVisible(i);
1509
+ const blankRowCell = sheet.getTag(i, 1);
1510
+ if (curRowVisible && (blankRowCell == null || blankRowCell == undefined || blankRowCell != 'BlankCell')) {
1511
+ allRowHeight += sheet.getRowHeight(i);
1512
+ }
1513
+ // 设置已创建的空白行索引
1514
+ if (blankRowCell == 'BlankCell') {
1515
+ createBlackRowIndex = i;
1516
+ }
1517
+ }
1518
+ // 针对纵表情况,工作表总高度-表头和表尾总高度>=remainingHeight,空白行不显示;<remainingHeight,空白行显示
1519
+ // 是否显示空白行
1520
+ let isShowBlankRow = true;
1521
+ if (pageDir == 1 && allRowHeight - headerRangeHeight - footerRangeHeight >= remainingHeight) {
1522
+ isShowBlankRow = false;
1523
+ }
1524
+ if (!isShowBlankRow) {
1525
+ // 设置行不可见
1526
+ if (createBlackRowIndex != -1) {
1527
+ sheet.setRowVisible(createBlackRowIndex, false);
1528
+ }
1529
+ return;
1530
+ }
1531
+ // 获取到最后一行动态加载区域的行索引
1532
+ const lastRowIndex = rowCells[rowCells.length - 1].rowSpan +
1533
+ sheet.getSpans({ row: rowCells[rowCells.length - 1].rowSpan, col: 1, rowCount: 1, colCount: 1 })[0].rowCount -
1534
+ 1; // dynamicLoadRangeJson[0].row + dynamicLoadRangeJson[0].rowCount - 1;
1535
+ // 创建空白行
1536
+ if (allRowHeight < sheetTotalHeight) {
1537
+ // 获取空白行单元格的标签
1538
+ const blankRowCell = sheet.getTag(lastRowIndex + 1, 1);
1539
+ if (!blankRowCell || blankRowCell !== 'BlankCell') {
1540
+ // 添加一行、合并单元格
1541
+ sheet.addRows(lastRowIndex + 1, 1);
1542
+ sheet.addSpan(lastRowIndex + 1, 1, 1, 77);
1543
+ // 设置添加这一行的行高
1544
+ sheet.setRowHeight(lastRowIndex + 1, sheetTotalHeight - allRowHeight);
1545
+ // 获取添加这一行的区域范围
1546
+ const addRowRange = sheet.getRange(lastRowIndex + 1, 1, 1, 77);
1547
+ // 设置边框线
1548
+ addRowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.thin), { all: true });
1549
+ addRowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.medium), {
1550
+ left: true,
1551
+ right: true,
1552
+ top: false,
1553
+ bottom: false,
1554
+ });
1555
+ // 设置单元格水平和垂直居中
1556
+ addRowRange.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
1557
+ addRowRange.vAlign(GC.Spread.Sheets.HorizontalAlign.center);
1558
+ sheet.setValue(lastRowIndex + 1, 1, blankRowCellValue);
1559
+ sheet.setTag(lastRowIndex + 1, 1, 'BlankCell');
1560
+ }
1561
+ else {
1562
+ // 设置添加这一行的行高
1563
+ sheet.setRowHeight(lastRowIndex + 1, sheetTotalHeight - allRowHeight);
1564
+ // 显示空白行单元格
1565
+ sheet.setRowVisible(lastRowIndex + 1, true);
1566
+ }
1567
+ }
1568
+ // 隐藏空白行单元格
1569
+ else {
1570
+ const blankRowCell = sheet.getTag(lastRowIndex + 1, 1);
1571
+ // 如果空白行单元格标签存在,则隐藏
1572
+ if (blankRowCell && blankRowCell == 'BlankCell') {
1573
+ sheet.setRowVisible(lastRowIndex + 1, false);
1574
+ }
1575
+ }
1576
+ };
1577
+ createBlackRowCell();
1578
+ // // 处理单元格边框线的问题
1579
+ // const allRowIndex = orderByJson(unionJson(hasValueRows, noValueRows));
1580
+ // const rowRange = sheet.getRange(allRowIndex[0], 1, allRowIndex.length, 77);
1581
+ // rowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.thin), { all: true });
1582
+ // rowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.medium), {
1583
+ // left: true,
1584
+ // right: true,
1585
+ // top: false,
1586
+ // bottom: false,
1587
+ // });
1588
+ // 恢复绘制
1589
+ sheet.resumePaint();
1590
+ return { hasValueIndex: hasValueRows, noValueIndex: noValueRows };
1591
+ },
1592
+ /**
1593
+ * 动态加载行(动态显示数据行和序号值)
1594
+ * @param GC GC对象
1595
+ * @param spread 工作簿实例
1596
+ * @param dynamicLoadRangeJson 动态加载的“试验结果”JSON数组范围,格式如:[{row: 1, col: 1, rowCount: 1, colCount: 1}]
1597
+ * @param headerRangeHeight 表头区域总高度
1598
+ * @param footerRangeHeight 表尾区域总高度
1599
+ * @param remainingHeight 剩余高度(针对纵表情况,工作表总高度-表头和表尾总高度>=remainingHeight,空白行不显示;<remainingHeight,空白行显示)
1600
+ * @param pageDir 页面方向(1:纵向、2:横向)
1601
+ * @param blankRowCellValue 空白行单元格值,默认为:空白
1602
+ * @returns 返回所有需要显示和隐藏的行索引结果对象,格式如:{hasValueIndex: [1, 2, 3], noValueIndex: [4, 5, 6]},hasValueIndex代表所有显示的行索引,noValueIndex代表所有隐藏的行索引
1603
+ */
1604
+ dynamicLoadRows_Backup: (GC, spread, dynamicLoadRangeJson, headerRangeHeight, footerRangeHeight, remainingHeight = 500, pageDir = 1, blankRowCellValue = '空白') => {
1380
1605
  const sheet = spread.getActiveSheet();
1381
1606
  // 暂停绘制
1382
1607
  sheet.suspendPaint();
@@ -1571,6 +1796,33 @@ const BusinessUtils = {
1571
1796
  * 公用方法,如:修约计算等
1572
1797
  */
1573
1798
  const EChartsUtilsComm = {
1799
+ /**
1800
+ * 过滤二维数组,移除包含无效值的列
1801
+ * @param {Array[]} valueArr - 二维数组,例如:[['',2,3], [10,null,30]]
1802
+ * @param {Array} invalidValues - 无效值集合,默认为:["", "/", null, undefined, 0]
1803
+ * @returns {Array[]} 过滤后的新二维数组
1804
+ */
1805
+ filterValues: (valueArr, invalidValues = ['', '/', null, undefined, 0]) => {
1806
+ if (!Array.isArray(valueArr) || valueArr.length === 0) {
1807
+ return [];
1808
+ }
1809
+ // 找出需要保留的列索引(该列在所有行中都是有效值)
1810
+ const validColumns = [];
1811
+ const columnCount = valueArr[0] ? valueArr[0].length : 0;
1812
+ for (let col = 0; col < columnCount; col++) {
1813
+ const isColumnValid = valueArr.every((row) => {
1814
+ const value = row[col];
1815
+ return !invalidValues.includes(value);
1816
+ });
1817
+ if (isColumnValid) {
1818
+ validColumns.push(col);
1819
+ }
1820
+ }
1821
+ // 构建结果数组,只保留有效的列
1822
+ return valueArr.map((row) => {
1823
+ return validColumns.map((colIndex) => row[colIndex]);
1824
+ });
1825
+ },
1574
1826
  /**
1575
1827
  * 计算常规修约
1576
1828
  * @param roundingVal 修约值
@@ -1813,7 +2065,7 @@ const EChartsUtilsAll = {
1813
2065
  //fx^0+ax^1+bx^2
1814
2066
  //fx^0+ax^1+bx^2+cx^3
1815
2067
  //fx^0+x^1+x^2+x^3+x^4
1816
- y += item * Math.pow(x, index);
2068
+ y += item * x ** index;
1817
2069
  });
1818
2070
  return y;
1819
2071
  }
@@ -2165,7 +2417,7 @@ const EChartsUtilsAll = {
2165
2417
  //fx^0+ax^1+bx^2
2166
2418
  //fx^0+ax^1+bx^2+cx^3
2167
2419
  //fx^0+x^1+x^2+x^3+x^4
2168
- y += item * Math.pow(x, index);
2420
+ y += item * x ** index;
2169
2421
  });
2170
2422
  return y;
2171
2423
  }
@@ -2656,7 +2908,7 @@ const EChartsUtilsAll = {
2656
2908
  //fx^0+ax^1+bx^2
2657
2909
  //fx^0+ax^1+bx^2+cx^3
2658
2910
  //fx^0+x^1+x^2+x^3+x^4
2659
- y += item * Math.pow(x, index);
2911
+ y += item * x ** index;
2660
2912
  });
2661
2913
  return y;
2662
2914
  }
@@ -3156,7 +3408,7 @@ const EChartsUtilsAll = {
3156
3408
  //fx^0+ax^1+bx^2
3157
3409
  //fx^0+ax^1+bx^2+cx^3
3158
3410
  //fx^0+x^1+x^2+x^3+x^4
3159
- y += item * Math.pow(x, index);
3411
+ y += item * x ** index;
3160
3412
  });
3161
3413
  return y;
3162
3414
  }
@@ -3591,7 +3843,7 @@ const EChartsUtilsAll = {
3591
3843
  //fx^0+ax^1+bx^2
3592
3844
  //fx^0+ax^1+bx^2+cx^3
3593
3845
  //fx^0+x^1+x^2+x^3+x^4
3594
- y += item * Math.pow(x, index);
3846
+ y += item * x ** index;
3595
3847
  });
3596
3848
  return y;
3597
3849
  }
@@ -4026,7 +4278,7 @@ const EChartsUtilsAll = {
4026
4278
  //fx^0+ax^1+bx^2
4027
4279
  //fx^0+ax^1+bx^2+cx^3
4028
4280
  //fx^0+x^1+x^2+x^3+x^4
4029
- y += item * Math.pow(x, index);
4281
+ y += item * x ** index;
4030
4282
  });
4031
4283
  return y;
4032
4284
  }
@@ -4813,7 +5065,7 @@ const EChartsUtilsAll = {
4813
5065
  //fx^0+ax^1+bx^2
4814
5066
  //fx^0+ax^1+bx^2+cx^3
4815
5067
  //fx^0+x^1+x^2+x^3+x^4
4816
- y += item * Math.pow(x, index);
5068
+ y += item * x ** index;
4817
5069
  });
4818
5070
  return y;
4819
5071
  }
@@ -5219,7 +5471,7 @@ const EChartsUtilsAll = {
5219
5471
  // 组装数据
5220
5472
  xDataSource.forEach((item, index) => {
5221
5473
  // 得到x轴原始数据的0.45次方值,并修约0.001
5222
- const val045 = Number(EChartsUtilsComm.getRound(Math.pow(item, 0.45), 0.001));
5474
+ const val045 = Number(EChartsUtilsComm.getRound(item ** 0.45, 0.001));
5223
5475
  xData.push([val045, yDataSource[index]]);
5224
5476
  markLineData.push({
5225
5477
  name: item + '',
@@ -8594,9 +8846,10 @@ const EChartsUtilsAll = {
8594
8846
  let dxsJs = chartExtJson != null ? chartExtJson.dxsJs : 5;
8595
8847
  // 趋势线和标注点的颜色
8596
8848
  const linePointColor = lineData[0].lineColor;
8849
+ const filterVals = EChartsUtilsComm.filterValues([xDataArr[0], yDataArr[0]]);
8597
8850
  // 原始数据
8598
- var xData = xDataArr[0]; //[0.26, 0.16, 0.22, 0.22, 0.17];
8599
- var yData = yDataArr[0]; // [90, 56, 42, 28, 14];
8851
+ var xData = filterVals[0]; // xDataArr[0]; //[0.26, 0.16, 0.22, 0.22, 0.17];
8852
+ var yData = filterVals[1]; // yDataArr[0]; // [90, 56, 42, 28, 14];
8600
8853
  /*var xData = [];
8601
8854
  var yData = [];*/
8602
8855
  // 计算多项式回归系数(强制截距为0):y = a*x^2 + b*x
@@ -15861,37 +16114,77 @@ const FormulaUtils = {
15861
16114
  return retData.allCellVals.length;
15862
16115
  },
15863
16116
  },
16117
+ // {
16118
+ // funName: 'YjMid',
16119
+ // funDesc: '获取所有选择的单元格中的中间值',
16120
+ // funDefaultVal: null,
16121
+ // funParams: [
16122
+ // {
16123
+ // name: '数值1',
16124
+ // repeatable: false,
16125
+ // optional: false,
16126
+ // },
16127
+ // {
16128
+ // name: '数值2',
16129
+ // repeatable: false,
16130
+ // optional: false,
16131
+ // },
16132
+ // {
16133
+ // name: '数值3',
16134
+ // repeatable: false,
16135
+ // optional: false,
16136
+ // },
16137
+ // ],
16138
+ // funCallback: (spread, sheet, retData) => {
16139
+ // //得到所有参数中为数字的集合,即:数字参数才参与计算
16140
+ // retData.allCellVals = retData.allCellVals.filter((item) => FormulaUtils.commFun.isNumber(item));
16141
+ // //如果传递的参数小于3个,则返回0
16142
+ // if (retData.allCellVals.length < 3) {
16143
+ // return 0;
16144
+ // }
16145
+ // let retArrVals: Array<number> = FormulaUtils.commFun.convertToInt(retData.allCellVals);
16146
+ // const maxVal = Math.max(...retArrVals),
16147
+ // minVal = Math.min(...retArrVals);
16148
+ // return retArrVals[0] * 1 + retArrVals[1] * 1 + retArrVals[2] * 1 - maxVal * 1 - minVal * 1;
16149
+ // },
16150
+ // },
15864
16151
  {
15865
- funName: 'YjMid',
16152
+ funName: 'YJMID',
15866
16153
  funDesc: '获取所有选择的单元格中的中间值',
15867
16154
  funDefaultVal: null,
15868
16155
  funParams: [
15869
16156
  {
15870
- name: '数值1',
15871
- repeatable: false,
15872
- optional: false,
15873
- },
15874
- {
15875
- name: '数值2',
15876
- repeatable: false,
15877
- optional: false,
15878
- },
15879
- {
15880
- name: '数值3',
16157
+ name: '单元格范围',
15881
16158
  repeatable: false,
15882
16159
  optional: false,
15883
16160
  },
15884
16161
  ],
15885
16162
  funCallback: (spread, sheet, retData) => {
15886
- //得到所有参数中为数字的集合,即:数字参数才参与计算
15887
- retData.allCellVals = retData.allCellVals.filter((item) => FormulaUtils.commFun.isNumber(item));
15888
- //如果传递的参数小于3个,则返回0
15889
- if (retData.allCellVals.length < 3) {
15890
- return 0;
16163
+ // 步骤1:过滤有效数字(包括数字字符串,如'8'),排除null、undefined、空字符串、'/'、0
16164
+ const validNumbers = retData.allCellVals
16165
+ .filter((item) => {
16166
+ // 将项转换为数字
16167
+ const num = Number(item);
16168
+ // 检查是否为有效数字:非NaN、非0、非无穷大,且原始项不是空字符串或'/'
16169
+ return !isNaN(num) && num !== 0 && isFinite(num) && item !== '' && item !== '/';
16170
+ })
16171
+ .map((item) => Number(item)); // 确保所有项都是数字类型
16172
+ // 如果没有有效数字,返回'/'
16173
+ if (validNumbers.length === 0) {
16174
+ return '/';
16175
+ }
16176
+ // 步骤2:对数字进行升序排序
16177
+ validNumbers.sort((a, b) => a - b);
16178
+ // 步骤3:计算中位数
16179
+ const midIndex = Math.floor(validNumbers.length / 2);
16180
+ // 数组长度为奇数:返回中间值
16181
+ if (validNumbers.length % 2 === 1) {
16182
+ return validNumbers[midIndex];
16183
+ }
16184
+ // 数组长度为偶数:返回中间两个值的平均值
16185
+ else {
16186
+ return (validNumbers[midIndex - 1] + validNumbers[midIndex]) / 2;
15891
16187
  }
15892
- let retArrVals = FormulaUtils.commFun.convertToInt(retData.allCellVals);
15893
- const maxVal = Math.max(...retArrVals), minVal = Math.min(...retArrVals);
15894
- return retArrVals[0] * 1 + retArrVals[1] * 1 + retArrVals[2] * 1 - maxVal * 1 - minVal * 1;
15895
16188
  },
15896
16189
  },
15897
16190
  {
@@ -22039,7 +22332,7 @@ const FormulaUtils = {
22039
22332
  if (dotProduct < 0) {
22040
22333
  return false;
22041
22334
  }
22042
- const squaredLength = Math.pow((segmentEnd.x - segmentStart.x), 2) + Math.pow((segmentEnd.y - segmentStart.y), 2);
22335
+ const squaredLength = (segmentEnd.x - segmentStart.x) ** 2 + (segmentEnd.y - segmentStart.y) ** 2;
22043
22336
  if (dotProduct > squaredLength) {
22044
22337
  return false;
22045
22338
  }