нужна помощь для создания календаря, как MS Outlook? - PullRequest
0 голосов
/ 22 ноября 2010

Я работаю над приложением, таким как MS Outlook Calender, где пользователь может помещать события и т. Д. У меня возникают проблемы с расположением объекта события в соответствии с размером и т. Д., Поскольку пользователь может перетаскивать и изменять размер объекта события в календаре MS Outlook иразмер объектов событий устанавливается автоматически.

Мне нужен алгоритм, поэтому я написал свой собственный, но требуется помощь по нескольким проблемам.

на этом снимке экрана показано расположение объекта события, котороединамический. alt text

Ответы [ 4 ]

1 голос
/ 01 декабря 2010

здесь ответ

Вы можете использовать алгоритм упаковки прямоугольника, но имейте в виду, что события должны быть отсортированы по времени и дате, и для вас будет работать только горизонтальная упаковка

прямоугольная упаковка алгоритм

1 голос
/ 29 ноября 2010

Поскольку вы используете Flex, это не прямой ответ на ваш вопрос, но, надеюсь, он укажет вам правильный путь.

Попробуйте взглянуть на то, как FullCalendar недельные и дневные представления реализуют это.FullCalendar - это плагин jQuery, который отображает календарь, который выполняет именно то, что вы ищете.

Вам придется извлечь логику рендеринга из FullCalendar и преобразовать ее в свой проект во Flex.Я знаю, что JavaScript и ActionScript очень похожи, но я никогда не использовал Flex - извините, я не могу больше помочь в этой области.

Репо FullCalendar здесь здесь .В частности, он выглядит так: AgendaView.js - наиболее интересный файл для вас.

0 голосов
/ 21 января 2015

Вот как я это сделал:

  1. События - это пакеты в столбцы, переменные по дням (или какому-то другому правилу)
  2. События в одном столбце далее разделяются на столбцы, какдо тех пор, пока существует непрерывное пересечение по оси Y.
  3. Событиям присваивается их значение оси X (от 0 до 1) и их размер X (от 0 до 1)
  4. Событиярекурсивно расширяется до тех пор, пока последняя из каждой пересеченной группы (по оси 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

0 голосов
/ 29 ноября 2010

Я думаю, вы спрашиваете об общем алгоритме размещения объектов , верно?

Я совершенно уверен, что это проблема NP-завершения: организовать набор, если интервалы , каждый из которых определяется началом и концом как несколькими столбцы по возможности.

Быть NP-завершенным означает, что ваш лучший выстрел, вероятно, пробует все возможные меры:

  • найдите кластеров в ваших объектах - групп , где вам есть чем заняться, где интервалы перекрываются.
  • для каждого кластера
    • пусть n будет количеством объектов в кластере
    • если n слишком высоко (например, 10 или 15), остановитесь и просто нарисуйте перекрывающиеся объекты
    • генерирует все возможные упорядочения объектов в кластере (для n объектов это n! возможных комбинаций, т.е. 6 объектов, 120 возможных упорядочений )
    • для каждого заказа раскладывайте объекты тривиальным образом: перебирайте элементы по элементам и помещайте их в существующий столбец, если он там подходит, начинайте новый столбец, если он вам нужен.
    • сохранить макет с наименьшим количеством столбцов
...