첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
------------------------------------------------------------------------------------------------------------------------------------------------------
728x90
728x170

TestProject.zip
다운로드

▶ HammerAitoffProjection.cs

using System;
using DevExpress.XtraMap;

namespace TestProject
{
    /// <summary>
    /// HAMMER-AITOFF 투영
    /// </summary>
    public class HammerAitoffProjection : ProjectionBase
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 최소 위도
        /// </summary>
        private const double MINIMUM_LATITUDE = -90.0;

        /// <summary>
        /// 최대 위도
        /// </summary>
        private const double MAXIMUM_LATITUDE = 90.0;

        /// <summary>
        /// 최소 경도
        /// </summary>
        private const double MINIMUM_LONGITUDE = -180.0;

        /// <summary>
        /// 최대 경도
        /// </summary>
        private const double MAXIMUM_LONGITUDE = 180.0;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 오프셋 X - OffsetX

        /// <summary>
        /// 오프셋 X
        /// </summary>
        [Obsolete]
        public override double OffsetX
        {
            get
            {
                return 0.5;
            }
        }

        #endregion
        #region 오프셋 Y - OffsetY

        /// <summary>
        /// 오프셋 Y
        /// </summary>
        [Obsolete]
        public override double OffsetY
        {
            get
            {
                return 0.5;
            }
        }

        #endregion
        #region 스케일 X - ScaleX

        /// <summary>
        /// 스케일 X
        /// </summary>
        [Obsolete]
        public override double ScaleX
        {
            get
            {
                return 0.5;
            }
        }

        #endregion
        #region 스케일 Y - ScaleY

        /// <summary>
        /// 스케일 Y
        /// </summary>
        [Obsolete]
        public override double ScaleY
        {
            get
            {
                return -0.25;
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 도 구하기 - GetDegree(value)

        /// <summary>
        /// 도 구하기
        /// </summary>
        /// <param name="value">값</param>
        /// <returns>도</returns>
        private static double GetDegree(double value)
        {
            return value * 180.0 / Math.PI;
        }

        #endregion
        #region 라디안 구하기 - GetRadian(value)

        /// <summary>
        /// 라디안 구하기
        /// </summary>
        /// <param name="value">값</param>
        /// <returns>라디안</returns>
        private static double GetRadian(double value)
        {
            return value * Math.PI / 180.0;
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 지도 단위 구하기 - GeoPointToMapUnit(geoPoint)

        /// <summary>
        /// 지도 단위 구하기
        /// </summary>
        /// <param name="geoPoint">지리 포인트</param>
        /// <returns>지도 단위</returns>
        public override MapUnit GeoPointToMapUnit(GeoPoint geoPoint)
        {
            double longitude = GetRadian(Math.Min(MAXIMUM_LONGITUDE, Math.Max(MINIMUM_LONGITUDE, geoPoint.Longitude)));
            double latitude  = GetRadian(Math.Min(MAXIMUM_LATITUDE , Math.Max(MINIMUM_LATITUDE , geoPoint.Latitude )));

            double z = Math.Sqrt(1 + Math.Cos(latitude) * Math.Cos(longitude / 2));
            double x = Math.Cos(latitude) * Math.Sin(longitude / 2) / z;
            double y = Math.Sin(latitude) / z;

            return new MapUnit(x * ScaleX + OffsetX, y * ScaleY + OffsetY);
        }

        #endregion
        #region 지리 포인트 구하기 - MapUnitToGeoPoint(mapUnit)

        /// <summary>
        /// 지리 포인트 구하기
        /// </summary>
        /// <param name="mapUnit">지도 단위</param>
        /// <returns>지리 포인트</returns>
        public override GeoPoint MapUnitToGeoPoint(MapUnit mapUnit)
        {
            double x = (mapUnit.X - OffsetX) / ScaleX;
            double y = Math.Min(1, Math.Max(-1, (mapUnit.Y - OffsetY) / ScaleY));

            if(IsValidPoint(x, y))
            {
                double z = Math.Sqrt(1 - 0.5 * Math.Pow(x, 2) - 0.5 * Math.Pow(y, 2));
                double c = Math.Sqrt(2) * z * x / (2 * Math.Pow(z, 2) - 1);

                double longitude = 2 * Math.Atan(c);
                double latitude  = Math.Asin(Math.Min(Math.Max(Math.Sqrt(2) * z * y, -1), 1));

                double latitudeDegree  = latitude  * 180.0 / Math.PI;
                double longitudeDegree = longitude * 180.0 / Math.PI;

                return new GeoPoint
                (
                    Math.Min(MAXIMUM_LATITUDE , Math.Max(MINIMUM_LATITUDE , GetDegree(latitude ))),
                    Math.Min(MAXIMUM_LONGITUDE, Math.Max(MINIMUM_LONGITUDE, GetDegree(longitude)))
                );
            }
            else
            {
                int signX = (x < 0) ? -1 : 1;
                int signY = (y < 0) ? -1 : 1;

                return new GeoPoint(MAXIMUM_LATITUDE * signY, MAXIMUM_LONGITUDE * signX);
            }
        }

        #endregion
        #region 킬로미터 크기 구하기 - GeoToKilometersSize(anchorPoint, mapSize)

        /// <summary>
        /// 킬로미터 크기 구하기
        /// </summary>
        /// <param name="anchorPoint">앵커 포인트</param>
        /// <param name="mapSize">맵 크기</param>
        /// <returns>킬로미터 크기</returns>
        public override MapSize GeoToKilometersSize(GeoPoint anchorPoint, MapSize mapSize)
        {
            return new MapSize
            (
                mapSize.Width  * LonToKilometersRatio * Math.Cos(GetRadian(anchorPoint.Latitude)),
                mapSize.Height * LatToKilometersRatio
            );
        }

        #endregion
        #region 지리 크기 구하기 - KilometersToGeoSize(anchorPoint, mapSize)

        /// <summary>
        /// 지리 크기 구하기
        /// </summary>
        /// <param name="anchorPoint">앵커 포인트</param>
        /// <param name="mapSize">맵 크기</param>
        /// <returns>지리 크기</returns>
        public override MapSize KilometersToGeoSize(GeoPoint anchorPoint, MapSize mapSize)
        {
            return new MapSize
            (
                mapSize.Width  / LonToKilometersRatio / Math.Cos(GetRadian(anchorPoint.Latitude)),
                mapSize.Height / LatToKilometersRatio
            );
        }
        
        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private

        #region 포인트 검증 여부 구하기 - IsValidPoint(x, y)

        /// <summary>
        /// 포인트 검증 여부 구하기
        /// </summary>
        /// <param name="x">X</param>
        /// <param name="y">Y</param>
        /// <returns>포인트 검증 여부</returns>
        private bool IsValidPoint(double x, double y)
        {
            if(Math.Pow(x, 2) + Math.Pow(y, 2) > 1)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        #endregion
    }
}

 

728x90

 

▶ MainForm.cs

using System;
using System.Reflection;

using DevExpress.XtraEditors;
using DevExpress.XtraMap;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : XtraForm
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            GeoMapCoordinateSystem geoMapCoordinateSystem = this.mapControl.CoordinateSystem as GeoMapCoordinateSystem;

            geoMapCoordinateSystem.Projection = new HammerAitoffProjection();

            Uri baseURI = new Uri(Assembly.GetEntryAssembly().Location);

            this.shapefileDataAdapter.FileUri = new Uri(baseURI, "Data/Countries.shp");
        }

        #endregion
    }
}
728x90
그리드형(광고전용)
Posted by icodebroker
,