Помощь - Поиск - Пользователи - Календарь
Полная версия: Нарисовать карту
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Страницы: 1, 2
}0pa
Проблема такова: В прикрепленном файле находятся файлы KRD-карты районов. Каждый из них содержит название района, координаты точек, макс. и мин. значения "х" и "у". Помогите вывести на экран хотя бы одну карту
Код


interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  x,y,h:real;
  I1,I2,J1,J2:integer;
  x1,x2,y1,y2:real;
implementation

{$R *.dfm}
{------------------------------------------------------------------------------}
function II(x:real):Integer;
begin
  II:=I1 + Trunc ((x-x1)*(I2-I1)/(x2-x1))
end;
{------------------------------------------------------------------------------}
function JJ(y:real):Integer;
begin
  JJ:=J1 + Trunc ((y-y1)*(J2-J1)/(y2-y1))
end;
{------------------------------------------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
begin
with Image1

end;

end.
}0pa
Смотрю по коду, вроде должно работать, но все равно карту не рисует из файла:
1.Название района
2.Название райцентра
3.Координаты
4.,5.Макс по Х и мин по Х, соотевтсвенно макс по у и мин по у... Остальные просто координаты!
В качестве примера взял один файл с название "район1"
Код

var
  Form1: TForm1;
  x1,y1,x2,y2,h:real;
  x,y,col:integer;
  I1,J1,I2,J2,n,j,k:integer;
  s1,s2:string;
  f:TextFile;
implementation

{$R *.dfm}
{------------------------------------------------------------------------------}
function II(x:real):integer;
begin
II:=I1+Trunc((x-x1)*(I2-I1)/(x2-x1))
end;
{------------------------------------------------------------------------------}
function JJ(x:real):integer;
begin
JJ:=J1+Trunc((y-y1)*(J2-J1)/(y2-y1))
end;
{------------------------------------------------------------------------------}
procedure DrawGraphic;
begin
reset(f);
k:=0;
   with Form1.Image1,Form1.Image1.Canvas do
    begin
    x:=1413;y:=1294;
    MoveTo(II(x),JJ(-y));
     while not eof(f) do
      begin
       k:=k+1;
       while not eoln(f) do
        begin
        Rectangle(0,0,Width,Height);
        if (k=1)or(k=2) then

          read(f,s1)

        else if k=4 then read(f,n)
        else if k=7 then read(f,col)
        else
         begin
          read(f,x,y);
          LineTo(II(x),JJ(-y))
         end
       end;
      readln(f)
     end;
    close(f);
   end;
end;
{------------------------------------------------------------------------------}
procedure TForm1.FormCreate(Sender: TObject);
begin
AssignFile(f, 'D:\Documents and Settings\Administrator\My Documents\Delfi_files\Map\RAION1.KRD');

   n:=200;
  x1:=-6; y1:=-6;
  x2:=6;y2:=6;

    I1:=0;J1:=0;
    I2:=Image1.Width;J2:=Image1.Height;

  DrawGraphic;
end;
мисс_граффити
Что значит вывести?
Что должно получиться на экране? Название района и куча точек?
}0pa
Да, куча точек - карта района с его названием и названиеи райцентра!
hiv
Что означает 7 в 7-ой строке файла данных о районе?
hiv
Вроде что-то получилось smile.gif
Нажмите для просмотра прикрепленного файла
Вот как выглядит:
Нажмите для просмотра прикрепленного файла
ЗЫ: Если хочешь несколько районов, то используй массив из TRegion. Но не забудь, что пересчитывать Delta (относительное смещение координат карты и формы на экране) придется для каждого региона по другому.
}0pa
Большой респект. Нашел свои ошибки!!!Спасибо!
}0pa
Цитата
Если хочешь несколько районов, то используй массив из TRegion

Не мог ты написать пример хотя бы для 2 карт.
}0pa
Код
Canvas.Ellipse(Region.CenterX-Region.Delta.X-th div 2 - 1,Region.CenterY-Region.Delta.Y-th div 2 - 1,Region.CenterX-Region.Delta.X+ th div 2,Region.CenterY-Region.Delta.Y+ th div 2);

Помогите разобраться в строчке

Понятно,что это эллипс, но каким же образом мы выбираем эти коордниты?
hiv
Цитата(}0pa @ 23.11.2006 2:30) *
Понятно,что это эллипс, но каким же образом мы выбираем эти коордниты?


(Region.CenterX,Region.CenterY) - центр окружности
th - ее диаметр (берется размером с высоту шрифта которым подписывать будем)
th div 2 - ее радиус (деление нацело)
Region.Delta - смещение координат по X и Y
Геометрию то помнишь?

Вместо Region :TRegion;
пишешь Region :array of TRegion;
Перед добавлением региона не забывай увеличить размер динамического массива:
setlength(Region,length(Region)+1);
}0pa
Цитата(hiv @ 21.11.2006 12:19) *

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

1.Наверное, придется заносить сещение в массив?
2.К тому же, нужно нарисовать карту региона,т.е.этот район не обязательно должен находиться в левом углу формы?
3.А нельзя ли не изменять в файле имя района и райцентра, вывести на экран при считывания из файла, эти имена в норм. "русской форме"?
hiv
Цитата(}0pa @ 23.11.2006 12:37) *

1.Наверное, придется заносить сещение в массив?
2.К тому же, нужно нарисовать карту региона,т.е.этот район не обязательно должен находиться в левом углу формы?
3.А нельзя ли не изменять в файле имя района и райцентра, вывести на экран при считывания из файла, эти имена в норм. "русской форме"?

1. Смещение находится в объекте, поэтому заносить его в массив не надо, т.к. сами объекты уже в массиве. Возможно нужно убрать смещение из регионов, если они у тебя относительно друг друга правильно расположены, и ввести общее смещение. Его вычислять как минимальное значение из Region[i].Rect.Left по X и минимальное значение из Region[i].Rect.Top по Y.
2. см. ответ на вопрос 1.
3. Можно, тогда ищи функцию перекодировки cp866 в кодировку cp1251. На форуме точно есть. Начни с FAQ smile.gif
}0pa
Масштаб не получается реализовать, т.е. на форме вся карта не умещаетя...Смещение для каждого района убрал и поставил для всей карты
}0pa
Вот этот проэкт. Вся карта не помещается на форму. Помогите организовать масштаб
hiv
Цитата(}0pa @ 27.11.2006 0:07) *

Вот этот проэкт. Вся карта не помещается на форму. Помогите организовать масштаб

Добавил масштаб (чего нет проще - подели итоговые координаты на масштаб и все!)
Исправил кучу нелепостей особенно с OnPaint (он должен быть связан с формой) и поиском файлов.
Нажмите для просмотра прикрепленного файла
}0pa
С маштабом я потом сам догадался, вспомнив про сжатие и растяжение. А вот, конечно, за поиск очередного файла с раширение КРД и за оптимизацию событийных процедур огромное спасибо!
Р.С. Помнится, вы спрашивали про 7 строчку в файле: это есть не что иное, как цвет района
Region.Cvet - содержит цвет, но при его подстановки в
Код
Canvas.Brush.Color:=clWhite;  (Canvas.Brush.Color:=Region[i].cvet;)

Происходит неурядица. И вот насчет кодировки у меня ничего в голову не лезет
hiv
Посмотри описание объекта TColor;
Из него можно создать палитру (массив цветов), номер в которой и будет твоим номером цвета.
}0pa
Sorry, сам разобрался...
Код
Function MyColor(c:integer):TColor;
begin
case c of
  0:MyColor:=clBlack;
  1:MyColor:=clBlue;
  2:MyColor:=clGreen;
  3:MyColor:=clLime;
  4:MyColor:=clRed;
  5:MyColor:=clSilver;
  6:MyColor:=clMaroon;
  7:MyColor:=clOlive;
  8:MyColor:=clNavy;
  9:MyColor:=clAqua;
  10:MyColor:=clYellow;
  11:MyColor:=clPurple;
  12:MyColor:=clTeal;
  13:MyColor:=clWhite;
end;
end;

Может, немного нерациорально, но тем не менее...
Тогда еще последний вопрос остается:
Кодировка - считывание из файла и вывод на экран русских букв без изменения самого файла...
hiv
Цитата(}0pa @ 27.11.2006 14:41) *

Может, немного нерациорально, но тем не менее...

Не менее, надо делать так:
const MyColor:array[0..13] of TColor = (clBlack, clBlue, clGreen, clLime,
clRed, clSilver, clMaroon, clOlive, clNavy, clAqua, clYellow, clPurple, clTeal, clWhite);

Цитата(}0pa @ 27.11.2006 14:41) *

Тогда еще последний вопрос остается:
Кодировка - считывание из файла и вывод на экран русских букв без изменения самого файла...

Это уж сам в инете найдешь - вещь распространенная. Но я бы просто все файлы данных перекодировал, чтоб не заниматься постоянной перекодировкой при их чтении, тем более что cp1251 стандартная кодировка windows с 1995 года.

ЗЫ: Можно заменить номер цвета в файле данных на сам цвет в формате RGB (красный синий голубой), а потом определяй цвет для каждого региона так Region[i].color:=RGB(r,g,b); Компоненты цвета r,b,b - байты (0..255).
}0pa
Не могу найти в инете ничего стоящего, Возможно это АПИ фукнции, а с ними я еще не сталкивался...
Код
CharToOEM/OEMToChar

Может что-нибудь это? Тогда что за тим PAnsiChar???
hiv
Цитата(}0pa @ 27.11.2006 20:00) *

Не могу найти в инете ничего стоящего, Возможно это АПИ фукнции, а с ними я еще не сталкивался...
Код
CharToOEM/OEMToChar

Может что-нибудь это? Тогда что за тим PAnsiChar???

Смотри DRKB (советую загрузить)
function StrToOem(const AnsiStr: string): string; 
begin
SetLength(result, Length(AnsiStr));
if Length(result) > 0 then
CharToOem(PChar(AnsiStr), PChar(result))
end;

Здесь win->dos , а наоборот сам переделаешь smile.gif
Удачи.
}0pa
Большое Вам спасибо, что потратили время на эту задачу...Вроде все сделано.
ЗЫ: Что такое DRKB?
hiv
Цитата(}0pa @ 28.11.2006 20:52) *

ЗЫ: Что такое DRKB?

Ну ты даешь!!! lol.gif Смотри заголовок...
}0pa
Тьфу,ты... mega_chok.gif mega_chok.gif mega_chok.gif
Кстати,
Код
Attr:=$FFFFFFFF - faDirectory;

Означает, все файлы в текущей директории??? wink.gif
hiv
Цитата(}0pa @ 29.11.2006 19:17) *
Кстати,
Код
Attr:=$FFFFFFFF - faDirectory;

Означает, все файлы в текущей директории??? wink.gif

Абсолютно верно. Причем faAnyFile не хляет, вместо него $FFFFFFFF. А не хляет потому, что мелкософтовцы в винде повводили еще новых атрибутов - да еще и в инвертированом виде. mega_chok.gif
}0pa
Код
    { if i=1 then
     begin //относительное смещение координат карты и формы на экране
       dX:=Region[i].Rect.Left;
       dY:=Region[i].Rect.Top;
     end
     else
     begin //выбираем минимальные значения
       if dX>Region[i].Rect.Left then dX:=Region[i].Rect.Left;
       if dY>Region[i].Rect.Top then dY:=Region[i].Rect.Top;
     end;  }

Я сомневаюсь,что эта часть кода жизненно необходима good.gif Да, к тому же зачем вообще рисовать прямоугольник? wink.gif
hiv
Цитата(}0pa @ 1.12.2006 1:08) *
Я сомневаюсь,что эта часть кода жизненно необходима good.gif

Необходима, если карты будут другие. Тогда смещения dx и dy, которые ты константами прописываешь в своей программе, прийдется менять, что повлечет перекомпиляцию кода. Тем более, что в этом коде используются все входные данные. Иначе зачем они тебе давались? Вспомни школьную физику или математику: "При решении задачи используются все данные, которые даны в условии, иначе задача решена НЕПРАВИЛЬНО!".
Цитата(}0pa @ 1.12.2006 1:08) *
Да, к тому же зачем вообще рисовать прямоугольник? wink.gif

Где ты видел рисование? blink.gif TRect - просто стандартный объект, содержащий только координаты прямоугольной области.
}0pa
Случилось самое страшное mad.gif . Мне нужно организовать, чтобы карта рисовалась точно в области формы и при иземенения размера формы менялся ее размер nea.gif
hiv
Цитата(}0pa @ 1.12.2006 16:44) *

Случилось самое страшное mad.gif . Мне нужно организовать, чтобы карта рисовалась точно в области формы и при иземенения размера формы менялся ее размер nea.gif

Тогда масштаб должен быть вещественным. Целочисленное деление DIV должно быть заменено вещественным /. Результируемые координаты должны быть округлены до целого.
И тот кусок кода что выкинул - верни и доработай, чтоб масштаб вычислять. yes2.gif
Гость
Нужно связать переменную m, отвечающую за масштаб с длиной и шириной формы, но другое дело, как это сделать?
}0pa
Цитата
Тогда масштаб должен быть вещественным. Целочисленное деление DIV должно быть заменено вещественным /. Результируемые координаты должны быть округлены до целого.

А это я сделал, тем самым уменьшив шаг масштаба... good.gif
}0pa
Еще требуется обратиться к каждому региону нажатием Левой кнопки мыши
Вот не пойму как можно это сделать7 mega_chok.gif
hiv
Цитата(}0pa @ 4.12.2006 14:06) *

Еще требуется обратиться к каждому региону нажатием Левой кнопки мыши
Вот не пойму как можно это сделать7 mega_chok.gif

Что значит обратиться? (поподробнее)

ЗЫ: Пересчитывай координаты мышки обратно в координаты карты, т.е. умножай на масштаб и добавляй смещение. Делать это по событию onMouseDown.
}0pa
Обратиться. При нажатии на отдельный регион, появляется новая форма с этим регионом, но при этом этот регион в точности имеет размер формы и при Resize карта менят размеры.
hiv
Главная проблема в определении принадлежности точки многоугольнику. Ее решение можешь посмотреть здесь.
NTL
Необходимо в этой же задаче: Дан рисунок, необходимо, создавая динмаически очередной ТАКОЙ же рисунок,
разместить его в точке, где находится Райцентр. Вот мой вариант, но что-то не получается...Не отображается копия. Помогите плзю
Код

       Image:=TImage.Create(Form1);
       BitMap:=TBitMap.Create;
       Myimage.width:=image1.width;
       Myimage.height:=image1.height;
       MyRect:=Rect(1,1,myImage.Width,myimage.Height);
       ImRect:=Rect(1,1,image1.Width,image1.Height);

        BitMap.Assign(Image1.Picture);

       MyImage.Canvas.CopyRect(MyRect,BitMap.Canvas,ImRect);

       Myimage.Left:=Round((Region[15].CenterX-dx-th div 2 - 1)/ m);
       Myimage.Top:= Round((Region[15].CenterY-dy-th div 2 - 1)/ m);
       MyImage.show;
NTL
А как же связать масштаб с габаритами формы? Чтобы при изменении размера формы, карта была в точности размером формы? mega_chok.gif
hiv
Цитата(NTL @ 8.12.2006 2:14) *

А как же связать масштаб с габаритами формы? Чтобы при изменении размера формы, карта была в точности размером формы? mega_chok.gif

Очень просто:
1) Определяешь масштаб горизонтальный = размер региона по горизонтали / ширину формы;
2) Определяешь масштаб вертикальный = размер региона по вертикали / высоту формы;
3) Выбираешь из этих двух масштабов выбираешь максимальный.

ЗЫ: А причем тут растровая графика TImage? Ведь все время работали с векторной графикой! !4.gif
NTL
Цитата(hiv @ 8.12.2006 9:09) *

ЗЫ: А причем тут растровая графика TImage? Ведь все время работали с векторной графикой! !4.gif

Поподробнее не могли бы... give_rose.gif
hiv
Цитата(NTL @ 7.12.2006 18:26) *

Необходимо в этой же задаче: Дан рисунок, необходимо, создавая динмаически очередной ТАКОЙ же рисунок,
разместить его в точке, где находится Райцентр. Вот мой вариант, но что-то не получается...Не отображается копия. Помогите плзю

Нет! Это Вы поподробней: dry.gif
1) Что за рисунок? Изображение региона мы сами рисуем по его координатам (это векторная графика)
2) Что значит разместить рисунок в точке? Это что - ужать его до такого состояния? Стандартные рисунки TImage (растровая графика) отображаются не в точке, а в прямоугольнике (который можно задавать типом TRect).
3) А где должна отображаться копия НЕИЗВЕСНОГО ТАКОГО ЖЕ рисунка?
NTL
Вообщем, дан на форма Image1 с загруженным туда рисунком в формате BMP или Icon,например,красная точка (уж не знаю, есть ли разница BMP, ICON?). Нужно, не создавая компоненты Image2,Imege3...Image23 на стадии контруировании формы, создать эти компоненты во время работы программы и скопировать туда этот рисунок из Image1,
затем вывести все эти рисунки на карту. Причем, каждый этот рисунок должен отобразиться в том месте, где находиться райцентр каждого района (ужимать ничего не надо, т.к.данный рисунок небольшой и в точности подходит к размерам нашего эллипса).В том примере, я пытался скопировать хотя бы в один рисунок, для общего слуачая понятно, что нужно будет array of TImage

Пересчитать обратно координаты так?
Код
for i:=0 to 23 do
   for j:=0 to length(Region[i].bounds)-1 do
      Region[i].bounds[j].X:=Round((bounds[j].X+dx)* m)


Цитата

1) Определяешь масштаб горизонтальный = размер региона по горизонтали / ширину формы;
2) Определяешь масштаб вертикальный = размер региона по вертикали / высоту формы;
3) Выбираешь из этих двух масштабов выбираешь максимальный.


Насчет масштаба, как определить размер всей карты? Я пытался подобрать,вроде так...
Код
if 1435/Form1.ClientWidth>854/Form1.ClientHeight then
   m:=1435/Form1.ClientWidth
else
  m:=854/Form1.ClientHeight;

hiv
Вместо
Canvas.Ellipse((Region[i].CenterX-x-th div 2 - 1)div m,(Region[i].CenterY-y-th div 2 - 1)div m,(Region[i].CenterX-x+ th div 2)div m,(Region[i].CenterY-y+ th div 2)div m);
напиши
Canvas.Draw((Region[i].CenterX-x) div m - Image1.Picture.Graphic.Width div 2,
(Region[i].CenterY-y) div m - Image1.Picture.Graphic.Height div 2,
Image1.Picture.Graphic.);
и не забудь поставить свойство Transparent=true у объекта Image1.

Цитата
Насчет масштаба, как определить размер всей карты? Я пытался подобрать,вроде так...
Ничего подбирать не нужно! nea.gif Я тебе говорил переделать код выделенный тобой как ненужный в посте 26! Тебе надо дополнительно выбрать максимальные значения. Имея также минимальные ... если подумать! ... то будешь знать размер твоей карты (в масштабе 1:1).
NTL
Цитата
Код
Canvas.Draw((Region[i].CenterX-x) div m - Image1.Picture.Graphic.Width div 2,
            (Region[i].CenterY-y) div m - Image1.Picture.Graphic.Height div 2,
            Image1.Picture.Graphic.);

для m:real; не подходит, а для целого в самый раз (гениальный вариант). Для вещественного никак нельзя?
А насчет пересчитывания координат из предыдущего поста, ничего не можете подсказать?
NTL
Тьфу ты norespect.gif Для m - любого дошло до меня...А вот насчет персчитывания координат мыши в координаты карты? give_rose.gif
NTL
Цитата(}0pa @ 1.12.2006 1:08) *

Код
    { if i=1 then
     begin //относительное смещение координат карты и формы на экране
       dX:=Region[i].Rect.Left;
       dY:=Region[i].Rect.Top;
     end
     else
     begin //выбираем минимальные значения
       if dX>Region[i].Rect.Left then dX:=Region[i].Rect.Left;
       if dY>Region[i].Rect.Top then dY:=Region[i].Rect.Top;
     end;  }



Почему именно i:=1
hiv
Цитата(NTL @ 11.12.2006 17:45) *

Почему именно i:=1

Если dX и dY не будут определены (как это делается на первом шаге), то не понятно к чему приведут сравнения dX>Region[i].Rect.Left и dY>Region[i].Rect.Top.
Цитата
А вот насчет персчитывания координат мыши в координаты карты?

Смотри снова пост 38. Что непонятного?
NTL
Цитата
Смотри снова пост 38. Что непонятного?

Мне собственно нужно теперь обратиться к этой карте, в частности нажатие на тот самый райцентр с рисунком и нажатие на любой район, чтобы в заголовке формы появилось название района. Т.е, по-моему,.координаты мыши нужно преобразовать или я ошибаюсь... cool.gif

Цитата(hiv @ 12.12.2006 9:48) *

Если dX и dY не будут определены (как это делается на первом шаге), то не понятно к чему приведут сравнения dX>Region[i].Rect.Left и dY>Region[i].Rect.Top.


Но у нас же условие будет проверяться только один раз, когда :=1...Т.е. только один раз будет сравниваться
NTL
К райцентру я смог обратитьсяся, мб немного неоптимально, но собсвена вот//
Код
      
MasX[i]:= Round((Region[i].CenterX-dx) / m) - round((Image1.Picture.Graphic.Width) / 2);
MasY[i]:= Round((Region[i].CenterY-dy) / m) - Image1.Picture.Graphic.Height div 2;
Canvas.Draw(MasX[i],MasY[i],Image1.Picture.Graphic);
---------------------------------------------------------------
if (x>=MasX[i])and (x<=MasX[i]+image1.Picture.Width) and (y>=MasY[i])and(y<=MasY[i]+image1.Picture.height) then
      label2.caption:=Region[i].Name;

Осталось только к самому региону...Может подскажете? smile.gif
NTL
Цитата(NTL @ 12.12.2006 14:30) *

Но у нас же условие будет проверяться только один раз, когда :=1...Т.е. только один раз будет сравниваться

Вопрос снимается, дошло good.gif
NTL
Может быть, что-нибудь похожее...рез-ат этого почти правильный, но погрешносить все еще велика. Как бы ее свести к минимуму?
Код
    
if (x>=Round(Region[i].Rect.Left-dx)/m) and (x<=round(Region[i].Rect.Right-dx)/m) and
(y<=round(Region[i].Rect.Bottom-dy)/m) and (y<=round(Region[i].Rect.Top-dy)/m) then
  label1.Caption:=region[i].Center;

ЗЫ: Принадлежность точки к многоугольнику рассмотрел, но слишком это сложный вариант
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.