-2

I want to generate a set of heights that fit a the onto a bell shaped curve for an array of points [0,1,2,3,4,5,6,7,8,9, 10].

I don't have a formula for the curve, all though this question does have various implementations.

The 0 should be at the beginning of the curve and the 10 should be at the end and the max height should be 100.

And the maximum point could be at the center but I'm also wondering if there is a way to skew it, so for example the max could be above 3?

If there's a library that can do this that would be great too.

Something like BezierJS that would allow for dragging points over an image and then sampling heights from the curve over the range of integers would be really awesome.

In Inkscape we can take the Bezier tool and fit a curve to a set of points. I wonder if it's possible to recreate a "Mini" version of this on canvas so that we could fit a curve to a set of points and then sample the heights over the integer range?

Ole
  • 41,793
  • 59
  • 191
  • 359
  • 1
    I'm a little confused here, because at 41k rep, you know that questions asking for libraries or approaches etc. is literally [one of the reasons](/help/on-topic) to close a question here, and you know that deleting your previously closed question and reposting it, instead of updating it and requesting it be reopened is essentially [not allowed](https://meta.stackexchange.com/a/305856/395686)... What did you try already? Because right now your post (whether you intended to or not) is asking folks to do your work for you, instead of you [(re)searching and trying things](/help/how-to-ask). – Mike 'Pomax' Kamermans Jul 27 '23 at 17:07

1 Answers1

0

The function to calculate height of x given mean and standard deviation is called probability density function. See here for the formula and math behind. The stretching of the height can be done in a linear fashion. I've added also drag plugin for chart js.

// calculate probability density function (chatGPT)
function calculateNormalPDF(x, mean, stdDev) {
  return 1 / (stdDev * Math.sqrt(2 * Math.PI)) * Math.exp(-Math.pow(x - mean, 2) / (2 * Math.pow(stdDev, 2)));
}

const step = 1;
const maxHeight = 100;
const left = 0;
const right = 10;
const stdDev = 2; // affects "thickness" of bell
const mean = (left + right) / 2 // or another center of graph (3?)

const dataPoints = [];
const labels = []

var maxY = -Infinity
for (let x = left; x <= right; x += step) {
  const y = calculateNormalPDF(x, mean, stdDev);
  dataPoints.push(y);
  labels.push(x.toFixed(1))
  if (maxY < y) {
    maxY = y
  }
}

// stretch
const factor = maxHeight / maxY;
for (let i = 0; i < dataPoints.length; i++) {
  dataPoints[i] = dataPoints[i] * factor
}

// graph
const ctx = myChart.getContext("2d");
const graph = new Chart(ctx, {
  type: "line",
  data: {
    labels: labels,
    datasets: [{
      data: dataPoints,
      label: "normal distribution - draggable points!",
      pointStyle: 'rect',
      radius: 10,
    }]
  },
  options: {
    onHover: function(e) {
      const point = e.chart.getElementsAtEventForMode(e, 'nearest', {
        intersect: true
      }, false)
      if (point.length) e.native.target.style.cursor = 'grab'
      else e.native.target.style.cursor = 'default'
    },
    plugins: {
      tooltip: {
        enabled: false // <-- this option disables tooltips
      },
      dragData: {
        round: 1,
        showTooltip: true,
        onDragStart: function(e, datasetIndex, index, value) {
          // console.log(e)
        },
        onDrag: function(e, datasetIndex, index, value) {
          e.target.style.cursor = 'grabbing'
          // console.log(e, datasetIndex, index, value)
        },
        onDragEnd: function(e, datasetIndex, index, value) {
          e.target.style.cursor = 'default'
          // console.log(datasetIndex, index, value)
        },
      }
    }
  }
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://chrispahm.github.io/chartjs-plugin-dragdata/assets/chartjs-plugin-dragdata.min.js"></script>
<canvas id="myChart" width="400" height="140"></canvas>
IT goldman
  • 14,885
  • 2
  • 14
  • 28