Вот как я это сделал:
- События представляют собой пакет в столбцы переменных в день (или какое-либо другое правило)
- События в одном столбце, дополнительно разделены на колонки, до тех пор, пока существует непрерывное пересечение на Y-оси.
- События присваивают свое значение оси X (от 0 до 1) и их размер X (от 0 до 1)
- События рекурсивно расширены, пока последняя из каждой пересеченной группы (по оси Y и X) не попадает барьер столбца или другое событие, которое завершило расширение.
По сути, это перебор, но работает достаточно быстро, так как там не так много событий, которые требуют дальнейшего расширения за шагом 3.
var physics = [];
var step = 0.01;
var PackEvents = function(columns){
var n = columns.length;
for (var i = 0; i < n; i++) {
var col = columns[ i ];
for (var j = 0; j < col.length; j++)
{
var bubble = col[j];
bubble.w = 1/n;
bubble.x = i*bubble.w;
}
}
};
var collidesWith = function(a,b){
return b.y < a.y+a.h && b.y+b.h > a.y;
};
var intersects = function(a,b){
return b.x < a.x+a.w && b.x+b.w > a.x &&
b.y < a.y+a.h && b.y+b.h > a.y;
};
var getIntersections = function(box){
var i = [];
Ext.each(physics,function(b){
if(intersects(box,b) && b.x > box.x)
i.push(b);
});
return i;
};
var expand = function(box,off,exp){
var newBox = {
x:box.x,
y:box.y,
w:box.w,
h:box.h,
collision:box.collision,
rec:box.rec
};
newBox.x += off;
newBox.w += exp;
var i = getIntersections(newBox);
var collision = newBox.x + newBox.w > 1;
Ext.each(i,function(n){
collision = collision || expand(n,off+step,step) || n.collision;
});
if(!collision){
box.x = newBox.x;
box.w = newBox.w;
box.rec.x = box.x;
box.rec.w = box.w;
}else{
box.collision = true;
}
return collision;
};
Ext.each(columns,function(column){
var lastEventEnding = null;
var columns = [];
physics = [];
Ext.each(column,function(a){
if (lastEventEnding !== null && a.y >= lastEventEnding) {
PackEvents(columns);
columns = [];
lastEventEnding = null;
}
var placed = false;
for (var i = 0; i < columns.length; i++) {
var col = columns[ i ];
if (!collidesWith(col[col.length-1], a)) {
col.push(a);
placed = true;
break;
}
}
if (!placed) {
columns.push([a]);
}
if (lastEventEnding === null || a.y+a.h > lastEventEnding) {
lastEventEnding = a.y+a.h;
}
});
if (columns.length > 0) {
PackEvents(columns);
}
Ext.each(column,function(a){
a.box = {
x:a.x,
y:a.y,
w:a.w,
h:a.h,
collision:false,
rec:a
};
physics.push(a.box);
});
while(true){
var box = null;
for(i = 0; i < physics.length; i++){
if(!physics[i].collision){
box = physics[i];
break;
}
}
if(box === null)
break;
expand(box,0,step);
}
});
Результат: http://imageshack.com/a/img913/9525/NbIqWK.jpg
Что вы используете для создать приложение для календаря? (HTML + JS, WPF и т. Д.) – josh3736
Я использую скрипт с гибким действием – Badr
Может ли каждый описать алгоритм шаг за шагом. – Badr