Skip to main content
Glama

Minecraft Bedrock Education MCP

by Mming-Lab
bezier-calculator.ts5.88 kB
/** * ベジェ曲線座標計算ユーティリティ * makecode-minecraft-geometry-ext の可変制御点ベジェ曲線を参考に実装 */ import { bernsteinBasis, calculateDistance, removeDuplicatePositions, } from "./coordinate-utils"; export interface Position { x: number; y: number; z: number; } /** * ベジェ曲線の座標を計算(可変制御点対応) * * @param startPoint 開始点 * @param endPoint 終了点 * @param controlPoints 制御点配列(1個以上) * @param segments セグメント数(デフォルト: 50) * @returns 座標配列 * * @example * ```typescript * // 3次ベジェ曲線(制御点2個) * const positions = calculateBezierPositions( * { x: 0, y: 70, z: 0 }, * { x: 60, y: 70, z: 30 }, * [{ x: 20, y: 85, z: 10 }, { x: 40, y: 60, z: 20 }], * 100 * ); * * // 2次ベジェ曲線(制御点1個) * const simplePositions = calculateBezierPositions( * { x: 0, y: 70, z: 0 }, * { x: 30, y: 70, z: 30 }, * [{ x: 15, y: 90, z: 15 }], * 50 * ); * ``` */ export function calculateBezierPositions( startPoint: Position, endPoint: Position, controlPoints: Position[], segments: number = 50 ): Position[] { if (controlPoints.length === 0) { // 制御点がない場合は直線 return calculateLinearPath(startPoint, endPoint, segments); } // 全ての点を配列にまとめる const allPoints = [startPoint, ...controlPoints, endPoint]; const n = allPoints.length - 1; // ベジェ曲線の次数 const positions: Position[] = []; let lastX = -Infinity; let lastY = -Infinity; let lastZ = -Infinity; // t パラメータを 0 から 1 まで変化させる for (let i = 0; i <= segments; i++) { const t = i / segments; let x = 0; let y = 0; let z = 0; // ベルンシュタイン基底多項式を使用してベジェ曲線を計算 for (let j = 0; j <= n; j++) { const basis = bernsteinBasis(j, n, t); x += allPoints[j].x * basis; y += allPoints[j].y * basis; z += allPoints[j].z * basis; } // 整数座標に丸める const roundedX = Math.floor(x); const roundedY = Math.floor(y); const roundedZ = Math.floor(z); // 重複を避ける if (roundedX !== lastX || roundedY !== lastY || roundedZ !== lastZ) { positions.push({ x: roundedX, y: roundedY, z: roundedZ }); lastX = roundedX; lastY = roundedY; lastZ = roundedZ; } } return positions; } /** * 直線経路を計算 */ function calculateLinearPath( start: Position, end: Position, segments: number ): Position[] { const positions: Position[] = []; for (let i = 0; i <= segments; i++) { const t = i / segments; positions.push({ x: Math.floor(start.x + (end.x - start.x) * t), y: Math.floor(start.y + (end.y - start.y) * t), z: Math.floor(start.z + (end.z - start.z) * t), }); } return removeDuplicatePositions(positions); } /** * ベジェ曲線の弧長を推定(適応的セグメント数計算用) * * @param startPoint 開始点 * @param endPoint 終了点 * @param controlPoints 制御点配列 * @param samplePoints サンプル点数(デフォルト: 100) * @returns 推定弧長 */ export function estimateBezierArcLength( startPoint: Position, endPoint: Position, controlPoints: Position[], samplePoints: number = 100 ): number { const allPoints = [startPoint, ...controlPoints, endPoint]; const n = allPoints.length - 1; let totalLength = 0; let prevPoint: Position | null = null; for (let i = 0; i <= samplePoints; i++) { const t = i / samplePoints; let x = 0; let y = 0; let z = 0; for (let j = 0; j <= n; j++) { const basis = bernsteinBasis(j, n, t); x += allPoints[j].x * basis; y += allPoints[j].y * basis; z += allPoints[j].z * basis; } const currentPoint = { x, y, z }; if (prevPoint !== null) { totalLength += calculateDistance( prevPoint.x, prevPoint.y, prevPoint.z, currentPoint.x, currentPoint.y, currentPoint.z ); } prevPoint = currentPoint; } return totalLength; } /** * 適応的セグメント数を計算 * 弧長に基づいて適切なセグメント数を自動決定 * * @param startPoint 開始点 * @param endPoint 終了点 * @param controlPoints 制御点配列 * @param blocksPerUnit 1単位あたりのブロック数(デフォルト: 1) * @returns 推奨セグメント数 */ export function calculateAdaptiveSegments( startPoint: Position, endPoint: Position, controlPoints: Position[], blocksPerUnit: number = 1 ): number { const arcLength = estimateBezierArcLength( startPoint, endPoint, controlPoints ); const segments = Math.ceil(arcLength * blocksPerUnit); // 最小50、最大1000の範囲で制限 return Math.max(50, Math.min(1000, segments)); } /** * 3次ベジェ曲線(制御点2個の簡易版) * * @param start 開始点 * @param end 終了点 * @param control1 制御点1 * @param control2 制御点2 * @param segments セグメント数 * @returns 座標配列 */ export function calculateCubicBezier( start: Position, end: Position, control1: Position, control2: Position, segments: number = 50 ): Position[] { return calculateBezierPositions(start, end, [control1, control2], segments); } /** * 2次ベジェ曲線(制御点1個の簡易版) * * @param start 開始点 * @param end 終了点 * @param control 制御点 * @param segments セグメント数 * @returns 座標配列 */ export function calculateQuadraticBezier( start: Position, end: Position, control: Position, segments: number = 50 ): Position[] { return calculateBezierPositions(start, end, [control], segments); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mming-Lab/minecraft-bedrock-education-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server