SAS.NEXT - FMX version of SAS.Planet

Форум для обсуждения деталей разработки программы SAS.Планета

Модераторы: vdemidov, Tolik

SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 24 мар 2017, 02:04

Попытка, как говорится, не пытка. А почему бы и нет? Давайте поиграем в кросс-платформенность. Представляю первую версию FMX движка для отображения тайлов из кэша SAS.Планета.
Прямая работа со слоями, полигонами, рисунками в FMX может очень пригодиться.

Теперь на вопрос "как отобразить карту в моей программе?" можно ответить : А вот так....

Вскоре проект поселится на облаке, а пока код под катом, (он совсем небольшой, около 110 кб).
Для сборки использовалась студия Берлин Upd2.

Всем разработчикам, думаю, будет интересно посмотреть. В программе нет ни одной операции "отрисовки" (по канвасу и графическому дескриптору). Загрузили рисунки внужные места , и указали им Parent = Layer. Остальное на себя берет 3D рендерер.

Длина кода менее 50 кб...Компонент изображения - еще 30кб, остальное мусор.

23.03.2017. Версия API 0.01a. Первая стабильная альфа-версия без серьезных утечек памяти.

24.03.2017.Версия API 0.02a.
Исправлена ошибка с рандомным пропуском тайлов. FMX, как и ее предшественница VCL, враждебна не только к отрисовке графики в потоке, но и к загрузке графики в потоке. Внутренний формат загрузки заменен на TMemoryStream.

27.03.2017.Версия API 0.03a.
Код программы был разбит на несколько малюсеньких юнитов, убраны кросс-зависимости.
Приведены в порядок относительные координаты слоев карт.

28.03.2017.Версия API 0.04a.
Позиция тайлов приведена к центру экрана. Вместо миллионных координат теперь довольно маленькие. Горизонтальные артефакты яндекс-проекции заметно поубавились. 23 бит одинарной точности не хватало. Постоянное приведение к центру экрана привело к тому, что число отрисовок заметно увеличилось.
На основе исходного кода FMX был создан компонент TNVAbstractLayer3D , в котором отсутствуют округления до целых координат, и наследник TNVImage3D. Артефакты исчезли совсем.

28.03.2017.Версия API 0.05a.
Переключение масштаба колесом мыши сохраняет точку карты под мышью.
Для каждого из объектов на карте можно задать свое изображение. Размер его на карте пока будет фиксированный.
Введен режим следования центра экрана за любым из объектов (пока без поворота).
Приведение карты к центру экрана позволило пользоваться поворотом карты на произвольный угол.
Введена возможность отображать дробный масштаб. Переключение слоя осуществляется на точке Z с половиной. (соответствует тайлу Z, увеличенному в корень из 2 раз и тайлам z+1 уменьшенным в корень из 2 раз).
Вложения
sas.fmx.jpg
Последний раз редактировалось DJ VK 29 мар 2017, 11:13, всего редактировалось 2 раз(а).
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 29 мар 2017, 02:49

Структура этой минималистской программки.

1. unit TNVMapper
+ Работа с API

скрытый текст: показать
TNV_FIELDS = 256; Поля тоже загружаемой невидимой за пределами экрана области.
TNV_LAYERSIZE = 256; Размер слоя. Виртуальная величина. На отображение 3d объектов не влияет, только на 2d.
TNV_UpdateMode = (umNoUpdate, umShiftUpdate, umPosUpdate, umFullUpdate); Режим требуемого обновления карты:нет, только сдвиг, установка произвольной позиции, полное перепроецирование


TNV_Mapper = class(TObject) основной объект api карты

FMaps: TThreadList<TNV_TileMap>; Защищенный список карт
FObjects: TThreadList<TNV_MapObject>; Защищенный список объектов на карте.
FProjection: TNV_MapProjection; Базовая проекция, в которой будут отрисовываться (по мере загрузки их тайлов) все без исключения карты.
FAbsScreen: TNV_ScreenCoord; Описание координат экрана и масштабов.
FCachePath: string; Путь к кэшу с картами.
FFollowObjIndex: Integer; Индекс объекта для отслеживания.
VP: TViewport3D; Указатель на 3d вьюпорт
Layer: TLayer3D; Общий слой на вьюпорте, на который складываются последовательно все слои карт. (здесь и далее слой - это не "слои" из сас.планета, это карта любого типа)
ObjLayer: TLayer3D; Слой для отрисовки объектов.
VPCenter: TPointF; Координаты центра вьюпорта
FFields: Single; Поля невидимой области
FInitFlag: Boolean; Флаг инициализации
FUpdateFlag: TNV_UpdateMode; Флаг обновления карты
FObjUpdateFlag: Boolean; Флаг обновления объектов на карте.

constructor Create(CachePath: string); Конструктор с параметром - путь к кэшу

procedure AddMap(MapDesk: TNV_MapDeskPtr); добавление карты. Параметр - описание карты.
procedure SetMapOpacity(Index: Integer; Opacity: Single); Установка прозрачности карты. В динамике не проверялось
procedure SetMapVisible(Index: Integer; Visible: Boolean); Установка видимости слоя карты. В динамике не проверялось
function GetMapsCount: Integer; Число добавленных карт (слоев)
function GetMapOpacity(Index: Integer): Single; Прозрачность слоя
function GetMapVisible(Index: Integer): Boolean; Видимость слоя

procedure AddObject(FileName: string); Добавление объекта параметр - его изображение
function GetObjectsCount: Integer; Число объектов.
procedure SetObjectLatLatLonAng(Index: Integer; Lat, Lon, Angle: Double); установка позиции объекта на карте и его ориентации.
procedure FollowObject(Index: Integer); Следовать за объектом или не следовать (если -1)

procedure SetViewport(Viewport: TViewport3D); Установка внешнего вьюпорта
procedure SetProjection(ProjKind: TNV_MapProj; TileSize: TNV_TileSize; Subtiles: TNV_Subtiles); Выбор проекции для отрисовки карт. Можно задать любую, тайлы масштабируемые.
procedure SetLatLon(Lat, Lon: Double); Установка позиции карты.
procedure SetScale(Z, DX, DY: Double); Измениение и установка масштаба + расстояние от точки масштабирования до центра экрана в пикселах.
procedure MoveMap(DX, DY: Single); Сдвиг карты на заданное число пикселов (плюсы: вправо вниз)
procedure SetRotationAngle(Angle: Single); Повернуть карту по азимуту.
procedure Proc; Обработать текущие изменения. Работает с визуальными объектами. Вызывать из основной формы (таймером).
end;

Работа с API

Код: Выделить всё
//---------------------------------------------------------------------------
__fastcall TMapViewer::TMapViewer(TComponent* Owner)
   : TForm(Owner)
{
TNV_MapDesk* MapDesk;
Mapper = new TNV_Mapper("d:\\SatMap");  // путь к кэшу
InitDone = false;

int P = 0;   //выбор проекции
if(P == 0) Mapper->SetProjection(prjMerkOnSph, ts256, SimpleTiles);   
else Mapper->SetProjection(prjMerkOnEll, ts256, SimpleTiles);

//добавление карт
   MapDesk = new TNV_MapDesk;
   MapDesk->SetName("Yandex Hybrid");  //название слоя
   MapDesk->SetFileInfo("yahyb", "", ctTiles, extPng);//папка в кэше
   MapDesk->SetProjection(prjMerkOnEll, ts256, SimpleTiles); //проекция
   MapDesk->SetOpacity(1.0); //непрозрачность
   MapDesk->SetVisible(True); //видимость
   Mapper->AddMap(MapDesk);

   MapDesk = new TNV_MapDesk;
   MapDesk->SetName("Google Satellite");
   MapDesk->SetFileInfo("sat", "", ctTiles, extJpg);
   MapDesk->SetProjection(prjMerkOnSph, ts256, SimpleTiles);
   MapDesk->SetOpacity(1.0);
   MapDesk->SetVisible(True);
   Mapper->AddMap(MapDesk);

   MapDesk = new TNV_MapDesk;
   MapDesk->SetName("Terraserver");
   MapDesk->SetFileInfo("Terraserver", "", ctTiles, extJpg);
   MapDesk->SetProjection(prjMerkOnSph, ts256, SimpleTiles);
   MapDesk->SetOpacity(1.0);
   MapDesk->SetVisible(True);
   Mapper->AddMap(MapDesk);

   
//Добавление объекта
Mapper->AddObject("Cursor.png");
Mapper->SetObjectLatLatLonAng(0, 55.746, 37.977, 0.0);
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::FormDestroy(TObject *Sender)
{
  Timer1->Enabled = false;
   delete Mapper;
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::FormShow(TObject *Sender)
{
   Mapper->SetScale(Z, 0.0, 0.0);            //установка масштаба
   Mapper->SetViewport(VP);                  //установка родительского вьюпорта (должен лежать где-то на форме)
   Mapper->SetLatLon(Lat, Lon);             //установка позиции
   InitDone = true;
   Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::Timer1Timer(TObject *Sender)
{
   Timer1->Enabled = false;
   Mapper->Proc();                  //вызов обновления
   Timer1->Enabled = true;
}


Движение карты мышью
Код: Выделить всё
//---------------------------------------------------------------------------
void __fastcall TMapViewer::VPMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, float X, float Y)
{
   PrevX = X;
   PrevY = Y;
   Moving = true;
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::VPMouseMove(TObject *Sender, TShiftState Shift, float X, float Y)
{
   MouseX = X;
   MouseY = Y;
   if(!Moving) return;
   Mapper->MoveMap(X-PrevX, Y-PrevY);
   PrevX = X;
   PrevY = Y;
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::VPMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, float X, float Y)
{
   if(!Moving) return;
   Mapper->MoveMap(X-PrevX, Y-PrevY);
   Moving = false;
}


Перемещение карты на заданную величину
Код: Выделить всё
//---------------------------------------------------------------------------
void __fastcall TMapViewer::Button1Click(TObject *Sender)
{
   Mapper->MoveMap(0, Step->Value);
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::Button4Click(TObject *Sender)
{
   Mapper->MoveMap(0, -Step->Value);
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::Button3Click(TObject *Sender)
{
   Mapper->MoveMap(-Step->Value, 0);
}
//---------------------------------------------------------------------------
void __fastcall TMapViewer::Button2Click(TObject *Sender)
{
   Mapper->MoveMap(Step->Value, 0);
}


Установка позиции
Код: Выделить всё
Mapper->SetLatLon(Lat, Lon);


Переключение масштабов
Код: Выделить всё
void __fastcall TMapViewer::ZmChange(TObject *Sender)
{
   if(!InitDone) return;
   if(MouseZoom) return;
   Z = Zm->Value;
   Mapper->SetScale(Z, 0, 0);
}


Масштабирование колесом мыши
Код: Выделить всё
//---------------------------------------------------------------------------
void __fastcall TMapViewer::VPMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, bool &Handled)
{
   Double Dx, Dy;
   MouseZoom = true;
   if(WheelDelta == 0) return;
   if(WheelDelta > 0)
   {
      Zm->Value = Zm->Value - 0.25;
   }
   else
   {
      Zm->Value = Zm->Value + 0.25;
   }
   MouseZoom = false;
   Dx = MouseX - VP->Width / 2;
   Dy = MouseY - VP->Height / 2;
   Mapper->SetScale(Zm->Value, Dx, Dy);
}


Поворот
Код: Выделить всё
//---------------------------------------------------------------------------
void __fastcall TMapViewer::AngChange(TObject *Sender)
{
   if(!InitDone) return;
   Mapper->SetRotationAngle(Ang->Value);
}
Вложения
Mapper3D.rar
(106.98 KiB) Скачиваний: 85
Последний раз редактировалось DJ VK 29 мар 2017, 11:14, всего редактировалось 5 раз(а).
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 29 мар 2017, 02:52

2. unit TNVMapObject
Движущийся или неподвижный объект на карте.
скрытый текст: показать
Код: Выделить всё

  TNV_MapObject  класс объекта
      FObjLayer: TLayer3D; указатель на слой объектов
      AbsX: Double; Долгота
      AbsY: Double; Широта
      FAngle: Double; Азимут
      FImg: TImage3D; Изображение

      constructor Create(ObjLayer: TLayer3D; FileName: string); создание объекта. Указатель на слой и полное имя файла изображения
      destructor Destroy; override; разрушение объекта

      procedure SetLatLonAng(Lat, Lon, Angle: Double); установка широты, долготы и азимута
      procedure DrawObject(AbsScreen: TNV_ScreenCoordPtr; BaseProj: TNV_MapProjectionPtr); рисование объекта. необходимо указать координаты центра экрана  с маштабами и проекцию вывода карт.


3. unit TNVTileMap
Карта

скрытый текст: показать
Код: Выделить всё

  TNV_LAYERSIZE = 256; Размер слоя каждой карты.

  TNV_TileMap  класс карты
      FMapDesk: TNV_MapDesk; описание карты
      FLoaderThread: TNV_TileLoader; Поток загрузки
      FLoadedQueue: TNV_TileQueue; Очередь для передачи загруженных тайлов в кэш.
      FCache: TNV_TileCache; Кэш загруженных тайлов
      FBaseProj: TNV_MapProjectionPtr; Указатель на проекцию вывода карт. Карта рисуется на своем слое не в своей проекции, а в общей.
      FAbsScreen: TNV_ScreenCoordPtr; Описание координат экрана и масштабов
      Layer: TLayer3D; Слой карты. Является дочерним по отношению к базовому слою класса TNV_Mapper

      constructor Create(Desk: TNV_MapDeskPtr; CachePath: string; BaseLayer: TLayer3D); создание карты. Параметры - описание, общий путь к кэшу, указатель на базовый слой
      destructor Destroy; override; разрушение карты

      function GetMapDesk: TNV_MapDeskPtr; получение указателя на описание карты
      procedure SetCacheSize(ScreenTiles, ScreenCounts, EmptyAge: Integer); Установка размера кэша. Параметры: максимальное количество тайлов на экране включая невидимые поля, количество экранов, возраст старения.
каждое обновление экрана увеличивает возраст тайлов выпавших за пределы экрана невидимых полей. По достижении указанного возраста тайлы удаляются из кэша.
      procedure ProcMap(AbsScreen: TNV_ScreenCoordPtr; BaseProj: TNV_MapProjectionPtr);    Процедура обновления данной карты. Вызывается извне. может быть указано только описание экрана (BaseProj = nil, если не требуется перепроецирование). Вычисляет новый прямоугольник тайлов, делает отрисовку и увеличивает возраст устаревших тайлов. Составляет список тайлов на загрузку. Затем Удаляет устаревшие тайлы по возрасту. Разбирает полученные тайлы из очереди и отрисовывает.
      procedure ProcMap;                                                                 Обработка карты без обновления позиции. Разбирает полученные тайлы из очереди и отрисовывает.


4. unit TNVMapDesk

Описания карт sas.

скрытый текст: показать
Код: Выделить всё

  TNV_MapProj = (prjLanLot, prjMerkOnSph, prjMerkOnEll); Тип проекции
  TNV_MapCacheType = (ctTiles, ctBinary); тип кэша карты. Пока поддержаны тайлы sas.планета. Планируется поддержка бинарных файлов sas4android.
  TNV_TileFileExt = (extJpg, extPng); расширение тайлов
  TNV_Subtiles = (SimpleTiles, HalfTiles, QuarterTiles); позволяет раздробить тайл на миниатюрные подтайлы с соответствующим увеличением порядковой нумерации. Число тайлов на том же масштабе увеличивается в 1,2 или 4 раза.
  TNV_TileSize = (ts512, ts256, ts128, ts64); размер тайла данной карты (без учета подтайлов). Косвенно задает длину в пикселах для каждого масштаба

  TNV_TileCoord  прямоугольник координат двойной точности.

  TNV_ScreenCoord  координаты экрана
    Left: Double;      прямоугольник краев экрана включая невидимые поля в абсолютных координатах
     Right: Double;
    Top: Double;
     Bottom: Double;
     CenterX: Double; центр экрана в абсолютных координатах
     CenterY: Double;
    CenterRelX: Double; центр экрана в относительных координатах проекции вывода.
     CenterRelY: Double;
    CenterRelShiftX: Double; сдвиг центра экрана в относительных координатах
     CenterRelShiftY: Double;
    Scale: Double; масштаб дробный
    Zoom: Byte; масштаб целый. загружаемый слой тайлов.
    ScaleCoef: Double; коэффициент масштабирования

  TNV_ScreenCoordPtr указатель на координаты экарана

  TNV_MapFileInfo  Описание кэша карты
    Path: string;   папка карты в кэше
     Prefix: string; префикс бинарных файлов в папке карты
     CacheType: TNV_MapCacheType; тип кэша карты
     Extention: TNV_TileFileExt; расширение файлов

  TNV_MapProjection  описание     проекции карты
Kind: TNV_MapProj; тип проекции
     Subtiles: TNV_Subtiles; дробные подтайлы.
     TileSize: TNV_TileSize; размер тайла.
    function MapTileSize: Integer; получение размера тайла
    function TileRealSize: Integer; размер тайла с учетом подтайлов
    function TilesCount(Zoom: Byte): Integer; количество тайлов без учета подтайлов
    function ConvAbs2ProjX(Value: Double; Zoom: Byte): Double; конвертирование широты из абсолютной в относительную данной проекции
    function ConvAbs2ProjY(Value: Double; Zoom: Byte): Double; конвертирование широты из относительной (для данной проекции) в абсолютную
    function ConvProj2AbsX(Value: Double; Zoom: Byte): Double; конвертирование долготы из абсолютной в относительную данной проекции
    function ConvProj2AbsY(Value: Double; Zoom: Byte): Double; конвертирование долготы из относительной (для данной проекции) в абсолютную

  TNV_MapProjectionPtr указатель на проекцию карты

  TNV_MapDesk  Описание карты
      FName: string;  Название карты
      FFileInfo: TNV_MapFileInfo;  Описание кэша карты
      FProjection: TNV_MapProjection; описание исходной проекции карты
      FOpacity: Single; Непрозрачность
      FVisible: Boolean; Видимость
      procedure SetName(AName: string); Установка названия
      procedure SetFileInfo(Path, Prefix: string; CacheType: TNV_MapCacheType; Extention: TNV_TileFileExt); установка кэша
      procedure SetProjection(ProjKind: TNV_MapProj; TileSize: TNV_TileSize; Subtiles: TNV_Subtiles); установка проекции
      procedure SetOpacity(Opacity: Single); установка непрозрачности
      procedure SetVisible(Visible: Boolean); установка видимости

  TNV_MapDeskPtr указатель на описание

Последний раз редактировалось DJ VK 29 мар 2017, 10:38, всего редактировалось 3 раз(а).
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 29 мар 2017, 03:02

5. unit TNVTileLoader
Загрузчик тайлов с диска. Работает в своем потоке.

скрытый текст: показать
Код: Выделить всё
  TNV_LoaderState = (ldrIdle, ldrProc); состояние загрузчика (отдыхаем, работаем)

  TNV_TileLoader = class(TThread) класс потока загрузчика
      FCachePath: string; путь к кэшу
      FMapDesk: TNV_MapDeskPtr; указатель на описание карты
      FLoadedTiles: TNV_TileQueue; указатель на очередь принятых тайлов
      FCurrentTask: TNV_TileList; выполняемая задача загрузки
      FNewTask: TNV_TileList; новая задача загрузки

      FUpdateFlag: Boolean; флаг присутствия новой задачи
      FState: TNV_LoaderState; состояние загрузчика
      FLock: TObject; объект потокозащищенной блокировки
      FTileIndex: Integer; номер получаемого тайла в задаче

      procedure Execute; тело потока

      constructor Create(MapDesk: TNV_MapDeskPtr; CachePath: string; LoadedTiles: TNV_TileQueue); создание. Праметры - указатель на описание карты, путь к кэшу, указатель на очередь приема

      procedure LoadBinaryIndex; загрузка бинарного индекса. (to do)
      procedure AddNewTask(NewTask: TNV_TileList); Добавление задачи на загрузку. Параметр - указатель на задачу
      procedure TestForNewTask; проверка на наличие новой задачи
      procedure StopCurrentTask; остановка текущей задачи.
      procedure LoadTile; загрузка текущего тайла



6. unit TNVTileCache
Кэш для хранения загруженных тайлов

скрытый текст: показать
Код: Выделить всё
  TNVImage3D = TNV_Image3D; приведение типа

  TNV_TileCache = class(TObject)  класс кэша карты
      FTileList: array of TNV_Tile; массив тайлов
      FCacheSize: Integer; размер массива
      FEmptyAge: Integer; возраст удаления
      FLock: TObject; объект потокозащищенной блокировки
      FSpiralIterator: Boolean; перебор тайлов короедом или слева направо
      procedure DrawTile(Tile: TNV_TilePtr; MapDesk: TNV_MapDeskPtr; MapLayer: TLayer3D;
                        AbsScreen: TNV_ScreenCoordPtr;BaseProj: TNV_MapProjectionPtr); отрисовка тайла из кеша(Параметры: указатель на тайл, на описание карты, на слой карты, на координаты экрана и проекцию вывода карты)
      procedure HideTile(Tile: TNV_TilePtr); скрытие невидимого тайла.
      procedure Clear; очистка кэша
      procedure SetCacheSize(ScreenTiles, ScreenCounts, EmptyAge: Integer); установка размера кэша.
      function GetCacheSize: Integer; получить размер кэша
      procedure UpdateTileList(MapRect: TRect; MapCenter: TPoint; LoadingTask: TNV_TileList; MapDesk: TNV_MapDeskPtr;
            MapLayer: TLayer3D; AbsScreen: TNV_ScreenCoordPtr; BaseProj: TNV_MapProjectionPtr); обновление списка тайлов для новой позиции экрана
                      (Параметры: Прямоугольник тайлов, центральный тайл, указатели на задачу загрузки, на описание карты, на слой карты, на координаты экрана и проекцию вывода карты)
      procedure EmptyOldTiles; удаление устаревших тайлов по возрасту
      procedure AddLoadedTiles(LoadedTiles: TNV_TileQueue; MapDesk: TNV_MapDeskPtr; MapLayer: TLayer3D;
                              AbsScreen: TNV_ScreenCoordPtr; BaseProj: TNV_MapProjectionPtr); обработка полученных тайлов (добавление в кэш и отрисовка через установку родителя)
                            (Параметры: указатель на очередь тайлов, на описание карты, на слой карты, на координаты экрана и проекцию вывода карты)
Последний раз редактировалось DJ VK 29 мар 2017, 11:11, всего редактировалось 3 раз(а).
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 29 мар 2017, 03:05

7. unit TNVTileDesk
Описание тайла для составления списка загрузки.

скрытый текст: показать
TNV_TileDesk Описание тайла
X: Integer; индекс x
Y: Integer; индекс y
Z: Byte; масштаб

TNV_TileDeskPtr указатель на описание

TNV_TileList список описаний тайлов. задание загрузчика тайлов.
FTileList: TThreadList<TNV_TileDeskPtr>; защищенный список тайлов
procedure AddTileDesk(AX, AY: Integer; AZ: Byte); добавление описания тайла
function GetTilesCount: Integer; количество описаний
function GetTile(Index: Integer): TNV_TileDeskPtr; извлечение описания тайла
procedure Clear; очистка списка


8. unit TNVTile

описание будут позже

скрытый текст: показать
Код: Выделить всё

  TNV_DataType = (dNull, dStream, dFmxBitmap, dFmxImage);

  TNVImage3D = TNV_Image3D;
  //TNVImage3D = TImage3D;

  TNV_Tile = {record} class(TObject)
    private
      Empty: Boolean;
      X: Integer;
      Y: Integer;
      Z: Byte;
      Age: Byte;
      DataType: TNV_DataType;
      Data: TObject;
    public
      constructor Create(AX, AY: Integer; AZ: Byte);
      destructor Destroy; override;
      procedure Assign(Tile: TObject); //assign & converting data to TImage3D

      function IsEmpty: Boolean;
      function IsNoData: Boolean;
      function CompareXYZ(AX, AY: Integer; AZ: Byte): Boolean;
      function CompareRect(MapRect: TRect; AZ: Byte): Boolean;

      function GetX: Integer;
      function GetY: Integer;
      function GetZ: Byte;
      function GetAge: Byte;
      function GetDataType: TNV_DataType;
      function GetData: TObject;

      procedure SetXYZ(AX, AY: Integer; AZ: Byte);
      procedure SetData(DType: TNV_DataType; DObj: TObject);
      procedure MakeEmpty;
      procedure ClearData;
      procedure LoadDataFromFile(FileName: String; DType: TNV_DataType);

  end;
  TNV_TilePtr = TNV_Tile;  { ^TNV_Tile; }

  TNV_TileQueue = class(TObject)
    private
      FTileQueue: TThreadedQueue<TNV_TilePtr>;

    public
      constructor Create;
      destructor Destroy; override;
      procedure SetTile(Tile: TNV_TilePtr);
      function GetTile: TNV_TilePtr;
      function GetTilesCount: Integer;
  end;


9.unit TNVMapImage
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 12 апр 2017, 20:46

30.03.2017.Версия API 0.06a.
Структура программы изменена. Маска поиска уже загруженных тайлов и итератор вынесены в отдельный класс.
В программе есть некоторые глюки, которые непросто отловить.
Добавлено обновление объектов при изменении координат экрана.

02.04.2017.Версия API 0.07a.
Исправлена установка размера кэша.
Добавлен код для отображения карты при смене зума в 2 этапа - сначала растягивание-сжатие, потом перерисовка после подгрузки. (Код до сих пор еще сырой).
Детектирование конца загрузки по пустому тайлу.

03.04.2017.Версия API 0.08a.
Добавлено отображение координат центра экрана.
Установки флага обновления и его чтение обрамлены потокозащищенной блокировкой.

04.04.2017.Версия API 0.09a.
Все движения карты осуществляются через пересчет абсолютных координат центра экрана. Ошибок с перескоком карты при нехватки времени на отрисовку больше нет.
Исправлено определение коэффициента масштабирования для текущего зума.
Увеличен размер очереди загружаемых тайлов с 10 до 100.
Убраны повторные присваивания Parent.
Кроссплатформенная функция TPath.Combine (на случай возможных глюков) заменена более простым аналогом.

07.04.2017.Версия API 0.10a.
Для объекта на карте добавлена установка размеров.
Добавлен новый класс объектов на карте с использованием векторных путей. Произвольный размер и цвет маркеров объектов.
Исправлен размер объекта при коэффициенте масштабирования зума отличном от единицы.
Устранена утечка памяти в основной программе.

10.04.2017.Версия API 0.11a.
Добавлено отслеживание объектов, находящихся за пределами экрана. Стрелка показывает направление на невидимый объект.
Возможность добавления названия объекта.
Помимо координат и азимута можно задавать скорость движения объекта.

Beta

api1.jpg

органы управления :
-вкл\выкл панель управления.
-масштаб. текстовый ввод с точность до 0,01. кнопки +/- 0.25
-колесо масштаба. шаг 0.01. 1 оборот = 1 масштаб.
-стрелки движения карты.
-колесо поворота карты
-шаг движения карты (от 1 до 512 пикселов)

11.04.2017.Версия API 1.00b.
Полностью переработан интерфейс программы. Добавлены "контролы" управления картой, по умолчанию спрятанные в левом верхнем углу.
Кнопка выхода из программы спрятана в правом верхнем углу.
Добавлено вычисление дистанции до объекта от центра экрана или отслеживаемого объекта.

12.04.2017.Версия API 1.01b.
Список объектов вынесен в отдельный класс.
Список карт вынесен в отдельный класс.
Добавлено определение ЮШ / СШ и ВД / 3Д.
Невидимые поля по краям карты подобраны под полное перекрытие экрана при повороте на любой угол.
Исправлено движение повернутой на угол карты мышью.
Добавлена метка "свой" для одного из объектов. При заданной метке расстояния меряются от своего объекта, а не от центра экрана.

API v 1.01b было скачано 6 раз.
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 14 апр 2017, 01:14

13.04.2017.Версия API 1.02b.
Исправлено масштабирование карты колесом мыши при повернутой карте.
Добавлен маркер центра экрана.
Добавлены кнопки ориентировки карты по 4-м сторонам света.
Координаты сгруппированы в статус бар.
Протестирован код для переключения карт в черно-белый режим, а также изменение яркости и контраста. С первого раза не заработало, пока отложен.
Добавлена поддержка тайлов прямоугольной формы.
Поддержан произвольный размер тайлов.
Добавлены множители, позволяющие задать горизонтальное и вертикальное число тайлов(а через размер тайла - кол-во пикселов) в масштабе, отличное от степени двойки.

api v1.02 было скачано 10 раз.
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 18 апр 2017, 17:28

14.04.2017.Версия API 1.03b.
Исправлено отображение объектов внутри и за пределами экрана при повернутой карте.
Добавлено хранение высот объектов.
Ускорен процесс загрузки тайлов на 200 мсек за счет отключения паузы. Основные затраты (около 700 мс) - внутреннее конвертирование jpg в bitmap.
Добавлен счетчик незавершенных загрузок для двухуровневой смены зума.

17.04.2017.Версия API 1.04b.
добавлена формула вычисление расстояний на карте.
добавлена на экран, но не подключена, масштабная линейка
Добавлен вывод названий (текстовых меток) объектов в одну из 8 позиций в зависимости от направления стрелки.

18.04.2017.Версия API 1.05b.
Подключена масштабная линейка.
Сделано вычисление м\пиксель
Отображаемые в статусе координаты и метры на пиксель привязаны к позиции мыши.
В статус добавлено отображение текущего масштаба и текущий zoom.

api 1.05 скачано 4 раза.
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение DJ VK » 19 апр 2017, 16:15

19.04.2017.Версия API 1.06b.
Поправлена ориентация текста при повернутой карте.
Доделана двухступенчатая отрисовка смены масштаба.
Добавлена поддержка системного датчика позиционирования (не тестировалось).
Добавлено чтение бинарного формата карты, но не подключено (индексные таблицы пока не обрабатываются)
Убраны тормоза при движении карты.

ожидается Версия API 1.07b.

Условия использования кода:
Необходимо указать автора (C) 2017 DJ VK и ссылку на сайт SASGIS.
Необходимо опубликовать исходники вашей программы и оставить здесь ссылку.
Использование в коммерческих целях опубликованного кода недопустимо. (По вопросам создания и приобретения коммерческой версии обращаться лично.)
Продажа скачанных с помощью SAS.Планета спутниковых снимков и карт сама по себе абсолютно незаконна и нелегальна, в связи с чем продажа программы со скачанными снимками третьим лицам бессмысленна.

Всячески приветствуется тестирование и доработка кода по вопросам совместимости с android и другими OS. Присоединяйтесь.

todo. (В перспективе).
+ добавить в информацию об объекте ошибку определения координат.
+ информация об отслеживаемом объекте (скорость, дистанция, азимут, координаты).
+ выбор объекта из окна программы.
+ доделать бинарный формат кэша sas4ce
+ проработать интерфейс под тачскрин и отсутствие мыши.
+ поддержать gps датчик на com-порт
Аватара пользователя
DJ VK
Гуру
 
Сообщения: 1467
Зарегистрирован: 16 апр 2009, 13:57
Откуда: 8 км. от МКАД
Благодарил (а): 82 раз.
Поблагодарили: 298 раз.

Re: SAS.NEXT - FMX version of SAS.Planet

Сообщение vdemidov » 19 апр 2017, 17:57

Зря не пользуешься битбакетом или гитхабом для хранения исходников. Архивчики с версиями это реально прошлый век. Даже для одного человека система контроля версий это очень нужная штука. Просто не представляю как можно писать что-то сложнее хелло-вордла без использования СКВ.
Чтобы понять программу, вы должны стать одновременно и машиной, и программой.

За это сообщение автора vdemidov поблагодарил:
garl (19 апр 2017, 19:41)
Рейтинг: 5.26%
 
Аватара пользователя
vdemidov
Гуру
 
Сообщения: 1686
Зарегистрирован: 12 дек 2008, 13:10
Откуда: Киев
Благодарил (а): 191 раз.
Поблагодарили: 135 раз.

След.

Вернуться в Раздел для разработчиков программы SAS.Планета

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0