WPF - XDL Tutorial

XDL PlanetView È°¿ë ³×¹ø°

(piXoneer XDL Tutorial)

 

 

 

 

 

Pixoneer.NXDL.NNCWÀÇ XncwObserver, XncwTheater¸¦ ÀÌ¿ëÇÏ¿©

NCW ½Ã¹Ä·¹À̼ÇÀ» À§ÇÑ È¯°æÀ» ±¸¼ºÇÏ°í,

 Pixoneer.NXDL.NEQUIPÀÇ XAircraftŬ·¡½º¸¦ ÀÌ¿ëÇÏ¿© ½Ã¹Ä·¹ÀÌ¼Ç ´ë»óÀ»

 NCW(Network Centric Warfare)ȯ°æÀ» ±¸ÇöÇØ º¸µµ·Ï ÇÕ´Ï´Ù.

 

 

2019. 04.

 

 

¸ñÂ÷

XDL PlanetView È°¿ë ³×¹ø°... 1

1    »ç¿ëÇϱâ... 1

1.1    XDL ¿£Áø... 1

2    NXPlanetView¸¦ ÀÌ¿ëÇÑ ¿¹Á¦ ÇÁ·Î±×·¥ ¸¸µé±â... 1

2.1    ±âº» ÇÁ·Î±×·¥ ÀÛ¼º... 1

2.2    ÇÁ·Î±×·¥ µðÀÚÀÎ... 1

2.3    ±â´É ¹× À̺¥Æ® Ãß°¡... 1

 

 

 

 

1     »ç¿ëÇϱâ

 

1.1    XDL ¿£Áø

¼³Ä¡ ÇÁ·Î±×·¥À¸·Î ¹èÆ÷µÇ´Â XDL ¿£ÁøÀº Visual Studio 2010 x86 Release ¹öÀüÀ¸·Î, Visual Studio 2010 ÀÌ»óÀÇ ¹öÀü¿¡¼­ »ç¿ë °¡´ÉÇÏ´Ù.

¾Æ·¡ÀÇ ¼³¸íÀº Visual Studio 2015¸¦ ±âÁØÀ¸·Î ÇÏ°Ú´Ù.

2     NXPlanetView¸¦ ÀÌ¿ëÇÑ ¿¹Á¦ ÇÁ·Î±×·¥ ¸¸µé±â

l  º» ¿¹Á¦ ÇÁ·Î±×·¥Àº Pixoneer.NXDL.NNCWÀÇ XncwObserver, XncwTheater¸¦ ÀÌ¿ëÇÏ¿© NCW ½Ã¹Ä·¹À̼ÇÀ» À§ÇÑ È¯°æÀ» ±¸¼ºÇÏ°í, Pixoneer.NXDL.NEQUIPÀÇ XAircraft Ŭ·¡½º¸¦ ÀÌ¿ëÇÏ¿© ½Ã¹Ä·¹ÀÌ¼Ç ´ë»óÀ» NCW(Network Centric Warfare) ȯ°æ¿¡ Ãß°¡Çغ¸µµ·Ï ÇÑ´Ù.

l  3D ¸ðµ¨°ú ½Ã¹Ä·¹À̼ÇÀ» À§ÇÑ µ¥ÀÌÅÍ ÆÄÀÏÀ» ÀÌ¿ëÇØ XAircraft¸¦ Ãß°¡ÇÏ¿© 2D/3D Planet View¿¡¼­ µµ½ÃÇÏ°í, 2D PlanetView¿¡¼­ ¸¶¿ì½º ´õºíŬ¸¯À¸·Î XAircraft¸¦ ¼±ÅÃÇÏ¸é ½Ã¹Ä·¹ÀÌ¼Ç ºñÇàüÀÇ µµ½Ã ¼Ó¼º ¹× Ä«¸Þ¶ó ¸ðµå¸¦ ¼³Á¤ÇÏ¿© ½Ã¹Ä·¹ÀÌ¼Ç °üÃø ¸ðµå¸¦ º¯°æÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù.

 

2.1    ±âº» ÇÁ·Î±×·¥ ÀÛ¼º

2.1.1     Visual Studio 2015À» ÀÌ¿ëÇÏ¿© ¿¹Á¦ ¡°XDL_PlanetView2¡±ÀÇ ¡°±âº» ÇÁ·Î±×·¥ ÀÛ¼º¡± ¹æ¹ýÀ» Âü°í·Î ±âº» ÇÁ·ÎÁ§Æ®¸¦ »ý¼ºÇÑ´Ù.

ÇÁ·ÎÁ§Æ® À̸§Àº ¡°XDL_PlanetView4¡±·Î ÇÑ´Ù.

 

2.1.2     Pixoneer.NXDL.NNCW ¿Í Pixoneer.NXDL.NEQUIPÀ» ÀÌ¿ëÇϱâ À§Çؼ­ ¡°NXDLncw.dll¡±À» ÇÁ·ÎÁ§Æ®ÀÇ ÂüÁ¶·Î Ãß°¡ÇÑ´Ù.

 

2.1.3     Pixoneer.NXDL.NEQUIP.XAircraft °´Ã¼¸¦ ´Ù·ç±â À§ÇØ ½ÇÇàÆú´õ¿¡ ModelDrivers Æú´õ¸¦ º¹»çÇؼ­ ³Ö´Â´Ù.

º» ¿¹Á¦ ÇÁ·Î±×·¥Àº NCWÀÇ ½Ã¹Ä·¹ÀÌ¼Ç ´ë»óÀÌ µÇ´Â XAircraft¸¦ ÀÌ¿ëÇÑ´Ù. XAircraft´Â 3D ¸ðµ¨ ÆÄÀÏÀ» ·ÎµùÇÏ¿© È­¸é¿¡ µµ½ÃÇÑ´Ù. À̸¦ À§ÇØ ModelDrivers Æú´õ¸¦ ½ÇÇàÆú´õ¿¡ º¹»çÇØ ÁÖ¾î¾ß ÇÑ´Ù.

XDL ¶óÀ̺귯¸®°¡ ¼³Ä¡µÈ °æ·Î(c:\Pixoneer\XDL1.2\bin)·Î À̵¿ÇÏ¿© ¡°ModelDrivers¡± Æú´õ¸¦ º¹»çÇÏ¿© º» ¿¹Á¦ ÇÁ·Î±×·¥ÀÇ ½ÇÇà Æú´õ(.\XDL_PlanetView4\bin\Debug\)¿¡ º¹»çÇÏ¿© ³Ö´Â´Ù.

 

 

2.2    ÇÁ·Î±×·¥ µðÀÚÀÎ

 

 

 

Number

Name

Control type

ºñ°í

¨ç

menu1

Menu

 

¨è

separator

Separator

 

¨é

nxPlanetView2D

NXPlanetView

EarthMode : Planet2D

¨ê

nxPlanetView3D

NXPlanetView

EarthMode : Planet3D

 

2.2.1     MainWindow.xaml â¿¡¼­ ±âº»À¸·Î »ý¼ºµÈ Grid ·¹À̾ƿô¿¡ Grid.RowDefinitionÀ» ÀÌ¿ëÇÏ¿© µÎ °³ÀÇ Grid¸¦ »ý¼ºÇÑ´Ù. ù ¹ø° Grid¿¡ ¸Þ´º¸¦ »ý¼ºÇÒ °ÍÀÌ´Ù.

º» ¿¹Á¦ ÇÁ·Î±×·¥ÀÇ Menu ±¸¼ºÀº ¾Æ·¡¿Í °°´Ù.

 

 

Control Type

Header

Name

MenuItem

Model

 

MenuItem

Add

addModelMenuItem

 

2.2.2     ½Ã¹Ä·¹ÀÌ¼Ç ´ë»óÀÎ ºñÇàü¸¦ Ãß°¡ÇÏ´Â ÆäÀÌÁö(WPF)¸¦ ¼Ö·ç¼Ç¿¡ Ãß°¡ÇÏ°í µðÀÚÀÎÇÑ´Ù.

»õ·Î¿î Window¸¦ Ãß°¡ÇÏ·Á¸é, Visual StudioÀÇ ¸Þ´º [ÇÁ·ÎÁ§Æ®]-[ÆäÀÌÁö Ãß°¡]¸¦ ¼±ÅÃÇϰųª, [¼Ö·ç¼Ç Ž»ö±â]¿¡¼­ ÇÁ·ÎÁ§Æ®¸¦ ¼±ÅÃÇÑ ÈÄ ¸¶¿ì½º ¿À¸¥ÂÊ ¹öÆ°À» Ŭ¸¯ÇÏ¿© »ý¼ºµÇ´Â ¸Þ´º¿¡¼­ [Ãß°¡]-[ÆäÀÌÁö]À» ¼±ÅÃÇÑ´Ù.

 

 

ºñÇàü Ãß°¡¸¦ À§ÇÑ ÆäÀÌÁöÀÇ À̸§Àº ¡°AddPlane.xaml¡±·Î ÇÑ´Ù.

 

 

AddPlane.xamlÀÇ µðÀÚÀÎÀº ¾Æ·¡¿Í °°´Ù.

 

 

 

¹øÈ£

Name

Control type

ºñ°í

¨ç

textBoxID

TextBox

 

¨è

textBoxName

TextBox

 

¨é

textBoxPathModel

TextBox

 

¨ê

buttonLoadModel

Button

 

¨ë

textBoxPathData

TextBox

 

¨ì

buttonLoadData

Button

 

¨í

buttonOK

Button

DialogResult : true

¨î

buttonCancel

Button

DialogResult : false

 

buttonOK¿Í buttonCancelÀÇ ´õºí Ŭ¸¯ÇÏ¿© ÀÚµ¿À¸·Î Click À̺¥Æ®¸¦ ±¸ÇöÇÏ°í DialogResult¸¦ °¢°¢ true¿Í false·Î ¼³Á¤ÇÑ´Ù.

 

private void buttonOK_Click(object sender, RoutedEventArgs e)
{
      this.DialogResult = true;
            
}

private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
      this.DialogResult = false;
}

 

2.2.3     ºñÇàüÀÇ µµ½Ã ¼Ó¼º ¹× Ä«¸Þ¶ó ¸ðµå¸¦ ¼³Á¤ÇÏ´Â ÆäÀÌÁö¸¦ ¼Ö·ç¼Ç¿¡ Ãß°¡ÇÏ°í µðÀÚÀÎÇÑ´Ù.

XDL_PlanetView4¿¡ ¡°PlaneProperty.xaml¡±¶ó´Â ÆÄÀÏÀ̸§À¸·Î ÆäÀÌÁö¸¦ Ãß°¡ÇÑ´Ù.

PlaneProperty.xamlÀÇ µðÀÚÀÎÀº ¾Æ·¡¿Í °°´Ù.

 

 

 

Number

Name

Control type

ºñ°í

¨ç

textBoxID

TextBox

ReadOnly : True

¨è

textBoxName

TextBox

 

¨é

textBoxScaleX

TextBox

 

¨ê

textBoxScaleY

TextBox

 

¨ë

textBoxScaleZ

TextBox

 

¨ì

checkBoxScalable

CheckBox

 

¨í

comboBoxCameraMode

ComboBox

 

¨î

checkBoxShowBoundingBox

CheckBox

 

¨ï

buttonOK

Button

DialogResult : true

¨ð

buttonCancel

Button

DialogResult : false

 

comboBoxCameraMode´Â Pixoneer.NXDL.NNCW.XncwObserver.eViewMode¸¦ ¼±ÅÃÇÒ ¼ö ÀÖµµ·Ï Ç׸ñÀ» ÆíÁýÇÑ´Ù.

 

 

ComboBoxÀÇ ¼Ó¼º¿¡¼­ (1)À» Ŭ¸¯Çϸé Ä÷º¼Ç ÆíÁý±â âÀÌ ¶á´Ù. (2)¹øÀ» Ŭ¸¯ÇÏ¿© ComboBoxItemÀ» Ŭ¸¯ÇÏ°í Ãß°¡¹öÆ°À» Ŭ¸¯ÇÏ¿© Ãß°¡ÇÑ´Ù. (3)ÀÇ Content¸¦ Ç׸ñÀ¸·Î´Â ¼ø¼­´ë·Î ¡°Back View¡±, ¡°Front View¡±, ¡°Left View¡±, ¡°Right View¡±, ¡°God¡¯s eye View¡±, ¡°God¡¯s eye View Static¡±, ¡°Bottom View¡±, ¡°Bottom View Static¡±, ¡°Inside View¡±, ¡°Inside View free¡±, ¡°Far View¡±, ¡°Unusable¡±À» ÀÔ·ÂÇÏ¿© ComboBoxItemÀ» »ý¼ºÇϵµ·Ï ÇÑ´Ù.

 

2.3    ±â´É ¹× À̺¥Æ® Ãß°¡

2.3.1     Window.xaml.cs¿¡ NCW¸¦ À§ÇÑ º¯¼ö¸¦ Ãß°¡ÇÏ°í Window.xaml.csÀÇ »ý¼ºÀÚ¿¡¼­ ÃʱâÈ­ÇÑ´Ù.

NCW ȯ°æÀ» À§ÇÑ ·¹À̾î´Â Pixoneer.NXDL.NNCW.XncwTheater xncwTheater º¯¼ö·Î ÇÏ°í, Planet 2D¿Í 3D¿¡¼­ ½Ã¹Ä·¹ÀÌ¼Ç Áֽø¦ À§ÇÑ ·¹À̾î´Â °¢°¢ Pixoneer.NXDL.NNCW.XncwObserverÀÇ xncwObserver2D, xncwObserver3D·Î ÇÏ°Ú´Ù. ÄÚµå´Â ¾Æ·¡¿Í °°´Ù.

using Pixoneer.NXDL;                // ±âº» ÇÔ¼ö °ü·Ã ±â´É
using Pixoneer.NXDL.NXPlanet;       // ±¸ ±â¹Ý µµ½Ã °ü·Ã ±â´É
using Pixoneer.NXDL.NNCW;           // NCW ȯ°æ °ü·Ã ±â´É
using Pixoneer.NXDL.NEQUIP;         // NCW ȯ°æ¿¡¼­ ½Ã¹Ä·¹À̼ÇÇÏ´Â ¸ðµ¨ °ü·Ã ±â´É

namespace XDL_PlanetView4
{
    public partial class MainWindow : Window
{
        private XncwTheater xncwTheater;        // ncw ȯ°æÀ» À§ÇÑ ·¹À̾î
        private XncwObserver xncwObserver2D;    
// 2D Planet¿¡¼­ ½Ã¹Ä·¹ÀÌ¼Ç ¸ðµ¨ Áֽà ±â´ÉÀ» ´ã´çÇÒ ·¹À̾î
        private XncwObserver xncwObserver3D;    
// 3D Planet¿¡¼­ ½Ã¹Ä·¹ÀÌ¼Ç ¸ðµ¨ Áֽà ±â´ÉÀ» ´ã´çÇÒ ·¹À̾î

         public MainWindow()
         {
            InitializeComponent();

            // PlanetView 2D/3DÀÇ ¹è°æ»ö ¼³Á¤
            nxPlanetView2D.BackColor =  System.Drawing.Color.Black;
            nxPlanetView3D.BackColor =  System.Drawing.Color.Black;

            // NCW¸¦ À§ÇÑ theater °´Ã¼, observer °´Ã¼ »ý¼º
            xncwTheater = new XncwTheater();
            xncwObserver2D = new XncwObserver();
            xncwObserver3D = new XncwObserver();
         }
    }

2.3.2     WindowÀ» ¼±ÅÃÇÏ°í [¼Ó¼º] â - [À̺¥Æ® ] ¸Þ´º¸¦ ¼±ÅÃÇÑ µÚ ¡°Loaded¡± À̺¥Æ®¿Í ¡°Closed¡± À̺¥Æ®¸¦ ´õºí Ŭ¸¯ÇÑ´Ù.

Window_Loaded ÇÔ¼ö¿¡´Â xncwTheater¿Í xncwObserver2D, xncwObserver3D¸¦ nxPlanetView2D¿Í nxPlanetView3D¿¡ Ãß°¡ÇÏ°í °¢ viewÀÇ Ä«¸Þ¶ó ÃʱⰪÀ» ¼³Á¤ÇÑ´Ù.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
      nxPlanetView2D.AddRenderLayer(ref nxPlanetLayer2D);

      // Theater °´Ã¼¸¦ Planet 2D/3D ºä¿¡ Ãß°¡
      xncwTheater.AttachTo(nxPlanetView2D);
      xncwTheater.AttachTo(nxPlanetView3D);

      // TheaterÀÇ ¸ðµç °´Ã¼¸¦ PlanetView 3D¿¡¼­´Â Ç×»ó ÁÖ½ÃÇÒ ¼ö ÀÖµµ·Ï ¼³Á¤
      xncwTheater.ShowAllObjects(nxPlanetView3D, true);

      // °¢ PlanetView¿¡ °üÂûÀ» À§ÇÑ Observer °´Ã¼¸¦ °¢°¢ Ãß°¡ÇÑ´Ù.
      xncwObserver2D.AttachTo(nxPlanetView2D);
      xncwObserver3D.AttachTo(nxPlanetView3D);

      XGeoPoint gpEye = XGeoPoint.FromDegree(127.4, 38.0, 1500000);
      // Planet2D ¸ðµåÀÇ camera À§Ä¡ ¼³Á¤
      nxPlanetView2D.SetCameraPosition(gpEye, XAngle.FromDegree(0.0));
      // Planet3D ¸ðµåÀÇ camera À§Ä¡ ¼³Á¤
      nxPlanetView3D.SetCameraPosition(gpEye, XAngle.FromDegree(0.0), 
XAngle.FromDegree(-90.0), XAngle.FromDegree(0.0));
}

 

private void Window_Closed(object sender, EventArgs e)
{
      Xfn.Close();
}

2.3.3     ½Ã¹Ä·¹ÀÌ¼Ç ´ë»óÀÎ ¸ðµ¨À» ±¸ÇöÇϱâ À§Çؼ­ ÇÁ·ÎÁ§Æ®¿¡ »õ·Î¿î Ŭ·¡½º¸¦ Ãß°¡ÇÑ´Ù.

½Ã¹Ä·¹ÀÌ¼Ç ´ë»óÀÇ ¸ðµ¨Àº MyPlaneÀ¸·Î ÇÏ°í À̸¦ ÇÁ·ÎÁ§Æ®¿¡ Ãß°¡ÇÑ´Ù. Visual Studio 2015ÀÇ ¸Þ´º [ÇÁ·ÎÁ§Æ®]-[»õ Ç׸ñ Ãß°¡] ¶Ç´Â [¼Ö·ç¼Ç Ž»ö±â]¿¡¼­ ¡°XDL_PlanetView4¡± ÇÁ·ÎÁ§Æ®¸¦ ¼±ÅÃÇÑ ÈÄ ¸¶¿ì½º ¿À¸¥ÂÊ ¹öÆ°À» Ŭ¸¯ÇÏ¿© »ý±â´Â ¸Þ´º Áß [Ãß°¡]-[»õ Ç׸ñ]À» ¼±ÅÃÇÑ´Ù.

¡°»õ Ç׸ñ Ãß°¡¡± ´ëÈ­»óÀÚ¿¡¼­ ¡°Å¬·¡½º¡±¸¦ ¼±ÅÃÇÑ ÈÄ À̸§À» ¡°MyPlane.cs¡±·Î ÇÏ°í ¡°Ãß°¡¡± ¹öÆ°À» Ŭ¸¯ÇÑ´Ù.

 

 

2.3.4     Pixoneer.NXDL.NEQUIPT.XAircraft¸¦ »ó¼Ó¹ÞÀº MyPlane Ŭ·¡½º¸¦ ±¸ÇöÇÑ´Ù.

MyPlaneÀº ½Ã¹Ä·¹À̼ÇÀ» À§ÇÑ ¸ðµ¨ÆÄÀÏÀ» ·ÎµùÇÏ¿© ÆÄÀÏ¿¡ ÀúÀåµÇ¾î ÀÖ´Â ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅ͸¦ 100 milli seconds¸¶´Ù Àоî À§Ä¡¿Í ÀÚ¼¼¸¦ ¼³Á¤Çϵµ·Ï ÇÑ´Ù. À̸¦ À§Çؼ­ System.Threading °ü·Ã ±â´É°ú System.IO °ü·Ã ±â´ÉÀ» »ç¿ëÇÑ´Ù. MyPlane Ŭ·¡½º ±¸ÇöÀº ¾Æ·¡¿Í °°´Ù.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


using System.IO;          // FileStream °ü·Ã ±â´É
using System.Threading;   // Threading °ü·Ã ±â´É

using Pixoneer.NXDL;          // ±âº» ÇÔ¼ö °ü·Ã ±â´É
using Pixoneer.NXDL.NNCW;     // NCW ȯ°æ °ü·Ã ±â´É
using Pixoneer.NXDL.NEQUIP;   // NCW ȯ°æ¿¡¼­ ½Ã¹Ä·¹À̼ÇÇÏ´Â ¸ðµ¨ °ü·Ã ±â´É

namespace XDL_PlanetView4
{
    class MyPlane : XAircraft
    {
        public string modelPathData;  // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ ÆÄÀÏ °æ·Î
        public string modelPathModel; // ¸ðµ¨ ÆÄÀÏ °æ·Î
        public string modelName;      // ¸ðµ¨ À̸§
        public int modelID;           // ¸ðµ¨ ±¸º°ÀÚ

        // ½Ã¹Ä·¹ÀÌ¼Ç ÁÖ½Ã(°üÃø) ¸ðµå
        public XncwObserver.eViewMode cameraMode;
        // ¸ðµ¨ÀÇ °æ°è ¿µ¿ª µµ½Ã ¿©ºÎ
        public bool modelShowBoundingBox;

        private FileStream modelFileData;      // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍÆÄÀÏ
        private Thread modelThread;            // ½Ã¹Ä·¹À̼ÇÀ» À§ÇÑ ¾²·¹µå
        private bool runThread;                // ½Ã¹Ä·¹ÀÌ¼Ç ¾²·¹µå ¿©ºÎ °áÁ¤
        //internal bool Scalable;

        // Ŭ·¡½º »ý¼ºÀÚ
        public MyPlane()
        {
            modelPathData = "";
            modelPathModel = "";
            modelName = "MyPlane";
            modelID = 0;

            // Camera °üÃø¸ðµå
            // UnuableÀÎ °æ¿ì ƯÁ¤ ¸ðµ¨À» ÁÖ½ÃÇÏÁö ¾ÊÀ» ¶§ »ç¿ë
            cameraMode = XncwObserver.eViewMode.Unusable;
            modelShowBoundingBox = false;
            modelFileData = null;
            modelThread = null;
            runThread = false;
        }

        // ¸ðµ¨ °æ·Î, ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ °æ·Î, 
// À̸§ ¹× ID¸¦ ÀÔ·ÂÀ¸·Î ¹Þ¾Æ ÃʱâÈ­ÇÏ´Â ÇÔ¼ö
        public bool Initialize(string pathModel, string pathData, string name, int nID)
       {
            // ÆÄÀÏ °æ·Î·ÎºÎÅÍ ¸ðµ¨ µ¥ÀÌÅÍ ·Îµù
            if (!LoadModel(pathModel)) return false;

            // ¸â¹ö º¯¼ö ¼³Á¤
            modelName = name;
            modelID = nID;
            modelPathData = pathData;

            // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ ·Îµù
            modelFileData = new FileStream(modelPathData, FileMode.Open, 
FileAccess.Read);
            return true;
        }

 

À̾ ´ÙÀ½ Äڵ带 Ãß°¡ÇÑ´Ù.

// ½Ã¹Ä·¹ÀÌ¼Ç ±â´É ¹× µ¥ÀÌÅ͸¦ ÇØÁ¦ÇÏ´Â ÇÔ¼ö
       public void Uninitialize()
       {

          // ¾²·¹µå°¡ ÀÖ´Â °æ¿ì À̸¦ ÇØÁ¦
          if (modelThread != null)
          {
              runThread = false;
              if (modelThread.IsAlive)
                   modelThread.Join();
              modelThread = null;

          }
          // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ°¡ ÀÖ´Â °æ¿ì À̸¦ ÇØÁ¦
          if (modelFileData != null) modelFileData.Close();
       }

       // ½Ã¹Ä·¹ÀÌ¼Ç ÇÔ¼ö
       public void SimulationThread()
       {
           // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ°¡ ¾ø´Â °æ¿ì ÁøÇàÇÏÁö ¾Ê´Â´Ù.
           if (modelFileData == null) return;

           // ½Ã¹Ä·¹ÀÌ¼Ç ½ÇÇà ¿©ºÎ¸¦ ½ÇÇàÇÏ´Â °ÍÀ¸·Î ¼³Á¤
           runThread = true;
           // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ Å©±â ¼³Á¤
           int frameDataSize = 14/* ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§¸¦ ÀÌ·ç´Â Ç׸ñ °³¼ö */ * 4 /*float µ¥ÀÌÅÍ Å©±â */;
           // Àüü ÆÄÀÏ Å©±â¸¦ ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ Å©±â·Î ³ª´©¾î Àüü ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ °³¼ö °è»ê
           long dataSize = modelFileData.Length / frameDataSize;
           // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§¸¦ Àбâ À§ÇÑ buffer »ý¼º
           byte[] buff = new byte[frameDataSize];

           while (runThread)
           {
               int idx = 0, count = 0;
               // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ ÆÄÀÏÀÇ Ã³À½À¸·Î À̵¿
               modelFileData.Seek(0, SeekOrigin.Begin);

               do
               {
                  if (!runThread) break;
 
                  // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ ÆÄÀÏ¿¡¼­ ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ Àбâ
                  count = modelFileData.Read(buff, 0, frameDataSize);

                  // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ¿¡¼­ ¼Óµµ °¡Á®¿À±â
                  double speed = BitConverter.ToSingle(buff, 0);
                  // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ¿¡¼­ À§Ä¡ÀÇ À§µµ °¡Á®¿À±â
                  double lat = BitConverter.ToSingle(buff, 4);
                  // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ¿¡¼­ À§Ä¡ÀÇ °æµµ °¡Á®¿À±â
                  double lon = BitConverter.ToSingle(buff, 8);
                  // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ¿¡¼­ À§Ä¡ÀÇ ³ôÀÌ °¡Á®¿À±â
                  double alt = BitConverter.ToSingle(buff, 12);

                  // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ¿¡¼­ ÀÚ¼¼ÀÇ yaw °¡Á®¿À±â
                  double yaw = BitConverter.ToSingle(buff, 16);
                  // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ¿¡¼­ ÀÚ¼¼ÀÇ roll °¡Á®¿À±â
                  double roll = BitConverter.ToSingle(buff, 20);
                  // ½Ã¹Ä·¹ÀÌ¼Ç ´ÜÀ§ µ¥ÀÌÅÍ¿¡¼­ ÀÚ¼¼ÀÇ pitch °¡Á®¿À±â
                  double pitch = BitConverter.ToSingle(buff, 24);

                  XGeoPoint geoPos = new XGeoPoint();
                  geoPos.lond = lon;
                  geoPos.latd = lat;
                  geoPos.hgt = alt;

                  // ¸ðµ¨ÀÇ À§Ä¡ ¼³Á¤
                  SetPosition(geoPos);
                 // ¸ðµ¨ÀÇ ÀÚ¼¼ ¼³Á¤
                  SetYawPitchRoll(XAngle.FromDegree(yaw), 
XAngle.FromDegree(pitch), XAngle.FromDegree(roll));
                  // 100 milli second µ¿¾È ½Ã¹Ä·¹À̼ÇÀ» ½®´Ù.
                  Thread.Sleep(100);

                  idx++;
                }
               // Thread Á¾·á Á¶°ÇÀ» °Ë»çÇÔ
               while ((count == frameDataSize) && (idx < dataSize));
               Thread.Sleep(100);
           }
}

       // ½Ã¹Ä·¹À̼ÇÀ» ½ÃÀÛÇÏ´Â ÇÔ¼ö
       public void Start()
       {
           // ÀÌ¹Ì thread°¡ ½ÇÇàµÈ »óÅÂÀÌ¸é ¸®ÅÏ
           if (modelThread != null) return;

           // SimulationThread ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ thread »ý¼º
           modelThread = new Thread(SimulationThread);
           // Thread ½ÃÀÛ
           modelThread.Start();
       }
}
}

 

2.3.5     WindowÀÇ ¸Þ´º [Model]-[Add]¸¦ Ŭ¸¯ÇÏ¿© MyPlaneÀ» Ãß°¡Çϱâ À§ÇÑ AddPlaneŬ·¡½º¸¦ ±¸ÇöÇÑ´Ù. AddPlane.xaml âÀ» ¿­°í Windowâ¿¡¼­ ModelÀ» ºÒ·¯¿À´Â ¹öÆ°°ú DataÀ» ºÒ·¯¿À´Â ¹öÆ°À» ´õºí Ŭ¸¯ÇÑ´Ù. ¶ÇÇÑ [OK] ¹öÆ°°ú [Cancel] ¹öÆ°µµ ´õºí Ŭ¸¯ÇÏ¿© À̺¥Æ® ÇÔ¼ö¸¦ Ãß°¡ÇÑ´Ù.

AddPlane Ŭ·¡½º¸¦ ÅëÇØ MyPlane »ý¼ºÀ» À§ÇÑ ¸ðµ¨ ÆÄÀÏ °æ·Î, ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ °æ·Î, ¸ðµ¨ À̸§°ú ¸ðµ¨ ID¸¦ ÀÔ·ÂÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù. AddPlane Ŭ·¡½º ±¸ÇöÀº ¾Æ·¡¿Í °°´Ù.

//AddPlane.xaml

namespace XDL_PlanetView4
{
    
    public partial class AddPlane : Window
    {
        public string pathModel;  // ¸ðµ¨ °æ·Î
        public string pathData;   // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ °æ°í
        public string nameModel;  // ¸ðµ¨ À̸§
        public int ID;            // ¸ðµ¨ ½Äº°ÀÚ

        // AddPlane »ý¼ºÀÚ
        public AddPlane()
        {
            InitializeComponent();
        }

        // OK ¹öÆ° À̺¥Æ®ÇÔ¼ö
        private void buttonOK_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            ID = int.Parse(textBoxID.Text);
            nameModel = textBoxName.Text;
        }

        private void buttonCancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        // 3DS ¸ðµ¨ ÆÄÀÏ °æ·Î¸¦ ¼³Á¤ÇÏ´Â buttonLoadModel ¹öÆ° À̺¥Æ® ÇÔ¼ö
        private void buttonLoadModel_Click(object sender, RoutedEventArgs e)
        {
            // ¿­±â ´ëÈ­ »óÀÚ »ý¼º
            OpenFileDialog dlg = new OpenFileDialog();
            // 3DS ¸ðµ¨ ÆÄÀÏÀ» ¼±ÅÃÇÒ ¼ö ÀÖµµ·Ï ¿­±â ´ëÈ­»óÀÚ ÇÊÅÍ ¼³Á¤
            dlg.Filter = "Model FIle(*.3ds)|*.3ds;||";
            Nullable<bool> result = dlg.ShowDialog();
            if (result != true) return;

            // ¸ðµ¨ °æ·Î ¼³Á¤
            pathModel = dlg.FileName;
            textBoxPathModel.Text = pathModel;
        }

        // ½Ã¹Ä·¹ÀÌ¼Ç µ¥ÀÌÅÍ °æ·Î¸¦ ¼³Á¤ÇÏ´Â buttonLoadData ¹öÆ° À̺¥Æ® ÇÔ¼ö
        private void buttonLoadData_Click(object sender, RoutedEventArgs e)
        {
            // ¿­±â ´ëÈ­ »óÀÚ »ý¼º
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "Data File(*.dat)|*.dat;||";
            Nullable<bool> result = dlg.ShowDialog();
            if (result != true) return;

            // ½Ã¹Ä·¹ÀÌ¼Ç °æ·Î ¼³Á¤
            pathData = dlg.FileName;
            textBoxPathData.Text = pathData;
        }
     }
}

2.3.6     NCW ȯ°æ¿¡ Ãß°¡ÇÏ´Â Model¸¦ °ü¸®Çϱâ À§ÇØ List °´Ã¼¸¦ MainWindow.xaml¿¡ Ãß°¡ÇÑ´Ù.

List<MyPlane> ÇüÀÇ º¯¼ö¸¦ Ãß°¡ÇÑ´Ù.

// MainWindow.xaml.cs

// NCW ¸ðµ¨À» °ü¸®Çϱâ À§ÇÑ List °´Ã¼
private List<MyPlane> modelList = new List<MyPlane>();

 

2.3.7     MyModel Ŭ·¡½º°¡ ½Ã¹Ä·¹À̼ÇÀ» ½ÃÀÛÇϸé 100 milliseconds¸¶´Ù °»½ÅµÇ´Â À§Ä¡¿Í ÀÚ¼¼¿¡ ´ëÇØ È­¸é¿¡ °»½ÅÇÏ¿© µµ½ÃÇÒ ¼ö ÀÖµµ·Ï thread º¯¼ö¸¦ Ãß°¡ÇÑ´Ù.

// MainWindow.xaml.cs

// È­¸é °»½ÅÀ» À§ÇÑ Thread
private Thread threadRefresh = null;
private bool runThread = false;

// È­¸é °»½ÅÀ» ¿äûÇÏ´Â thread¸¦ À§ÇÑ ÇÔ¼ö
public void RefreshScreenThread()
{
       // thread ½ÇÇà ¿©ºÎ ¼³Á¤
       runThread = true;
       while (runThread)
       {
            // xnwTheaterÀÇ °¡½Ã¿µ¿ª °»½Å
            xncwTheater.UpdateVisibleArea();

            // nxPlanetView2D¿Í nxPlanetView3D¿¡ È­¸é °»½Å ¿äû
            nxPlanetView2D.RefreshScreen();
            nxPlanetView3D.RefreshScreen();

            // 100 mili seconds µ¿¾È threadingÀ» ½®´Ù.
            Thread.Sleep(100);
       }
}

 

2.3.8     MenuÀÇ [Model]-[Add]¸¦ Ŭ¸¯ÇÑ ÈÄ [¼Ó¼º]â¿¡¼­ ClickÀ» ´õºí Ŭ¸¯ÇÏ¿© À̺¥Æ®ÇÔ¼ö¸¦ Ãß°¡ÇÑ´Ù.

[Model]-[Add] ¸Þ´º¸¦ ¼±ÅÃÇؼ­ NCW ȯ°æ¿¡ MyPlane ¸ðµ¨À» Ãß°¡ÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù.

private void addModelMenuItem_Click(object sender, RoutedEventArgs e)
{
       // AddPlane »ý¼ºÇÏ¿© MyPlaneÀ» À§ÇÑ ¼Ó¼º ¼³Á¤
       AddPlane addForm = new AddPlane();

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

       MyPlane newPlane = new MyPlane();
       // MyPlane °´Ã¼¿¡ ¸Å°³º¯¼ö¸¦ ÀÌ¿ëÇÏ¿© ÃʱâÈ­
       if (!newPlane.Initialize(addForm.pathModel, addForm.pathData, addForm.nameModel, addForm.ID))
       {
            MessageBox.Show("ModelÀ» ·ÎµùÇÒ ¼ö ¾ø½À´Ï´Ù.");
            return;
       }

       // MyPlane °´Ã¼ÀÇ Å©±âÁ¶Àý ¿©ºÎ¸¦ Á¶ÀýÇÑ´Ù.
       newPlane.Scalable = false;

       XEquipObj newObj = newPlane;
       // xncwTheater¿¡ »õ·Î¿î ¸ðµ¨À» Ãß°¡ÇÑ´Ù.
       if (xncwTheater.AddEquipment(newPlane.modelID, ref newObj))
       {
           // ¸ðµ¨ ¸®½ºÆ®¿¡ »õ·Î¿î ¸ðµ¨ Ãß°¡
           modelList.Add(newPlane);

           // »õ·Î¿î ¸ðµ¨ÀÇ ½Ã¹Ä·¹ÀÌ¼Ç ½ÃÀÛ
           newPlane.Start();
           // xncwTheaterÀÇ °¡½Ã¿µ¿ª °»½Å
           xncwTheater.UpdateVisibleArea();

           // nxPlanetView2D¿Í nxPlanetView3DÀÇ µµ½Ã °»½Å ¿äû
           nxPlanetView2D.RefreshScreen();
           nxPlanetView3D.RefreshScreen();

           if (threadRefresh == null)
           {
                // È­¸é °»½ÅÀ» À§ÇÑ thread »ý¼º
                threadRefresh = new Thread(RefreshScreenThread);
                threadRefresh.Start();
           }
        }
        else
        // xncwTheater¿¡ ¸ðµ¨ Ãß°¡¸¦ ÇÏÁö ¸øÇϸé MyPlaneÀ» ÇØÁ¦ÇÑ´Ù.
         newPlane.Uninitialize();
}

 

2.3.9     Window°¡ ´ÝÈú ¶§ È­¸é °»½ÅÀ» À§ÇÑ thread¿Í MyPlaneÀ» ÇØÁ¦ÇÑ´Ù. À̸¦ À§ÇØ Window¿¡ ¡°Closing¡± À̺¥Æ®¸¦ Ãß°¡ÇÑ´Ù.

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
     // È­¸é °»½ÅÀ» À§ÇÑ thread¸¦ ÇØÁ¦ÇÑ´Ù.
     if (threadRefresh != null)
     {
          runThread = false;
          if (threadRefresh.IsAlive)
          threadRefresh.Join();
          threadRefresh = null;
      }

      // MyPlane °´Ã¼¸¦ ÇØÁ¦ÇÑ´Ù.
      foreach (MyPlane obj in modelList)
      {
          obj.Uninitialize();
      }
      modelList.Clear();
}

 

2.3.10  ¼Ö·ç¼ÇÀ» ºôµåÇÏ°í ½ÇÇàÇÑ´Ù.

¼Ö·ç¼ÇÀ» ½ÇÇàÇÏ¿© ¸Þ´º [Model]-[Add]¸¦ Ŭ¸¯ÇÑ´Ù.

 

 

½Ã¹Ä·¹ÀÌ¼Ç ¸ðµ¨À» Ãß°¡Çϱâ À§Çؼ­ ¸ðµ¨ ÆÄÀÏ°ú ½Ã¹Ä·¹ÀÌ¼Ç ÆÄÀÏÀ» ¼³Á¤ÇÑ´Ù. µÎ °³ÀÇ ÆÄÀÏÀº ȨÆäÀÌÁö¿¡ ¿¹Á¦ ÆÄÀÏ°ú ÇÔ²² ÀÖ´Â »ùÇõ¥ÀÌÅ͸¦ ÀÌ¿ëÇÏ±æ ¹Ù¶õ´Ù.

AddPlane¿¡¼­ ModelÀ» ºÒ·¯¿À´Â ¹öÆ°À» Ŭ¸¯Çؼ­ ¡°uav0216.3DS¡± ÆÄÀÏÀ» ¼±ÅÃÇÑ´Ù. À̾ Data¸¦ ºÒ·¯¿À´Â ¹öÆ°À» Ŭ¸¯Çؼ­ ¡°FlightData1.dat¡± ÆÄÀÏÀ» ¼±ÅÃÇÑ´Ù.

 

 

ID¿Í Name ¼Ó¼ºµµ ¼³Á¤ÇÏ°í ¡°OK¡± ¹öÆ°À» Ŭ¸¯ÇÑ´Ù. »õ·Î¿î ¸ðµ¨ÀÌ Ãß°¡µÇ¸é nxPlanetView2D¿Í nxPlanetView3D¿¡ ¸ðµ¨ÀÌ Ãß°¡µÇ¾î È­¸é¿¡ µµ½ÃµÇ°í 100 milliseconds¸¶´Ù ºñÇàüÀÇ À§Ä¡¿Í ÀÚ¼¼°¡ º¯È­µÇ´Â °ÍÀ» È®ÀÎÇÒ ¼ö ÀÖ´Ù.

 

 

2.3.11  nxPlanetView2D¿¡¼­ ½Ã¹Ä·¹ÀÌ¼Ç ¸ðµ¨À» ¸¶¿ì½º ´õºí Ŭ¸¯Çϸé ÇØ´ç ¸ðµ¨ÀÇ µµ½Ã ¼Ó¼º ¹× camera ¸ðµå¸¦ ¼³Á¤ÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù. À̸¦ À§ÇØ nxPlanetView2D¿¡ NXPlanetLayer¸¦ Ãß°¡ÇÏ°í xncwTheaterÀÇ PickÇÔ¼ö¿Í OnPicked À̺¥Æ®¸¦ ÀÌ¿ëÇÑ´Ù.

NXPlanetLayer Ŭ·¡½ºÀÇ nxPlanetLayer2D º¯¼ö¸¦ Ãß°¡ÇÏ°í WindowÀÇ Loaded ÇÔ¼ö¿¡¼­ nxPlanetView2D¿¡ Ãß°¡ÇÏ°í nxPlanetLayer2DÀÇ OnWndProc À̺¥Æ® ÇÔ¼ö¿Í xncwTheaterÀÇ OnPicked À̺¥Æ® ÇÔ¼ö¸¦ Ãß°¡ÇÑ´Ù.

ÄÚµå´Â ¾Æ·¡¿Í °°´Ù.

private NXPlanetLayer nxPlanetLayer2D;

public MainWindow()
{
    ¡¦

    // À©µµ¿ì À̺¥Æ®¸¦ ¹Þ±â À§ÇÑ NXPlanetLayer º¯¼ö ¹× À̺¥Æ® ÇÔ¼ö Ãß°¡
    nxPlanetLayer2D = new NXPlanetLayer();
    nxPlanetLayer2D.OnWndProc += 
new NXPlanetLayerWndProcEvent(nxPlanetLayer2D_OnWndProc);

    // xncwTheaterÀÇ OnPicked À̺¥Æ® ÇÔ¼ö Ãß°¡
    xncwTheater.OnPicked += new XncwTheaterPickEvent(xncwTheater_OnPicked);
}

private bool nxPlanetLayer2D_OnWndProc(object sender, NXPlanetDrawArgs e, ref System.Windows.Forms.Message m)
{
     // ¸¶¿ì½º ¿ÞÂÊ ¹öÆ°À» ´õºí Ŭ¸¯
     if (m.Msg == Pixoneer.NXDL.XWndMsg.XWM_LBUTTONDBLCLK)
     {
          // È­¸é ÁÂÇ¥
          XVertex2d scrPos = new XVertex2d();
          scrPos.x = Pixoneer.NXDL.XWndMsg.GetLowValue(m.LParam);
          scrPos.y = Pixoneer.NXDL.XWndMsg.GetHighValue(m.LParam);

          // xncwTheater¿¡ È­¸é ÁÂÇ¥¿¡ ´ëÇØ nxPlanetView2D¿¡¼­ hit-test¸¦ ¼öÇàÇÑ´Ù.
          // Pick ÇÔ¼ö°¡ ¼º°øÀûÀ¸·Î ½ÇÇàµÇ¸é xncwTheaterÀÇ OnPicked°¡ È£ÃâµÈ´Ù.
           xncwTheater.Pick(nxPlanetView2D.GetHandle(), scrPos);
      }
            return default(bool);
}

 

2.3.12  MyPlane °´Ã¼ÀÇ µµ½Ã¼Ó¼º ¹× Ä«¸Þ¶ó ¸ðµå¸¦ ¼³Á¤ÇÏ´Â PlaneProperty Ŭ·¡½º¸¦ ±¸ÇöÇÏ´Ù. xncwTheaterÀÇ Pick ÇÔ¼ö·Î ¼±ÅÃµÈ °´Ã¼°¡ returnµÇ¸é ÀÌ Å¬·¡½º¸¦ ÀÌ¿ëÇÏ¿© °´Ã¼ÀÇ ¼Ó¼ºÀ» º¯°æÇÑ´Ù.

PlaneProperty Window¿¡ Loaded À̺¥Æ®¿Í [OK] ¹öÆ°°ú [Cancel] ¹öÆ°¿¡ Click À̺¥Æ® ÇÔ¼ö¸¦ Ãß°¡ÇÏ°í Äڵ带 ÀÛ¼ºÇÑ´Ù. PlanePropertyÀÇ ±¸Çö ³»¿ëÀº ¾Æ·¡¿Í °°´Ù.

using Pixoneer.NXDL.NNCW;
using System.Windows.Threading;

namespace XDL_PlanetView4
{
   public partial class PlaneProperty : Window
   {
        public string modelName;    // ¸ðµ¨ À̸§
        public int modelID;

        public double modelScaleX, modelScaleY, modelScaleZ; //¸ðµ¨Å©±â Á¶Àý ¿ä¼Ò
        public bool modelScalable;                              //¸ðµ¨ Å©±â Á¶Àý ¿©ºÎ
        public XncwObserver.eViewMode cameraMode;               // Ä«¸Þ¶ó ¸ðµå
        public bool modelShowBoundingBox;                   //¸ðµ¨ °æ°è ¿µ¿ª µµ½Ã ¿©ºÎ
     
        public PlaneProperty()
        {
                InitializeComponent();

                modelName = "";
                modelID = 0;
                modelScaleX = modelScaleY = modelScaleZ = 1.0;
                modelScalable = false;
                cameraMode = XncwObserver.eViewMode.Unusable;
                modelShowBoundingBox = false;        
        }
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            textBoxID.Text = modelID.ToString();
            textBoxName.Text = modelName;

            textBoxScaleX.Text = modelScaleX.ToString();
            textBoxScaleY.Text = modelScaleY.ToString();
            textBoxScaleZ.Text = modelScaleZ.ToString();
            checkBoxScalable.IsChecked = modelScalable;
            checkBoxShowBoundingBox.IsChecked = modelShowBoundingBox;

            int idx = (int)cameraMode;

            // Camera mode°¡ À¯È¿ÇÑ °ªÀÌ ¾Æ´Ñ °æ¿ì,
            // Camera mode¸¦ À§ÇÑ combo boxÀÇ ¸¶Áö¸· ¾ÆÀÌÅÛÀÎ Unusable·Î ¼³Á¤
            if (idx < 0 || idx >= comboBoxCameraMode.Items.Count)
                idx = comboBoxCameraMode.Items.Count - 1;

            comboBoxCameraMode.SelectedIndex = idx;
        }

        private void buttonOK_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            int idx = comboBoxCameraMode.SelectedIndex;
            // Camera mode°¡ À¯È¿ÇÏÁö ¾Ê´Â °æ¿ì¿¡´Â InusableÀ¸·Î ¼³Á¤
            if (idx > (int)XncwObserver.eViewMode.Far2Obj)
                idx = (int)XncwObserver.eViewMode.Unusable;

            cameraMode = (XncwObserver.eViewMode)idx;
            modelName = textBoxName.Text;

            // ¸ðµ¨ Å©±â Á¶Àý. ModelScalableÀÌ trueÀÎ °æ¿ì Àû¿ëµÈ´Ù.
            modelScaleX = double.Parse(textBoxScaleX.Text);
            modelScaleY = double.Parse(textBoxScaleY.Text);
            modelScaleZ = double.Parse(textBoxScaleZ.Text);
            Nullable<bool> result = checkBoxScalable.IsChecked;
            if (result != true)
            {
                modelScalable = false;
            }
            else
            {
                modelScalable = true;
            }

            Nullable<bool> result1 = checkBoxShowBoundingBox.IsChecked;
            if (result1 != true)
            {
                modelShowBoundingBox = false;
            }
            else
            {
                modelShowBoundingBox = true;
            }
        }

        private void buttonCancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }
    }
}

 

2.3.13  xncwTheaterÀÇ OnPicked À̺¥Æ® ÇÔ¼ö¸¦ Ãß°¡ÇÏ°í PlaneProperty Ŭ·¡½º¸¦ ÀÌ¿ëÇÏ¿© ¸ðµ¨ÀÇ µµ½Ã¼Ó¼ºÀ» º¯°æÇÏ´Â Äڵ带 Ãß°¡ÇÑ´Ù.

xncwTheaterÀÇ OnPicked À̺¥Æ® ÇÔ¼ö´Â xncwTheater_OnPicked·Î ÇÑ´Ù.

//MainWindow.xaml

bool xncwTheater_OnPicked(object sender, NXPlanetDrawArgs e, long ID)
{
        // ID¿¡ ´ëÀÀµÇ´Â Àåºñ¸¦ xncwTheater¿¡¼­ °¡Á®¿Â´Ù.
        XEquipObj obj = xncwTheater.GetEquipment(ID);
        // ID¿¡ ´ëÀÀµÇ´Â °´Ã¼°¡ ¾ø´Â °æ¿ì null °´Ã¼¸¦ ¹ÝȯÇÑ´Ù.
        if (obj == null) return false;

        MyPlane modelPlane = (MyPlane)obj;

        //MyPlane °´Ã¼ÀÇ ¼Ó¼ºÀ¸·Î PlaneProperty °ªÀ» ¼³Á¤ÇÑ´Ù.
        Action action = () =>
        {
             PlaneProperty property = new PlaneProperty();

            property.modelID = (int)ID;
            property.modelName = modelPlane.modelName;
            property.modelScalable = modelPlane.Scalable;
            property.modelScaleX = modelPlane.Scale.x;
            property.modelScaleY = modelPlane.Scale.y;
            property.modelScaleZ = modelPlane.Scale.z;
            property.modelShowBoundingBox = modelPlane.modelShowBoundingBox;
            property.cameraMode = modelPlane.cameraMode;

            Nullable<bool> result = property.ShowDialog();
            if (result != true)
            {
                  return;// false;
            }

           // PlaneProperty.xamlÀ» ÀÌ¿ëÇØ ¼³Á¤ÇÑ °ªÀ» MyPlane¿¡ ¼³Á¤ÇÑ´Ù.
modelPlane.Scalable = property.modelScalable;
           modelPlane.Scale = new XVertex3d(property.modelScaleX,
 property.modelScaleY, property.modelScaleZ);
           
modelPlane.ShowBoundingBox(property.modelShowBoundingBox);
           modelPlane.cameraMode = property.cameraMode;

           // CameraMode¸¦ Unusable·Î ¼³Á¤ÇÑ °æ¿ì,
           // ƯÁ¤ °´Ã¼¸¦ ÁÖ½ÃÇÏ´Â °ÍÀÌ ¾Æ´Ï¶ó ¸ðµç °´Ã¼¸¦ È®ÀÎÇÒ ¼ö ÀÖµµ·Ï
// xncwObserver2D, xncwObserver3DÀÇ SurveyNone() ÇÔ¼ö·Î ¼³Á¤
           if (modelPlane.cameraMode == XncwObserver.eViewMode.Unusable)
           {
               xncwObserver2D.SurveyNone();
               xncwObserver3D.SurveyNone();
           }
           else
           {
               // xncwObserver2D¿¡¼­ ¼±ÅÃÇÑ °´Ã¼¿Í camera mode·Î ´ë»ó °´Ã¼¸¦
// ÁÖ½ÃÇϵµ·Ï ¼³Á¤
               xncwObserver2D.SurveyTargetObj(obj, modelPlane.cameraMode);
               // °´Ã¼ Áֽø¦ À§ÇÑ °Å¸®¸¦ ¼³Á¤
               xncwObserver2D.SetDistance(4000);
               // xncwObserver3D¿¡¼­ ¼±ÅÃÇÑ °´Ã¼¿Í camera mode·Î ´ë»ó °´Ã¼¸¦ 
// ÁÖ½ÃÇϵµ·Ï ¼³Á¤
               xncwObserver3D.SurveyTargetObj(obj, modelPlane.cameraMode);
               xncwObserver3D.SetDistance(4000);
           }

           // xncwTheaterÀÇ °¡½Ã ¿µ¿ªÀ» °»½ÅÇÑ´Ù.
           xncwTheater.UpdateVisibleArea();

           // nxPlanetView2D¿Í nxPlanetView3D¿¡ È­¸é °»½ÅÀ» ¿äûÇÑ´Ù.
           nxPlanetView2D.RefreshScreen();
           nxPlanetView3D.RefreshScreen();
        };
Dispatcher.BeginInvoke(action);
        return default(bool);
}

 

2.3.14  ¼Ö·ç¼ÇÀ» ºôµåÇÏ°í ½ÇÇàÇÑ´Ù. ÇÁ·Î±×·¥¿¡¼­ ºñÇàü¸¦ Ãß°¡ÇÑ µÚ nxPlanetView2D¿¡¼­ ºñÇàü¸¦ ´õºí Ŭ¸¯ÇÑ´Ù. ºñÇàü°¡ ¼±ÅõǸé PlanePropertyÀÌ »ý¼ºµÇ°í ÀÌ Window¿¡¼­ CameraMode¸¦ ¡°Front View¡±¸¦ ¼±ÅÃÇÏ°í OK ¹öÆ°À» Ŭ¸¯ÇÑ´Ù.