英文:
Generating heights from a Bezier curve or bell / cubic/ quadratic function over a range of integers?
问题
我想生成一组高度值,使其符合钟形曲线,用于一组点[0,1,2,3,4,5,6,7,8,9,10]。
我没有曲线的公式,尽管这个问题中有各种实现方式。
0应该在曲线的开头,10应该在曲线的末尾,最大高度应该是100。
最大点可以在中间,但我也想知道是否有办法倾斜它,例如,最大值可以在3以上吗?
如果有一个可以实现这个的库,那就太好了。
类似于BezierJS,允许在图像上拖动点,然后从整数范围内的曲线中采样高度,这将非常棒。
在Inkscape中,我们可以使用Bezier工具将曲线拟合到一组点上。我想知道是否有可能在画布上重新创建一个“迷你”版本,以便我们可以将曲线拟合到一组点上,然后在整数范围内采样高度?
英文:
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?
答案1
得分: 0
计算给定均值和标准差的 x
高度的概率密度函数被称为概率密度函数。查看这里以获取相关公式和数学原理。高度的伸缩可以以线性方式完成。我还添加了拖拽插件用于图表js。
// 计算概率密度函数(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; // 影响钟形曲线的“厚度”
const mean = (left + right) / 2 // 或图形的另一个中心(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
}
}
// 伸缩
const factor = maxHeight / maxY;
for (let i = 0; i < dataPoints.length; i++) {
dataPoints[i] = dataPoints[i] * factor
}
// 图表
const ctx = myChart.getContext("2d");
const graph = new Chart(ctx, {
type: "line",
data: {
labels: labels,
datasets: [{
data: dataPoints,
label: "正态分布 - 可拖动点!",
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 // <-- 这个选项禁用了工具提示
},
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>
英文:
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.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-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)
},
}
}
}
});
<!-- language: lang-html -->
<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>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论