Re[12]: Параллельная иерархия классов
От: genre Россия  
Дата: 25.02.06 10:05
Оценка:
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>1) точками отрезков прямых линий;

КЛ>2) точками кривых Безье 3-го порядка;
КЛ>3) точками arc'ов.

КЛ>Собственно, мы ничего нового не придумываем. В языке векторной графики PostScript уже давно выделены эти 3 примитива, и с помощью них представляется любая картинка.

вот эти три класса и должны быть в иерархии классов
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[12]: Параллельная иерархия классов
От: Cyberax Марс  
Дата: 25.02.06 10:52
Оценка:
Кирилл Лебедев wrote:
> G>есть одно небольшое препятствие. для круга m_Points.size() будет
> стремится к бесконечности.
> Вовсе нет. Коллега сказал, что максимальное количество точек для круга —
> 3600. Но и это можно оптимизировать. Круг и эллипс легко представляются
> с помощью 4-х кривых Безье 3-го порядка. Для задания каждой такой кривой
> необходимы 4 точки. Соответственно, для 4-х состыкованных кривых,
> представляющих круг, нужно всего 12 (!) точек.
Но тогда у вас фигуры будут выглядеть так:
class TFigure
{
public:

    // ...

protected:

    std::vector<TPoint> m_Points;
    bool usesCurves;
    std::vector<TCurve> m_Curves;
};

То есть даже в прямоугольнике будут ненужные описания кривых.

Далее, рисование окружности/эллипса происходит в десятки раз быстрее,
чем рисование кривых Безье. А значит для нормальной скорости нам нужно
добавить в фигуру еще и набор эллипсов:
class TFigure
{
public:

    // ...

protected:

    std::vector<TPoint> m_Points;
    bool usesCurves;
    std::vector<TCurve> m_Curves;
    bool usesEllipses;
    std::vector<TEllipse> m_Ellipses;
};


А ведь в фигуре еще может содержаться текст! Или фигура может состоять
из композиции нескольких фигур.

> Собственно, мы ничего нового не придумываем. В языке векторной графики

> PostScript уже давно выделены эти 3 примитива, и с помощью них
> представляется любая картинка.
А к чему усложнять? Любая реальная фигура представима в виде набора
окружностей достаточно маленького радиуса.

Нам ведь кроме представления еще нужно и уметь осмысленно манипулировать
фигурами.

Например, как в вашем случае будет выглядеть изменение радиуса окружности?
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[8]: Параллельная иерархия классов
От: Cyberax Марс  
Дата: 25.02.06 11:08
Оценка:
Кирилл Лебедев wrote:
> A>И что с того? Оверхед в 114 виртуальных таблиц?
> A>И самое главное: что это доказывает?
> Дело не в 114 виртуальных таблицах, а в трудоемкости создания и
> сопровождения 114 классов фигур. Это бессмысленно тем более, что можно
> обойтись всего *одним (1!)* классом.
Ага, одним классом с баааальшим switch'ем.

> Принципиальная ошибочность доказывается очень просто: с увеличением

> разнообразия фигур и операций по их преобразованию "стройная" иерархия
> классов в стиле подхода *"по классу на фигуру"* просто разлетается.
Почему? Преобразования замечательно делаются в таком подходе — мы просто
выделяем трансформаторы в отдельную иерархию.

> Жаль, если это *Вам* непонятно. Возможно, *Вам* имеет смысл

> посопровождать ряд графических редакторов, написанных в стиле "по классу
> на фигуру" и, так сказать, воочию убедиться в ошибочности данного подхода.
Кхм. Именно сейчас это и делаю — ошибочности подхода пока не вижу.

У меня сделано так:
1. Базовый класс (точнее интерфейс) IWidget имеет методы для проверки
попадания, передвижения, вращения и описания регионов (то есть областей,
которые объект может закрывать) объекта.
2. У IWidget'а есть наследники IConnectorWidget, ITextWidget...
3. Есть специальный интерфейс ICompositeWidget, позволяющий задавать
виджеты, состоящие из нескольких дочерних виджетов.
4. Есть конкретные потомки ICustomDrawWidget (с потомком IActiveXWidget)
и т.п.

Для трансформации используется механизм FOURCC (Four-Character Code) —
каждый виджет экспортирует набор FOURCC в которые он может превращаться,
и у каждого типа виджетов есть свой FOURCC. Если мне нужно преобразовать
один тип в другой — то трансформатор просто смотрит можно ли построить
цепочку преобразований из одного FOURCC в другой.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[13]: Параллельная иерархия классов
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 25.02.06 19:24
Оценка:
Здравствуйте, genre, Вы писали:

G>вот эти три класса и должны быть в иерархии классов

Возможно. А зачем их (отрезок, кривую и дугу) представлять в виде классов?
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[13]: Параллельная иерархия классов
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 25.02.06 19:40
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Но тогда у вас фигуры будут выглядеть так:

Нет, не так. Один из вариантов:
enum IPointFlag
{
   PF_MOVE,
   PF_LINE,
   PF_CURVE
};

class TFigure
{
public:

   // ...

private:

   std::vector<IPointFlag> m_Flags;
   std::vector<TPoint> m_Points;
};

Код рисования фигуры на устройстве будет выглядеть так:
size_t i = 0;

while (i < m_Points.size())
{
   switch (m_Flags[i])
   {
      case PF_MOVE:
         dc.MoveTo(m_Points[i]);
         i++;
         break;
      case PF_LINE:
         dc.LineTo(m_Points[i]);
         i++;
         break;
      case PF_CURVE:
         ASSERT((i + 2) < m_Points.size());
         dc.CurveTo(m_Points[i], m_Points[i + 1], m_Points[i + 2]);
         i += 3;
         break;
   }
}


C>То есть даже в прямоугольнике будут ненужные описания кривых.

Как видите, не будет.

C>Далее, рисование окружности/эллипса происходит в десятки раз быстрее,

C>чем рисование кривых Безье. А значит для нормальной скорости нам нужно
C>добавить в фигуру еще и набор эллипсов:
Глифы TrueType и Type1 шрифтов представляют собой комбинацию отрезков прямых линий и кривых Безье. Как видите, выводятся нормально — не тормозят.

Алгоритм же рисования повернутого эллипса, который я вычитал в одной из "умных" книжек, настолько непростой и глючный, что — ей богу — проще использовать кривые Безье. Собственно говоря, профессиональные пакеты для создания векторной графики так и поступают. То же Corel Draw.

C>А ведь в фигуре еще может содержаться текст! Или фигура может состоять

C>из композиции нескольких фигур.
Я не случайно обратил Ваше внимание на язык PostScript. Там эта проблема уже решена.

C>Например, как в вашем случае будет выглядеть изменение радиуса окружности?

Очень просто. Я пересчитаю точки фигуры точно так же, как если бы это был полигон.
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[9]: Параллельная иерархия классов
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 25.02.06 19:50
Оценка: +1
Здравствуйте, Cyberax, Вы писали:

C>Ага, одним классом с баааальшим switch'ем.

Откуда Вы взяли огромный switch?

C>Почему? Преобразования замечательно делаются в таком подходе — мы просто

C>выделяем трансформаторы в отдельную иерархию.
Я говорил о двух вещах:
1) О том, что иерархия начинает разрастаться, и ее трудно сопровождать. Согласитесь, 115 классов — это уже перебор.
2) О том, что фигуры становится трудно трансформировать. Как пример, Вам нужно сделать скос эллипса или прямоугольника. Если Вы задаете эллипс при помощи rect'а (левая верхняя и правая нижняя точки), то скос без создания новой фигуры (например, полигона) Вам будет сделать сложно.

C>Кхм. Именно сейчас это и делаю — ошибочности подхода пока не вижу.

Вам приходится:
1) писать класс для каждой фигуры;
2) писать иерархию классов для преобразования фигур.

На мой взгляд, это трудоемко да и не нужно. Понятно, что у Вас может быть другое мнение.
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[14]: Параллельная иерархия классов
От: genre Россия  
Дата: 25.02.06 20:44
Оценка:
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>Здравствуйте, genre, Вы писали:


G>>вот эти три класса и должны быть в иерархии классов

КЛ>Возможно. А зачем их (отрезок, кривую и дугу) представлять в виде классов?
а что б switch-ей не писать на каждый чих.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[10]: Параллельная иерархия классов
От: genre Россия  
Дата: 25.02.06 20:44
Оценка:
Здравствуйте, Кирилл Лебедев, Вы писали:


C>>Кхм. Именно сейчас это и делаю — ошибочности подхода пока не вижу.

КЛ>Вам приходится:
КЛ>1) писать класс для каждой фигуры;
КЛ>2) писать иерархию классов для преобразования фигур.

КЛ>На мой взгляд, это трудоемко да и не нужно. Понятно, что у Вас может быть другое мнение.

Выскажу свое мнение. В один класс все запихивать действительно не надо.
И Делать развесистую иерархию тоже не стоит.
Надо разделить действительно разные сущности, например полигоны, и кривые безье. у иж из них делать иерархию, в итоге она получится маленькая и по делу.
А еще лучше как-то так(упрощенно):
class Element{
virtual void Draw()=0;
}

class Polygon:public Draw{
...
}
class Figure{
...
std::vector<Element*> elements;
}

вот собственно Figure и будет самой фигурой, которая агрегирует в себе различные элементы.
но вообще все сильно зависит от задачи.
требования эффективности могут накладывать свои ограничения.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[15]: Параллельная иерархия классов
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 25.02.06 21:56
Оценка:
Здравствуйте, genre, Вы писали:

G>а что б switch-ей не писать на каждый чих.

Какие конкретно switches Вы хотите убрать этой иерархией?
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[11]: Параллельная иерархия классов
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 25.02.06 22:00
Оценка:
Здравствуйте, genre, Вы писали:

G>Надо разделить действительно разные сущности, например полигоны, и кривые безье.

Можно спросить: почему Вы решили, что полигоны и кривые Безье — это разные сущности? (Вопрос серьезный.)
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[4]: Параллельная иерархия классов
От: remark Россия http://www.1024cores.net/
Дата: 25.02.06 22:26
Оценка: :)
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>Здравствуйте, SleepyDrago, Вы писали:


SD>>Было бы интересно увидеть развитие ваших идей до интерфейса исходя из базового примера фигур круг/квадрат и 2х устройств просмотра.

КЛ>Как ни странно, круг и квадрат — это не две разных фигуры, а одна. Т.е. иерархия классов в стиле:
КЛ>
КЛ>// Базовый класс фигуры.
КЛ>class TFigure {...};

КЛ>// Круг.
КЛ>class TCircle : public TFigure {...};

КЛ>// Квадрат.
КЛ>class TQuadrate : public TFigure {...};
КЛ>

КЛ>- принципиально ошибочна.


Я понял причину Вашего спора — если поглядеть на название данного форума, то Вы находитесь по разные стороны от "/"



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[16]: Параллельная иерархия классов
От: genre Россия  
Дата: 25.02.06 23:02
Оценка:
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>Здравствуйте, genre, Вы писали:


G>>а что б switch-ей не писать на каждый чих.

КЛ>Какие конкретно switches Вы хотите убрать этой иерархией?
Re[13]: Параллельная иерархия классов
Автор: Кирилл Лебедев
Дата: 25.02.06
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[12]: Параллельная иерархия классов
От: genre Россия  
Дата: 25.02.06 23:02
Оценка: :)
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>Здравствуйте, genre, Вы писали:


G>>Надо разделить действительно разные сущности, например полигоны, и кривые безье.

КЛ>Можно спросить: почему Вы решили, что полигоны и кривые Безье — это разные сущности? (Вопрос серьезный.)
да я не решал
в каком-то из сообщений треда так было разделено я и написал что в голову первое пришло.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[14]: Параллельная иерархия классов
От: Cyberax Марс  
Дата: 26.02.06 03:45
Оценка: +1
Кирилл Лебедев wrote:
> Код рисования фигуры на устройстве будет выглядеть так:
Вы прямо цитируете пример из учебника как НЕ надо писать код и для чего
был придуман полиморфизм. Вы это специально?

> C>Далее, рисование окружности/эллипса происходит в десятки раз быстрее,

> C>чем рисование кривых Безье. А значит для нормальной скорости нам нужно
> C>добавить в фигуру еще и набор эллипсов:
> Глифы TrueType и Type1 шрифтов представляют собой комбинацию отрезков
> прямых линий и кривых Безье. Как видите, выводятся нормально — не тормозят.
Простите, я знаю что говорю. Тот же GDI рисует окружности _намного_
быстрее кривых Безье. Хотя бы из-за того, что не всегда нормально
работает аппаратное ускорение для кривых Безье.

> Алгоритм же рисования повернутого эллипса, который я вычитал в одной из

> "умных" книжек, настолько непростой и глючный, что — ей богу — проще
> использовать кривые Безье. Собственно говоря, профессиональные пакеты
> для создания векторной графики так и поступают. То же Corel Draw.
Вы знаете внутренности CD?

> C>А ведь в фигуре еще может содержаться текст! Или фигура может состоять

> C>из композиции нескольких фигур.
> Я не случайно обратил Ваше внимание на язык PostScript. Там эта проблема
> уже решена.
Еще раз. PS, PDF, bitmap — это конечные _представления_. Они не
предоставляют нормальной поддержки для манипуляции объектами.

> C>Например, как в вашем случае будет выглядеть изменение радиуса окружности?

> Очень просто. Я пересчитаю точки фигуры точно так же, как если бы это
> был полигон.
_КАК_ вы определите какие точки принадлежат окружности?
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[10]: Параллельная иерархия классов
От: Cyberax Марс  
Дата: 26.02.06 03:51
Оценка:
Кирилл Лебедев wrote:
> C>Ага, одним классом с баааальшим switch'ем.
> Откуда Вы взяли огромный switch?
Смотрите свое другое письмо

> C>Почему? Преобразования замечательно делаются в таком подходе — мы просто

> C>выделяем трансформаторы в отдельную иерархию.
> Я говорил о двух вещах:
> 1) О том, что иерархия начинает разрастаться, и ее трудно сопровождать.
> Согласитесь, 115 классов — это уже перебор.
Всего 115 классов? Какая мелочь, у меня их за тысячу перевалило.

Вы лучше подумайте как вы метод 'Draw' со switch'ем в 115 case'ов
сопровождать будете.

> 2) О том, что фигуры становится трудно трансформировать. Как пример, Вам

> нужно сделать скос эллипса или прямоугольника.
Заданием матрицы отображения. При этом координаты точек модели не
меняются, а просто изменяется метод их перевода в глобальные координаты.
Именно так и работают все нормальные рисовальные системы, кстати.

GDI, кстати, это прямо поддерживает — смотрите метод SetWorldTransform.

> C>Кхм. Именно сейчас это и делаю — ошибочности подхода пока не вижу.

> Вам приходится:
> 1) писать класс для каждой фигуры;
Да.

> 2) писать иерархию классов для преобразования фигур.

> На мой взгляд, это *трудоемко* да и *не нужно*. Понятно, что у Вас может
> быть другое мнение.
Расскажите как это сделать правильно и проще. Я не вижу более простого
способа.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[12]: Параллельная иерархия классов
От: Cyberax Марс  
Дата: 26.02.06 03:52
Оценка:
Кирилл Лебедев wrote:
> G>Надо разделить действительно *разные* сущности, например полигоны, и
> кривые безье.
> Можно спросить: почему Вы решили, что полигоны и кривые Безье — это
> *разные сущности*? (Вопрос серьезный.)
Кривые поддерживают принципиально больше возможностей управления. И при
этом принципиально медленнее рисуются.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[17]: Параллельная иерархия классов
От: Аноним  
Дата: 26.02.06 09:15
Оценка:
Здравствуйте, genre, Вы писали:

КЛ>>Какие конкретно switches Вы хотите убрать этой иерархией?

G>Re[13]: Параллельная иерархия классов
Автор: Кирилл Лебедев
Дата: 25.02.06


1) Кроме иерархии классов существуют еще и другие способы устранения свитчей. Вы уверены, что именно этот свитч нужно устранять именно иерархией классов?

2) Вы уверены, что этот свитч нужно вообще устранять? Его размер ограничен, и он никогда не разрастется.
Re[18]: Параллельная иерархия классов
От: genre Россия  
Дата: 26.02.06 09:34
Оценка:
Здравствуйте, <Аноним>, Вы писали:


А>1) Кроме иерархии классов существуют еще и другие способы устранения свитчей. Вы уверены, что именно этот свитч нужно устранять именно иерархией классов?

ну так предложите свой способ.
А>2) Вы уверены, что этот свитч нужно вообще устранять? Его размер ограничен, и он никогда не разрастется.
его размер зависит от очень большого количества параметров.
вполне может быть что и тремя классами ограничится не получится, отличия же могут быть не только по типу фигуры.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[15]: Параллельная иерархия классов
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 26.02.06 09:35
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Вы прямо цитируете пример из учебника как НЕ надо писать код и для чего

C>был придуман полиморфизм. Вы это специально?
Полиморфизм — лишь один из инструментов организации кода, который в ряде случаев не только не полезен, но и вреден. Где-то выгоднее использовать иерархию и виртуальные функции, где-то — массив и указатели, где-то — перечисление, где-то — union, где-то — просто структуру.

Недостатки полиморфизма для данного конкретного случая я уже привел. Их привели и Вы в своем сообщении
http://www.rsdn.ru/Forum/Message.aspx?mid=1698098&amp;only=1
Автор: Cyberax
Дата: 25.02.06


Потрудитесь теперь и Вы перечислить недостатки предложенного мною решения:
http://www.rsdn.ru/Forum/Message.aspx?mid=1698542&amp;only=1
Автор: Кирилл Лебедев
Дата: 25.02.06


Сожаления о том, что там не используется полиморфизм, эмоционально понятны, но профессионально "не прокатывают".

C>Простите, я знаю что говорю. Тот же GDI рисует окружности _намного_

C>быстрее кривых Безье. Хотя бы из-за того, что не всегда нормально
C>работает аппаратное ускорение для кривых Безье.
И что с того? К чему нам такое ускорение, если оно нам не нужно? Повторюсь, глифы TrueType и Type1 шрифтов используют кривые Безье.

C>Вы знаете внутренности CD?

Мне приходилось проводить research на тему того, как лучше организовать классы фигур для редактора векторной графики.

C>Еще раз. PS, PDF, bitmap — это конечные _представления_. Они не

C>предоставляют нормальной поддержки для манипуляции объектами.

1) Bitmap упомянули Вы, а не я.
2) Что касается PS и PDF, то тут Вы ошибаетесь.

В любом случае, приведите конкретные примеры, чтобы было понятно, о чем речь.

C>_КАК_ вы определите какие точки принадлежат окружности?

Преобразую в полигон и проверю.
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[18]: Параллельная иерархия классов
От: Cyberax Марс  
Дата: 26.02.06 09:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>1) Кроме иерархии классов существуют еще и другие способы устранения свитчей. Вы уверены, что именно этот свитч нужно устранять именно иерархией классов?

Перечислите эти способы, пожалуйста, с объяснениями чем оно принципиально отличается.

Вместо полиморфизма, конечно, можно использовать объект с кучей делегатов, например. Или аналогичные извращения — смысл от этого не изменится, так как все равно останется точки использования полиморфного поведения.

А>2) Вы уверены, что этот свитч нужно вообще устранять? Его размер ограничен, и он никогда не разрастется.

Во-первых, кроме этого свитча будет еще с десяток подобных (в других методах). Во-вторых, этот свитч очень даже разрастется.

У меня моим первым детским проектом был растровый редактор на Бейсике (QuickBasic'е, а не на VisualBasic!), потом этот растровый редактор стал векторным и там был как раз такой свитч. При размере редактора в 140Кб кода на Бейсике поддерживать основную функцию рисования стало невозможно У меня там в итоге даже свой рендерер шрифтов был (шрифты сам рисовал с помощью "черепашьей графики").
Sapienti sat!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.