- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要均匀分布一堆与轴对齐的滑动矩形,这些矩形受最大宽度/高度和一些水平/垂直坐标的约束,具体取决于滑动形状本身的位置。矩形限制在一个方向上,可以沿另一个轴滑动,也可以不重叠且也不能跨步。
这个问题基于:How to implement a constraint solver for 2-D geometry?和Spektre关于力驱动约束求解器的公认建议。
整个结构像通常的图形一样构建,其中的矩形代表节点。
现在,我需要检查每个矩形的大小以进行正确的力计算并避免重叠,但是我很难理解如何将力场应用于二维形状以及两个矩形之间的距离应计算。也许是顶点还是边?
相关代码在下面的功能Solver.solve()中,其中s.Z分别代表水平形状的高度和垂直形状的宽度:
for(var i=0, l=sliders.length; i<l; i++) {
var si = sliders[i];
for(var j=i+1, k=sliders.length; j<k; j++) {
var sj = sliders[j];
if(si._horizontal == sj._horizontal) {
// longer side interaction
if(si._horizontal == 1) {
a0 = si.X + si.a; a1 = sj.X + sj.a;
b0 = si.X + si.b; b1 = sj.X + sj.b;
x0 = si.Y; x1 = sj.Y;
} else {
a0 = si.Y + si.a; a1 = sj.Y + sj.a;
b0 = si.Y + si.b; b1 = sj.Y + sj.b;
x0 = si.X; x1 = sj.X;
}
if(((a0 <= b1) && (b0 >= a1)) || ((a1 <= b0) && (b1 >= a0))) {
x0 = x1 - x0;
if((si.ia >= 0) && (x0 < 0.0) && ((fabs(si.x0) < si.Z) || (fabs(si.x0) > fabs(x0)))) si.x0 = -x0;
if((si.ia >= 0) && (x0 > 0.0) && ((fabs(si.x1) < si.Z) || (fabs(si.x1) > fabs(x0)))) si.x1 = -x0;
if((sj.ia >= 0) && (x0 < 0.0) && ((fabs(sj.x0) < sj.Z) || (fabs(sj.x0) > fabs(x0)))) sj.x0 = +x0;
if((sj.ia >= 0) && (x0 > 0.0) && ((fabs(sj.x1) < sj.Z) || (fabs(sj.x1) > fabs(x0)))) sj.x1 = +x0;
}
// shorter side interaction
if(si._horizontal == 1) {
a0 = si.Y - si.Z; a1 = sj.Y + sj.Z;
b0 = si.Y + si.Z; b1 = sj.Y + sj.Z;
x0 = si.X; x1 = sj.X;
} else {
a0 = si.X - si.Z; a1 = sj.X + sj.Z;
b0 = si.X + si.Z; b1 = sj.X + sj.Z;
x0 = si.Y; x1 = sj.Y;
}
if(((a0 <= b1) && (b0 >= a1)) || ((a1 <= b0) && (b1 >= a0))) {
if(x0 < x1) {
x0 += si.b; x1 += sj.a;
} else{
x0 += si.a; x1 += sj.b;
}
x0 = x1 - x0;
if(si.ia >= 0) {
var sa = this.sliders[si.ia];
if((sa.ia >= 0) && (x0 < 0.0) && ((fabs(sa.x0) < sa.Z) || (fabs(sa.x0) > fabs(x0)))) sa.x0 = -x0;
if((sa.ia >= 0) && (x0 > 0.0) && ((fabs(sa.x1) < sa.Z) || (fabs(sa.x1) > fabs(x0)))) sa.x1 = -x0;
}
if(sj.ia >= 0) {
var sa = sliders[sj.ia];
if((sa.ia >= 0) && (x0 < 0.0) && ((fabs(sa.x0) < sa.Z) || (fabs(sa.x0) > fabs(x0)))) sa.x0 = +x0;
if((sa.ia >= 0) && (x0 > 0.0) && ((fabs(sa.x1) < sa.Z) || (fabs(sa.x1) > fabs(x0)))) sa.x1 = +x0;
}
}
}
}
}
// set x0 as 1D vector to closest perpendicular neighbour before and x1 after
for(var i=0, l=sliders.length; i<l; i++) {
var si = sliders[i];
for(var j=i+1, k=sliders.length; j<k; j++) {
var sj = sliders[j];
if(si._horizontal != sj._horizontal) {
// skip ignored sliders for this
var ignore = false;
for(var n=0, m=si.ic.length; n<m; n++) {
if(si.ic[n] == j) {
ignore = true;
break;
}
}
if(ignore === true) continue;
if(si._horizontal == 1) {
a0 = si.X + si.a; a1 = sj.X - sj.Z;
b0 = si.X + si.b; b1 = sj.X + sj.Z;
x0 = si.Y;
} else {
a0 = si.Y + si.a; a1 = sj.Y - sj.Z;
b0 = si.Y + si.b; b1 = sj.Y + sj.Z;
x0 = si.X;
}
if(((a0 <= b1) && (b0 >= a1)) || ((a1 <= b0) && (b1 >= a0))){
if(si._horizontal == 1) {
a1 = sj.Y + sj.a;
b1 = sj.Y + sj.b;
} else {
a1 = sj.X + sj.a;
b1 = sj.X + sj.b;
}
a1 -= x0; b1 -= x0;
if(fabs(a1) < fabs(b1)) x0 = -a1; else x0 = -b1;
if((si.ia >= 0) && (x0 < 0.0) && ((fabs(si.x0) < si.Z) || (fabs(si.x0) > fabs(x0)))) si.x0 = +x0;
if((si.ia >= 0) && (x0 > 0.0) && ((fabs(si.x1) < si.Z) || (fabs(si.x1) > fabs(x0)))) si.x1 = +x0;
if(sj.ia < 0) continue;
var sa = sliders[sj.ia];
if((sa.ia >= 0) && (x0 < 0.0) && ((fabs(sa.x0) < sa.Z) || (fabs(sa.x0) > fabs(x0)))) sa.x0 = -x0;
if((sa.ia >= 0) && (x0 > 0.0) && ((fabs(sa.x1) < sa.Z) || (fabs(sa.x1) > fabs(x0)))) sa.x1 = -x0;
}
}
}
}
最佳答案
如果我正确地回答了这个问题,OP会要求您提供一组驱动滑块的规则,以便最终的模拟状态可以得出有效的解决方案。
所以这是我的方法,它实际上是从OP中的链接答案中概括出我的求解器代码,但由于我已经达到30 KB的限制,因此它不适合在那里,我觉得需要更多的解释,然后才是注释的代码,所以这里是:
势力
为了确保尽可能相等的间距,您需要稍微更改规则(除了实际物理学之外),因此您只考虑驱动力的最近障碍,而不是现实世界中的所有障碍。而且,该力仅受距离影响,而不像大多数物理力一样受接触/重叠区域的权重(包括静电)。
因此,在i-th
滑块(黄色)的迭代过程中,找到所有四个方向(红色)上最接近障碍物的距离:
并计算必须随距离缩放的驱动力。线性与否无关紧要,但对于从左/右或上/下均匀间隔的障碍物,合力应为零。缩放比例主要改变动力学行为。最终结果仅在约束限制运动以实现均匀间距的状态下受其影响。因此,您可以使用以下任何一种示例:
F = c * (d1-d0)
F = c * (d1^2 - d0^2)
F = c * (1/d1^2 - 1/d0^2)
c
是某个量值系数,
d0,d1
是同一轴上的两个最接近的障碍物距离。
Fx
-水平轴力
Fy
-垂直轴力
Fx
驱动力。
Fy
力应驱动其水平的且可以在y轴上移动的父滑块(蓝色)(如果未固定为粗略值)。
Fy
,因此您应该始终仅从两侧选择最强的力。这意味着您需要记住两侧的两个距离/力,并始终选择最小距离或|最高|。双方的力量。
x0,x1
变量的来源,它们在可移动轴上保持到最近障碍物(包括子对象)的最小距离,并且仅在将所有滑块的计算值转换为
Fx,Fy
驱动力之后。
关于javascript - 约束矩形的受力导向布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41190656/
我有一个顶点系统,并用线连接它们。我通过比较每个顶点和它的“下一个”点来测量每个顶点的 Angular (顶点是一个双向链表)。 var next = this.get("next"), dX
我是一名优秀的程序员,十分优秀!