태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.


'2009/12'에 해당되는 글 12건

  1. 2009/12/23 양력, 음력 변환
  2. 2009/12/17 아날로그 시계 만들어 보기 #5 : 완성
  3. 2009/12/17 이미지 투명도 설정
  4. 2009/12/14 아날로그 시계 만들어 보기 #4 : 이미지를 사용해서 만들기(2)
  5. 2009/12/11 아날로그 시계 만들어 보기 #3 : 이미지를 사용해서 만들기
  6. 2009/12/11 Rotate Transform
  7. 2009/12/11 아날로그 시계 만들어 보기 #2 : 시계 완성
  8. 2009/12/11 아날로그 시계 만들어 보기 #1 : 삼각함수를 이용해 원주위의 좌표 구하기
  9. 2009/12/11 데카르트 좌표계(Cartesian coordinates) 클래스
  10. 2009/12/11 삼각함수를 이용해서 아날로그 시계 만들기
  11. 2009/12/10 Google Data API for .NET
  12. 2009/12/03 SSAS HTTP 액세스 구성
2009/12/23 16:09

양력, 음력 변환

# 프로그램 소스 파일

Lunar.cs

 

해당 클래스로 양력을 음력으로 변환할 수 있는 범위는 양력 1800-01-25 ~ 2050-01-22 까지이고,

음력을 양력으로 변환할 수 있는 범위는 음력 1800-01-01 ~ 2049-12-08 까지이다.

 

다음 링크에서 c로 구현된 소스를 구해 일부 버그를 수정하고 변환 범위 확장 및 양력->음력 변환 기능 추가, 음력 간지 계산 기능을 추가해서 c#으로 다시 작성했다.

 

링크(http://openwrld.egloos.com/1417170)

 

천문연구원의 음력/양력 변환 데이터와 대조 확인 완료했으며 위 변환 범위 내에서 문제 없음을 확인했다.

 

변환 클래스(Lunar)의 코드는 다음과 같다.

 

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

namespace Solar2Lunar
{
/// <summary>
/// 양력<->음력 변환 클래스<br/>
/// 변환이 가능한 양력 범위(1800-01-25 ~ 2050-01-22)<br/>
/// 변환이 가능한 음력 범위(1800-01-01 ~ 2049-12-08)<br/>
/// 다음 링크에 있는 알고리즘을 C#코드로 수정해서 작성했음을 밝힌다.<br/>
/// http://openwrld.egloos.com/1417170<br/>
/// </summary>
public class Lunar
{
#region 음력데이터

/// <summary>
/// 음력 달의 특징<br/>
/// 1: 평달 (작은달)<br/>
/// 2: 평달 (큰달)<br/>
/// 3: 윤달 (작은달 + 작은달)<br/>
/// 4: 윤달 (작은달 + 큰달)<br/>
/// 5: 윤달 (큰달 + 작은달)<br/>
/// 6: 윤달 (큰달 + 큰달)<br/>
/// 작은달=29, 큰달=30<br/>
readonly int[,] LUNAR_FEATURES = {{2,1,2,5,2,1,2,1,2,1,2,1}, // 1800
{1,2,2,1,2,1,2,2,1,2,1,2}, // 1801
{1,1,2,1,2,1,2,2,2,1,2,1}, // 1802
{2,3,2,1,2,1,2,2,1,2,2,1}, // 1803
{2,1,1,2,1,1,2,2,1,2,2,2}, // 1804
{1,2,1,2,1,3,2,1,2,2,2,1}, // 1805
{2,2,1,2,1,1,1,2,1,2,2,1}, // 1806
{2,2,2,1,1,2,1,1,2,1,2,2}, // 1807
{1,2,2,1,5,2,1,2,1,1,2,1}, // 1808
{2,2,1,2,2,1,2,1,2,1,1,2}, // 1809
{1,2,1,2,2,1,2,2,1,2,1,2}, // 1810
{1,1,5,2,1,2,2,1,2,2,1,2}, // 1811
{1,1,2,1,2,1,2,1,2,2,2,1}, // 1812
{2,1,2,1,1,1,2,1,2,2,2,1}, // 1813
{2,5,2,1,1,1,2,1,2,2,1,2}, // 1814
{2,2,1,1,2,1,1,2,1,2,1,2}, // 1815
{2,2,1,2,1,5,1,2,1,2,1,2}, // 1816
{2,1,2,2,1,2,1,2,1,1,2,1}, // 1817
{2,1,2,2,1,2,2,1,2,1,1,2}, // 1818
{1,2,1,5,2,2,1,2,2,1,2,1}, // 1819
{1,2,1,2,1,2,1,2,2,2,1,2}, // 1820
{1,1,2,1,1,2,1,2,2,2,1,2}, // 1821
{2,1,5,1,1,2,1,2,2,1,2,2}, // 1822
{2,1,2,1,1,1,2,1,2,1,2,2}, // 1823
{2,1,2,1,2,1,4,1,2,1,2,2}, // 1824
{2,1,2,1,2,1,1,2,1,2,1,2}, // 1825
{2,1,2,2,1,2,1,1,2,1,2,1}, // 1826
{2,1,2,2,4,1,2,1,2,1,2,1}, // 1827
{2,1,2,1,2,2,1,2,1,2,1,2}, // 1828
{1,2,1,2,1,2,1,2,2,1,2,2}, // 1829
{1,1,2,3,2,1,2,2,1,2,2,2}, // 1830
{1,1,2,1,1,2,1,2,1,2,2,2}, // 1831
{1,2,1,2,1,1,2,1,5,2,2,2}, // 1832
{1,2,1,2,1,1,2,1,2,1,2,2}, // 1833
{1,2,2,1,2,1,1,2,1,2,1,2}, // 1834
{1,2,2,1,2,5,1,2,1,2,1,2}, // 1835
{1,2,1,2,2,1,2,1,2,1,2,1}, // 1836
{2,1,2,1,2,1,2,2,1,2,1,2}, // 1837
{1,2,1,5,1,2,2,1,2,2,1,2}, // 1838
{1,2,1,1,2,1,2,1,2,2,2,1}, // 1839
{2,1,2,1,1,2,1,2,1,2,2,2}, // 1840
{1,2,4,1,1,2,1,2,1,2,2,1}, // 1841
{2,2,1,2,1,1,2,1,2,1,2,1}, // 1842
{2,2,2,1,2,1,4,1,2,1,2,1}, // 1843
{2,2,1,2,1,2,1,2,1,2,1,2}, // 1844
{1,2,1,2,2,1,2,1,2,1,2,1}, // 1845
{2,1,2,1,5,2,1,2,2,1,2,1}, // 1846
{2,1,1,2,1,2,1,2,2,2,1,2}, // 1847
{1,2,1,1,2,1,2,1,2,2,2,1}, // 1848
{2,1,2,3,2,1,2,1,2,1,2,2}, // 1849
{2,1,2,1,1,2,1,1,2,2,1,2}, // 1850
{2,2,1,2,1,1,2,3,2,1,2,2}, // 1851
{2,1,2,2,1,1,2,1,2,1,1,2}, // 1852
{2,1,2,2,1,2,1,2,1,2,1,2}, // 1853
{1,2,1,2,1,2,5,2,1,2,1,2}, // 1854
{1,1,2,1,2,2,1,2,2,1,2,1}, // 1855
{2,1,1,2,1,2,1,2,2,2,1,2}, // 1856
{1,2,1,1,5,2,1,2,1,2,2,2}, // 1857
{1,2,1,1,2,1,1,2,2,1,2,2}, // 1858
{2,1,2,1,1,2,1,1,2,1,2,2}, // 1859
{2,1,6,1,1,2,1,1,2,1,2,2}, // 1860
{1,2,2,1,2,1,2,1,2,1,1,2}, // 1861
{2,1,2,1,2,2,1,5,2,1,1,2}, // 1862
{1,2,2,1,2,1,2,2,1,2,1,2}, // 1863
{1,1,2,1,2,1,2,2,1,2,2,1}, // 1864
{2,1,1,2,4,1,2,2,1,2,2,1}, // 1865
{2,1,1,2,1,1,2,2,1,2,2,2}, // 1866
{1,2,1,1,2,1,1,2,1,2,2,2}, // 1867
{1,2,2,3,2,1,1,2,1,2,2,1}, // 1868
{2,2,2,1,1,2,1,1,2,1,2,1}, // 1869
{2,2,2,1,2,1,2,1,1,5,2,1}, // 1870
{2,2,1,2,2,1,2,1,2,1,1,2}, // 1871
{1,2,1,2,2,1,2,1,2,2,1,2}, // 1872
{1,1,2,1,2,4,2,1,2,2,1,2}, // 1873
{1,1,2,1,2,1,2,1,2,2,2,1}, // 1874
{2,1,1,2,1,1,2,1,2,2,2,1}, // 1875
{2,2,1,1,5,1,2,1,2,2,1,2}, // 1876
{2,2,1,1,2,1,1,2,1,2,1,2}, // 1877
{2,2,1,2,1,2,1,1,2,1,2,1}, // 1878
{2,2,4,2,1,2,1,1,2,1,2,1}, // 1879
{2,1,2,2,1,2,2,1,2,1,1,2}, // 1880
{1,2,1,2,1,2,5,2,2,1,2,1}, // 1881
{1,2,1,2,1,2,1,2,2,1,2,2}, // 1882
{1,1,2,1,1,2,1,2,2,2,1,2}, // 1883
{2,1,1,2,3,2,1,2,2,1,2,2}, // 1884
{2,1,1,2,1,1,2,1,2,1,2,2}, // 1885
{2,1,2,1,2,1,1,2,1,2,1,2}, // 1886
{2,2,1,5,2,1,1,2,1,2,1,2}, // 1887
{2,1,2,2,1,2,1,1,2,1,2,1}, // 1888
{2,1,2,2,1,2,1,2,1,2,1,2}, // 1889
{1,5,2,1,2,2,1,2,1,2,1,2}, // 1890
{1,2,1,2,1,2,1,2,2,1,2,2}, // 1891
{1,1,2,1,1,5,2,2,1,2,2,2}, // 1892
{1,1,2,1,1,2,1,2,1,2,2,2}, // 1893
{1,2,1,2,1,1,2,1,2,1,2,2}, // 1894
{2,1,2,1,5,1,2,1,2,1,2,1}, // 1895
{2,2,2,1,2,1,1,2,1,2,1,2}, // 1896
{1,2,2,1,2,1,2,1,2,1,2,1}, // 1897
{2,1,5,2,2,1,2,1,2,1,2,1}, // 1898
{2,1,2,1,2,1,2,2,1,2,1,2}, // 1899
{1,2,1,1,2,1,2,5,2,2,1,2}, // 1900
{1,2,1,1,2,1,2,1,2,2,2,1}, // 1901
{2,1,2,1,1,2,1,2,1,2,2,2}, // 1902
{1,2,1,2,3,2,1,1,2,2,1,2}, // 1903
{2,2,1,2,1,1,2,1,1,2,2,1}, // 1904
{2,2,1,2,2,1,1,2,1,2,1,2}, // 1905
{1,2,2,4,1,2,1,2,1,2,1,2}, // 1906
{1,2,1,2,1,2,2,1,2,1,2,1}, // 1907
{2,1,1,2,2,1,2,1,2,2,1,2}, // 1908
{1,5,1,2,1,2,1,2,2,2,1,2}, // 1909
{1,2,1,1,2,1,2,1,2,2,2,1}, // 1910
{2,1,2,1,1,5,1,2,2,1,2,2}, // 1911
{2,1,2,1,1,2,1,1,2,2,1,2}, // 1912
{2,2,1,2,1,1,2,1,1,2,1,2}, // 1913
{2,2,1,2,5,1,2,1,2,1,1,2}, // 1914
{2,1,2,2,1,2,1,2,1,2,1,2}, // 1915
{1,2,1,2,1,2,2,1,2,1,2,1}, // 1916
{2,3,2,1,2,2,1,2,2,1,2,1}, // 1917
{2,1,1,2,1,2,1,2,2,2,1,2}, // 1918
{1,2,1,1,2,1,5,2,2,1,2,2}, // 1919
{1,2,1,1,2,1,1,2,2,1,2,2}, // 1920
{2,1,2,1,1,2,1,1,2,1,2,2}, // 1921
{2,1,2,2,3,2,1,1,2,1,2,2}, // 1922
{1,2,2,1,2,1,2,1,2,1,1,2}, // 1923
{2,1,2,1,2,2,1,2,1,2,1,1}, // 1924
{2,1,2,5,2,1,2,2,1,2,1,2}, // 1925
{1,1,2,1,2,1,2,2,1,2,2,1}, // 1926
{2,1,1,2,1,2,1,2,2,1,2,2}, // 1927
{1,5,1,2,1,1,2,2,1,2,2,2}, // 1928
{1,2,1,1,2,1,1,2,1,2,2,2}, // 1929
{1,2,2,1,1,5,1,2,1,2,2,1}, // 1930
{2,2,2,1,1,2,1,1,2,1,2,1}, // 1931
{2,2,2,1,2,1,2,1,1,2,1,2}, // 1932
{1,2,2,1,6,1,2,1,2,1,1,2}, // 1933
{1,2,1,2,2,1,2,2,1,2,1,2}, // 1934
{1,1,2,1,2,1,2,2,1,2,2,1}, // 1935
{2,1,4,1,2,1,2,1,2,2,2,1}, // 1936
{2,1,1,2,1,1,2,1,2,2,2,1}, // 1937
{2,2,1,1,2,1,4,1,2,2,1,2}, // 1938
{2,2,1,1,2,1,1,2,1,2,1,2}, // 1939
{2,2,1,2,1,2,1,1,2,1,2,1}, // 1940
{2,2,1,2,2,4,1,1,2,1,2,1}, // 1941
{2,1,2,2,1,2,2,1,2,1,1,2}, // 1942
{1,2,1,2,1,2,2,1,2,2,1,2}, // 1943
{1,1,2,4,1,2,1,2,2,1,2,2}, // 1944
{1,1,2,1,1,2,1,2,2,2,1,2}, // 1945
{2,1,1,2,1,1,2,1,2,2,1,2}, // 1946
{2,5,1,2,1,1,2,1,2,1,2,2}, // 1947
{2,1,2,1,2,1,1,2,1,2,1,2}, // 1948
{2,2,1,2,1,2,3,2,1,2,1,2}, // 1949
{2,1,2,2,1,2,1,1,2,1,2,1}, // 1950
{2,1,2,2,1,2,1,2,1,2,1,2}, // 1951
{1,2,1,2,4,2,1,2,1,2,1,2}, // 1952
{1,2,1,1,2,2,1,2,2,1,2,2}, // 1953
{1,1,2,1,1,2,1,2,2,1,2,2}, // 1954
{2,1,4,1,1,2,1,2,1,2,2,2}, // 1955
{1,2,1,2,1,1,2,1,2,1,2,2}, // 1956
{2,1,2,1,2,1,1,5,2,1,2,2}, // 1957
{1,2,2,1,2,1,1,2,1,2,1,2}, // 1958
{1,2,2,1,2,1,2,1,2,1,2,1}, // 1959
{2,1,2,1,2,5,2,1,2,1,2,1}, // 1960
{2,1,2,1,2,1,2,2,1,2,1,2}, // 1961
{1,2,1,1,2,1,2,2,1,2,2,1}, // 1962
{2,1,2,3,2,1,2,1,2,2,2,1}, // 1963
{2,1,2,1,1,2,1,2,1,2,2,2}, // 1964
{1,2,1,2,1,1,2,1,1,2,2,2}, // 1965
{1,2,5,2,1,1,2,1,1,2,2,1}, // 1966
{2,2,1,2,2,1,1,2,1,2,1,2}, // 1967
{1,2,2,1,2,1,5,2,1,2,1,2}, // 1968
{1,2,1,2,1,2,2,1,2,1,2,1}, // 1969
{2,1,1,2,2,1,2,1,2,2,1,2}, // 1970
{1,2,1,1,5,2,1,2,2,2,1,2}, // 1971
{1,2,1,1,2,1,2,1,2,2,2,1}, // 1972
{2,1,2,1,1,2,1,1,2,2,2,1}, // 1973
{2,2,1,5,1,2,1,1,2,2,1,2}, // 1974
{2,2,1,2,1,1,2,1,1,2,1,2}, // 1975
{2,2,1,2,1,2,1,5,2,1,1,2}, // 1976
{2,1,2,2,1,2,1,2,1,2,1,1}, // 1977
{2,2,1,2,1,2,2,1,2,1,2,1}, // 1978
{2,1,1,2,1,6,1,2,2,1,2,1}, // 1979
{2,1,1,2,1,2,1,2,2,1,2,2}, // 1980
{1,2,1,1,2,1,1,2,2,1,2,2}, // 1981
{2,1,2,3,2,1,1,2,2,1,2,2}, // 1982
{2,1,2,1,1,2,1,1,2,1,2,2}, // 1983
{2,1,2,2,1,1,2,1,1,5,2,2}, // 1984
{1,2,2,1,2,1,2,1,1,2,1,2}, // 1985
{1,2,2,1,2,2,1,2,1,2,1,1}, // 1986
{2,1,2,2,1,5,2,2,1,2,1,2}, // 1987
{1,1,2,1,2,1,2,2,1,2,2,1}, // 1988
{2,1,1,2,1,2,1,2,2,1,2,2}, // 1989
{1,2,1,1,5,1,2,2,1,2,2,2}, // 1990
{1,2,1,1,2,1,1,2,1,2,2,2}, // 1991
{1,2,2,1,1,2,1,1,2,1,2,2}, // 1992
{1,2,5,2,1,2,1,1,2,1,2,1}, // 1993
{2,2,2,1,2,1,2,1,1,2,1,2}, // 1994
{1,2,2,1,2,2,1,5,2,1,1,2}, // 1995
{1,2,1,2,2,1,2,1,2,2,1,2}, // 1996
{1,1,2,1,2,1,2,2,1,2,2,1}, // 1997
{2,1,1,2,3,2,2,1,2,2,2,1}, // 1998
{2,1,1,2,1,1,2,1,2,2,2,1}, // 1999
{2,2,1,1,2,1,1,2,1,2,2,1}, // 2000
{2,2,2,3,2,1,1,2,1,2,1,2}, // 2001
{2,2,1,2,1,2,1,1,2,1,2,1}, // 2002
{2,2,1,2,2,1,2,1,1,2,1,2}, // 2003
{1,5,2,2,1,2,1,2,1,2,1,2}, // 2004
{1,2,1,2,1,2,2,1,2,2,1,1}, // 2005
{2,1,2,1,2,1,5,2,2,1,2,2}, // 2006
{1,1,2,1,1,2,1,2,2,2,1,2}, // 2007
{2,1,1,2,1,1,2,1,2,2,1,2}, // 2008
{2,2,1,1,5,1,2,1,2,1,2,2}, // 2009
{2,1,2,1,2,1,1,2,1,2,1,2}, // 2010
{2,1,2,2,1,2,1,1,2,1,2,1}, // 2011
{2,1,6,2,1,2,1,1,2,1,2,1}, // 2012
{2,1,2,2,1,2,1,2,1,2,1,2}, // 2013
{1,2,1,2,1,2,1,2,5,2,1,2}, // 2014
{1,2,1,1,2,1,2,2,2,1,2,1}, // 2015
{2,1,2,1,1,2,1,2,2,1,2,2}, // 2016
{1,2,1,2,3,2,1,2,1,2,2,2}, // 2017
{1,2,1,2,1,1,2,1,2,1,2,2}, // 2018
{2,1,2,1,2,1,1,2,1,2,1,2}, // 2019
{2,1,2,5,2,1,1,2,1,2,1,2}, // 2020
{1,2,2,1,2,1,2,1,2,1,2,1}, // 2021
{2,1,2,1,2,2,1,2,1,2,1,2}, // 2022
{1,5,2,1,2,1,2,2,1,2,1,2}, // 2023
{1,2,1,1,2,1,2,2,1,2,2,1}, // 2024
{2,1,2,1,1,5,2,1,2,2,2,1}, // 2025
{2,1,2,1,1,2,1,2,1,2,2,2}, // 2026
{1,2,1,2,1,1,2,1,1,2,2,2}, // 2027
{1,2,2,1,5,1,2,1,1,2,2,1}, // 2028
{2,2,1,2,2,1,1,2,1,1,2,2}, // 2029
{1,2,1,2,2,1,2,1,2,1,2,1}, // 2030
{2,1,5,2,1,2,2,1,2,1,2,1}, // 2031
{2,1,1,2,1,2,2,1,2,2,1,2}, // 2032
{1,2,1,1,2,1,2,1,2,2,5,2}, // 2033
{1,2,1,1,2,1,2,1,2,2,2,1}, // 2034
{2,1,2,1,1,2,1,1,2,2,1,2}, // 2035
{2,2,1,2,1,4,1,1,2,2,1,2}, // 2036
{2,2,1,2,1,1,2,1,1,2,1,2}, // 2037
{2,2,1,2,1,2,1,2,1,1,2,1}, // 2038
{2,2,1,2,5,2,1,2,1,2,1,1}, // 2039
{2,1,2,2,1,2,2,1,2,1,2,1}, // 2040
{2,1,1,2,1,2,2,1,2,2,1,2}, // 2041
{1,5,1,2,1,2,1,2,2,1,2,2}, // 2042
{1,2,1,1,2,1,1,2,2,1,2,2}, // 2043
{2,1,2,1,1,2,3,2,1,2,2,2}, // 2044
{2,1,2,1,1,2,1,1,2,1,2,2}, // 2045
{2,1,2,2,1,1,2,1,1,2,1,2}, // 2046
{2,1,2,2,4,1,2,1,1,2,1,2}, // 2047
{1,2,2,1,2,2,1,2,1,2,1,1}, // 2048
{2,1,2,1,2,2,1,2,2,1,2,1}, // 2049
};
#endregion

/// <summary>
/// 음력 달의 특징<br/>
/// 0: 평달 (작은달)<br/>
/// 1: 평달 (큰달)<br/>
/// 2: 윤달 (작은달 + 작은달)<br/>
/// 3: 윤달 (작은달 + 큰달)<br/>
/// 4: 윤달 (큰달 + 작은달)<br/>
/// 5: 윤달 (큰달 + 큰달)<br/>
/// 작은달=29, 큰달=30<br/>
/// </summary>
private readonly int[] DAYS_OF_LUNAR_FEATURES = { 29, 30, 58, 59, 59, 60 };
private readonly int[] NORMAL_DAYS_OF_LEAP_MONTH = { 0, 0, 29, 29, 30, 30 };

/// <summary>
/// 양력 달의 날 수
/// </summary>
private readonly int[] SOLAR_DAYS_OF_MONTH = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

/// <summary>
/// 10간
/// </summary>
private readonly string[] GAN = { "갑", "을", "병", "정", "무", "기", "경", "신", "임", "계" };

/// <summary>
/// 12지
/// </summary>
private readonly string[] JI = { "자", "축", "인", "묘", "진", "사", "오", "미", "신", "유", "술", "해" };

// 1800-01-25 (토) 1800-01-01 경신(庚申)년 무인(戊寅)월 갑인(甲寅)일
private readonly int[] SOLAR_BASIC_DATE = { 1800, 1, 25 }; // 년, 월, 일
private readonly int[] BASIC_GANJI = { 6, 8, 4, 2, 0, 2 }; // 경신년, 무인월, 갑인일


/// <summary>
/// 양력 달의 날 수 조회<br/>
/// 윤년일 경우 2월은 29일
/// </summary>
/// <param name="year"></param>
/// <param name="month"></param>
/// <returns></returns>
public int GetSolarDaysOfMonth(int year, int month)
{ // 월별 일수 계산
if (month != 2)
return SOLAR_DAYS_OF_MONTH[month - 1];

if (IsLeapYear(year))
return 29;
else
return 28;
}

/// <summary>
/// 윤년체크
/// </summary>
/// <param name="year"></param>
/// <returns></returns>
public bool IsLeapYear(int year)
{
if ((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0)))
return true;
else
return false;
}

/// <summary>
/// 양력 해의 날 수 조회<br/>
/// 윤년일 경우 366일, 평년일 경우 365일
/// </summary>
/// <param name="year"></param>
/// <returns></returns>
public int GetSolarDaysOfYear(int year)
{
if (IsLeapYear(year))
return 366;
else
return 365;
}

/// <summary>
/// 특정 일자의 양력 날 수 조회
/// </summary>
/// <param name="year"></param>
/// <param name="month"></param>
/// <param name="day"></param>
/// <returns></returns>
public int GetSolarDays(int year, int month, int day)
{
int ret = 0;

for (int i = SOLAR_BASIC_DATE[0]; i < year; i++)
ret += GetSolarDaysOfYear(i);

for (int i = 1; i < month; i++)
ret += GetSolarDaysOfMonth(year, i);

ret += day;

for (int i = 1; i < SOLAR_BASIC_DATE[1]; i++)
ret -= GetSolarDaysOfMonth(SOLAR_BASIC_DATE[0], i);

ret -= SOLAR_BASIC_DATE[2];

return ret;
}

/// <summary>
/// 특정 일자의 음력 날 수 조회
/// </summary>
/// <param name="ly"></param>
/// <param name="lm"></param>
/// <param name="ld"></param>
/// <param name="leapMonth"></param>
/// <returns></returns>
public int GetLunarDays(int ly, int lm, int ld, bool leapMonth)
{
int ret = 0;

for (int i = SOLAR_BASIC_DATE[0]; i < ly; i++)
ret += GetLunarDaysOfYear(i);

for (int i = 1; i < lm; i++)
ret += GetLunarDaysOfMonth(ly, i);

// 윤달일 경우 동월 평달 날짜 더해 줌
if (leapMonth)
{
ret += NORMAL_DAYS_OF_LEAP_MONTH[LUNAR_FEATURES[ly - SOLAR_BASIC_DATE[0], lm - 1] - 1];
}

ret += ld;

return ret;
}

/// <summary>
/// 양력을 음력으로 변환
/// </summary>
/// <param name="year"></param>
/// <param name="month"></param>
/// <param name="day"></param>
/// <returns></returns>
public string ToLunarDate(int year, int month, int day)
{

int ly = 0, lm = 0, ld = 0;
return ToLunarDate(GetSolarDays(year, month, day), out ly, out lm, out ld);
}

/// <summary>
/// 양력을 음력으로 변환
/// </summary>
/// <param name="solarDays"></param>
/// <param name="ly"></param>
/// <param name="lm"></param>
/// <param name="ld"></param>
/// <returns></returns>
public string ToLunarDate(int solarDays, out int ly, out int lm, out int ld)
{
int lunarDays = 0;
ly = 0;
lm = 0;
ld = 0;
for (int y = 0; y < LUNAR_FEATURES.GetLength(0); y++)
{
for (int m = 0; m < 12; m++)
{
int lday = DAYS_OF_LUNAR_FEATURES[LUNAR_FEATURES[y, m] - 1];

if (lunarDays + lday > solarDays)
{
ly = y + SOLAR_BASIC_DATE[0];
lm = m + 1;
ld = solarDays - lunarDays + 1;
if (ld > NORMAL_DAYS_OF_LEAP_MONTH[LUNAR_FEATURES[y, m] - 1])
ld -= NORMAL_DAYS_OF_LEAP_MONTH[LUNAR_FEATURES[y, m] - 1];
return string.Format("{0:0000}-{1:00}-{2:00}", ly, lm, ld);
}

lunarDays += lday;
}
}

return string.Format("{0:0000}-{1:00}-{2:00}", ly, lm, ld);
}

/// <summary>
/// 음력을 양력으로 변환
/// </summary>
/// <param name="ly"></param>
/// <param name="lm"></param>
/// <param name="ld"></param>
/// <param name="leapMonth"></param>
/// <returns></returns>
public string ToSolarDate(int ly, int lm, int ld, bool leapMonth)
{
int year = 0, month = 0, day = 0;
return ToLunarDate(GetLunarDays(ly, lm, ld, leapMonth), out year, out month, out day);
}


/// <summary>
/// 음력을 양력으로 변환
/// </summary>
/// <param name="lunarDays"></param>
/// <param name="year"></param>
/// <param name="month"></param>
/// <param name="day"></param>
/// <returns></returns>
public string ToSolarDate(int lunarDays, out int year, out int month, out int day)
{
int solarDays = 0;
year = 0;
month = 0;
day = 0;

lunarDays += SOLAR_BASIC_DATE[2] - 1;

for (int y = 0; y < LUNAR_FEATURES.GetLength(0); y++)
{
for (int m = 0; m < 12; m++)
{
int lday = GetSolarDaysOfMonth(y + SOLAR_BASIC_DATE[0], m + 1);

if (solarDays + lday >= lunarDays)
{
year = y + SOLAR_BASIC_DATE[0];
month = m + 1;
day = lunarDays - solarDays;

return string.Format("{0:0000}-{1:00}-{2:00}", year, month, day);
}

solarDays += lday;
}
}
return string.Format("{0:0000}-{1:00}-{2:00}", year, month, day);
}

/// <summary>
/// 음력 연도의 간지 문자열 조회
/// </summary>
/// <param name="ly"></param>
/// <returns></returns>
public string GetYearGanji(int ly)
{
string gan = GAN[(ly - SOLAR_BASIC_DATE[0] + BASIC_GANJI[0]) % 10];
string ji = JI[(ly - SOLAR_BASIC_DATE[0] + BASIC_GANJI[1]) % 12];
return gan + ji;
}

/// <summary>
/// 음력 월의 간지 문자열 조회
/// </summary>
/// <param name="ly"></param>
/// <param name="lm"></param>
/// <returns></returns>
public string GetMonthGanji(int ly, int lm)
{
int lunarMonthes = (ly - SOLAR_BASIC_DATE[0]) * 12 + lm - 1;

string gan = GAN[(lunarMonthes + BASIC_GANJI[2]) % 10];
string ji = JI[(lunarMonthes + BASIC_GANJI[3]) % 12];
return gan + ji;
}

/// <summary>
/// 음력 날의 간지 문자열 조회
/// </summary>
/// <param name="totalDaySolar"></param>
/// <returns></returns>
public string GetDayGanji(int solarDays)
{
string gan = GAN[(solarDays + BASIC_GANJI[4]) % 10];
string ji = JI[(solarDays + BASIC_GANJI[5]) % 12];
return gan + ji;
}

/// <summary>
/// 음력 연도의 전체 날 수
/// </summary>
/// <param name="ly"></param>
/// <returns></returns>
public int GetLunarDaysOfYear(int ly)
{
int ret = 0;
for (int i = 0; i < 12; i++)
{
ret += DAYS_OF_LUNAR_FEATURES[LUNAR_FEATURES[ly - SOLAR_BASIC_DATE[0], i] - 1];
}

return ret;
}

/// <summary>
/// 음력 월의 날 수
/// </summary>
/// <param name="ly"></param>
/// <param name="lm"></param>
/// <returns></returns>
public int GetLunarDaysOfMonth(int ly, int lm)
{
return DAYS_OF_LUNAR_FEATURES[LUNAR_FEATURES[ly - SOLAR_BASIC_DATE[0], lm - 1] - 1];
}

/// <summary>
/// 양력 연도의 특정 월까지의 전체 날 수
/// </summary>
/// <param name="year"></param>
/// <param name="month"></param>
/// <returns></returns>
public int GetSolarDaysOfYear(int year, int month)
{
int ret = 0;
for (int i = 0; i < month; i++)
{
ret += GetSolarDaysOfMonth(year, i + 1);
}

return ret;
}
}
}

Lunar 클래스는 다음 처럼 사용한다.

 

Lunar lunar = new Lunar();
int ly = 2000;
int lm = 2;
int ld = 22;
bool leapMonth = false; // 윤달 여부

int year = 0;
int month = 0;
int day = 0;

string ret = lunar.ToSolarDate(lunar.GetLunarDays(ly, lm, ld, leapMonth), out year, out month, out day);
Console.WriteLine("평달 음력 {0}년 {1}월 {2}일은 양력 {3}년 {4}월 {5}일 입니다.",
ly, lm, ld,
year, month, day);

ret = lunar.ToLunarDate(lunar.GetSolarDays(year, month, day), out ly, out lm, out ld);
Console.WriteLine("양력 {0}년 {1}월 {2}일은 음력 {3}년 {4}월 {5}일 입니다.",
year, month, day,
ly, lm, ld);

 
끝.
Trackback 0 Comment 0
2009/12/17 16:35

아날로그 시계 만들어 보기 #5 : 완성


관련 포스트


소스 다운로드

Clock.zip

이번에는 다음과 같이 실제 시계처럼 시계 바늘의 회전축을 중심으로 회전하도록 수정해 보자.


image

 

소스는 다음과 같다.

private void DrawHands(CartesianCoordinates cd, double rad, SizeF size)
{
using (Bitmap bitmap = new Bitmap((int)size.Width, (int)size.Height))
using (Graphics g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(0, 0, (int)size.Width, (int)size.Height));

PointF p1 = new PointF();
PointF p2 = new PointF();
PointF p3 = new PointF();

float ox = 20;
double twidth;
double atanA;

// 왼쪽 위 좌표
twidth = Math.Sqrt(Math.Pow(ox, 2) + Math.Pow(size.Height / 2, 2));
atanA = Math.Atan((size.Height / 2) / ox);
p1.X = (float)(twidth * Math.Cos(rad - (Math.PI - atanA)));
p1.Y = (float)(twidth * Math.Sin(rad - (Math.PI - atanA)));


// 오른쪽 위 좌표
twidth = Math.Sqrt(Math.Pow(size.Width , 2) + Math.Pow(size.Height / 2, 2));
atanA = Math.Atan((size.Height / 2) / (size.Width ));
p2.X = (float)(twidth * Math.Cos(rad - atanA));
p2.Y = (float)(twidth * Math.Sin(rad - atanA));

// 왼쪽 아래 좌표
twidth = Math.Sqrt(Math.Pow(ox, 2) + Math.Pow(size.Height / 2, 2));
atanA = Math.Atan((size.Height / 2) / ox);
p3.X = (float)(twidth * Math.Cos(rad - (Math.PI + atanA)));
p3.Y = (float)(twidth * Math.Sin(rad - (Math.PI + atanA)));

cd.DrawImage(bitmap, new PointF[] { p1, p2, p3 }, 90);
}
}

끝.
Trackback 0 Comment 0
2009/12/17 14:51

이미지 투명도 설정

http://www.geekpedia.com/code110_Set-Image-Opacity-Using-Csharp.html

Trackback 0 Comment 0
2009/12/14 15:39

아날로그 시계 만들어 보기 #4 : 이미지를 사용해서 만들기(2)

관련 포스트

프로그램 소스

Clock.zip

이전 포스트에서 이미지를 사용해 만든 시계는 부자연스러운 점이 있다.

시계바늘 이미지가 왼쪽위 모서리를 중심으로 돌기 때문인데, 다음과 같은 모양이 출력된다.

 

 

왼쪽 변의 중앙을 중심으로 돌도록 다음과 같이 수정해 보도록 한다.

 

 

다음 그림을 보자.

 

 

왼쪽변 p1p3의 중점 o를 중심으로 시계바늘 이미지를 회전시켜야 한다.

선분 op에서 p의 좌표는 구하는 방법을 이미 알고 있다.(이전 포스트 참조)

포인트 o(x,y)를 중심으로 회전하려면 p1, p2, p3의 좌표를 구해야 하는데 선분 op를 기준으로 다음과 같이 구할 수 있다.

 

// 중심선(선분op)보다 90도(∏/2) 앞서 있다.
p1.X = (float)((float)_hImg.Size.Height / 2 * Math.Cos(rad - Math.PI / 2));
p1.Y = (float)((float)_hImg.Size.Height / 2 * Math.Sin(rad - Math.PI / 2));

// 오른쪽 위 좌표(p2)의 반지름(선분op2)은 (밑변(op)의제곱 + 높이/2(pp2)의제곱)의 제곱근
// 중심선(선분op)과 선분op2의 radian A = atan(pp2/op)
// 중심선(선분op)보다 radian A만큼 앞서 있다.
twidth = Math.Sqrt(Math.Pow(_hImg.Size.Width, 2) + Math.Pow(_hImg.Size.Height / 2, 2));
atanA = Math.Atan(((float)_hImg.Size.Height/2) / _hImg.Size.Width);
p2.X = (float)(twidth * Math.Cos(rad - atanA)); // 밑변=width, 높이=heigt/2를 알때 tanA의 각도A는 atanA
p2.Y = (float)(twidth * Math.Sin(rad - atanA));

// 중심선(선분op)보다 90도(∏/2) 뒤에 있다.
p3 = new PointF();
p3.X = (float)(_hImg.Size.Height / 2 * Math.Cos(rad + Math.PI / 2));
p3.Y = (float)(_hImg.Size.Height / 2 * Math.Sin(rad + Math.PI / 2));
cd.DrawImage(_hImg, new PointF[] { p1, p2, p3 });

p1의 경우 중심선 op보다 90도 앞에 있고 p3의 경우 90도 뒤에 있으므로 수식이 간단하지만 p2의 경우에는 A각 만큼 앞서 있으므로 A각을 먼저 구해야 한다.

 

tanA는 pp2/op이므로 역함수 atan으로 radian A를 구할 수 있다.(atanA = atan(tanA))

 

끝.

Trackback 0 Comment 0
2009/12/11 18:49

아날로그 시계 만들어 보기 #3 : 이미지를 사용해서 만들기

관련 포스트

프로그램 소스



이번에는 시침/분침/초침을 이미지를 사용해 만들어보도록 하자.

 

# 이미지의 회전 : Graphics.DrawImage(Image image, PointF[] destPoints)

 

이미지를 출력하는 Graphics.DrawImage 메서드 중에 Graphics.DrawImage(Image image, PointF[] destPoints) 메서드를 살펴보자.

이 메서드의 두번째 매개변수인 PointF[] destPoints는 세 개의 포인트 좌표를 사용한다.

이미지를 평행사변형으로 보고 이미지가 회전되었을때 왼쪽위, 오른쪽위 왼쪽아래 세 개의 꼭지점 좌표만 알면 회전을 구현할 수 있는데 이 세 개의 꼭지점 좌표를 배열로 받는 것이다.

 

다음 그림을 보면,

 

 

 

왼쪽위 좌표는 원점이고 오른쪽위 좌표는 p에서 p’로 왼쪽아래 좌표는 q에서 q’로 변화되어 이미지가 원점을 중심으로 회전했음을 알 수 있다.

 

포인트 p와 p’는 삼각함수를 사용해 반지름이 w일때 각도에 따른 원주위의 좌표를 구하면 되고,

문제는 q와 q’의 좌표를 구하는 것이다.

 

q와 q’의 좌표도 잘 살펴보면 h를 반지름으로 하는 작은 원주위의 좌표임을 알 수 있고 p의 좌표와 90도 차이남을 알 수 있다.

즉, 다음과 같은 코드로 q와 q’의 좌표를 구할 수 있다.

 

pt2 = new PointF();
pt2.X = (float)(_sImg.Size.Height * Math.Cos(rad + Math.PI / 2));
pt2.Y = (float)(_sImg.Size.Height * Math.Sin(rad + Math.PI / 2));
//cd.DrawLine(new PointF(0, 0), pt);
cd.DrawImage(_sImg, new PointF[] { new PointF(0, 0), pt, pt2 });

전체 프로그램 소스는 다음과 같다.

 

protected override void OnPaint(PaintEventArgs e)
{
Point origin = new Point(200, 200);
CartesianCoordinates cd = new CartesianCoordinates(e.Graphics, origin);

//시계의 반지름 = 50
cd.DrawCircle(new Point(0, 0), 50);

// 현재 시각을 아날로그 시계로 표현해 봐요.
int h, m, s;
// 3시 30분 15초
h = DateTime.Now.Hour;
m = DateTime.Now.Minute;
s = DateTime.Now.Second;

double rad = 0;
int hlen, mlen, slen;
hlen = 30; // 시침의 길이
mlen = 40; // 분침의 길이
slen = 45; // 초침의 길이

PointF pt = new PointF();
PointF pt2 = new PointF();

// 시침 그리기
rad = GetHourRadian(h, m, s); // 1degree = 1/360 * 2∏ = ∏/180, 1radian = ∏/180 * degrees
pt.X = (float)(hlen * Math.Cos(rad)); // cosΘ = x/r => x = r * cosΘ(Θ = radian)
pt.Y = (float)(hlen * Math.Sin(rad)); // sinΘ = y/r => y = r * sinΘ(Θ = radian)
//cd.DrawLine(new PointF(0,0), pt);

pt2 = new PointF();
pt2.X = (float)(_hImg.Size.Height * Math.Cos(rad + Math.PI / 2));
pt2.Y = (float)(_hImg.Size.Height * Math.Sin(rad + Math.PI / 2));
//cd.DrawLine(new PointF(0, 0), pt);
cd.DrawImage(_hImg, new PointF[] { new PointF(0, 0), pt, pt2 });

// 분침 그리기
rad = GetMinuteRadian(m, s); // 1degree = 1/360 * 2∏ = ∏/180, 1radian = ∏/180 * degrees
pt.X = (float)(mlen * Math.Cos(rad)); // cosΘ = x/r => x = r * cosΘ(Θ = radian)
pt.Y = (float)(mlen * Math.Sin(rad)); // sinΘ = y/r => y = r * sinΘ(Θ = radian)
//cd.DrawLine(new PointF(0, 0), pt);

pt2 = new PointF();
pt2.X = (float)(_mImg.Size.Height * Math.Cos(rad + Math.PI / 2));
pt2.Y = (float)(_mImg.Size.Height * Math.Sin(rad + Math.PI / 2));
//cd.DrawLine(new PointF(0, 0), pt);
cd.DrawImage(_mImg, new PointF[] { new PointF(0, 0), pt, pt2 });

// 초침 그리기
rad = GetSecondRadian(s); // 1degree = 1/360 * 2∏ = ∏/180, 1radian = ∏/180 * degrees
pt.X = (float)(slen * Math.Cos(rad)); // cosΘ = x/r => x = r * cosΘ(Θ = radian)
pt.Y = (float)(slen * Math.Sin(rad)); // sinΘ = y/r => y = r * sinΘ(Θ = radian)
//cd.DrawLine(new PointF(0, 0), pt);

// 이미지에서 왼쪽 아래 좌표 구하기
// 초침과 90도 차이가 난다.
pt2 = new PointF();
pt2.X = (float)(_sImg.Size.Height * Math.Cos(rad + Math.PI / 2));
pt2.Y = (float)(_sImg.Size.Height * Math.Sin(rad + Math.PI / 2));
//cd.DrawLine(new PointF(0, 0), pt);
cd.DrawImage(_sImg, new PointF[] { new PointF(0, 0), pt, pt2 });


base.OnPaint(e);
}

Trackback 0 Comment 0
2009/12/11 16:46

Rotate Transform

Rotate Transform

Trackback 0 Comment 0
2009/12/11 15:38

아날로그 시계 만들어 보기 #2 : 시계 완성

관련 포스트

 

ConvertToClockDegree(360 / 60 * s)
 

일반각도는 반시계방향으로 각도가 증가한다.

따라서 단순히 시/분/초의 값을 일반각으로 변환하게 되면 엉뚱한 시간을 가리키는 시계를 보게 된다.

// 일반각도를 시계각도로 변환한다.
private double ConvertToClockDegree(double x)
{
return (360 + 90 - x) % 360;
}

일반각의 0도는 시계의 3시(90도)에 해당하므로 360도에서 시계의 각을 뺀 후 90도를 더해줘야 한다.

이렇게 계산된 값을 360으로 나눈 나머지가 우리가 원하는 시계의 일반각도이다.

 

// 시침은 분과 초의 값에 영향을 받으므로 시간에 분/초 값을 더해줘야 한다.
private double GetHourRadian(int h, int m, int s)
{
return Math.PI * ConvertToClockDegree(360 / 12 * ((double)h + (double)m/60 + (double)s/3600)) / 180;
}

// 분침은 초의 값에 영향을 받으므로 분 값에 초 값을 더해줘야 한다.
private double GetMinuteRadian(int m, int s)
{
return Math.PI * ConvertToClockDegree(360 / 60 * (m + (double)s / 60)) / 180;
}

private double GetSecondRadian(int s)
{
return Math.PI * ConvertToClockDegree(360 / 60 * s) / 180;
}

 

시침은 현재 시간에 몇 분 몇 초까지의 값을 추가로 더해준 후 각도를 구해야 한다.

분침도 마찬가지로 초 값을 더해준 후 각도를 구한다.

 

 

시/분/초에 따른 시침/분침/초침을 모두 그려줄 수 있다면 타이머를 이용해 실제로 동작하는 시계를 구현할 수 있다.

다음 프로그램은 타이머를 사용해 1초에 한 번 시계를 다시 그려주어 시계가 동작하는 것 처럼 보여준다.

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Clock
{
public partial class Form1 : Form
{
Timer _timer = new Timer();

public Form1()
{
InitializeComponent();

_timer.Interval = 1000;
_timer.Tick += new EventHandler(_timer_Tick);
_timer.Enabled = true;
}

void _timer_Tick(object sender, EventArgs e)
{
Invalidate();
}

protected override void OnPaint(PaintEventArgs e)
{
Point origin = new Point(200, 200);
CartesianCoordinates cd = new CartesianCoordinates(e.Graphics, origin);

//시계의 반지름 = 50
cd.DrawCircle(new Point(0, 0), 50);

// 현재 시각을 아날로그 시계로 표현해 봐요.
int h, m, s;
// 3시 30분 15초
h = DateTime.Now.Hour;
m = DateTime.Now.Minute;
s = DateTime.Now.Second;

double rad = 0;
int hlen, mlen, slen;
hlen = 30; // 시침의 길이
mlen = 40; // 분침의 길이
slen = 45; // 초침의 길이

PointF pt = new PointF();

// 시침 그리기
rad = GetHourRadian(h, m, s); // 1degree = 1/360 * 2∏ = ∏/180, 1radian = ∏/180 * degrees
pt.X = (float)(hlen * Math.Cos(rad)); // cosΘ = x/r => x = r * cosΘ(Θ = radian)
pt.Y = (float)(hlen * Math.Sin(rad)); // sinΘ = y/r => y = r * sinΘ(Θ = radian)
cd.DrawLine(new PointF(0,0), pt);

// 분침 그리기
rad = GetMinuteRadian(m, s); // 1degree = 1/360 * 2∏ = ∏/180, 1radian = ∏/180 * degrees
pt.X = (float)(mlen * Math.Cos(rad)); // cosΘ = x/r => x = r * cosΘ(Θ = radian)
pt.Y = (float)(mlen * Math.Sin(rad)); // sinΘ = y/r => y = r * sinΘ(Θ = radian)
cd.DrawLine(new PointF(0, 0), pt);

// 초침 그리기
rad = GetSecondRadian(s); // 1degree = 1/360 * 2∏ = ∏/180, 1radian = ∏/180 * degrees
pt.X = (float)(slen * Math.Cos(rad)); // cosΘ = x/r => x = r * cosΘ(Θ = radian)
pt.Y = (float)(slen * Math.Sin(rad)); // sinΘ = y/r => y = r * sinΘ(Θ = radian)
cd.DrawLine(new PointF(0, 0), pt);

base.OnPaint(e);
}

// 시침은 분과 초의 값에 영향을 받으므로 시간에 분/초 값을 더해줘야 한다.
private double GetHourRadian(int h, int m, int s)
{
return Math.PI * ConvertToClockDegree(360 / 12 * ((double)h + (double)m/60 + (double)s/3600)) / 180;
}

// 분침은 초의 값에 영향을 받으므로 분 값에 초 값을 더해줘야 한다.
private double GetMinuteRadian(int m, int s)
{
return Math.PI * ConvertToClockDegree(360 / 60 * (m + (double)s / 60)) / 180;
}

private double GetSecondRadian(int s)
{
return Math.PI * ConvertToClockDegree(360 / 60 * s) / 180;
}

// 일반각도를 시계각도로 변환한다.
private double ConvertToClockDegree(double x)
{
return (360 + 90 - x) % 360;
}
}
}


완성된 아날로그 시계

 

Trackback 0 Comment 0
2009/12/11 14:14

아날로그 시계 만들어 보기 #1 : 삼각함수를 이용해 원주위의 좌표 구하기

다음 코드를 사용하려면 CartesianCoordinates 클래스가 필요하다.

해당 클래스는 다음 포스트에서 구할 수 있다.

본격적으로 구현하기 앞서 다음과 같이 원점(0,0)을 중심으로 10도(360도 기준) 간격으로 선분을 출력하는 코드를 구현해 보자.

 

코드는 다음과 같다.

 

protected override void OnPaint(PaintEventArgs e)
{
Point origin = new Point(200, 200);
CartesianCoordinates cd = new CartesianCoordinates(e.Graphics, origin);

double cr = 50; // 반지름
PointF pt = new PointF(); // xy좌표

Pen pen = new Pen(Color.Black);
for (double a = 0; a <= 360; a+=10)
{
double rad = (Math.PI * a) / 180; // 1degree = 1/360 * 2∏ = ∏/180, 1radian = ∏/180 * degrees

pt.X = (float)(cr * Math.Cos(rad)); // cosΘ = x/r => x = r * cosΘ(Θ = radian)
pt.Y = (float)(cr * Math.Sin(rad)); // sinΘ = y/r => y = r * sinΘ(Θ = radian)

cd.DrawLine(new PointF(0,0), pt);
}

base.OnPaint(e);
}

원주를 지나는 특정 위치의 좌표(x,y)를 구하려면 호도법과 삼각함수를 사용해야 한다.

일반각도(degree)를 호도(radian)로 변환하는 식은 다음과 같다.

 

1각도(degree) = ∏/180
1호도(radian) = ∏/180 * 각도(degrees)

원점이 0,0이고 반지름이 r인 원에서 Θradian에 대한 삼각비는 다음과 같다.

 

cosΘ = x/r => x = r * cosΘ(Θ = radian)
sinΘ = y/r => y = r * sinΘ(Θ = radian)

위의 식에 의해 호도의 변화에 따른 x와 y의 좌표를 구할 수 있게 된다.

Trackback 0 Comment 0
2009/12/11 14:00

데카르트 좌표계(Cartesian coordinates) 클래스

좌상단 좌표를 원점(0,0)으로 시작해서 오른쪽이 X의 양의 값, 아래가 Y의 양의 값인 일반적인 컴퓨터 좌표계를 원점(0,0)을 중심으로 오른쪽이 X의 양의 값, 위쪽이 Y의 양의 값을 갖도록 변환하여 그림을 그려주는 클래스를 다음과 같이 구현했다.

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Clock
{
public class CartesianCoordinates
{
private PointF _origin;
private Graphics _g;
private Pen _pen;
private Brush _brush;

public CartesianCoordinates(Graphics g, PointF origin)
{
_origin = origin;
_g = g;

_pen = new Pen(Color.Black);
_brush = new SolidBrush(Color.White);
}

public void SetPen(Pen newPen)
{
if (_pen != null)
{
_pen.Dispose();
_pen = null;
}

_pen = newPen;
}

public void SetBrush(Brush newBrush)
{
if (_brush != null)
{
_brush.Dispose();
_brush = null;
}

_brush = newBrush;
}

public PointF ToDeviceCoordinates(PointF pt)
{
pt.X = _origin.X + pt.X;
pt.Y = _origin.Y - pt.Y;

return pt;
}

public void DrawPoint(PointF pt)
{
DrawLine(pt, pt);
}

public void DrawLine(PointF pt1, PointF pt2)
{
_g.DrawLine(_pen, ToDeviceCoordinates(pt1), ToDeviceCoordinates(pt2));
}

public void DrawCircle(PointF o, int r)
{
PointF devo = ToDeviceCoordinates(o);

RectangleF rect = new RectangleF();
rect.X = devo.X - r;
rect.Y = devo.Y - r;
rect.Width = r * 2;
rect.Height = r * 2;

_g.DrawEllipse(_pen, rect);
}

public void DrawEllipse(PointF pt, SizeF size)
{
pt = ToDeviceCoordinates(pt);
RectangleF rect = new RectangleF(pt, size);

_g.DrawEllipse(_pen, rect);
}

public void DrawRectangle(PointF pt, SizeF size)
{
pt = ToDeviceCoordinates(pt);
RectangleF rect = new RectangleF(pt, size);

_g.DrawRectangle(_pen, rect.X, rect.Y, rect.Width, rect.Height);
}


public void FillCircle(PointF o, float r)
{
PointF devo = ToDeviceCoordinates(o);

RectangleF rect = new RectangleF();
rect.X = devo.X - r;
rect.Y = devo.Y - r;
rect.Width = r * 2;
rect.Height = r * 2;

_g.FillEllipse(_brush, rect);
}

public void FillEllipse(PointF pt, SizeF size)
{
pt = ToDeviceCoordinates(pt);
RectangleF rect = new RectangleF(pt, size);

_g.FillEllipse(_brush, rect);
}

public void FillRectangle(PointF pt, SizeF size)
{
pt = ToDeviceCoordinates(pt);
RectangleF rect = new RectangleF(pt, size);

_g.FillRectangle(_brush, rect);
}
}
}

간단히 점, 선, 원, 타원, 사각형을 그려주는 함수도 추가했다.

위 클래스를 사용하면 간단히 수학시간에 배운 데카르트 좌표계를 사용해서 도형을 그릴 수 있다.

Trackback 0 Comment 0
2009/12/11 10:30

삼각함수를 이용해서 아날로그 시계 만들기

삼각함수를 이용해서 아날로그 시계 만들기

Trackback 0 Comment 0
2009/12/10 11:15

Google Data API for .NET

구글검색 : http://www.google.co.kr/search?complete=1&hl=ko&q=google+data+api+c%23&btnG=Google+%EA%B2%80%EC%83%89&lr=&aq=f

0;

http://code.google.com/apis/gdata/client-cs.html

 

http://www.fryan0911.com/2009/03/c-using-google-data-apis-on-your.html

Trackback 0 Comment 0
2009/12/03 14:27

SSAS HTTP 액세스 구성

http://dw.insideitsolution.com/archive/20090410

Trackback 0 Comment 0