// Time.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다. // #include "stdafx.h" #include #include #include #include #include #include #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 bool IsCheckPolygon( X2D::Point< int >* point, X2D::Polygon* 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* p ) { delete p; } }; struct polygon_allocator { X2D::Polygon* operator()() { return new X2D::Polygon< int >(); } }; X2D::QuadTree_divide_polygon< int, X2D::Polygon*, 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 * pPoints = new X2D::Point[nPtCnt]; pStream->Read( pPoints, sizeof( X2D::Point ) * 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 *> & vPolygons ) { X2D::Point ptStart( x1, y1 ), ptEnd( x2, y2 ); X2D::Box boxRegion( ptStart, ptEnd ); g_qtBlockInfo.Enum( boxRegion, &vPolygons ); } bool FindPath( int x1, int y1, int x2, int y2 ) { std::vector< X2D::Polygon* > pathFindPolygons; GetCollisionPolygons( x1, y1, x2, y2, pathFindPolygons ); if( pathFindPolygons.empty() ) { return true; } typedef std::vector< X2D::Point > PATH; PATH vPath; X2D::Point< int > ptStart( x1, y1 ), ptEnd( x2, y2 ); // 최대 길찾기를 통하여 갈 수 있는 거리는 가시거리 * 2이다. (적절한 파라미터 테스트 중) X2D::PathFinder< int, X2D::Polygon* >::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 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*, 1, 2 > qtBlockInfo2( 0, 0, 100, 100 ); X2D::Point 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 ptStart( 0, 0 ), ptEnd( 700000, 1000000 ); X2D::Box boxRegion( ptStart, ptEnd ); std::vector *> vPolygons; g_qtBlockInfo.Enum( boxRegion, &vPolygons ); size_t max_size = 0; X2D::Polygon* p_m = NULL; for( auto pos = vPolygons.begin(); pos != vPolygons.end(); ++pos ) { X2D::Polygon* 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 rc(x, y, w, h); g_qtBlockInfo.Remove( rc, polygon_deleter() ); assert(g_qtBlockInfo.getItemCount() == 0); // 일부 라인이 겹칠때 { X2D::Point 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* > r = X2D::QuadTree_divide_polygon< int, X2D::Polygon*, 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 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* > r = X2D::QuadTree_divide_polygon< int, X2D::Polygon*, 1 >::divide_polygon( &temp, center, polygon_allocator(), polygon_deleter() ); assert( r.size() == 2 ); int a = 0; } // X2D::QuadTree_divide_polygon< int, X2D::Polygon*, 1, 2 > qtBlockInfo2( 0, 0, 100, 100 ); X2D::Point 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; }