Список форумов www.integro.ru www.integro.ru
ЦСИ ИНТЕГРО
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 

Файл с изображением карты в формате EMF

 
Начать новую тему   Ответить на тему    Список форумов www.integro.ru -> Вопросы разработчиков
Предыдущая тема :: Следующая тема  
Автор Сообщение
Codegen



Зарегистрирован: 26.03.2006
Сообщения: 14
Откуда: Екатеринбург

СообщениеДобавлено: Пт 31 Мар 2006 16:11    Заголовок сообщения: Файл с изображением карты в формате EMF Ответить с цитатой

Пытаюсь получить изображение карты командой
Код:

procedure GetEMF(Ingeo: IIngeoApplication; aResX, aResY, aSizeX, aSizeY: Longint; CenterX, CenterY, ZoomScale, XAngle: double; YMirror: boolean);
begin
    Ingeo.ActiveProjectView.MakeImageFile(aResX, aResY, aSizeX, aSizeY, CenterX, CenterY, ZoomScale, XAngle, YMirror, clWhite, 'C:\123.emf');
end;

Получаю следующую ошибку:
Ошибка имени растрового файла: некорректное расширение файла.
Если ставить расширение bmp, jpg, gif то изображение создается. Это не подходит, как получить emf? В хелпе указано что это можно сделать.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Codegen



Зарегистрирован: 26.03.2006
Сообщения: 14
Откуда: Екатеринбург

СообщениеДобавлено: Сб 01 Апр 2006 22:55    Заголовок сообщения: Ответить с цитатой

Нашел в чем ошибка..
Имя файла не должно начинаться на цифру, т.е. 123.emf - так нельзя, qwerty123.emf - так сработает.
Привожу функцию, которая возвращает копию экрана Ингео, она некорректно работает для EMF. Код полностью рабочий. Надеюсь этот баг будет исправлен как можно быстрее. Он тормозит мою разработку!
Код:
function GetPicture(Ingeo: IIngeoApplication; zAngle: double): IInImage;
var
    IngeoDb: IIngeoDb;
    theImage: IInImage;
    // копируем вариантный массив в поток
    function VariantArrayToStream(VarArray: OleVariant): TMemoryStream;
    var
        pLocked: Pointer;
    begin
        Result:= TMemoryStream.Create;
        if VarIsEmpty(VarArray) or VarIsNull(VarArray) then Exit;
        Result.Size := VarArrayHighBound(VarArray, 1) - VarArrayLowBound(VarArray, 1) + 1;
        pLocked := VarArrayLock(VarArray);
        try
            Result.Write(pLocked^, Result.Size);
        finally
            VarArrayUnlock(VarArray);
            Result.Position := 0;
        end;
    end;
    procedure PaintObject(anID: String);
    var
        IngeoMapObject: IIngeoMapObject;
    begin
        IngeoMapObject := IngeoDb.MapObjects.GetObject(anID);
        if not assigned(IngeoMapObject) then exit;
        IngeoMapObject.Paint(theImage.Surface);
    end;
    function ZoomScaleInRange(aZoomScale, aMinScale, aMaxScale: Double): Boolean;
    begin
       Result :=
          (aZoomScale = 0) or
          (((aMinScale = 0) or
           ((aMinScale > 0) and (aZoomScale <= aMinScale)) or
           ((aMinScale < 0) and (aZoomScale < -aMinScale)))
             and
          ((aMaxScale = 0) or
           ((aMaxScale > 0) and (aZoomScale >= aMaxScale)) or
           ((aMaxScale < 0) and (aZoomScale > -aMaxScale))))
    end;
   function LayerHaveVisibleSyles(aZoomScale: Double; const aLayer: IIngeoLayer): Boolean;
   var
      aStyle: IIngeoStyle;
      aPainter: IIngeoPainter;
      i, j: Integer;
   begin
      Result := True;
      for i := 0 to aLayer.Styles.Count - 1 do begin
         aStyle := aLayer.Styles[i];
         for j := 0 to aStyle.Painters.Count - 1 do begin
            aPainter := aStyle.Painters[j];
            if ZoomScaleInRange(aZoomScale, aPainter.VisibleMin, aPainter.VisibleMax) then
               Exit;
         end;
      end;
      Result := False;
   end;
var
    IngeoProjectView: IIngeoProjectView;
   IngeoMapView: IIngeoMapView;
   IngeoLayerView: IIngeoLayerView;
   IngeoMapObjects: IIngeoMapObjects;
   IngeoMapObjectsQuery: IIngeoMapObjectsQuery;
    aZoomScale, xx1, yy1, xx2, yy2, x1, y1, x2, y2: double;
    i, j: integer;
    zStream: TMemoryStream;
    IngeoMapWindow: IIngeoMapWindow;
    ProjectionNavigator: IIngeoMatrixProjectionNavigator;
begin
    // создаем экземпляр картинки
    theImage := Ingeo.CreateObject(inocImage, EmptyParam) as IInImage;
    // устанавливаем разрешение и размеры картинки
    theImage.ResolutionX := 96;
    theImage.ResolutionY := 96;
    with Ingeo.MainWindow.MapWindow.Surface do begin
        theImage.Width := DeviceRight - DeviceLeft;
        theImage.Height := DeviceBottom - DeviceTop;
    end;
    IngeoMapWindow := Ingeo.MainWindow.MapWindow;
    ProjectionNavigator := IngeoMapWindow.Navigator as IIngeoMatrixProjectionNavigator;
    // синхронизируем положение картинки с окном ингео
    with ProjectionNavigator do theImage.Surface.Navigator.Navigate(CenterX, CenterY, ZoomScale);
    IngeoDb := Ingeo.ActiveDb;
    IngeoProjectView := Ingeo.ActiveProjectView;
    IngeoMapObjects := Ingeo.ActiveDb.MapObjects;
    // получаем координаты левой верхней и правой нижней точки карты в ингео
    with theImage.Surface do begin
        PointDeviceToWorld(DeviceLeft, DeviceTop, x1, y1);
        PointDeviceToWorld(DeviceRight, DeviceBottom, x2, y2);
        aZoomScale := Projection.ZoomScale;
        ProjectionNavigator := Navigator as IIngeoMatrixProjectionNavigator;
        ProjectionNavigator.YMirror := IngeoMapWindow.Surface.Projection.YMirror;
        // ставим какой-то свой угол поворота карты,
        // карта отрисовывается с нужным углом, но потом ни как не прочитать
        // реальный угол!!
        ProjectionNavigator.XAngle  := zAngle;
    end;
    // если так не сделать, то QueryByRect не работает
    xx1 := Min(x1, x2); yy1 := Min(y1, y2);
    xx2 := Max(x1, x2); yy2 := Max(y1, y2);
    // проходим по всем картам/слоям, видимые объекты отрисовываем на theImage
    for i := IngeoProjectView.MapViews.Count - 1 downto 0 do begin
        IngeoMapView := IngeoProjectView.MapViews[i];
        if not IngeoMapView.Visible or not ZoomScaleInRange(aZoomScale, IngeoMapView.Map.VisibleMin, IngeoMapView.Map.VisibleMax) then Continue;
        for j := IngeoMapView.LayerViews.Count - 1 downto 0 do begin
            IngeoLayerView := IngeoMapView.LayerViews[j];
            if not IngeoMapView.Visible or not ZoomScaleInRange(aZoomScale, IngeoLayerView.Layer.VisibleMin, IngeoLayerView.Layer.VisibleMax) or
                not LayerHaveVisibleSyles(aZoomScale, IngeoLayerView.Layer) then Continue;
            IngeoMapObjectsQuery := IngeoMapObjects.QueryByRect(IngeoLayerView.Layer.ID, xx1, yy1, xx2, yy2, false);
            while not IngeoMapObjectsQuery.EOF do begin
                PaintObject(IngeoMapObjectsQuery.ObjectID);
                IngeoMapObjectsQuery.MoveNext;
            end;
        end;
    end;
    zStream := VariantArrayToStream(theImage.Data[inidBMP]);
    zStream.SaveToFile('C:\bmp.bmp');
    theImage.SaveToFile('C:\~bmp.bmp');
    zStream.Clear;
    zStream := VariantArrayToStream(theImage.Data[inidJPEG]);
    zStream.SaveToFile('C:\jpeg.jpeg');
    theImage.SaveToFile('C:\~jpeg.jpeg');
    zStream.Clear;
    zStream := VariantArrayToStream(theImage.Data[inidGIF]);
    zStream.SaveToFile('C:\gif.gif');
    theImage.SaveToFile('C:\~gif.gif');
    zStream.Clear;
    try
        zStream := VariantArrayToStream(theImage.Data[inidEMF]);
        // ФАЙЛ СОЗДАЕТСЯ, НО ОН ПУСТОЙ
        zStream.SaveToFile('C:\emf.emf');
        // ОШИБКА ИМЕНИ РАСТРОВОГО ФАЙЛА: НЕКОРРЕКТНОЕ РАСШИРЕНИЕ ФАЙЛА
        theImage.SaveToFile('C:\~emf.emf');
    finally
        zStream.Clear;
        zStream.Free;
        result := theImage;
    end;
end;

P.S.
Нашел еще один очень досадный баг.. Image который возвращает приведенная функция не корректно возвращает XAngle:
Код:
procedure TReportForm.Button1Click(Sender: TObject);
var
    theImage: IInImage;
    angle1, angle2: double;
begin
    try
        // угол поворота карты ставим ноль
        theImage := GetPicture(Ingeo, 0);
    finally
        angle1 := OleVariant(theImage.Surface.Navigator).XAngle;
        angle2 := (theImage.Surface.Navigator as IIngeoMatrixProjectionNavigator).XAngle;
        // угол поворота всегда Pi/2!!
        MessageBox(Handle, PChar(FloatToStr(angle1)), 'OleVariant(theImage.Surface.Navigator).XAngle', MB_APPLMODAL);
        MessageBox(Handle, PChar(FloatToStr(angle2)), '(theImage.Surface.Navigator as IIngeoMatrixProjectionNavigator).XAngle', MB_APPLMODAL);
        theImage := nil;
    end;
end;
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Кузнецов Андрей



Зарегистрирован: 22.04.2005
Сообщения: 28
Откуда: Магнитогорск

СообщениеДобавлено: Вт 04 Апр 2006 12:08    Заголовок сообщения: Ответить с цитатой

Можно немного сократить код используя метод PaintXml.
Вот примерчики на vbs:
Код:

  Sub PaintLayerByID (aDB, aSurface, aLayerID)
    aDB.PaintXml aSurface, "<paint><layer oid='" & aLayerID & "' /></paint>"
  end Sub
  Sub PaintMapByID (aDB, aSurface, aMapID)
    aDB.PaintXml aSurface, "<paint><map oid='" & aMapID & "' /></paint>"
  end Sub
  Sub PaintProjectByID (aDB, aSurface, aProjectID)
    aDB.PaintXml aSurface, "<paint><project oid='" & aProjectID & "' /></paint>"
  end Sub
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Рустам Тукаев
Администратор сайта


Зарегистрирован: 14.02.2005
Сообщения: 30
Откуда: ИНТЕГРО

СообщениеДобавлено: Вт 04 Апр 2006 15:43    Заголовок сообщения: Файл с изображением карты в формате EMF Ответить с цитатой

Codegen писал(а):
IInImage ..

Во-первых, IInImage не умеет создавать emf файлы
Во-вторых, если нужно создать файл с изображением карты, лучше использовать метод MakeImageFile объекта типа IIngeoProjectView
вот примерчик на vbs:
Код:

sub MakeImageFile(aFileName, aWorldX1, aWorldY1, aWorldX2, aWorldY, aZoomScale, aResolution, aForeColor)
  dim   aProjection
  dim   aSizeX, aSizeY
   
  dim aCenterX, aCenterY, anAngle
   
  dim aProjectView, aSurface
   
  if aZoomScale <> 0 then
    aZoomScale = 1/aZoomScale
  end if
  set aSurface = Application.MainWindow.MapWindow.Surface
  set   aProjection = aSurface.Projection
  set   aProjectView = Application.ActiveProjectView
   
   
  anAngle = Application.MainWindow.MapWindow.Navigator.XAngle*180/pi
  aSizeX = CInt(Abs(aWorldX1 - aWorldX2)*(aResolution / 0.0254)*aZoomScale)
  aSizeY = CInt(Abs(aWorldY2 - aWorldY1)*(aResolution / 0.0254)* aZoomScale)
   
  aCenterX = (aWorldX1 + aWorldX2)/2
  aCenterY = (aWorldY2 + aWorldY1)/2
   
  call aProjectView.MakeImageFile(aResolution, aResolution, aSizeX, aSizeY, aCenterX, aCenterY, _
  aZoomScale, anAngle, aProjection.YMirror, aForeColor, _
  aFileName)
end sub
sub MakeMapWindowImageFile(aFileName, aZoomScale, aResolution, aForeColor)
  dim   aWorldX1, aWorldY1, aWorldX2, aWorldY2
  with Application.MainWindow.MapWindow.Surface
    aWorldX1 = .PaperX1
    aWorldY1 = .PaperY1
    aWorldX2 = .PaperX2
    aWorldY2 = .PaperY2
  call .Projection.sUnProjectBounds(aWorldX1, aWorldY1, aWorldX2,   aWorldY2, aWorldX1, aWorldY1, aWorldX2, aWorldY2)
  end with
  call MakeImageFile(aFileName, aWorldX1, aWorldY1, aWorldX2, aWorldY2, aZoomScale, aResolution, aForeColor)   
end sub
MakeMapWindowImageFile "C:\1.emf", 500, 100, vbWhite

В-третьих, если вам нужно вставить изображение карты в Word, например, то нет необходимости создавать файл, можно сделать так:
Код:

sub MakeImage(X1, Y1, X2, Y2, MapScale)
  dim LayoutWindow, Map
  set LayoutWindow = OpenWindow("LayoutWindow", Null)
  LayoutWindow.Visible = False
  set Map = LayoutWindow.Figures.Add(inftMap)
  Map.CenterX = (X1 + X2) / 2
  Map.CenterY = (Y1 + Y2) / 2
  Map.ZoomScale = 1/MapScale
  Map.Width = ((Y2 - Y1) + 10)* Map.ZoomScale
  Map.Height = ((X2 - X1) + 10)* Map.ZoomScale
  LayoutWindow.Actions("ActionsEditSelectAll").Execute
  LayoutWindow.Actions("ActionsEditCopy").Execute
  LayoutWindow.Close
end sub
sub MakeDocument
  dim Word, Doc, Range
  Set Word = CreateObject("Word.Application")
  Word.Visible = True
  Set Doc = Word.Documents.Add("c:\template.dot")
  Doc.Bookmarks("Map").Range.Paste
  Doc.Range.InlineShapes(1).Width = PictureWidthInMM
  Doc.Range.InlineShapes(1).ScaleHeight = Doc.Range.InlineShapes(1).ScaleWidth
end sub

В-четвертых, действительно Surface.Navigator не правильно возвращает угол, эта ошибка будет исправлена, но сейчас можно использовать MapWindow.Navigator
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Показать сообщения:   
Начать новую тему   Ответить на тему    Список форумов www.integro.ru -> Вопросы разработчиков Часовой пояс: GMT + 5
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете добавлять приложения в этом форуме
Вы можете скачивать файлы в этом форуме


© phpBB Group
Русская поддержка phpBB