Мне нужно равномерно распределить кучу выровненных по оси скользящих прямоугольников, ограниченных максимальной шириной/высотой и некоторыми горизонтальными/вертикальными координатами в зависимости от положения самих скользящих фигур. Прямоугольники ограничены в одном направлении, могут скользить вдоль другой оси, не могут пересекаться и не перешагиваться.Принудительная компоновка для прямоугольных прямоугольных форм
Этот вопрос основан на: How to implement a constraint solver for 2-D geometry? и хорошо принятом предложении Спектра для принудительного решения с принудительным управлением.
Вся структура построена, как обычно, как график, где прямоугольники представляют узлы.
Теперь мне нужно проверить размер каждого прямоугольника, чтобы получить правильный расчет силы и избежать совпадения, но у меня есть некоторые проблемы, чтобы понять, как силовое поле может быть применено к двумерной форме, и как расстояние между двумя прямоугольниками должно быть рассчитано. Может быть, вершины или стороны?
Соответствующий код в функции Solver.solve() ниже, где Sz представляют собой, соответственно, высоту формы для горизонтальных, а ширина для вертикальных:
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.
Любая помощь будет принята с благодарностью.
EDIT:
Пример: https://plnkr.co/edit/3xGmAKsly2qCGMp3fPrJ?p=preview
Hi Spektre, не могли бы вы помочь мне завершить этот проект? У меня много тестовых данных, с вашей помощью я мог бы это сделать вовремя. – deblocker
@deblocker мое свободное время ограничено, что вам нужно? – Spektre
@deblocker Есть еще несколько проблем: например, как определить решение действительно оптимально? Как предложила Нина, может быть какая-то весовая функция, которая будет отражать деформации интервала ... что-то вроде 1. получить соседние отношения. 2. вычислить максимальные и средние различия в интервалах в каждой строке/столбце. 3. решить решаемое или нерассмотренное состояние. Дело в том, что вам нужно указать формат ввода. Как я уже упоминал ранее, есть конфликты, так как некоторые слайдеры пересекаются уже так, как их обрабатывать (я игнорирую их для пересекающихся слайдеров, но правильно ли это?) – Spektre