- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
具体来说,我正在使用 javascript 在 Canvas 上工作。
基本上,我的对象有我想避免的边界,但仍然用贝塞尔曲线环绕。但是,我什至不确定从哪里开始编写一个可以移动控制点以避免碰撞的算法。
问题在下图中,即使你不熟悉乐谱,问题应该还是很清楚的。曲线的点是红点
此外,我可以访问每个音符的边界框,其中包括词干。
所以自然地,必须在边界框和曲线之间检测到碰撞(这里有一些方向会很好,但我一直在浏览,发现有很多关于这方面的信息)。但是在检测到碰撞后会发生什么?计算控制点位置以使某些东西看起来更像:
最佳答案
贝塞尔方法
最初,这个问题是一个广泛的问题 - 甚至对于 SO 来说甚至可能是广泛的,因为需要考虑许多不同的场景以制定“适合所有人的解决方案”。它本身就是一个完整的项目。因此,我将为您提供可以构建的解决方案的基础 - 它不是一个完整的解决方案(但接近一个..)。我在最后添加了一些补充建议。
此解决方案的基本步骤是:
将音符分为两组,左部分和右部分。
然后,控制点基于从第一个(结束)点的最大 Angular 和到该组中任何其他音符的距离,以及最后一个结束点到第二组中任何点的距离。
然后将两组得到的 Angular 加倍(最大 90°)并用作计算控制点的基础(基本上是点旋转)。可以使用张力值进一步 trim 距离。
Angular 、加倍、距离、张力和填充偏移将允许微调以获得最佳的整体结果。可能存在需要额外条件检查的特殊情况,但这超出了本文的范围(它不是一个完整的 key 就绪解决方案,但为进一步工作提供了良好的基础)。
该过程的几个快照:
示例中的主要代码分为两部分,两个循环解析每一半以找到最大 Angular 和距离。这可以组合成一个循环,除了从左到中的迭代器之外,还有第二个迭代器从右到中,但为了简单起见并更好地理解发生了什么,我将它们分成两个循环(并引入了一个错误在下半场 - 请注意。我将把它留作练习):
var dist1 = 0, // final distance and angles for the control points
dist2 = 0,
a1 = 0,
a2 = 0;
// get min angle from the half first points
for(i = 2; i < len * 0.5 - 2; i += 2) {
var dx = notes[i ] - notes[0], // diff between end point and
dy = notes[i+1] - notes[1], // current point.
dist = Math.sqrt(dx*dx + dy*dy), // get distance
a = Math.atan2(dy, dx); // get angle
if (a < a1) { // if less (neg) then update finals
a1 = a;
dist1 = dist;
}
}
if (a1 < -0.5 * Math.PI) a1 = -0.5 * Math.PI; // limit to 90 deg.
// get min angle from the half last points
for(i = len * 0.5; i < len - 2; i += 2) {
var dx = notes[len-2] - notes[i],
dy = notes[len-1] - notes[i+1],
dist = Math.sqrt(dx*dx + dy*dy),
a = Math.atan2(dy, dx);
if (a > a2) {
a2 = a;
if (dist2 < dist) dist2 = dist; //bug here*
}
}
a2 -= Math.PI; // flip 180 deg.
if (a2 > -0.5 * Math.PI) a2 = -0.5 * Math.PI; // limit to 90 deg.
var da1 = Math.abs(a1); // get angle diff
var da2 = a2 < 0 ? Math.PI + a2 : Math.abs(a2);
a1 -= da1*2; // double the diff
a2 += da2*2;
var t = 0.8, // tension
cp1x = notes[0] + dist1 * t * Math.cos(a1),
cp1y = notes[1] + dist1 * t * Math.sin(a1),
cp2x = notes[len-2] + dist2 * t * Math.cos(a2),
cp2y = notes[len-1] + dist2 * t * Math.sin(a2);
ctx.moveTo(notes[0], notes[1]);
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, notes[len-2], notes[len-1]);
ctx.stroke();
fill()
将隐式关闭路径):
// first path from left to right
ctx.beginPath();
ctx.moveTo(notes[0], notes[1]); // start point
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, notes[len-2], notes[len-1]);
// taper going from right to left
var taper = 0.15; // angle offset
cp1x = notes[0] + dist1*t*Math.cos(a1-taper);
cp1y = notes[1] + dist1*t*Math.sin(a1-taper);
cp2x = notes[len-2] + dist2*t*Math.cos(a2+taper);
cp2y = notes[len-1] + dist2*t*Math.sin(a2+taper);
// note the order of the control points
ctx.bezierCurveTo(cp2x, cp2y, cp1x, cp1y, notes[0], notes[1]);
ctx.fill(); // close and fill
关于javascript - 如何计算避开物体的贝塞尔曲线控制点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23964091/
在编写 C++ 应用程序时,我通常会限制自己使用 C++ 特定的语言功能。这主要意味着尽可能使用 STL 而不是 CRT。 对我来说,STL 比使用 CRT 更流畅且更易于维护。请考虑以下事项: st
我的 Condor 网格上有一台主机由于某种原因坏了,即在这台主机上运行的作业永远运行。我不是管理员,无法登录,因此我无法调查,也无法将其从网格中移除。我只想在我的提交文件中指定我不想在该主机上运行作
我想使用 JavaScript API 避开 route 的某些区域。我知道,路由API包含这种可能性 我使用这种方式避免了 JS API 中的某些区域 是否可以使用此处 map 的 JS API 避
我开始使用 OleDB。我正在尝试从 Excel 文件(在 C# 中)中提取大量随机数据。这是我的查询: SELECT * FROM NAMED_RANGE 但是我有很多空行。我循环删除它们,但我不太
我正在浏览互联网上所有可能的样本来解决这个问题。还是很头疼。 我只想避免在 www.mylararavelsite.com/public/ 中使用“public”并使其像 www.mylararave
如何安装并使用 mysql? 我试过: $ brew install mysql ==> Downloading https://homebrew.bintray.com/bottles/mysql-
我是一名优秀的程序员,十分优秀!