diff --git a/packages/core/src/app/tools/cylinder/makeCylinder.ts b/packages/core/src/app/tools/cylinder/makeCylinder.ts index 4bafeb07..30d14f1d 100644 --- a/packages/core/src/app/tools/cylinder/makeCylinder.ts +++ b/packages/core/src/app/tools/cylinder/makeCylinder.ts @@ -2,90 +2,91 @@ import { block } from 'components/matrix/matrix'; /** - * 返回一个圆。 + * 生成一个圆。 * ![cylinder](./cylinder.png) * @source FastAsyncWorldEdit */ -export default function makeCylinder( - radiusX: number, - radiusZ: number, - thickness: number, - filled: boolean -): block[] { - const blocks: block[] = []; - function setBlock(x: number, z: number) { - const pushOne = (a: number, b: number) => blocks.push([Number(a.toFixed(0)) - 1, Number(b.toFixed(0)) - 1]); +export default class Cylinder extends Array { + setBlock(x: number, z: number, radiusX: number, radiusZ: number) { + const pushOne = (a: number, b: number) => super.push([Number(a.toFixed(0)) - 1, Number(b.toFixed(0)) - 1]); pushOne(radiusX + x, radiusZ + z); pushOne(radiusX - x, radiusZ + z); pushOne(radiusX + x, radiusZ - z); pushOne(radiusX - x, radiusZ - z); } - radiusX += 0.5; - radiusZ += 0.5; - const invRadiusX = 1 / radiusX, - invRadiusZ = 1 / radiusZ, - ceilRadiusX = Math.ceil(radiusX), - ceilRadiusZ = Math.ceil(radiusZ); - let xSqr: number, - zSqr: number, - distanceSq: number, - nextXn = 0; - if (thickness != 0) { - let nextMinXn = 0; - const minInvRadiusX = 1 / (radiusX - thickness), - minInvRadiusZ = 1 / (radiusZ - thickness); - forX: for (let x = 0; x <= ceilRadiusX; ++x) { - const xn = nextXn, - dx2 = nextMinXn * nextMinXn; - nextXn = (x + 1) * invRadiusX; - nextMinXn = (x + 1) * minInvRadiusX; - let nextZn = 0, - nextMinZn = 0; - xSqr = xn * xn; - forZ: for (let z = 0; z <= ceilRadiusZ; ++z) { - const zn = nextZn, - dz2 = nextMinZn * nextMinZn; - nextZn = (z + 1) * invRadiusZ; - nextMinZn = (z + 1) * minInvRadiusZ; - zSqr = zn * zn; - distanceSq = xSqr + zSqr; - if (distanceSq > 1) { - if (z == 0) { - break forX; + constructor( + radiusX: number, + radiusZ: number, + thickness: number, + filled: boolean + ) { + super(); + radiusX += 0.5; + radiusZ += 0.5; + const invRadiusX = 1 / radiusX, + invRadiusZ = 1 / radiusZ, + ceilRadiusX = Math.ceil(radiusX), + ceilRadiusZ = Math.ceil(radiusZ); + let xSqr: number, + zSqr: number, + distanceSq: number, + nextXn = 0; + if (thickness != 0) { + let nextMinXn = 0; + const minInvRadiusX = 1 / (radiusX - thickness), + minInvRadiusZ = 1 / (radiusZ - thickness); + forX: for (let x = 0; x <= ceilRadiusX; ++x) { + const xn = nextXn, + dx2 = nextMinXn * nextMinXn; + nextXn = (x + 1) * invRadiusX; + nextMinXn = (x + 1) * minInvRadiusX; + let nextZn = 0, + nextMinZn = 0; + xSqr = xn * xn; + forZ: for (let z = 0; z <= ceilRadiusZ; ++z) { + const zn = nextZn, + dz2 = nextMinZn * nextMinZn; + nextZn = (z + 1) * invRadiusZ; + nextMinZn = (z + 1) * minInvRadiusZ; + zSqr = zn * zn; + distanceSq = xSqr + zSqr; + if (distanceSq > 1) { + if (z == 0) { + break forX; + } + break forZ; } - break forZ; - } - if ((dz2 + nextMinXn * nextMinXn <= 1) && (nextMinZn * nextMinZn + dx2 <= 1)) { - continue; + if ((dz2 + nextMinXn * nextMinXn <= 1) && (nextMinZn * nextMinZn + dx2 <= 1)) { + continue; + } + this.setBlock(x, z, radiusX, radiusZ); } - setBlock(x, z); } - } - } else { - forX: for (let x = 0; x <= ceilRadiusX; ++x) { - const xn = nextXn; - nextXn = (x + 1) * invRadiusX; - let nextZn = 0; - xSqr = xn * xn; - forZ: for (let z = 0; z <= ceilRadiusZ; ++z) { - const zn = nextZn; - nextZn = (z + 1) * invRadiusZ; - zSqr = zn * zn; - distanceSq = xSqr + zSqr; - if (distanceSq > 1) { - if (z == 0) { - break forX; + } else { + forX: for (let x = 0; x <= ceilRadiusX; ++x) { + const xn = nextXn; + nextXn = (x + 1) * invRadiusX; + let nextZn = 0; + xSqr = xn * xn; + forZ: for (let z = 0; z <= ceilRadiusZ; ++z) { + const zn = nextZn; + nextZn = (z + 1) * invRadiusZ; + zSqr = zn * zn; + distanceSq = xSqr + zSqr; + if (distanceSq > 1) { + if (z == 0) { + break forX; + } + break forZ; } - break forZ; - } - if (!filled) { - if ((zSqr + nextXn * nextXn <= 1) && (nextZn * nextZn + xSqr <= 1)) { - continue; + if (!filled) { + if ((zSqr + nextXn * nextXn <= 1) && (nextZn * nextZn + xSqr <= 1)) { + continue; + } } + this.setBlock(x, z, radiusX, radiusZ); } - setBlock(x, z); } } } - return blocks; -} +} \ No newline at end of file diff --git a/packages/core/src/app/tools/cylinder/page.tsx b/packages/core/src/app/tools/cylinder/page.tsx index 39a0f8a9..66b8958b 100644 --- a/packages/core/src/app/tools/cylinder/page.tsx +++ b/packages/core/src/app/tools/cylinder/page.tsx @@ -8,7 +8,7 @@ import { useMemo, useRef } from "react"; -import makeCylinder from "./makeCylinder"; +import Cylinder from "./makeCylinder"; import { Typography, Grid, @@ -26,7 +26,7 @@ import { import drawMatrix, { block } from 'components/matrix/matrix'; -function Cylinder(): JSX.Element { +function CylinderPage(): JSX.Element { const [radiusX, setRadiusX] = useState(50), [radiusZ, setRadiusZ] = useState(50), [thickness, setThickness] = useState(1), @@ -36,7 +36,7 @@ function Cylinder(): JSX.Element { theme = useTheme(), posCache = useRef([1, 1]), cache = useRef([]), - blocks = useMemo(() => makeCylinder(radiusX, radiusZ, thickness, filled), [radiusX, radiusZ, thickness, filled]), + blocks = useMemo(() => new Cylinder(radiusX, radiusZ, thickness, filled), [radiusX, radiusZ, thickness, filled]), updatePos = throttle(17 /* 1000(ms, = 1s) / 60(60fps) = 17(ms) */, (X: number, Z: number) => { drawMatrix(blocks.slice(0), Math.max(radiusX, radiusZ), X, Z, posCache.current, cache.current, theme.palette, true); posCache.current = [X, Z]; @@ -151,4 +151,4 @@ function Cylinder(): JSX.Element { ); } -export default Cylinder; +export default CylinderPage; diff --git a/packages/core/src/app/tools/info.tsx b/packages/core/src/app/tools/info.tsx index bd2635f1..60fc4523 100644 --- a/packages/core/src/app/tools/info.tsx +++ b/packages/core/src/app/tools/info.tsx @@ -80,106 +80,104 @@ export interface tool extends noIconTool { }) | FC; } -export const getTools = (get: typeof intlGet): tool[] => { - return [ - { - name: "AudioTools", - to: "audiotools", - desc: get('录音、复读'), - icon: AudiotrackIcon, - color: [hex("84fab0"), hex("8fd3f4")] - }, - { - name: "CountLetter", - to: "countletter", - desc: get('找出字母在26字母表中的顺序'), - icon: ABCIcon, - color: [hex("e0c3fc"), hex("8ec5fc")] - }, - { - name: get('pi.π计算器'), - to: "pi", - desc: get('pi.计算π的小数点后任意位'), - icon: PiIcon, - color: [hex("4facfe"), hex("00f2fe")] - }, - { - name: get('翻转'), - to: "reversal", - desc: get('随机翻转字符串'), - icon: FlipCameraAndroidIcon, - color: [hex("fa709a"), hex("fee140")] - }, - { - name: get('shaizi.掷色子'), - to: "shaizi", - desc: get('shaizi.随机掷色子'), - icon: Casino, - color: [hex("a8edea"), hex("fed6e3")] - }, - { - name: get('滤镜'), - to: "filter", - desc: get('将一张图片处理成不同的'), - icon: FilterIcon, - color: [hex("d299c2"), hex("fef9d7")] - }, - { - name: get('读数字'), - to: "readnumber", - desc: get('将数字转换成汉字字符串'), - icon: NumbersIcon, - color: [hex("89f7fe"), hex("66a6ff")] - }, - { - name: get('算式生成器'), - to: "mathgen", - desc: get('生成一些算式'), - icon: CalculateIcon, - color: [hex("96fbc4"), hex("f9f586")] - }, - { - name: get('拼图'), - to: "jigsaw", - desc: get('能自定义的拼图'), - icon: ExtensionIcon, - color: [hex("cd9cf2"), hex("f6f3ff")] - }, - { - name: get('立方体'), - to: "cubic", - desc: get('可视化的立方体'), - icon: ViewInArIcon, - color: [hex("37ecba"), hex("72afd3")] - }, - { - name: get('cylinder.name'), - to: "cylinder", - desc: get('cylinder.description'), - icon: AdjustIcon, - color: [hex("fff1eb"), hex("ace0f9")] - }, - { - name: get('pillar.name'), - to: "pillar", - desc: get('pillar.description'), - icon: AccountBalanceIcon, - color: [hex("ffe53b"), hex("ff2525")] - }, - { - name: get('speech.name'), - to: "speech", - desc: get('speech.description'), - icon: KeyboardVoiceIcon, - color: [hex("d9afd9"), hex("97d9e1")] - }, - { - name: get('人生倒计时'), - to: "https://github.neila.vip/countdown.js/", - desc: get('显示时间过去了多少'), - icon: AccessTimeIcon, - color: [hex("c1dfc4"), hex("deecdd")], - isGoto: true - } - ] -}; +export const getTools = (get: typeof intlGet): tool[] => [ + { + name: "AudioTools", + to: "audiotools", + desc: get('录音、复读'), + icon: AudiotrackIcon, + color: [hex("84fab0"), hex("8fd3f4")] + }, + { + name: "CountLetter", + to: "countletter", + desc: get('找出字母在26字母表中的顺序'), + icon: ABCIcon, + color: [hex("e0c3fc"), hex("8ec5fc")] + }, + { + name: get('pi.π计算器'), + to: "pi", + desc: get('pi.计算π的小数点后任意位'), + icon: PiIcon, + color: [hex("4facfe"), hex("00f2fe")] + }, + { + name: get('翻转'), + to: "reversal", + desc: get('随机翻转字符串'), + icon: FlipCameraAndroidIcon, + color: [hex("fa709a"), hex("fee140")] + }, + { + name: get('shaizi.掷色子'), + to: "shaizi", + desc: get('shaizi.随机掷色子'), + icon: Casino, + color: [hex("a8edea"), hex("fed6e3")] + }, + { + name: get('滤镜'), + to: "filter", + desc: get('将一张图片处理成不同的'), + icon: FilterIcon, + color: [hex("d299c2"), hex("fef9d7")] + }, + { + name: get('读数字'), + to: "readnumber", + desc: get('将数字转换成汉字字符串'), + icon: NumbersIcon, + color: [hex("89f7fe"), hex("66a6ff")] + }, + { + name: get('算式生成器'), + to: "mathgen", + desc: get('生成一些算式'), + icon: CalculateIcon, + color: [hex("96fbc4"), hex("f9f586")] + }, + { + name: get('拼图'), + to: "jigsaw", + desc: get('能自定义的拼图'), + icon: ExtensionIcon, + color: [hex("cd9cf2"), hex("f6f3ff")] + }, + { + name: get('立方体'), + to: "cubic", + desc: get('可视化的立方体'), + icon: ViewInArIcon, + color: [hex("37ecba"), hex("72afd3")] + }, + { + name: get('cylinder.name'), + to: "cylinder", + desc: get('cylinder.description'), + icon: AdjustIcon, + color: [hex("fff1eb"), hex("ace0f9")] + }, + { + name: get('pillar.name'), + to: "pillar", + desc: get('pillar.description'), + icon: AccountBalanceIcon, + color: [hex("ffe53b"), hex("ff2525")] + }, + { + name: get('speech.name'), + to: "speech", + desc: get('speech.description'), + icon: KeyboardVoiceIcon, + color: [hex("d9afd9"), hex("97d9e1")] + }, + { + name: get('人生倒计时'), + to: "https://github.neila.vip/countdown.js/", + desc: get('显示时间过去了多少'), + icon: AccessTimeIcon, + color: [hex("c1dfc4"), hex("deecdd")], + isGoto: true + } +]; \ No newline at end of file