외국: 링크

국내: 링크


직선과 직선 교차 판정

사격형과 직선의 교차 판정 등

선분과 점의 위치 관계를 리턴해 준다. 선분의 왼쪽에 있을 경우 음수를 리턴하고, 오른쪽에 있을 땐 양수, 동일하면 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);

}

참고로 이 함수 수행속도가 굉장히 느리므로 다른 방법을 강구하기를 추천...

저 같은 경우는 선분과 점의 위치 관계를 리턴해주는 함수를 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;
}


참고자료: 링크1, 링크2

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 와 같은 가상 키코드, 알파벳 가상 키코드


#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


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;

};


속도 검증 코드


MapTest.zip



Q>

더블버퍼링써서 그림들은 전혀 안 깜박이는데요. 

에디트박스가 심하게 깜박여요 ㅠ_ㅠ



A>

 뒷 배경 그림을 다시 그리게 되는 경우

전체가 다 지워지고 그림이 그려진 다음 컨트롤이 그려지게 됩니다.

따라서 더블 버퍼링으로 뒷 배경은 깜박이지 않게 했다 하더라도

컨트롤이 그려질대는 당연히 깜박이겠죠?

 

그렇다면 어덯게 해결해야 할까요?

 

컨트롤 위치에는 배경을 그려주지 않으면 해결됩니다.

API에 다음과 같은 함수가 잇습니다.

 

ExcludeClipRect();

 

이 함수로 지정한 영역은 Invalidate()를 하여도 다시 그려지지 않습니다.

용어가 잘 생각이 나지 않는데

화면에 가려져 있어 그릴 필요가 없는 영역으로 만들어버립니다.


출처:링크


파란색 선분 길이와 각을 알 때 

초록색 = 파란색 * sin(42)

붉은색 = 파란색 * sin(48)


초록색 선분 길이와 각을 알 때

붉은색 = 초록색 * tan(48)

파란색 = 초록색 / sin(42)


붉은색 선분 길이와 각을 알 때

파란색 = 붉은색 / sin(48)

초록색 = 붉은색 * tan(42)


#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;

}











+ Recent posts