프로그래밍
- 교차 판정 카탈로그 2012.08.28
- LinePointRightSide (선분과 점의 위치 관계를 리턴) 2012.08.23
- 삼각형 안에 점이 있는지 없는지 체크하는 함수 (PtInTriangle) 2012.08.21
- swprintf 근처 함수 놀라운 기능 2012.07.26 1
- VK_A 와 같은 가상 키코드, 알파벳 가상 키코드 2012.07.25 2
- STL map 보다 더 빠른 MyMap 2012.07.19 2
- 컨트롤, 에디트, 더블 버퍼링 깜빡임 2012.07.17 1
- 삼각 함수 2012.07.16
- 두 점 사이의 각도를 구하는 방법 atan2() 2012.07.11 1
- 미니 덤프 클래스화 2012.06.28 1
교차 판정 카탈로그
LinePointRightSide (선분과 점의 위치 관계를 리턴)
선분과 점의 위치 관계를 리턴해 준다. 선분의 왼쪽에 있을 경우 음수를 리턴하고, 오른쪽에 있을 땐 양수, 동일하면 0
static float LinePointRightSide(float fstart_x, float fstart_y, float fend_x, float fend_y, float fpoint_x, float fpoint_y)
{
return (fend_x-fstart_x)*(fpoint_y-fstart_y)-(fpoint_x-fstart_x)*(fend_y-fstart_y);
}
삼각형 안에 점이 있는지 없는지 체크하는 함수 (PtInTriangle)
참고로 이 함수 수행속도가 굉장히 느리므로 다른 방법을 강구하기를 추천...
저 같은 경우는 선분과 점의 위치 관계를 리턴해주는 함수를 4번 사용 함
BOOL BTriangle::PtInTriangle( POINT *Verts, POINT pt )
{
HRGN hRgn =CreatePolygonRgn( Verts, 3, WINDING); // 핵심..정점수만큼의 Region 영역을 생성..
if( PtInRegion( hRgn, pt.x, pt.y ) )
{
DeleteObject( hRgn );
return TRUE;
}
DeleteObject( hRgn );
return FALSE;
}
swprintf 근처 함수 놀라운 기능
Visual Studio 2005로 넘어가면서 _s 가 붙어 있는 safe 타입의 함수들로 변경하지 않으면 warning C4996 이 나타나면서 안전하지 않다면서 _s가 붙여 있는 함수를 추천해 줍니다.
wcscpy를 교체하다가 아래에 swprintf 가 있길래 이것도 _s 가 있나~ 싶어서 보니까 swprintf_s 는 없고 _swprintf_p, _swprintf_l_s 이런 함수들이 등장했습니다.
_swprintf_l_s는 로케일을 설정하기 위한 것 같고 _swprintf_p가 알맞은 형태인것 같은데 이 _p 가 뭔가 싶어서 MSDN을 뒤져보니
Positional Parameter 라는 기능이 지원된다는 의미 였습니다.
그래서 Positional Parameter가 뭔고 하니 sprintf에서 사용되는 가변 인자들의 위치를 내 마음대로 지정해 줄 수 있는 방식 이었습니다.
뭐 말로하니까 헷갈리고 설명하기도 어려우니 예제를 보면 간단하겠습니다.
_printf_p("%1$d times %1$d is %2$d", 10, 100);
이러한 형태로 사용하면 다음과 같은 형태로 출력이 가능합니다.
10 times 10 is 100
이 기능을 쓰려고 boost::format 을 사용했었는데, 이런게 있다면 이걸 사용하면 되겠네요.
출처 : 링크
VK_A 와 같은 가상 키코드, 알파벳 가상 키코드
VK_A 와 같은 가상 키코드, 알파벳 가상 키코드
#define VK_A 0x41
#define VK_B 0x42
#define VK_C 0x43
#define VK_D 0x44
#define VK_E 0x45
#define VK_F 0x46
#define VK_G 0x47
#define VK_H 0x48
#define VK_I 0x49
#define VK_J 0x4A
#define VK_K 0x4B
#define VK_L 0x4C
#define VK_M 0x4D
#define VK_N 0x4E
#define VK_O 0x4F
#define VK_P 0x50
#define VK_Q 0x51
#define VK_R 0x52
#define VK_S 0x53
#define VK_T 0x54
#define VK_U 0x55
#define VK_V 0x56
#define VK_W 0x57
#define VK_X 0x58
#define VK_Y 0x59
#define VK_Z 0x5A
STL map 보다 더 빠른 MyMap
template<class T>
class MyMap
{
public:
MyMap( int _nSize = 1 )
{
Init(_nSize);
}
~MyMap()
{
SAFE_DELETE_ARRAY(ayKey);
SAFE_DELETE_ARRAY(ayData);
}
void Init( int _nSize )
{
nMaxSize = _nSize;
nNowSize = 0;
ayKey = new int[nMaxSize];
ayData = new T[nMaxSize];
memset( ayKey, -1, sizeof(int) * nMaxSize );
}
bool insert( int _nKey, T _Val )
{
int nIndex = find(_nKey);
if( nMaxSize != nIndex )
{
ayData[nIndex] = _Val;
return true;
}
for(int i = 0; i < nMaxSize; ++i)
{
if( -1 == ayKey[i] )
{
ayKey[i] = _nKey;
ayData[i] = _Val;
nNowSize++;
return true;
}
}
// 빈 공간이 없다!
int* ayKey2 = new int[nMaxSize * 2];
T* ayData2 = new T[nMaxSize * 2];
memset( ayKey2, -1, sizeof(int) * nMaxSize * 2 );
memcpy(ayKey2, ayKey, sizeof(int) * nMaxSize );
memcpy(ayData2, ayData, sizeof(T) * nMaxSize );
SAFE_DELETE_ARRAY(ayKey);
SAFE_DELETE_ARRAY(ayData);
ayKey = ayKey2;
ayData = ayData2;
nMaxSize = nMaxSize * 2;
return insert(_nKey, _Val);
}
int find( int _nKey )
{
for(int i = 0; i < nMaxSize; ++i)
{
if( _nKey == ayKey[i] )
return i;
}
return nMaxSize; // 찾지 못 함!
}
bool erase( int _nKey )
{
int nIndex = find(_nKey);
if( nMaxSize != nIndex )
{
ayKey[nIndex] = -1;
nNowSize--;
return true;
}
return false;
}
int GetMaxSize()
{
return nMaxSize;
}
int GetNowSize()
{
return nNowSize;
}
T* KeyToValue(int _nKey)
{
int nIndex = find(_nKey);
if( nMaxSize != nIndex )
return ArrayIndexToValue( nIndex );
return NULL;
}
int ArrayIndexToKey(int _nIndex)
{
if( 0 > _nIndex || nMaxSize - 1 < _nIndex ) // 배열 바운더리 체크
{
_asm int 3
return nMaxSize;
}
return ayKey[_nIndex];
}
T* ArrayIndexToValue(int _nIndex)
{
if( 0 > _nIndex || nMaxSize - 1 < _nIndex ) // 배열 바운더리 체크
{
_asm int 3
return NULL;
}
return &ayData[_nIndex];
}
int GetMaximumValueKey()
{
int nKey = -1;
int nValue = 0;
for(int i = 0; i < nMaxSize;++i)
{
if( nValue < ayData[i] )
{
nKey = ayKey[i];
nValue = ayData[i];
}
}
return nKey;
}
void clear()
{
memset( ayKey, -1, sizeof(int) * nMaxSize );
}
private:
int* ayKey;
T* ayData;
int nMaxSize;
int nNowSize;
};
속도 검증 코드
컨트롤, 에디트, 더블 버퍼링 깜빡임
Q>
더블버퍼링써서 그림들은 전혀 안 깜박이는데요.
에디트박스가 심하게 깜박여요 ㅠ_ㅠ
A>
뒷 배경 그림을 다시 그리게 되는 경우
전체가 다 지워지고 그림이 그려진 다음 컨트롤이 그려지게 됩니다.
따라서 더블 버퍼링으로 뒷 배경은 깜박이지 않게 했다 하더라도
컨트롤이 그려질대는 당연히 깜박이겠죠?
그렇다면 어덯게 해결해야 할까요?
컨트롤 위치에는 배경을 그려주지 않으면 해결됩니다.
API에 다음과 같은 함수가 잇습니다.
ExcludeClipRect();
이 함수로 지정한 영역은 Invalidate()를 하여도 다시 그려지지 않습니다.
용어가 잘 생각이 나지 않는데
화면에 가려져 있어 그릴 필요가 없는 영역으로 만들어버립니다.
출처:링크
삼각 함수
파란색 선분 길이와 각을 알 때
초록색 = 파란색 * sin(42)
붉은색 = 파란색 * sin(48)
초록색 선분 길이와 각을 알 때
붉은색 = 초록색 * tan(48)
파란색 = 초록색 / sin(42)
붉은색 선분 길이와 각을 알 때
파란색 = 붉은색 / sin(48)
초록색 = 붉은색 * tan(42)
두 점 사이의 각도를 구하는 방법 atan2()
#define D3DX_PI ((FLOAT) 3.141592654f)
#define D3DXToRadian(degree)((degree) * (D3DX_PI / 180.f))
#define D3DXToDegree(radian)((radian) * (180.f / D3DX_PI))
// 원에 십자를 그었을때 ┾ 두꺼운 선이 각도 0도이고 시계방향으로 1도, 2도... 한바퀴 돌아 두꺼운 선직전까지 360도이다.
// 각도 = 기준 점, 확인 할 점
static float GetDirectionAngle( float x1, float y1, float x2, float y2 )
{
x2 -= x1;
y2 -= y1;
//float Angle = D3DXToDegree( atan2(y2, x2) );
float Angle = atan2(y2, x2) * 57.3f;
if( 0 > Angle )
Angle += 360;
return Angle;
}
미니 덤프 클래스화
MiniDump.h
#pragma once
#include "dbghelp.h"
class Mini_Dump
{
public:
Mini_Dump(void);
static Mini_Dump *gpDumper;
protected:
static LONG WINAPI Handler(struct _EXCEPTION_POINTERS *pExceptionInfo);
_EXCEPTION_POINTERS *m_pExceptionInfo;
TCHAR m_szDumpPath[_MAX_PATH];
TCHAR m_szAppPath[_MAX_PATH];
TCHAR m_szAppBaseName[_MAX_PATH];
LONG WriteMiniDump(_EXCEPTION_POINTERS *pExceptionInfo);
virtual void VSetDumpFileName(void);
virtual MINIDUMP_USER_STREAM_INFORMATION *VGetUserStreamArray() {return NULL;};
};
typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess,
DWORD dwPid,HANDLE hFile,MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
MiniDump.cpp
#include <windows.h>
#include "MiniDump.h"
#include "assert.h"
Mini_Dump *Mini_Dump::gpDumper = NULL;
//// 클래스 생성 함수
Mini_Dump::Mini_Dump( void )
{
assert(!gpDumper);
if(!gpDumper)
{
::SetUnhandledExceptionFilter(Handler);
gpDumper = this;
}
}
//// 덤저장 핸들
LONG Mini_Dump::Handler(_EXCEPTION_POINTERS *pExceptionInfo)
{
LONG retvel = EXCEPTION_CONTINUE_SEARCH;
// 덤프 확인
if(!gpDumper)
{
return retvel;
}
// 텀프 저장
return gpDumper->WriteMiniDump(pExceptionInfo);
}
//// 덤프를 저장한다.
LONG Mini_Dump::WriteMiniDump(_EXCEPTION_POINTERS *pExceptionInfo)
{
LONG retvel = EXCEPTION_CONTINUE_SEARCH;
// 익셉션 포인터 저장
m_pExceptionInfo = pExceptionInfo;
// dbghelp.dll 찾기
HMODULE hDll = NULL;
TCHAR szDbgHelpPath[_MAX_PATH];
if(GetModuleFileName(NULL,m_szAppPath,_MAX_PATH))
{
TCHAR *pSlash = strrchr(m_szAppPath,'\\');
if(pSlash)
{
strcpy(m_szAppBaseName,pSlash +1);
*(pSlash+1) = 0;
}
strcpy(szDbgHelpPath,m_szAppPath);
strcat(szDbgHelpPath,"DBGHELP.DLL");
hDll = ::LoadLibrary(szDbgHelpPath);
}
if(hDll == NULL)
{
// DLL 다시 한번 찾기
hDll = ::LoadLibrary("DBGHELP.DLL");
}
TCHAR szResult[_MAX_PATH];
BOOL bResult;
if(hDll)
{
MINIDUMPWRITEDUMP pMiniDumpWriteDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll,"MiniDumpWriteDump");
if(pMiniDumpWriteDump)
{
// 덤프 파일 이름 설정
VSetDumpFileName();
// 덤프 파일 저장
HANDLE hFile = ::CreateFile(m_szDumpPath,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = pExceptionInfo;
ExInfo.ClientPointers = NULL;
// 덤프 기록
BOOL bOK = pMiniDumpWriteDump(GetCurrentProcess(),GetCurrentProcessId(),
hFile,MiniDumpNormal,&ExInfo,VGetUserStreamArray(),NULL);
if(bOK)
{
wsprintf(szResult,"");
bResult = false;
retvel = EXCEPTION_EXECUTE_HANDLER;
}
else
{
bResult = true;
}
::CloseHandle(hFile);
}
else
{
// 파일 생성 오류
bResult = true;
}
}
else
{
wsprintf(szResult,"DBGHELP.DLL 구버전 입니다.");
bResult = true;
}
}
else
{
wsprintf(szResult,"DBBHELP.DLL 없습니다.");
bResult = true;
}
TerminateProcess(GetCurrentProcess(),0);
return retvel;
}
//// 저장 덤프 파일의 풀 경로 설정
void Mini_Dump::VSetDumpFileName()
{
// 저장 파일 이름 설정
wsprintf(m_szDumpPath,"%s%s.dmp",m_szAppPath,m_szAppBaseName);
}
Main.cpp
#include "stdafx.h"
#include <Windows.h>
#include "MiniDump.h"
void (*g_pRandFunction[5])();
void OnTest1(void)
{
int nRandValue = rand()%5;
g_pRandFunction[nRandValue]();
}
void OnTest2(void)
{
int nRandValue = rand()%5;
g_pRandFunction[nRandValue]();
}
void OnTest3(void)
{
int *p = NULL;
for( int i = 0; i < 20000; i++ )
{
p[i] = 100;
}
}
void OnTest4(void)
{
int nRandValue = rand()%5;
g_pRandFunction[nRandValue]();
}
void OnTest5(void)
{
int *p = NULL;
for( int i = 0; i < 1000; i++ )
{
p[i] = 100;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Mini_Dump::gpDumper = new Mini_Dump;
// 메모리 할당 실패 테스트
//char *pc1 = new char[1000000000];
//char *pc2 = new char[1000000000];
//char *pc3 = new char[1000000000];
//char *pc4 = new char[0x7fffffff];
g_pRandFunction[0] = OnTest1;
g_pRandFunction[1] = OnTest2;
g_pRandFunction[2] = OnTest3;
g_pRandFunction[3] = OnTest4;
g_pRandFunction[4] = OnTest5;
srand(GetTickCount());
int nRandValue = rand()%5;
g_pRandFunction[nRandValue]();
return 0;
}