计算通过所有点的曲线
Calculate a curve that goes through all the points
我在构建一条通过所有点但不在这些点之外的曲线时遇到了问题,就像 SVG 中的贝塞尔曲线所做的那样。
我试过了
贝塞尔曲线,
二次曲线,
光滑的曲线,
和卡斯特廖
这是我的示例 link https://dotnetfiddle.net/KEqts0
不幸的是,我可以使用第 3 方来做映射。
我不想将输出放入,因为那只会是噪音,我附上了一张图片以供参考。
Observation: The initial question was tagged javascript
. After posting my answer the javascript tag was deleted (not by the OP).
给定一个点数组 pointsRy
,您需要计算贝塞尔曲线控制点的位置。第一条和最后一条曲线是二次贝塞尔曲线。所有其他曲线都是三次贝塞尔曲线。
这是一张图像,我在其中标记了点和通过每个点的曲线的切线。控制点是切线的起点和终点。
切线的大小是相对于点之间的距离计算的:let t = 1 / 5;
改变这个来改变曲率。
let svg = document.querySelector("svg")
let t = 1 / 5;// change this to change the curvature
let pointsRy = [[100,100],[250,150],[300,300],[450,250], [510,140],[590,250],[670,140]];
thePath.setAttribute("d", drawCurve(pointsRy));
function drawCurve(p) {
var pc = controlPoints(pointsRy); // the control points array
let d="";
d += `M${p[0][0]}, ${p[0][1]}`
// the first & the last curve are quadratic Bezier
// because I'm using push(), pc[i][1] comes before pc[i][0]
d += `Q${pc[1][1].x}, ${pc[1][1].y}, ${p[1][0]}, ${p[1][1]}`;
if (p.length > 2) {
// central curves are cubic Bezier
for (var i = 1; i < p.length - 2; i++) {
d+= `C${pc[i][0].x}, ${pc[i][0].y} ${pc[i + 1][1].x},${pc[i + 1][1].y} ${p[i + 1][0]},${p[i + 1][1]}`;
}//end for
// the first & the last curve are quadratic Bezier
let n = p.length - 1;
d+=`Q${pc[n - 1][0].x}, ${pc[n - 1][0].y} ${p[n][0]},${p[n][1]}`;
}
return d;
}
function controlPoints(p) {
// given the points array p calculate the control points
let pc = [];
for (var i = 1; i < p.length - 1; i++) {
let dx = p[i - 1][0] - p[i + 1][0]; // difference x
let dy = p[i - 1][1] - p[i + 1][1]; // difference y
// the first control point
let x1 = p[i][0] - dx * t;
let y1 = p[i][1] - dy * t;
let o1 = {
x: x1,
y: y1
};
// the second control point
var x2 = p[i][0] + dx * t;
var y2 = p[i][1] + dy * t;
var o2 = {
x: x2,
y: y2
};
// building the control points array
pc[i] = [];
pc[i].push(o1);
pc[i].push(o2);
}
return pc;
}
body{background:black; margin:1em;}
svg{border: 1px solid #999;}
path{fill:none; stroke:white;}
<svg viewBox="0 0 800 400">
<path id="thePath" stroke="white"/>
</svg>
我在构建一条通过所有点但不在这些点之外的曲线时遇到了问题,就像 SVG 中的贝塞尔曲线所做的那样。
我试过了 贝塞尔曲线, 二次曲线, 光滑的曲线, 和卡斯特廖
这是我的示例 link https://dotnetfiddle.net/KEqts0
不幸的是,我可以使用第 3 方来做映射。
我不想将输出放入,因为那只会是噪音,我附上了一张图片以供参考。
Observation: The initial question was tagged
javascript
. After posting my answer the javascript tag was deleted (not by the OP).
给定一个点数组 pointsRy
,您需要计算贝塞尔曲线控制点的位置。第一条和最后一条曲线是二次贝塞尔曲线。所有其他曲线都是三次贝塞尔曲线。
这是一张图像,我在其中标记了点和通过每个点的曲线的切线。控制点是切线的起点和终点。
切线的大小是相对于点之间的距离计算的:let t = 1 / 5;
改变这个来改变曲率。
let svg = document.querySelector("svg")
let t = 1 / 5;// change this to change the curvature
let pointsRy = [[100,100],[250,150],[300,300],[450,250], [510,140],[590,250],[670,140]];
thePath.setAttribute("d", drawCurve(pointsRy));
function drawCurve(p) {
var pc = controlPoints(pointsRy); // the control points array
let d="";
d += `M${p[0][0]}, ${p[0][1]}`
// the first & the last curve are quadratic Bezier
// because I'm using push(), pc[i][1] comes before pc[i][0]
d += `Q${pc[1][1].x}, ${pc[1][1].y}, ${p[1][0]}, ${p[1][1]}`;
if (p.length > 2) {
// central curves are cubic Bezier
for (var i = 1; i < p.length - 2; i++) {
d+= `C${pc[i][0].x}, ${pc[i][0].y} ${pc[i + 1][1].x},${pc[i + 1][1].y} ${p[i + 1][0]},${p[i + 1][1]}`;
}//end for
// the first & the last curve are quadratic Bezier
let n = p.length - 1;
d+=`Q${pc[n - 1][0].x}, ${pc[n - 1][0].y} ${p[n][0]},${p[n][1]}`;
}
return d;
}
function controlPoints(p) {
// given the points array p calculate the control points
let pc = [];
for (var i = 1; i < p.length - 1; i++) {
let dx = p[i - 1][0] - p[i + 1][0]; // difference x
let dy = p[i - 1][1] - p[i + 1][1]; // difference y
// the first control point
let x1 = p[i][0] - dx * t;
let y1 = p[i][1] - dy * t;
let o1 = {
x: x1,
y: y1
};
// the second control point
var x2 = p[i][0] + dx * t;
var y2 = p[i][1] + dy * t;
var o2 = {
x: x2,
y: y2
};
// building the control points array
pc[i] = [];
pc[i].push(o1);
pc[i].push(o2);
}
return pc;
}
body{background:black; margin:1em;}
svg{border: 1px solid #999;}
path{fill:none; stroke:white;}
<svg viewBox="0 0 800 400">
<path id="thePath" stroke="white"/>
</svg>