【发布时间】:2017-05-02 14:52:33
【问题描述】:
我需要均匀分布一组轴对齐的滑动矩形,这些矩形受最大宽度/高度和一些水平/垂直坐标的约束,具体取决于滑动形状本身的位置。矩形被限制在一个方向上,可以沿着另一个轴滑动,也不能重叠,也不能跨过。
此问题基于: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;
}
}
}
}
如何计算矩形形状的力,以从力场中获得均匀分布,即矩形之间的距离尽可能大?认为矩形真的很热,并且最多只能根据它们的自定义 x/y 约束进行间隔。
任何帮助将不胜感激。
编辑:
【问题讨论】:
标签: javascript geometry rectangles force-layout