WPF - XDL Tutorial

XDL MapView 활용 여섯번째

(piXoneer XDL Tutorial)

 

 

 

 

 

 

NXMapView를 활용하여 영상을 기반으로 하여

벡터 객체를 생성하는 기능을 구현합니다.

 

 

2019. 04.

 

 

내용

XDL MapView 활용 여섯번째... 1

1    사용하기... 1

1.1    메뉴에 Open/Save 기능 넣기... 1

1.2    메뉴에 벡터 기능 넣기... 1

1.3    참조 dll 추가하기... 1

1.4    코드 추가하기... 1

 

 

 

 

1     사용하기

본 튜터리얼을 공부하기 전에 먼저 XDL MapView 활용 다섯번째를 먼저 선행하시기 바랍니다.

 

1.1    메뉴에 Open/Save 기능 넣기

1.1.1     Window 창에 MenuItem을 이용하여 [File]-[Open XvcVector][File]-[Save XvcVector] 메뉴를 추가한다. 또한 [Save XvcVector] 메뉴 하부에 [Pixoneer XVML][External Vector Format] 메뉴를 추가한다. (표 참고)

 

 

 

Control Type

Header

Name

MenuItem

_Open XVcVector

openVectorFileMenuItem

 

Control Type

Header

Name

MenuItem

_Save XvcVector

 

MenuItem

_Pixoneer XVML

pixoneerXVMLFileMenuItem

MenuItem

_External Vector Format

externalVectorFormatFileMenuItem

 

1.2    메뉴에 벡터 기능 넣기

1.2.1     상위 메뉴로 Vector를 입력하고 다음과 같이 메뉴를 구성한다. (표 참고)

 

 

Control Type

Header

Name

MenuItem

_Vector

 

MenuItem

_Point

pointVectorMenuItem

MenuItem

_Line

lineVectorMenuItem

MenuItem

_Ellipse

ellipseVectorMenuItem

MenuItem

_Rectangle

rectangleVectorMenuItem

MenuItem

_PlolyLine

polyLineVectorMenuItem

MenuItem

_Polygon

polygonVectorMenuItem

MenuItem

_Text

textVectorMenItem

MenuItem

_Text Box

textBoxVectorMenuItem

MenuItem

_Measure

 

MenuItem

_MeasurePoint

measurePointVectorMenuItem

MenuItem

_MeasureDistance

measureDistanceVectorMenuItem

MenuItem

_MeasureArea

measureAreaVectorMenuItem

MenuItem

_MeasureAngle

measureAngleVectorMenuItem

MenuItem

_Property

propertyVectorMenuItem

 

1.3    참조 dll 추가하기

1.3.1     [참조추가] 기능을 통해 “C:\Pixoneer\XDL1.2\bin”으로 폴더를 이동하여 NXDLvc.dll를 선택하여 추가한다.

 

 

1.4    코드 추가하기

1.4.1     생성된 벡터를 저장하고 다시 열기 위한 XVectorIO객체를 생성한다.

namespace XLD_MapView6_2
{
public partial class MainWindow : Window
    {
        public XRasterIO m_RasterIO;   // 영상의 입출력을 담당할 객체 선언
        public XVectorIO m_VectorIO;   //벡터 객체의 입출력을 담당할 객체 선언
       

        public MainWindow()
        {
…

 

1.4.2     선언부에 벡터 객체를 핸들링하기 위해 using Pixoneer.NXDL.NVC;을 추가하고 생성자에 XMapLayerVectorEditor객체에 편집이 가능하도록 Editable속성을 true플래그로 설정하고, m_VectorIO객체를 생성 및 초기화 시킨다.

using Pixoneer.NXDL;        // 기본 함수 관련 기능
using Pixoneer.NXDL.NCC;    // 좌표 시스템 관련 기능
using Pixoneer.NXDL.NIO;    // 파일 입출력 관련 기능
using Pixoneer.NXDL.NRS;    // Remote Sensing 관련 기능
using Pixoneer.NXDL.NGR;    // Graphic관련 기능
using Pixoneer.NXDL.NVC;    // Vector 객체와 관련된 기능
using Pixoneer.NXDL.NXMap;  // MapView 관련 기능


public MainWindow()
{
    InitializeComponent();
    String StrError;
    m_RasterIO = new XRasterIO();   // 객체 생성
    if (m_RasterIO.Initialize(out StrError) == false)  // 영상 입출력 객체 초기화
    {
           System.Windows.Forms.MessageBox.Show(StrError);
    }
    nxMapLayerComposite1.LayerVisible = true;   // 영상레이어를 보이도록 속성을 변경

    if (!nxMapView1.SetBackgroundMap("C:\\Pixoneer\\XDL1.2\\Config\\XMapBase.xml"))
     {
            System.Windows.MessageBox.Show("배경맵이 설정되지 않았습니다.");
      }

    // 벡터 객체를 생성하고 편집하기 위해 
    nxMapLayerVectorEditor1.Editable = true;

    // 벡터를 저장하기 위해 벡터 IO객체를 생성
    m_VectorIO = new XVectorIO();
    if (m_VectorIO.Initialize(out StrError) == false)
        MessageBox.Show(StrError);
}

1.4.3     [File] 하부에 [Open XvcVector][Save XvcVector]에 대한 메뉴를 더블 클릭하고 자동 함수를 생성하여 다음과 같이 코드를 생성한다.

// Vector 객체 로딩
private void openXvcVectorFileMenuItem_Click(object sender, RoutedEventArgs e)
{
     // 열기위한 파일 다이얼로그 창 생성
     OpenFileDialog openFileDialog = new OpenFileDialog();
     openFileDialog.Multiselect = false;
     openFileDialog.Filter = "XvcBase Files|*.xvml";
     openFileDialog.RestoreDirectory = true;

      Nullable<bool> result = openFileDialog.ShowDialog();
      if (result != true) return;

      // XvcBase객체 생성(XvcObject들을 담기 위한 최상위 객체)
      String strError;
      XvcBase vcBase = new XvcBase();

      // XvcBase객체 로딩
      bool bres = vcBase.LoadFile(openFileDialog.FileName, out strError, null);

      if (bres)
       MessageBox.Show("Vector File Open Succeed", "Success",
 MessageBoxButton.OK, MessageBoxImage.Information);
      else
      {
          MessageBox.Show("Vector File Open Failed", "Fail",
MessageBoxButton.OK, MessageBoxImage.Error);
          return;
      }

      // 로딩된 XvcBase객체를 XMapLayerVectorEditor객체에 설정하여 재 편집이 
// 가능하도록 설정
      nxMapLayerVectorEditor1.SetEditBase(vcBase);
}

 

// 내부 xml 포맷인 XVML 파일로 저장
private void pixoneerXVMLFileMenuItem_Click(object sender, RoutedEventArgs e)
{
      // XvcBase 객체 생성(XvcObject들을 담기 위한 최상위 객체)
      Pixoneer.NXDL.NVC.XvcBase vcbase = nxMapLayerVectorEditor1.GetEditBase();
      if (vcbase == null) return;

      // 저장 경로 생성을 위한 Save 파일 다이얼로그 생성
      SaveFileDialog dialog = new SaveFileDialog();
      dialog.Title = "Save XvcBase File";
      dialog.DefaultExt = "xvml";
      dialog.Filter = "XvcBase Files|*.xvml";

      Nullable<bool> result = dialog.ShowDialog();
      if (result == true )
      {
      String strError;

      // XvcBase에 저장된 객체를 파일로 저장
       bool bres = vcbase.SaveFile(dialog.FileName, out strError, null);

       if (bres)
       MessageBox.Show("Vector File Save Succeed", "Success", MessageBoxButton.OK, 
MessageBoxImage.Information);
       else
       MessageBox.Show("Vector File Save Failed", "Fail", MessageBoxButton.OK, 
MessageBoxImage.Error);
       }         
}

 

// XDL이 지원하는 외부 벡터 객체를 로딩
private void externalVectorFormatFileMenuItem_Click(object sender, RoutedEventArgs e)
{
      // XMapLayerVectorEditor객체에 있는 XvcBase객체를 꺼내기.
      XvcBase vcbase = nxMapLayerVectorEditor1.GetEditBase();
      if (vcbase == null) return;

      // XDL이 지원하는 File filter 꺼내기
      String fileFilters = m_VectorIO.GetFiltersForSave();

      // 외부 파일로 저장하기 위해 저장 다이얼로그 생성
      SaveFileDialog dialog = new SaveFileDialog();
      dialog.Filter = fileFilters;

      Nullable<bool> result = dialog.ShowDialog();
      if (result == true) 
      {
          String vectorFileName = dialog.FileName;
          String VectorFileKey = ExtractFilterKey(fileFilters,
dialog.FilterIndex - 1);

          String strError;

      // 벡터를 외부 파일로 저장.
      bool bres = m_VectorIO.Export(ref vcbase, dialog.FileName, VectorFileKey,
 out strError, null);

      if (bres)
       MessageBox.Show("Vector File Save Succeed", "Success", MessageBoxButton.OK, MessageBoxImage.Information);
      else
      MessageBox.Show("Vector File Save Failed", "Fail", MessageBoxButton.OK, MessageBoxImage.Error);
      }
}

private String ExtractFilterKey(String strFilter, int idx)
{
       int tempidx = 0;
       String strKey = "";

       do
       {
            int idxDelim = strFilter.IndexOf(";|");
            if (idxDelim != -1)
            {
                String strKeyTemp = strFilter.Substring(0, idxDelim).Trim();
                int idxPipe = strKeyTemp.IndexOf('|');
                if (idxPipe != -1)
                {
                    strKey = strKeyTemp.Substring(0, idxPipe).Trim();
                }
                else
                {
                    strKey = strKeyTemp;
                }

                strFilter = strFilter.Remove(0, idxDelim + 2);
                tempidx++;
             }

       }    while (tempidx <= idx);
            return strKey;
}

1.4.4     [Vector] 하부에 [Point], [Line], [Ellipse], [Rectangle], [PolyLine], [Polygon,] [Text], [Text Box]의 메뉴를 더블클릭하고 자동 함수를 생성하여 다음과 같이 코드를 생성한다.

private void pointVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Point, null);
}

private void lineVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Line, null);
}

private void ellipseVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Ellipse, null);
}

private void rectangleVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Rectangle, null);
}

private void polyLineVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Polyline, null);
}

private void polygonVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Polygon, null);
}

private void textVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Text, null);
}

private void textBoxVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.Textbox, null);
}

 

1.4.5     측정도구를 위해 [MeasurePoint], [MeasureDistance], [MeasureArea], [MeasureAngle] 를 더블 클릭하여 자동 코드를 생성하고 다음과 같이 코드를 삽입한다.

private void measurePointVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.MeasurePoint, null);
}

private void measureDistanceVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.MeasureDist, null);
}

private void measureAreaVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.MeasureArea, null);
}

private void measureAngleVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
    nxMapLayerVectorEditor1.CreateNewOBJ(Pixoneer.NXDL.NVC.eXvcObjType.MeasureAngle, null);
}

 

1.4.6     특정 객체를 마우스로 선택한다. [Vector]-[Property]버튼을 더블 클릭하여 코드를 생성한다.

private void propertyVectorMenuItem_Click(object sender, RoutedEventArgs e)
{
        XvcObj Obj = nxMapLayerVectorEditor1.GetSelectedObj();
        if (Obj == null) return;
        ChangeProperty(Obj);
}

public void ChangeProperty(XvcObj Obj)
{
       // 선택된 객체가 null인 경우는 실행하지 않는다.
       if (Obj == null) { return; }

       eXvcObjType type = Obj.Type;

       // Property 창을 생성하고 기존 Object의 속성값을 Property창에 설정한다.
       PropertyXvcObj propertyDlg = new PropertyXvcObj();
       propertyDlg.m_strObjType = type.ToString();
       propertyDlg.m_nID = Obj.ID;
       propertyDlg.m_strName = Obj.Name;
       propertyDlg.m_crBack = Obj.ColorBack;
       propertyDlg.m_crFore = Obj.ColorFore;
       propertyDlg.m_crLine = Obj.ColorLine;
       propertyDlg.m_crText = Obj.ColorText;
       propertyDlg.m_dblThick = Obj.GetThick();
       propertyDlg.m_StyleFill = Obj.StyleFill;
       propertyDlg.m_StyleLine = Obj.StyleLine;

       //propertyDlg.Show();
            
       // Object Type에 따라 속성값을 Property창에 설정한다.
      if (type == eXvcObjType.Text)
      {
            propertyDlg.m_dblFontSize = ((XvcText)Obj).FontSize;
            propertyDlg.m_strFontName = ((XvcText)Obj).FontName;
            propertyDlg.m_bBold = ((XvcText)Obj).Bold;
            propertyDlg.m_bUnderline = ((XvcText)Obj).Underline;
            propertyDlg.m_bItalic = ((XvcText)Obj).Italic;
            propertyDlg.m_bStrikeOut = ((XvcText)Obj).StrikeOut;
       }

       else if (type == eXvcObjType.Line)
       {
            propertyDlg.m_LineStartShape = ((XvcLine)Obj).StartShapeType;
            propertyDlg.m_LineEndShape = ((XvcLine)Obj).EndShapeType;
       }

       // Object Type에 따라 속성값을 Property창에 설정한다.
       if((bool)propertyDlg.ShowDialog())
       {
            Obj.ID = propertyDlg.m_nID;
            Obj.Name = propertyDlg.m_strName;
            Obj.ColorBack = propertyDlg.m_crBack;
            Obj.ColorFore = propertyDlg.m_crFore;
            Obj.ColorLine = propertyDlg.m_crLine;
            Obj.SetThick(propertyDlg.m_dblThick);
            Obj.StyleFill = propertyDlg.m_StyleFill;
            Obj.StyleLine = propertyDlg.m_StyleLine;
            Obj.ColorText = propertyDlg.m_crText;

           // Object가 텍스트인경우 Text객체에 Property창에서 정의한 값을 설정한다.
           if (type == eXvcObjType.Text)
           {
               XvcText text = (XvcText)Obj;
               text.FontSize = propertyDlg.m_dblFontSize;
               text.FontName = propertyDlg.m_strFontName;
               text.Bold = propertyDlg.m_bBold;
               text.Underline = propertyDlg.m_bUnderline;
               text.Italic = propertyDlg.m_bItalic;
               text.StrikeOut = propertyDlg.m_bStrikeOut;
           }
           // Object가 Line인경우 Line객체에 Property창에서 정의한 값을 설정한다.
           else if (type == eXvcObjType.Line)
           {
               ((XvcLine)Obj).StartShapeType = propertyDlg.m_LineStartShape;
               ((XvcLine)Obj).EndShapeType = propertyDlg.m_LineEndShape;
           }
           this.nxMapView1.RefreshScreen();            
       }
}

 

1.4.7     [F5]키를 눌러 프로그램을 실행한다. [Vector]-[Line], [Polygon]등을 누른 후 도시화면상에 마우스를 클릭 및 드래깅하여 객체를 생성한다.

 

 

1.4.8     프로그램을 종료한다.

 

1.4.9     페이지(WPF)를 솔루션에 새롭게 추가하고 디자인한다.

새로운 Window를 추가하려면, Visual Studio의 메뉴 [프로젝트]-[페이지 추가]를 선택하거나, [솔루션 탐색기]에서 프로젝트를 선택한 후 마우스 오른쪽 버튼을 클릭하여 생성되는 메뉴에서 [추가]-[페이지]을 선택한다.

 

 

파일이름은 “PropertyXvcObj.xaml” 으로 정의한다.

 

 

1.4.10  XAML 창을 생성하여 Property 창을 디자인한다. Property 창에 대한 코드는 생략한다. 샘플코드를 다운로드 후 참조한다.

 

 

1.4.11   [F5]키를 눌러 프로그램을 실행시킨다. [Vector]-[Line]를 눌러 라인을 하나 그린다.

 

 

1.4.12   특정 객체를 마우스로 선택한다. [Vector]-[Property]버튼을 누른다.

 

 

 

1.4.13   속성값을 변경 후 OK를 클릭한다.