You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为整数点集生成贝塞尔或钟形曲线高度并支持偏移与交互?

自定义钟形曲线高度生成方案

针对点集[0,1,2,...,10]生成符合要求的钟形高度,我们可以基于正态分布公式调整参数,满足起点/终点高度为0、最大高度100、峰值可偏移的需求:

核心实现逻辑

正态分布的基础公式为:

f(x) = (1/(σ√(2π))) * e^(-((x-μ)²)/(2σ²))

我们对其进行缩放和平移,使其适配边界与高度要求:

  • 强制x=0和x=10时高度为0
  • 将曲线最大值缩放至100
  • 自定义峰值位置μ(比如中点5或偏移点3)

可偏移峰值的代码实现(JavaScript)

function generateBellCurvePoints(peakPosition = 5, maxHeight = 100, range = 10) {
  // 计算标准差σ,确保曲线在端点趋近于0
  const sigma = Math.abs(peakPosition - range/2) * 0.6 || range/4;
  const points = [];
  
  for (let x = 0; x <= range; x++) {
    // 计算正态分布原始值
    const exponent = -Math.pow(x - peakPosition, 2) / (2 * Math.pow(sigma, 2));
    const rawValue = Math.exp(exponent);
    // 缩放至目标高度,强制端点为0
    let height = rawValue * maxHeight;
    if (x === 0 || x === range) height = 0;
    // 可选:对高度取整
    points.push(Math.round(height));
  }
  return points;
}

// 示例:峰值在3时的生成结果
console.log(generateBellCurvePoints(3));
// 输出:[0, 12, 44, 100, 73, 30, 8, 1, 0, 0, 0]
推荐工具库
  • bezierjs:完全匹配你的需求,支持创建贝塞尔曲线、拖拽调整控制点,还能通过get(t)方法在任意参数位置采样点。只需将t映射到0-10的整数范围,即可计算对应高度:
    // 示例:创建峰值在中间的贝塞尔曲线
    const curve = new Bezier(0,0, 2,100, 8,100, 10,0);
    const heights = [];
    for (let x = 0; x <=10; x++) {
      const t = x / 10;
      const point = curve.get(t);
      heights.push(Math.round(point.y));
    }
    
  • D3.js:提供多种曲线插值方法(如d3.curveBasis),支持快速生成平滑曲线,结合交互功能可实现控制点拖拽,适合调整后采样整数点高度。
Canvas简化贝塞尔拟合与采样实现

下面是一个极简Canvas实现,支持拖拽贝塞尔控制点,实时采样0-10的整数点高度:

<canvas id="curveCanvas" width="400" height="200"></canvas>
<pre id="sampleOutput"></pre>

<script>
const canvas = document.getElementById('curveCanvas');
const ctx = canvas.getContext('2d');
const output = document.getElementById('sampleOutput');

// 贝塞尔控制点:起点、控制点1、控制点2、终点
let points = [
  {x: 0, y: canvas.height, draggable: false},
  {x: 100, y: 50, draggable: true},
  {x: 300, y: 50, draggable: true},
  {x: 400, y: canvas.height, draggable: false}
];

let draggingPoint = null;

// 绘制曲线与控制点
function draw() {
  ctx.clearRect(0,0,canvas.width,canvas.height);
  
  // 绘制贝塞尔曲线
  ctx.beginPath();
  ctx.moveTo(points[0].x, points[0].y);
  ctx.bezierCurveTo(points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y);
  ctx.strokeStyle = '#2c3e50';
  ctx.lineWidth = 2;
  ctx.stroke();
  
  // 绘制控制点
  points.forEach(p => {
    ctx.beginPath();
    ctx.arc(p.x, p.y, 6, 0, Math.PI*2);
    ctx.fillStyle = p.draggable ? '#e74c3c' : '#3498db';
    ctx.fill();
  });
  
  // 实时采样并输出高度值
  sampleHeights();
}

// 采样0-10整数点的高度
function sampleHeights() {
  const curve = new Bezier(
    points[0].x, points[0].y,
    points[1].x, points[1].y,
    points[2].x, points[2].y,
    points[3].x, points[3].y
  );
  const heights = [];
  for (let x = 0; x <=10; x++) {
    const t = x / 10;
    const point = curve.get(t);
    // 转换为底部为0、顶部为100的高度值
    const height = Math.round(100 - (point.y / canvas.height) * 100);
    heights.push(height);
  }
  output.textContent = `采样高度值:[${heights.join(', ')}]`;
}

// 拖拽交互逻辑
canvas.addEventListener('mousedown', (e) => {
  const rect = canvas.getBoundingClientRect();
  const mouseX = e.clientX - rect.left;
  const mouseY = e.clientY - rect.top;
  
  draggingPoint = points.find(p => p.draggable && 
    Math.hypot(mouseX - p.x, mouseY - p.y) < 10);
});

canvas.addEventListener('mousemove', (e) => {
  if (!draggingPoint) return;
  const rect = canvas.getBoundingClientRect();
  draggingPoint.x = e.clientX - rect.left;
  draggingPoint.y = e.clientY - rect.top;
  draw();
});

canvas.addEventListener('mouseup', () => draggingPoint = null);

// 初始化绘制
draw();
</script>

注:上述代码依赖bezierjs库,需提前引入。

内容的提问来源于stack exchange,提问作者Ole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:58:19