|
#1
|
|||
|
|||
Картография
Доброго времени суток.
Суть задачи: Работа с картой. максимальный размер карты: 16160х14140 пикселей. вывод топоосновы и рисование на ней, разного типа обьектов. Реализация: Карта разбита на квадраты 8х7, в макимальном разрешении размер квадрата 2020х2020пик. в минимальном 202х202. Для масштабирования созданы карты разной степени детализации размерами 202, 404, 606, 808, 1010, 1212, 1414, 1616, 1818, 2020 пикселей, помещены в соотвествующие папки на диске. По скольку грузить целую картинку очень ресурсозатратно реализован вывод только видимой области. Прокрутка реализована посредством scrollbar получаем позицию ползунка и вычисляем диапазон видимой области. Код:
procedure Tform1.ris(Sender: TObject; x1,y1,x2,y2,xs,ys:integer); //получаем картинку по ширине имейджа var polosa,ykt,xp,yp,sdx,sdy,y,x,kvadrat,xr1,yr1,xr2,yr2:integer; rx1,rx2,ry1,ry2,nx1,nx2,ny1,ny2:integer; JpegIm: TJpegImage; bm_razova,bm_razova1:tbitmap; begin polosa:=round(2020*combobox1.Tag/100); //в комбобоксе текущий масштаб и соответственно имя папки где лежат карты (10,20. //..90,100) bm_razova := TBitmap.Create; bm_razova.PixelFormat:=pf24Bit; bm_razova.Width:=image1.Width; bm_razova.Height:=image1.Height; ykt:=0; xp:=x1; yp:=y1; sdx:=0; sdy:=0; for y:=((y1 div polosa)+1) to ((y2 div polosa)+1) do begin xp:=x1; sdx:=0; for x:=((x1 div polosa)+1) to ((x2 div polosa)+1) do begin kvadrat:=N_kvadrat(x,y);//получаем номер квадрата который попадает в видимый диапазон xr1:=xp; yr1:=yp; if x2<mass[kvadrat].xk2 then xr2:=x2 else xr2:=mass[kvadrat].xk2; if y2<mass[kvadrat].yk2 then yr2:=y2 else yr2:=mass[kvadrat].yk2; xp:=xr2; ykt:=yr2; karta.Close; karta.SQL.Clear; karta.SQL.Add('select * from karta where x=:x and y=:y'); karta.ParamByName('x').Asinteger:=x; karta.ParamByName('y').Asinteger:=y; karta.Open; bm_razova1 := TBitMap.Create; JpegIm := TJpegImage.Create; JpegIm.LoadFromFile(ini.readstring('base','karta','no')+'/'+inttostr(combobox1.tag)+'/'+karta.Fields[3].asstring+'.jpg'); bm_razova1.Assign(JpegIm); JpegIm.Destroy; if xr1>=polosa then xr1:=xr1-mass[kvadrat].xk1; if yr1>=polosa then yr1:=yr1-mass[kvadrat].yk1; if xr2>=polosa then xr2:=xr2-mass[kvadrat].xk1; if yr2>=polosa then yr2:=yr2-mass[kvadrat].yk1; // область вырезания rx1:=xr1; ry1:=yr1; rx2:=xr2-xr1; ry2:=yr2-yr1; // область в которую помещаем nx1:=sdx; ny1:=sdy; nx2:=xr2-xr1; ny2:=yr2-yr1; bm_razova.Canvas.CopyRect(bounds(nx1,ny1,nx2,ny2),bm_razova1.Canvas,bounds(rx1,ry1,rx2,ry2)); bm_razova1.Free; sdx:=sdx+(xr2-xr1); end; yp:=ykt; sdy:=sdy+(yr2-yr1); end; image1.Picture.Assign(bm_razova); bm_razova.Free; end; Все работает, но не удовлетворяет скорость отображения и прокрутки карты. Вопрос: В каком направлении копать для оптимизации, или может стоит выбрать совсем другой подход? Последний раз редактировалось Admin, 14.02.2016 в 19:13. |
#2
|
||||
|
||||
можно хранить в память сформированный участок карты, по размерам превосходящий видимый участок, например в два раза (по ширине и высоте), при перемещении вырезать из этого участка выводимый кусок и его отображать, а в памяти формировать новый участок, содержащий выводимый участок и также его превосходящий по размерам, в этом случае отображение фактически занимает время копирования из памяти на канву + формирование участка в памяти, что значительно меньше, чем напрямую отображать
Понять, что хочет заказчик - бесценно, ведь он платит MasterCard |
#3
|
|||
|
|||
Если в видимую область попало схождение 4 квадратов 2020х2020 пикс. то прийдется в памяти держать 4 полновесные картинки, в bmp формате которые занимают порядка 50 mb каждая - для слабых компютеров - оч ресурсозатратно
|
#4
|
||||
|
||||
а если при текущем положении дел в выводимую область попало это же самое вхождение?
я писал о том, чтобы то, что делается сейчас строить предварительно в памяти и затем выводить Понять, что хочет заказчик - бесценно, ведь он платит MasterCard |