Files
2026-06-01 12:46:52 +02:00

371 lines
7.8 KiB
C++

// Time.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include <cstring>
#include <cstdio>
#include <cassert>
#include <ctime>
#include <vector>
#include <Windows.h>
#include "../../include/geometry/X2DPolygon.h"
#include "../../include/geometry/X2DQuadTree_divide_polygon.h"
#include "../../include/geometry/X2DPathFinder.h"
#include "../../include/toolkit/XFileUtil.h"
#include "../../include/kfile/IFileSystem.h"
#include <internal_lib_include.h>
bool IsCheckPolygon( X2D::Point< int >* point, X2D::Polygon<int>* polygon, size_t count )
{
assert( count == polygon->Size() );
if( count != polygon->Size() )
{
return false;
}
for( size_t i = 0; i < count; ++i )
{
assert( point[i] == polygon->GetPoint( i ) );
if( point[i] != polygon->GetPoint( i ) )
{
return false;
}
}
return true;
}
int g_nMapWidth = 700000;
int g_nMapHeight = 1000000;
struct polygon_deleter
{
void operator()( X2D::Polygon<int>* p )
{
delete p;
}
};
struct polygon_allocator
{
X2D::Polygon<int>* operator()()
{
return new X2D::Polygon< int >();
}
};
X2D::QuadTree_divide_polygon< int, X2D::Polygon<int>*, 10 > g_qtBlockInfo( 0, 0, g_nMapWidth, g_nMapHeight );
bool LoadAttributeFile( const char * szFileName, int x, int y )
{
if( !XFileUtil::IsFile( szFileName ) )
return false;
float fAttrLen = 5.25;
float fMapLength = 16128;
std::auto_ptr< KStream > pStream( new KFileStream( szFileName ) );
int nPolygonCnt = 0;
pStream->Read( &nPolygonCnt, sizeof( nPolygonCnt ) );
X2D::Polygon< int > block_info;
for( int i = 0; i < nPolygonCnt; ++i )
{
int nPtCnt = 0;
pStream->Read( &nPtCnt, sizeof( nPtCnt ) );
if( nPtCnt < 3 ) continue;
X2D::Point<int> * pPoints = new X2D::Point<int>[nPtCnt];
pStream->Read( pPoints, sizeof( X2D::Point<int> ) * nPtCnt );
block_info.Clear();
for( int nPointNum = 0; nPointNum < nPtCnt; ++nPointNum )
{
pPoints[nPointNum].x = fMapLength * x + pPoints[nPointNum].x * fAttrLen;
pPoints[nPointNum].y = fMapLength * y + pPoints[nPointNum].y * fAttrLen;
}
if( block_info.Set( pPoints, pPoints + nPtCnt ) )
{
X2D::Polygon< int > * pBlock_Info = new X2D::Polygon< int > ( block_info );
g_qtBlockInfo.Add( pBlock_Info, polygon_allocator(), polygon_deleter() );
}
delete [] pPoints;
}
return true;
}
bool IsBlocked( int x, int y )
{
X2D::Point< int > pt( x, y );
if( g_qtBlockInfo.LooseCollision( pt ) )
{
return true;
}
return false;
}
void GetCollisionPolygons( int x1, int y1, int x2, int y2, std::vector<X2D::Polygon<int> *> & vPolygons )
{
X2D::Point<int> ptStart( x1, y1 ), ptEnd( x2, y2 );
X2D::Box<int> boxRegion( ptStart, ptEnd );
g_qtBlockInfo.Enum( boxRegion, &vPolygons );
}
bool FindPath( int x1, int y1, int x2, int y2 )
{
std::vector< X2D::Polygon<int>* > pathFindPolygons;
GetCollisionPolygons( x1, y1, x2, y2, pathFindPolygons );
if( pathFindPolygons.empty() )
{
return true;
}
typedef std::vector< X2D::Point<int> > PATH;
PATH vPath;
X2D::Point< int > ptStart( x1, y1 ), ptEnd( x2, y2 );
// 최대 길찾기를 통하여 갈 수 있는 거리는 가시거리 * 2이다. (적절한 파라미터 테스트 중)
X2D::PathFinder< int, X2D::Polygon<int>* >::Find( pathFindPolygons.begin(), pathFindPolygons.end(), ptStart, ptEnd, vPath, 525 * 2 );
if( vPath.empty() )
{
return false;
}
return true;
}
bool CollisionToLine( int x1, int y1, int x2, int y2 )
{
X2D::Line<int> line( x1, y1, x2, y2 );
if( g_qtBlockInfo.LooseCollision( line ) == false )
{
return false;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
// 문제 사항 테스트
{
//
X2D::QuadTree_divide_polygon< int, X2D::Polygon<int>*, 1, 2 > qtBlockInfo2( 0, 0, 100, 100 );
X2D::Point<int> pPoints[6];
X2D::Polygon< int >* temp = new X2D::Polygon< int >();
pPoints[0].x = 50;
pPoints[0].y = 70;
pPoints[1].x = 10;
pPoints[1].y = 10;
pPoints[2].x = 50;
pPoints[2].y = 10;
pPoints[3].x = 50;
pPoints[3].y = 30;
pPoints[4].x = 90;
pPoints[4].y = 90;
pPoints[5].x = 50;
pPoints[5].y = 90;
temp->Set( pPoints, pPoints + _countof( pPoints ) );
qtBlockInfo2.Add( temp, polygon_allocator(), polygon_deleter() );
}
// 맵 파일에서 실제 충돌 폴리곤을 읽어보자.
// map 폴더에 충돌 파일(.nfa)이 있어야 한다.
for( int y = 0; y < 16; ++y )
{
for( int x = 0; x < 14; ++x )
{
char file_name[MAX_PATH] = "";
sprintf_s( file_name, _countof( file_name ), "map/M%03d_%03d.nfa", x, y );
if( LoadAttributeFile( file_name, x, y ) == true )
{
printf( "%s map file loaded.\n", file_name );
}
}
}
X2D::Point<int> ptStart( 0, 0 ), ptEnd( 700000, 1000000 );
X2D::Box<int> boxRegion( ptStart, ptEnd );
std::vector<X2D::Polygon<int> *> vPolygons;
g_qtBlockInfo.Enum( boxRegion, &vPolygons );
size_t max_size = 0;
X2D::Polygon<int>* p_m = NULL;
for( auto pos = vPolygons.begin(); pos != vPolygons.end(); ++pos )
{
X2D::Polygon<int>* p = (*pos);
if( p->Size() > max_size )
{
max_size = p->Size();
p_m = p;
}
}
IsBlocked(169960,10568);
int x = g_qtBlockInfo.GetX();
int y = g_qtBlockInfo.GetY();
int w = g_qtBlockInfo.GetWidth();
int h = g_qtBlockInfo.GetWidth();
X2D::Rect<int> rc(x, y, w, h);
g_qtBlockInfo.Remove( rc, polygon_deleter() );
assert(g_qtBlockInfo.getItemCount() == 0);
// 일부 라인이 겹칠때
{
X2D::Point<int> pPoints[6];
pPoints[0].x = 10;
pPoints[0].y = 10;
pPoints[1].x = 50;
pPoints[1].y = 10;
pPoints[2].x = 50; // in
pPoints[2].y = 20;
pPoints[3].x = 70;
pPoints[3].y = 20;
pPoints[4].x = 70;
pPoints[4].y = 30;
pPoints[5].x = 40;
pPoints[5].y = 30;
X2D::Polygon< int > temp;
temp.Set( pPoints, pPoints + _countof( pPoints ) );
X2D::Line< int > center( 50, 0, 50, 100 );
static std::vector< X2D::Polygon<int>* > r =
X2D::QuadTree_divide_polygon< int, X2D::Polygon<int>*, 1 >::divide_polygon( &temp, center, polygon_allocator(), polygon_deleter() );
X2D::Point< int > result_pt1[5];
result_pt1[0].Set( 10, 10 );
result_pt1[1].Set( 50, 10 );
result_pt1[2].Set( 50, 20 );
result_pt1[3].Set( 50, 30 );
result_pt1[4].Set( 40, 30 );
X2D::Point< int > result_pt2[4];
result_pt2[0].Set( 50, 20 );
result_pt2[1].Set( 70, 20 );
result_pt2[2].Set( 70, 30 );
result_pt2[3].Set( 50, 30 );
assert( r.size() == 2 );
assert( IsCheckPolygon( result_pt1, r[0], _countof( result_pt1 ) ) );
assert( IsCheckPolygon( result_pt2, r[1], _countof( result_pt2 ) ) );
}
{
X2D::Point<int> pPoints[4];
pPoints[0].x = 0;
pPoints[0].y = 0;
pPoints[1].x = 100;
pPoints[1].y = 0;
pPoints[2].x = 100; // in
pPoints[2].y = 100;
pPoints[3].x = 0;
pPoints[3].y = 100;
X2D::Polygon< int > temp;
temp.Set( pPoints, pPoints + _countof( pPoints ) );
X2D::Line< int > center( 50, 0, 50, 100 );
static std::vector< X2D::Polygon<int>* > r =
X2D::QuadTree_divide_polygon< int, X2D::Polygon<int>*, 1 >::divide_polygon( &temp, center, polygon_allocator(), polygon_deleter() );
assert( r.size() == 2 );
int a = 0;
}
//
X2D::QuadTree_divide_polygon< int, X2D::Polygon<int>*, 1, 2 > qtBlockInfo2( 0, 0, 100, 100 );
X2D::Point<int> pPoints[12];
X2D::Polygon< int >* temp = new X2D::Polygon< int >();
// 대충 ㄹ모양임 (100,100 좌표에 점 12개 ㄹ 모양으로)
pPoints[0].x = 1;
pPoints[0].y = 99;
pPoints[1].x = 99;
pPoints[1].y = 99;
pPoints[2].x = 99;
pPoints[2].y = 40;
pPoints[3].x = 20;
pPoints[3].y = 40;
pPoints[4].x = 20;
pPoints[4].y = 20;
pPoints[5].x = 99;
pPoints[5].y = 20;
pPoints[6].x = 99;
pPoints[6].y = 1;
pPoints[7].x = 1;
pPoints[7].y = 1;
pPoints[8].x = 1;
pPoints[8].y = 60;
pPoints[9].x = 80;
pPoints[9].y = 60;
pPoints[10].x = 80;
pPoints[10].y = 80;
pPoints[11].x = 1;
pPoints[11].y = 80;
temp->Set( pPoints, pPoints + _countof( pPoints ) );
qtBlockInfo2.Add( temp, polygon_allocator(), polygon_deleter() );
return 0;
}