Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Программирование игр, графики и искусственного интеллекта > Движок для GIS системы


Автор: amarenkov 31.3.2008, 11:12
А кто-нибудь знает, на каком движке работает AutoCad? Мне необходим 2D-движок для создания подобия ГИС-системы, может кто подскажет, где искать smile?

И еще один вопрос, а из всех вышеперечисленных движков есть такие, которые могут генерировать WMF файлы сцены? Иными словами, мне необходимо результат его работы печатать, но вариант с растром не подходит.

Автор: arilou 31.3.2008, 11:56
amarenkov, AutoCAD работает на своем движке.

Добавлено через 2 минуты
а что входит в понятие "подобие ГИС-системы"? что она должна уметь делать?

Автор: amarenkov 31.3.2008, 12:26
Это программа для расчета рассеивания загрязняющих веществ. Должна позволять создавать карты из заданного набора примитивов (точка, полилиния, полигон, текст, прямоугольник, окружность и т.п.). Операции выделения примитивов, перемещения, преобразования. Операции с системами координат, масштабом. 

В данный момент основная проблема для меня - производительность. Все есть, все работает, но медленно... Я пишу на C# Net2.0 с помощью GDI+. GDI+ в основном из-за того, что теми же командами я могу создавать WMF-файлы для печати. DirectX, OpenGL и иже с ними не позволяют, на сколько я знаю, формировать файлы в каком-либо векторном виде. Сейчас производительность оптимизирую тем, что рисую в отдельном потоке и через заданные промежутки времени синхронизирую с основным потоком. При этом, понятное дело, получается так, что сцена отрисовывается не полностью, а как бы поэтапно. 

А когда смотрю на AutoCAD меня съедает черная зависть smile). У них же миллионы примитивов рисуются мгновенно... И печатается в любой формат файла, и на принтер печать идет отлично.

Вот и возник вопрос: как же они так делают? Как это у них получается smile?

Автор: arilou 31.3.2008, 16:07
Странно конечно. ИМХО, надо смотреть в сторону оптимизации путем группировки сходных объектов, и постановки их на рисование меньшим кол-вом вызовов ф-ций GDI+. 

Плюс еще -- ты рисуешь как - постоянно перерисовываешь, или только в OnPaint? У тебя всегда все примитивы рисуются, или только когда они попадают в видимую часть окна (т.е. карта всегда полностью помещается в окне?). Сколько примитивов на конвейер попадает? 

Автор: amarenkov 1.4.2008, 10:20
Цитата(arilou @  31.3.2008,  16:07 Найти цитируемый пост)
... группировки сходных объектов, и постановки их на рисование меньшим кол-вом вызовов ф-ций GDI+. 

Как это?

Поток рисует в свой Bitmap. Этот битмап отображается на OnPaint, или если поток закончил рисование, или если прошел заданный промежуток времени. Из теории построения интерфейсов отклик в 200 мс является допустимым. Таким образом у меня отрисовка сцены разбивается на промежутки времени по 200 мс. А когда поток дорисовал все - он останавливается, и на OnPaint происходит просто отрисовка битмапа потока. Если пользователь добавил объект или сместил зону видимости - все начинается сначала.

Я рисую только те примитивы, которые попадают в область видимости. Плюс к этому, если они находятся слишком далеко они рисуются либо точками, либо отрезками, либо прямоугольниками. А что именно ты подразумеваешь под "конвеером"?

С точки зрения оптимизации можно попробовать еще BSP-Tree. Но я не знаю, насколько это может ускорить работу?

У меня такое ощущение, что GDI+ сам по себе довольно медленный. То есть, набор из 1000 линий он часто не успевает отрисовать за 200 мс.

Автор: arilou 2.4.2008, 17:47
amarenkov, а ты не мог бы выложить кусок кода мегафункции, которая занимается отрисовкой примитивов?

Добавлено через 1 минуту и 51 секунду
теоретически, все это можно рисовать с помощью XNA. Только придется реализовать обертки для векторных примитивов. 

Автор: amarenkov 3.4.2008, 08:54
arilou, я могу smile. Но она вряд ли что-то разъяснит. Там все это дело поделено на несколько классов... Ну, вот, например отрисовка полилинии (привожу цепочку связанных функций):

Код

        public void DrawLines(Pen SomePen, SPointD[] Points, bool Closed)
        {
            if (Points.Length > 1)
            {
                for (int i = 1; i < Points.Length; i++)
                    DrawLine(SomePen, Points[i - 1], Points[i]);
                if (Closed) DrawLine(SomePen, Points[Points.Length - 1], Points[0]);
            }
        }

        public void DrawLine(Pen SomePen, SPointD Pd1, SPointD Pd2)
        {
            fobj_graphics.DrawLine(SomePen, fobj_viewPort.PointForDraw(Pd1), fobj_viewPort.PointForDraw(Pd2));
        }

        public PointF PointForDraw(SPointD Point)
        {
            return new PointF((float)(Point.x * fdbl_pixPerM * frec_scale.MapDReal), (float)(-Point.y * fdbl_pixPerM * frec_scale.MapDReal));
        }


То есть, здесь мои, какие-то внутренние координаты преобразуются в координаты изображения и рисуются.

Цитата(arilou @  2.4.2008,  17:47 Найти цитируемый пост)
... теоретически, все это можно рисовать с помощью XNA.


А эта ХНЯ (пардон, XNA smile) реально может сильно ускорить процесс отрисовки? Насколько процесс рисования по скорости будет отличаться от GDI+.

Автор: arilou 3.4.2008, 10:00
amarenkov, конечно ускорит! Там же 3D акселерация будет использоваться, плюс несколько уровней от API до железа напрямую обходится, за счет DirectX.

Добавлено через 1 минуту и 57 секунд
насчет кода -- покажи мегафункцию, котора разбирает список примитивов и вызывает соответствующие методы рисования, наверняка есть что-то типа

Код

void DoThePainting()
{
  for(int i=0; i<primitives.Count; i++)
  {
      Primitive p = primitives[i];
      switch(p.PrimitiveType)
          // .... etc
   }
}

Автор: amarenkov 3.4.2008, 11:40
Цитата(arilou @  3.4.2008,  10:00 Найти цитируемый пост)
3D акселерация будет использоваться


О, а чем сможет помочь 3D акселерация с двух-мерной сценой? ИМХО, она будет мешать smile.

А, вот ты о какой функции smile. Вот кусок, который крутится во втором потоке (правда еще не до конца доработанный - переносил из Delphi):

Код

                            while (fenm_drawState == EMDThreadState.edtsDrawing && !End)
                            {
                                fobj_mutex.WaitOne();

                                if (iLayer < List.Count)
                                {
                                    if (List[iLayer] is CLayerGroup)
                                    {
                                        foreach (CLayerHierarchic Layer in (List[iLayer] as CLayerGroup))
                                            List.Add(Layer);
                                        iLayer++;
                                    }
                                    else if (List[iLayer] is CLayerFigures)
                                    {
                                        if (iFigures < (List[iLayer] as CLayerFigures).Count)
                                        {
                                            fobj_graph.DrawFigure((List[iLayer] as CLayerFigures)[iFigures]);
                                            iFigures++;
                                        }
                                        else
                                        {
                                            iFigures = 0;
                                            iLayer++;
                                        }
                                    }
                                    else iLayer++;
                                }
                                else End = true;

                                fobj_mutex.ReleaseMutex();
                            }


А вот функция, которую он вызывает для каждой фигуры:

Код

        public void DrawFigure(CFigure Figure)
        {
            if (frec_mapRect.Crosses(Figure.frec_border) && (Figure.fenm_state != EFigureState.efsDeleted) && (Figure.fobj_content != null))
            {
                if (Figure.fenm_state == EFigureState.efsSelected)
                {
                    fbol_drawingSelected = true;
                    fobj_currentPen = fobj_selectPen;
                    fobj_currentBrush = fobj_selectBrush;
                }
                else
                {
                    fbol_drawingSelected = false;
                    fobj_currentPen = fobj_layerPen;
                    fobj_currentBrush = fobj_layerBrush;
                }

                switch (Figure.fenm_type)
                {
                    case EFigureType.eftPoint: DrawPoint((CPoint)Figure.fobj_content); break;
                    case EFigureType.eftPlot: DrawPlot((CPlot)Figure.fobj_content); break;
                    case EFigureType.eftPolygon: DrawPolygon((CPolygon)Figure.fobj_content); break;
                    case EFigureType.eftPolyline: DrawPolyline((CPolyline)Figure.fobj_content); break;
                    case EFigureType.eftRect: DrawRect((CRect)Figure.fobj_content); break;
                    case EFigureType.eftText: DrawText((CText)Figure.fobj_content); break;
                }
            }
        }

Автор: arilou 3.4.2008, 13:51
Цитата(amarenkov @  3.4.2008,  11:40 Найти цитируемый пост)
О, а чем сможет помочь 3D акселерация с двух-мерной сценой? ИМХО, она будет мешать

как раз наоборот. просто ты будешь рисовать в проекции "сверху-вниз".

судя по всему, это будет наиболее предпочтительный вариант по производительности. 

Автор: addnr 27.6.2008, 12:38
http://www.esti-map.ru/Программы/MapInfo/MapInfoMapXtreme/tabid/66/Default.aspx

может тебе помоч

Автор: amarenkov 16.7.2008, 12:46
Спасибо, addnr, MapInfo я знаю, но это не то smile. Проблема состояла в том, на чем мне писать свою ГИС. Мне нужен был либо движок (самый-самый простой - сложное я сам бы наворотил), либо такая технология, которая удовлетворяла все мои потребности (построение полигонов с дырками, печать результата в WMF и т.п.). MapInfo, инъекции AutoCad'a и т.п. не подходят smile.

Автор: QryStaL 17.7.2008, 14:08
WPF ?

Автор: amarenkov 23.7.2008, 08:44
QryStaL, WPF не очень подходит, потому как это в корне иная технология. Это весь интерфейс на нее пересаживать надо. А у меня есть только панель (ну или что-то типа), на которой я должен выполнять свои задачи. Плюс, оно медленнее обычного DirectX (читал разные обзоры).

Автор: inkognitum 24.7.2008, 13:41
Добрый день, amarenkov.

В данный момент я занимаюсь написанием GIS движка.

Я сам не обладаю достаточным знанием чтобы использовать технологии OpenGL или D3D, но написанную объектную модель можно легко переписать под данные технологии. В данный момент я использую GDI+, могу дать несколько советов как можно ускорить работу.

Для начала я всю карту разбиваю на регионы (прямоугольники), и к каждому прямоугольнику принадлежит его список объектов. если весь прямоугольник попадаетя в поле видимости пользователя то рисуем все что находится в этом прямоугольнике, иначе пропускаем.. таким образом можно урезать большую часть карты и не пробегать ее.

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

и такими способами можно значительно ускорить вывод графических элементов.

Желаю удачи.

Автор: amarenkov 29.7.2008, 13:21
Спасибо, inkognitum, я уже делаю все Вами перечисленное и еще много другое smile). Плюс к этому я еще и рисую в отдельном потоке, чтобы у пользователя не было ощущения торможения интерфейса. 

И все равно мне не нравится производительность. А больше всего не нравится ощущение, что я делаю велосипеды из материала, для этого не предназначенного smile

Автор: inkognitum 29.7.2008, 18:22
Цитата(amarenkov @ 29.7.2008,  13:21)
Спасибо, inkognitum, я уже делаю все Вами перечисленное и еще много другое smile). Плюс к этому я еще и рисую в отдельном потоке, чтобы у пользователя не было ощущения торможения интерфейса. 

И все равно мне не нравится производительность. А больше всего не нравится ощущение, что я делаю велосипеды из материала, для этого не предназначенного smile

Прекрасно понимаю Вас.

И по этому советую изучать OpenGL и переводить вашу программу именно на этот движок.
Я имено так и собираюсь постпать, я знаю что всеми данными ухищрениями далеко не уедишь.

Автор: inkognitum 18.8.2008, 20:59
<b>amarenkov</b>, если тема еще актуальна.

Я добился довольно хороших результатов используя OpenGL.
Я слегонца дописал свою объектную модель и стал выводить карту в OpenGL, скорость увеличилась более чем в 17 раз (!), исчезли лаги и временные задержки. Я эксперементировал над картой (55000 на 35000 пкселей), на ней было более 40000 объектов и порядка 1 мил. точек. Но это не предел. просто у меня нет карты больше. И у меня все летает.

И ксведенью на все это у меня понадобилось 3 суток. До этого с ОпенГЛ не работал.
Так что имеет смысл копать именно в эту сторону.

Автор: mrgloom 15.6.2011, 17:22
Можете поделиться примером как оптимизировать вывод на OpenGL?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)