blob: dadbbbe22b29507c63be489eb49723081ca49537 [file] [log] [blame] [edit]
//===========================================================================//
// Purpose : Template version for a TTPT_TilePlane tile plane object class.
//
// Reference : "Corner Stitching: A Data-Structuring Technique for VLSI
// Layout Tools", John K. Ousterhout, IEEE Transactions on
// Computer-Aided Design, Vol. CAD-3, No. 1, January 1984
//
// Inline methods include:
// - GetRegion, GetMinGrid
// - IsWithin
// - IsValid
//
// Public methods include:
// - TTPT_TilePlane_c, ~TTPT_TilePlane_c
// - operator=
// - operator==, operator!=
// - Print, PrintLaff
// - Init
// - Reset
// - Add
// - Delete
// - Clear
// - Find
// - FindNearest
// - FindConnected
// - FindAdjacents
// - FindData
// - FindCount
// - FindRegion
// - Split
// - Merge
// - MergeAdjacents
// - JoinAdjacents
// - HasAdjacents
// - HasNeighbor
// - IsClear, IsSolid, IsSolidNot
// - IsIntersecting
// - IsAdjacent
// - IsMergable
// - IsSplitable
// - IsLegal
//
// Private methods include:
// - AddPerRegion_
// - AddPerNew_
// - AddPerMerge_
// - AddPerMergeNew_
// - AddPerOverlap_
// - AddPerUpperSideSplit_
// - AddPerLowerSideSplit_
// - AddPerCenterSideSplits_
// - AddPerSolidTileMerges_
// - AddPerSolidTileCorners_
// - AddPerSolidTileCorner_
// - DeletePerExact_
// - DeletePerWithin_
// - DeletePerIntersect_
// - DeletePerIntersectMin_
// - DeletePerRightSide_
// - DeletePerLeftSide_
// - DeletePerLowerSide_
// - DeletePerUpperSide_
// - FindPerPoint_
// - FindPerExact
// - FindPerWithin_
// - FindPerIntersect_
// - FindNearestBySides_
// - FindNearestBySide_
// - FindNearestByRegion_
// - FindCountRefresh_
// - SplitRegionCoords_
// - MergeRegionCoords_
// - MergeAdjacentsByExtent_
// - MergeAdjacentsToLeft_
// - MergeAdjacentsToRight_
// - MergeAdjacentsToLower_
// - MergeAdjacentsToUpper_
// - JoinAdjacentsPerExact_
// - JoinAdjacentsPerIntersect_
// - JoinAdjacentsBySide_
// - CornerRegionCoords_
// - CornerTileRemerge_
// - StitchToSplit_
// - StitchToMerge_
// - StitchFromSide_
// - EstAspectRatio_
// - HasAspectRatio_
// - IsClearMatch_, IsClearAny_, IsClearAll_
// - IsSolidMatch_, IsSolidAny_, IsSolidAll_, IsSolidMax_
// - IsSolidNotMatch_, IsSolidNotAny_, IsSolidNotAll_
// - Allocate_, Deallocate_
// - ShowInternalMessage_
//
//===========================================================================//
//---------------------------------------------------------------------------//
// Copyright (C) 2012-2013 Jeff Rudolph, Texas Instruments (jrudolph@ti.com) //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"),//
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included //
// in all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS //
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF //
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN //
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, //
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR //
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE //
// USE OR OTHER DEALINGS IN THE SOFTWARE. //
//---------------------------------------------------------------------------//
#ifndef TTPT_TILE_PLANE_H
#define TTPT_TILE_PLANE_H
#include <cstdio>
using namespace std;
#include "TC_Typedefs.h"
#include "TC_MinGrid.h"
#include "TCT_Generic.h"
#include "TCT_OrderedVector.h"
#include "TIO_PrintHandler.h"
#include "TIO_SkinHandler.h"
#include "TGS_Typedefs.h"
#include "TGS_Region.h"
#include "TGS_Line.h"
#include "TGS_Point.h"
#include "TTP_Typedefs.h"
#include "TTPT_Tile.h"
#include "TTPT_TilePlaneIter.h"
//===========================================================================//
// Purpose : Class declaration
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > class TTPT_TilePlane_c
{
public:
TTPT_TilePlane_c( void );
TTPT_TilePlane_c( const TGS_Region_c& region );
TTPT_TilePlane_c( const TTPT_TilePlane_c< T >& tilePlane );
~TTPT_TilePlane_c( void );
TTPT_TilePlane_c< T >& operator=( const TTPT_TilePlane_c< T >& tilePlane );
bool operator==( const TTPT_TilePlane_c< T >& tilePlane ) const;
bool operator!=( const TTPT_TilePlane_c< T >& tilePlane ) const;
void Print( FILE* pfile = stdout, size_t spaceLen = 0 ) const;
void PrintLaff( void ) const;
void PrintLaff( const char* pszFileName ) const;
bool Init( const TGS_Region_c& region );
bool Init( const TTPT_TilePlane_c< T >& tilePlane );
void Reset( void );
const TGS_Region_c& GetRegion( void ) const;
double GetMinGrid( void ) const;
bool Add( const TTPT_Tile_c< T >& tile,
TTP_AddMode_t addMode = TTP_ADD_OVERLAP );
bool Add( const TTPT_TilePlane_c< T >& tilePlane,
TTP_AddMode_t addMode = TTP_ADD_OVERLAP );
bool Add( const TTPT_Tile_c< T >& tile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode = TTP_ADD_OVERLAP );
bool Add( const TGS_Region_c& region,
TTP_AddMode_t addMode = TTP_ADD_OVERLAP );
bool Add( const TGS_Region_c& region,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode = TTP_ADD_OVERLAP );
bool Add( const TGS_Region_c& region,
const T& data,
TTP_AddMode_t addMode = TTP_ADD_OVERLAP );
bool Add( const TGS_Region_c& region,
const T& data,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode = TTP_ADD_OVERLAP );
bool Delete( TTPT_Tile_c< T >* ptile );
bool Delete( const TGS_Region_c& region,
TTP_DeleteMode_t deleteMode = TTP_DELETE_INTERSECT );
bool Delete( const TGS_Region_c& region,
const T& data,
TTP_DeleteMode_t deleteMode = TTP_DELETE_INTERSECT );
bool Clear( void );
TTPT_Tile_c< T >* Find( double x, double y,
TTPT_Tile_c< T >* ptile = 0 ) const;
TTPT_Tile_c< T >* Find( const TGS_Point_c& point,
TTPT_Tile_c< T >* ptile = 0 ) const;
TTPT_Tile_c< T >* Find( const TGS_Region_c& region,
TTP_FindMode_t findMode = TTP_FIND_EXACT,
TTP_TileMode_t tileMode = TTP_TILE_ANY ) const;
TTPT_Tile_c< T >* FindNearest( const TGS_Region_c& refRegion,
const TGS_OrientMode_t* porientMode = 0 ) const;
TTPT_Tile_c< T >* FindNearest( const TGS_Region_c& refRegion,
double searchDistance,
const TGS_OrientMode_t* porientMode = 0 ) const;
TTPT_Tile_c< T >* FindNearest( const TGS_Region_c& refRegion,
TC_SideMode_t searchSide ) const;
bool FindConnected( const TGS_Region_c& region,
TTPT_TilePlane_c< T >* ptilePlane ) const;
bool FindAdjacents( const TGS_Region_c& region,
TTPT_TilePlane_c< T >* ptilePlane ) const;
bool FindAdjacents( const TGS_Region_c& searchRegion,
const TGS_Region_c& region,
TTPT_TilePlane_c< T >* ptilePlane ) const;
bool FindData( double x, double y,
TCT_OrderedVector_c< T >* pdataList ) const;
bool FindData( const TGS_Point_c& point,
TCT_OrderedVector_c< T >* pdataList ) const;
bool FindData( const TGS_Region_c& region,
TCT_OrderedVector_c< T >* pdataList ) const;
size_t FindCount( TTP_TileMode_t tileMode ) const;
size_t FindCount( const TGS_Region_c& region,
TTP_TileMode_t tileMode ) const;
void FindRegion( TTP_TileMode_t tileMode,
TGS_Region_c* pregion ) const;
bool Split( TTPT_Tile_c< T >* ptile,
const TGS_Line_c& line,
TGS_DirMode_t dir = TGS_DIR_UNDEFINED );
bool Split( TTPT_Tile_c< T >* ptile,
TC_SideMode_t side = TC_SIDE_UNDEFINED );
bool Merge( TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB );
bool Merge( TTPT_Tile_c< T >* ptile,
TC_SideMode_t side = TC_SIDE_UNDEFINED );
bool MergeAdjacents( const TGS_Point_c& point,
TGS_Region_c* pregion,
TGS_OrientMode_t orientMode = TGS_ORIENT_UNDEFINED,
TTP_MergeMode_t mergeMode = TTP_MERGE_EXACT,
TTP_TileMode_t tileMode = TTP_TILE_SOLID ) const;
bool MergeAdjacents( const TGS_Region_c& region,
TGS_Region_c* pregion,
TGS_OrientMode_t orientMode = TGS_ORIENT_UNDEFINED,
TTP_MergeMode_t mergeMode = TTP_MERGE_EXACT,
TTP_TileMode_t tileMode = TTP_TILE_SOLID ) const;
bool MergeAdjacents( const TTPT_Tile_c< T >& tile,
TGS_Region_c* pregion,
TGS_OrientMode_t orientMode = TGS_ORIENT_UNDEFINED,
TTP_MergeMode_t mergeMode = TTP_MERGE_EXACT ) const;
bool JoinAdjacents( const TGS_Point_c& point,
TGS_RegionList_t* pregionList ) const;
bool JoinAdjacents( const TGS_Region_c& region,
TGS_RegionList_t* pregionList,
TTP_JoinMode_t joinMode = TTP_JOIN_EXACT ) const;
bool JoinAdjacents( const TTPT_Tile_c< T >& tile,
TGS_RegionList_t* pregionList ) const;
bool HasAdjacents( const TGS_Region_c& region ) const;
bool HasNeighbor( const TGS_Region_c& region,
double minDistance ) const;
bool HasNeighbor( const TTPT_Tile_c< T >& tile,
double minDistance ) const;
bool IsClear( void ) const;
bool IsClear( double x, double y ) const;
bool IsClear( const TGS_Point_c& point ) const;
bool IsClear( const TGS_Region_c& region ) const;
bool IsClear( TTP_IsClearMode_t isClearMode,
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile = 0 ) const;
bool IsSolid( double x, double y ) const;
bool IsSolid( const TGS_Point_c& point ) const;
bool IsSolid( const TGS_Point_c& point,
const T& data ) const;
bool IsSolid( const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const;
bool IsSolid( const TGS_Region_c& region ) const;
bool IsSolid( const TGS_Region_c& region,
const T& data ) const;
bool IsSolid( const TGS_Region_c& region,
unsigned int count,
const T* pdata ) const;
bool IsSolid( TTP_IsSolidMode_t isSolidMode,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolid( TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolid( TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
const T& data,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolid( TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidNot( const TGS_Point_c& point,
const T& data ) const;
bool IsSolidNot( const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const;
bool IsSolidNot( const TGS_Region_c& region,
const T& data ) const;
bool IsSolidNot( const TGS_Region_c& region,
unsigned int count,
const T* pdata ) const;
bool IsSolidNot( TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
const T& data,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidNot( TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsIntersecting( const TGS_Region_c& region,
TGS_Region_c* pintersectRegion = 0,
TTP_TileMode_t tileMode = TTP_TILE_ANY ) const;
bool IsAdjacent( const TGS_Region_c& regionA,
const TGS_Region_c& regionB,
TC_SideMode_t* pside = 0 ) const;
bool IsAdjacent( const TTPT_Tile_c< T >& tileA,
const TTPT_Tile_c< T >& tileB,
TC_SideMode_t* pside = 0 ) const;
bool IsMergable( const TTPT_Tile_c< T >& tileA,
const TTPT_Tile_c< T >& tileB,
TGS_OrientMode_t* porientMode = 0 ) const;
bool IsSplitable( const TTPT_Tile_c< T >& tile,
const TGS_Line_c& intersectLine,
TGS_DirMode_t dirMode,
TGS_OrientMode_t* porientMode = 0 ) const;
bool IsWithin( const TGS_Point_c& point ) const;
bool IsWithin( const TGS_Region_c& region ) const;
bool IsWithin( const TTPT_Tile_c< T >& tile ) const;
bool IsLegal( void ) const;
bool IsValid( void ) const;
private:
bool AddPerRegion_( const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient );
bool AddPerNew_( const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient );
bool AddPerMerge_( const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode );
bool AddPerMergeNew_( const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode );
bool AddPerOverlap_( const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode );
bool AddPerOverlap_( const TTPT_Tile_c< T >& addTile,
const TTPT_Tile_c< T >* poverlapTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode );
bool AddPerUpperSideSplit_( const TGS_Region_c& addRegion );
bool AddPerLowerSideSplit_( const TGS_Region_c& addRegion );
bool AddPerCenterSideSplits_( const TGS_Region_c& addRegion );
bool AddPerSolidTileMerges_( const TGS_Region_c& addRegion );
bool AddPerSolidTileCorners_( const TGS_Region_c& addRegion,
TGS_OrientMode_t addOrient );
bool AddPerSolidTileCorner_( const TGS_Region_c& addRegion,
const TGS_Point_c& cornerPoint,
TGS_OrientMode_t addOrient );
bool DeletePerExact_( const TGS_Region_c& deleteRegion );
bool DeletePerExact_( const TGS_Region_c& deleteRegion,
const T& deleteData );
bool DeletePerWithin_( const TGS_Region_c& deleteRegion );
bool DeletePerWithin_( const TGS_Region_c& deleteRegion,
const T& deleteData );
bool DeletePerIntersect_( const TGS_Region_c& deleteRegion );
bool DeletePerIntersect_( const TGS_Region_c& deleteRegion,
const T& deleteData );
bool DeletePerIntersectMin_( const TGS_Region_c& deleteRegion );
bool DeletePerIntersectMin_( const TGS_Region_c& deleteRegion,
const T& deleteData );
bool DeletePerRightSide_( const TTPT_Tile_c< T >& deleteTile );
bool DeletePerLeftSide_( const TTPT_Tile_c< T >& deleteTile );
bool DeletePerLowerSide_( const TTPT_Tile_c< T >& deleteTile );
bool DeletePerUpperSide_( const TTPT_Tile_c< T >& deleteTile );
TTPT_Tile_c< T >* FindPerPoint_( const TGS_Point_c& point,
TTPT_Tile_c< T >* ptile = 0 ) const;
TTPT_Tile_c< T >* FindPerExact_( const TGS_Region_c& region,
TTP_TileMode_t tileMode = TTP_TILE_ANY ) const;
TTPT_Tile_c< T >* FindPerWithin_( const TGS_Region_c& region,
TTP_TileMode_t tileMode = TTP_TILE_ANY ) const;
TTPT_Tile_c< T >* FindPerIntersect_( const TGS_Region_c& region,
TTP_TileMode_t tileMode = TTP_TILE_ANY ) const;
TTPT_Tile_c< T >* FindNearestBySides_( const TGS_Region_c& refRegion,
const TTPT_Tile_c< T >& searchTile,
const TGS_OrientMode_t* porientMode = 0 ) const;
TTPT_Tile_c< T >* FindNearestBySide_( const TGS_Region_c& refRegion,
const TTPT_Tile_c< T >& searchTile,
TC_SideMode_t searchSide ) const;
TTPT_Tile_c< T >* FindNearestBySide_( const TGS_Region_c& refRegion,
TC_SideMode_t searchSide,
double searchDistance = TC_FLT_MAX ) const;
TTPT_Tile_c< T >* FindNearestByRegion_( const TGS_Region_c& refRegion,
const TGS_Region_c& searchRegion,
const TGS_OrientMode_t* porientMode = 0 ) const;
TTPT_Tile_c< T >* FindNearestByRegion_( const TGS_Region_c& refRegion,
double searchDistance,
const TGS_OrientMode_t* porientMode = 0 ) const;
void FindCountRefresh_( void ) const;
void FindCountRefresh_( const TGS_Region_c& region ) const;
void SplitRegionCoords_( TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
const TGS_Line_c& line,
TGS_DirMode_t dirMode,
TGS_OrientMode_t orientMode );
void MergeRegionCoords_( TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
TGS_OrientMode_t orientMode,
TGS_CornerMode_t cornerMode );
bool MergeAdjacentsByExtent_( TGS_OrientMode_t orientMode,
unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const;
bool MergeAdjacentsToLeft_( unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const;
bool MergeAdjacentsToRight_( unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const;
bool MergeAdjacentsToLower_( unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const;
bool MergeAdjacentsToUpper_( unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const;
bool JoinAdjacentsPerExact_( const TGS_Region_c& region,
TGS_RegionList_t* pregionList ) const;
bool JoinAdjacentsPerIntersect_( const TGS_Region_c& region,
TGS_RegionList_t* pregionList ) const;
bool JoinAdjacentsBySide_( TC_SideMode_t side,
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTP_TileMode_t tileMode,
TGS_RegionList_t* pregionList ) const;
bool CornerRegionCoords_( const TGS_Region_c& regionA,
const TGS_Region_c& regionB,
TGS_Region_c* pregionA,
TGS_Region_c* pregionB,
TGS_OrientMode_t addOrient );
bool CornerTileRemerge_( TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
const TGS_Region_c& regionA,
const TGS_Region_c& regionB,
TGS_OrientMode_t addOrient );
void StitchToSplit_( TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
TGS_OrientMode_t orientMode );
void StitchToMerge_( TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
TGS_OrientMode_t orientMode,
TGS_CornerMode_t cornerMode );
void StitchFromSide_( TTPT_Tile_c< T >* ptile,
TC_SideMode_t side,
TTPT_Tile_c< T >* ptileP = 0 );
void LoadTileList_( TTPT_Tile_c< T >* ptile,
TCT_OrderedVector_c< TTPT_Tile_c< T >* >* ptileList );
void EstAspectRatio_( const TGS_Region_c& newRegion,
const TGS_Region_c& curRegion,
double* pminAspectRatio,
double* pmaxAspectRatio ) const;
bool HasAspectRatio_( const TGS_Region_c& newRegion,
const TGS_Region_c& curRegion ) const;
bool IsClearMatch_( const TGS_Point_c& point ) const;
bool IsClearMatch_( const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile ) const;
bool IsClearAny_( const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile ) const;
bool IsClearAll_( const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile ) const;
bool IsSolidMatch_( const TGS_Point_c& point ) const;
bool IsSolidMatch_( const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const;
bool IsSolidMatch_( const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidMatch_( const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidAny_( const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidAny_( const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidAll_( const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidAll_( const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidMax_( const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidMax_( const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile = 0 ) const;
bool IsSolidNotMatch_( const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const;
bool IsSolidNotMatch_( const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidNotTile ) const;
bool IsSolidNotAny_( const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidNotTile ) const;
bool IsSolidNotAny_( const TGS_Region_c& region ) const;
bool IsSolidNotAll_( const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidNotTile ) const;
TTPT_Tile_c< T >* Allocate_( const TTPT_Tile_c< T >& tile );
void Deallocate_( TTPT_Tile_c< T >* ptile );
bool ShowInternalMessage_( TTP_MessageType_t messageType,
const char* pszSourceMethod,
const TGS_Region_c* ptileRegion = 0,
const TGS_Region_c* pnextRegion = 0 ) const;
private:
TGS_Region_c region_; // Define tile plane bounding region
TTPT_Tile_c< T >* ptileLL_; // Ptr to lower-left most tile in plane
TTPT_Tile_c< T >* ptileMRC_;// Ptr to most-recently referenced clear tile
// (most-recent reference is cached for performance)
TTPT_Tile_c< T >* ptileMRS_;// Ptr to most-recently referenced solid tile
// (most-recent reference is cached for performance)
TTPT_TilePlaneIter_c< T > tilePlaneIter_;
// Local cached tile plane iterator
// (improves performance by avoiding mallocs)
double minGrid_; // Define min grid value for tile region coords
class TTP_TilePlaneCount_c
{
public:
size_t clear; // Define total number of clear tiles in plane
size_t solid; // Define total number of solid tiles in plane
bool isValid; // TRUE => clear & solid tile counts are valid
} count_;
};
//===========================================================================//
// Purpose : Class inline definition(s)
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > inline const TGS_Region_c& TTPT_TilePlane_c< T >::GetRegion(
void ) const
{
return( this->region_ );
}
//===========================================================================//
template< class T > inline double TTPT_TilePlane_c< T >::GetMinGrid(
void ) const
{
return( this->minGrid_ );
}
//===========================================================================//
template< class T > inline bool TTPT_TilePlane_c< T >::IsWithin(
const TGS_Point_c& point ) const
{
return( this->region_.IsWithin( point ));
}
//===========================================================================//
template< class T > inline bool TTPT_TilePlane_c< T >::IsWithin(
const TGS_Region_c& region ) const
{
return( this->region_.IsWithin( region ));
}
//===========================================================================//
template< class T > inline bool TTPT_TilePlane_c< T >::IsWithin(
const TTPT_Tile_c< T >& tile ) const
{
return( this->region_.IsWithin( tile.GetRegion( )));
}
//===========================================================================//
template< class T > inline bool TTPT_TilePlane_c< T >::IsValid(
void ) const
{
return(( this->region_.IsValid( )) &&
( this->ptileLL_ && this->ptileMRC_ && this->ptileMRS_ ) ?
true : false );
}
//===========================================================================//
// Method : TTPT_TilePlane_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_TilePlane_c< T >::TTPT_TilePlane_c(
void )
:
ptileLL_( 0 ),
ptileMRC_( 0 ),
ptileMRS_( 0 )
{
this->minGrid_ = TC_MinGrid_c::GetInstance( ).GetGrid( );
this->count_.clear = 0;
this->count_.solid = 0;
this->count_.isValid = false;
TGS_Region_c region( static_cast< double >( INT_MIN ),
static_cast< double >( INT_MIN ),
static_cast< double >( INT_MAX ),
static_cast< double >( INT_MAX ));
this->Init( region );
}
//===========================================================================//
template< class T > TTPT_TilePlane_c< T >::TTPT_TilePlane_c(
const TGS_Region_c& region )
:
ptileLL_( 0 ),
ptileMRC_( 0 ),
ptileMRS_( 0 )
{
this->minGrid_ = TC_MinGrid_c::GetInstance( ).GetGrid( );
this->count_.clear = 0;
this->count_.solid = 0;
this->count_.isValid = false;
this->Init( region );
}
//===========================================================================//
template< class T > TTPT_TilePlane_c< T >::TTPT_TilePlane_c(
const TTPT_TilePlane_c< T >& tilePlane )
:
ptileLL_( 0 ),
ptileMRC_( 0 ),
ptileMRS_( 0 )
{
this->minGrid_ = TC_MinGrid_c::GetInstance( ).GetGrid( );
this->count_.clear = 0;
this->count_.solid = 0;
this->count_.isValid = false;
this->Init( tilePlane );
}
//===========================================================================//
// Method : ~TTPT_TilePlane_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_TilePlane_c< T >::~TTPT_TilePlane_c(
void )
{
this->Reset( );
}
//===========================================================================//
// Method : operator=
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_TilePlane_c< T >& TTPT_TilePlane_c< T >::operator=(
const TTPT_TilePlane_c< T >& tilePlane )
{
if( &tilePlane != this )
{
this->Init( tilePlane );
}
return( *this );
}
//===========================================================================//
// Method : operator==
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::operator==(
const TTPT_TilePlane_c< T >& tilePlane ) const
{
bool isEqual = false;
if( this->region_ == tilePlane.region_ )
{
isEqual = true;
if( isEqual )
{
// Test to see if every tile in this plane matches given tile plane
TTPT_TilePlaneIter_c< T > thisIter( *this );
TTPT_Tile_c< T >* ptile = 0;
while( thisIter.Next( &ptile, TTP_TILE_SOLID ))
{
const TGS_Region_c& region = ptile->GetRegion( );
const TTPT_Tile_c< T >* pfoundTile = tilePlane.Find( region.x1,
region.y1 );
isEqual = ( pfoundTile && *pfoundTile == *ptile ? true : false );
if( !isEqual )
break;
}
}
if( isEqual )
{
// Test to see if every tile in given tile plane matches this plane
TTPT_TilePlaneIter_c< T > tilePlaneIter( tilePlane );
TTPT_Tile_c< T >* ptile = 0;
while( tilePlaneIter.Next( &ptile, TTP_TILE_SOLID ))
{
const TGS_Region_c& region = ptile->GetRegion( );
const TTPT_Tile_c< T >* pfoundTile = this->Find( region.x1,
region.y1 );
isEqual = ( pfoundTile && *pfoundTile == *ptile ? true : false );
if( !isEqual )
break;
}
}
}
return( isEqual );
}
//===========================================================================//
// Method : operator!=
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::operator!=(
const TTPT_TilePlane_c< T >& tilePlane ) const
{
return( !this->operator==( tilePlane ) ? true : false );
}
//===========================================================================//
// Method : Print
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::Print(
FILE* pfile,
size_t spaceLen ) const
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
if( this->region_.IsValid( ) &&
TCTF_IsGT( this->region_.x1, static_cast< double >( INT_MIN )) &&
TCTF_IsGT( this->region_.y1, static_cast< double >( INT_MIN )) &&
TCTF_IsLT( this->region_.x2, static_cast< double >( INT_MAX )) &&
TCTF_IsLT( this->region_.y2, static_cast< double >( INT_MAX )))
{
string srRegion;
this->region_.ExtractString( &srRegion );
printHandler.Write( pfile, spaceLen, "[%s]\n", TIO_SR_STR( srRegion ));
spaceLen += 3;
}
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this );
TTPT_Tile_c< T >* ptile = 0;
while( ptilePlane->tilePlaneIter_.Next( &ptile, TTP_TILE_SOLID ))
{
ptile->Print( pfile, spaceLen );
}
}
//===========================================================================//
// Method : PrintLaff
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::PrintLaff(
void ) const
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
TIO_SkinHandler_c& skinHandler = TIO_SkinHandler_c::GetInstance( );
unsigned int laffColorRed = 1;
// unsigned int laffColorGreen = 2;
// unsigned int laffColorBlue = 3;
// unsigned int laffColorCyan = 4;
unsigned int laffColorYellow = 5;
// unsigned int laffColorPink = 6;
unsigned int laffColorWhite = 7;
unsigned int laffLayerBoundary = 1;
unsigned int laffLayerTileClear = 2;
unsigned int laffLayerTileSolid = 3;
TC_MinGrid_c& MinGrid = TC_MinGrid_c::GetInstance( );
double minGrid = MinGrid.GetGrid( );
unsigned int precision = MinGrid.GetPrecision( );
unsigned int magnitude = MinGrid.GetMagnitude( );
unsigned int units = MinGrid.GetUnits( );
printHandler.Write( "(OBJECT 'BARINFO' (\n" );
printHandler.Write( " (ATTR 'UNITS' (\n" );
printHandler.Write( " (TEXT '%0.*f MICRONS')))\n", precision, 1.0 / static_cast< double >( magnitude ));
printHandler.Write( " (ATTR 'MINGRID' (\n" );
printHandler.Write( " (TEXT '%0.*f %0.*f')))\n", precision, minGrid, precision, minGrid );
printHandler.Write( " (ATTR 'LAYERS' (\n" );
printHandler.Write( " (TEXT '%u 1 0 %u %u BOUNDARY')\n", laffColorYellow, laffLayerBoundary, laffLayerBoundary );
printHandler.Write( " (TEXT '%u 1 7 %u %u TILE_CLEAR')\n", laffColorWhite, laffLayerTileClear, laffLayerTileClear );
printHandler.Write( " (TEXT '%u 1 8 %u %u TILE_SOLID')\n", laffColorRed, laffLayerTileSolid, laffLayerTileSolid );
printHandler.Write( " ))\n" );
printHandler.Write( "))\n" );
printHandler.Write( "(OBJECT '%s' (\n", skinHandler.GetSourceName( ));
printHandler.Write( " (DETAIL (\n" );
printHandler.Write( " ; Tile Plane Boundary\n" );
if( this->region_.IsValid( ))
{
const TGS_Region_c& region = this->region_;
unsigned int layer = laffLayerBoundary;
long int x1 = MinGrid.FloatToLongInt( region.x1 ) * magnitude / units;
long int y1 = MinGrid.FloatToLongInt( region.y1 ) * magnitude / units;
long int x2 = MinGrid.FloatToLongInt( region.x2 ) * magnitude / units;
long int y2 = MinGrid.FloatToLongInt( region.y2 ) * magnitude / units;
printHandler.Write( " (RECT %u %ld %ld %ld %ld)\n", layer, x1, y1, x2, y2 );
}
printHandler.Write( " ; Tile Plane\n" );
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this );
TTPT_Tile_c< T >* ptile = 0;
while( ptilePlane->tilePlaneIter_.Next( &ptile ))
{
const TGS_Region_c& region = ptile->GetRegion( );
unsigned int layer = ( ptile->IsClear( ) ? laffLayerTileClear : laffLayerTileSolid );
long int x1 = MinGrid.FloatToLongInt( region.x1 ) * magnitude / units;
long int y1 = MinGrid.FloatToLongInt( region.y1 ) * magnitude / units;
long int x2 = MinGrid.FloatToLongInt( region.x2 ) * magnitude / units;
long int y2 = MinGrid.FloatToLongInt( region.y2 ) * magnitude / units;
if( ptile->IsClear( ))
{
printHandler.Write( " (RECT %u %ld %ld %ld %ld)\n", layer, x1, y1, x2, y2 );
}
else if( ptile->IsSolid( ) && !ptile->GetCount( ))
{
printHandler.Write( " (RECT %u %ld %ld %ld %ld)\n", layer, x1, y1, x2, y2 );
}
else if( ptile->IsSolid( ) && ptile->GetCount( ))
{
unsigned int height = ( units >= 100 ? 16 : 4 );
for( unsigned int i = 0; i < ptile->GetCount( ); ++i )
{
const T& data = *ptile->FindData( i );
string srData;
data.ExtractString( &srData );
printHandler.Write( " (RECT %u %ld %ld %ld %ld (\n", layer, x1, y1, x2, y2 );
printHandler.Write( " (SNAM %u %u 1 %ld %ld '%s')))\n", layer, height, x1, y1 + i * units, TIO_SR_STR( srData ));
}
}
}
printHandler.Write( " ))\n" );
printHandler.Write( " (BOUNDARY)\n" );
printHandler.Write( " (STRUCT)\n" );
printHandler.Write( " (PORTS)\n" );
printHandler.Write( " (NAMES)\n" );
printHandler.Write( " (SYMBOLIC)\n" );
printHandler.Write( " (DIAGNOSTIC)\n" );
printHandler.Write( "))\n" );
}
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::PrintLaff(
const char* pszFileName ) const
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
string srLogFileName = printHandler.GetLogFileName( );
printHandler.DisableStdioOutput( );
printHandler.SetLogFileOutput( pszFileName );
this->PrintLaff( );
printHandler.SetLogFileOutput( );
printHandler.EnableStdioOutput( );
const char* pszLogFileName = srLogFileName.data( );
if( pszLogFileName && *pszLogFileName )
{
printHandler.SetLogFileOutput( pszLogFileName,
TIO_FILE_OPEN_APPEND );
}
}
//===========================================================================//
// Method : Init
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Init(
const TGS_Region_c& region )
{
TGS_Region_c thisRegion = region;
this->Reset( );
this->region_ = thisRegion;
TTPT_Tile_c< T > tile( TTP_TILE_CLEAR, region );
TTPT_Tile_c< T >* ptile = this->Allocate_( tile );
this->ptileLL_ = this->ptileMRC_ = this->ptileMRS_ = ptile;
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Init(
const TTPT_TilePlane_c< T >& tilePlane )
{
bool ok = true;
if( tilePlane.IsValid( ))
{
ok = this->Init( tilePlane.GetRegion( ));
TTPT_TilePlaneIter_c< T > tilePlaneIter( tilePlane );
TTPT_Tile_c< T >* ptile = 0;
while( ok && tilePlaneIter.Next( &ptile, TTP_TILE_SOLID ))
{
ok = this->Add( *ptile );
}
}
return( ok );
}
//===========================================================================//
// Method : Reset
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::Reset(
void )
{
if( this->ptileLL_ )
{
size_t tilePlaneCount = this->IsClear( ) ? 1 :
this->FindCount( TTP_TILE_CLEAR ) +
this->FindCount( TTP_TILE_SOLID );
if( tilePlaneCount == 1 )
{
// Handle simplest case of single tile (for fastest delete code)
delete this->ptileLL_;
}
else if( tilePlaneCount <= 16 )
{
// Handle next case of small tile count (for fast delete code)
TCT_OrderedVector_c< TTPT_Tile_c< T >* > tileList( tilePlaneCount );
// Use recursion to enable "fast" deletion on "small" tile planes
this->LoadTileList_( this->ptileLL_, &tileList );
for( size_t i = 0; i < tileList.GetLength( ); ++i )
{
TTPT_Tile_c< T >* ptile_ = *tileList[i];
delete ptile_;
}
}
else
{
// Handle worst case where we iterate to delete allocated memory
this->tilePlaneIter_.Init( *this, this->region_ );
TTPT_Tile_c< T >* ptile = 0;
while( this->tilePlaneIter_.Next( &ptile ))
{
// Update "most recent" that reference this tile prior to deleting tile
if( this->ptileMRC_ == ptile )
{
this->ptileMRC_ = 0;
}
if( this->ptileMRS_ == ptile )
{
this->ptileMRS_ = 0;
}
// Update any tiles that reference this tile prior to deleting tile
TTPT_Tile_c< T >* ptileLeftLower = ptile->GetStitchLeftLower( );
while( ptileLeftLower && ( ptileLeftLower->GetStitchRightUpper( ) == ptile ))
{
ptileLeftLower->SetStitchRightUpper( 0 );
ptileLeftLower = ptileLeftLower->GetStitchUpperRight( );
}
// Update any tiles that reference this tile prior to deleting tile
TTPT_Tile_c< T >* ptileUpperRight = ptile->GetStitchUpperRight( );
while( ptileUpperRight && ( ptileUpperRight->GetStitchLowerLeft( ) == ptile ))
{
ptileUpperRight->SetStitchLowerLeft( 0 );
ptileUpperRight = ptileUpperRight->GetStitchLeftLower( );
}
delete ptile;
}
}
}
this->region_.Reset( );
this->ptileLL_ = this->ptileMRC_ = this->ptileMRS_ = 0;
this->count_.clear = 0;
this->count_.solid = 0;
this->count_.isValid = false;
}
//===========================================================================//
// Method : Add
// Purpose : Adds or inserts a solid tile into the current tile plane.
// This method handles adding a new solid tile if and only
// if there are no solid tiles in the desired area. This
// method also handles adding a merged solid tile when the
// new solid tile intersects with existing solid tiles.
// This method also handles adding an overlapping solid
// tile when the new solid tile overlaps with existing
// solid tiles
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Add(
const TTPT_Tile_c< T >& tile,
TTP_AddMode_t addMode )
{
return( this->Add( tile, TGS_ORIENT_VERTICAL, addMode ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Add(
const TTPT_TilePlane_c< T >& tilePlane,
TTP_AddMode_t addMode )
{
bool ok = true;
if( tilePlane.IsValid( ))
{
TTPT_TilePlaneIter_c< T > tilePlaneIter( tilePlane );
TTPT_Tile_c< T >* ptile = 0;
while( ok && tilePlaneIter.Next( &ptile, TTP_TILE_SOLID ))
{
ok = this->Add( *ptile, addMode );
}
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Add(
const TTPT_Tile_c< T >& tile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode )
{
bool ok = true;
const TGS_Region_c& tileRegion = tile.GetRegion( );
if( tileRegion.IsLegal( ))
{
switch( addMode )
{
case TTP_ADD_REGION:
ok = this->AddPerRegion_( tile, addOrient );
break;
case TTP_ADD_NEW:
ok = this->AddPerNew_( tile, addOrient );
break;
case TTP_ADD_MERGE:
ok = this->AddPerMerge_( tile, addOrient, addMode );
break;
case TTP_ADD_OVERLAP:
case TTP_ADD_DIFFERENCE:
ok = this->AddPerOverlap_( tile, addOrient, addMode );
break;
default:
break;
}
this->count_.isValid = false;
}
else
{
ok = this->ShowInternalMessage_( TTP_MESSAGE_TILE_REGION_ILLEGAL,
"TTPT_TilePlane_c::Add", &tileRegion );
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Add(
const TGS_Region_c& region,
TTP_AddMode_t addMode )
{
TTPT_Tile_c< T > tile( TTP_TILE_SOLID, region );
return( this->Add( tile, addMode ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Add(
const TGS_Region_c& region,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode )
{
TTPT_Tile_c< T > tile( TTP_TILE_SOLID, region );
return( this->Add( tile, addOrient, addMode ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Add(
const TGS_Region_c& region,
const T& data,
TTP_AddMode_t addMode )
{
TTPT_Tile_c< T > tile( TTP_TILE_SOLID, region, data );
return( this->Add( tile, addMode ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Add(
const TGS_Region_c& region,
const T& data,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode )
{
TTPT_Tile_c< T > tile( TTP_TILE_SOLID, region, data );
return( this->Add( tile, addOrient, addMode ));
}
//===========================================================================//
// Method : Delete
// Purpose : Deletes a solid tile from the current tile plane. The
// solid "dead" tile is replaced by a clear tile. The clear
// "dead" tile is subsequently split and/or merged with
// neighboring clear tiles, as possible.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Delete(
TTPT_Tile_c< T >* ptile )
{
bool ok = true;
// Change the given solid tile into a clear "dead" tile
ptile->MakeClear( );
// Make copy of clear "dead" tile for iteration over right/left sides
TTPT_Tile_c< T > deadTile( *ptile );
if( ok )
{
ok = this->DeletePerRightSide_( deadTile );
}
if( ok )
{
ok = this->DeletePerLeftSide_( deadTile );
}
if( ok )
{
ok = this->DeletePerLeftSide_( deadTile );
}
if( ok )
{
ok = this->DeletePerLowerSide_( deadTile );
}
if( ok )
{
ok = this->DeletePerUpperSide_( deadTile );
}
this->count_.isValid = false;
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Delete(
const TGS_Region_c& region,
TTP_DeleteMode_t deleteMode )
{
bool ok = true;
if( region.IsLegal( ))
{
switch( deleteMode )
{
case TTP_DELETE_EXACT:
ok = this->DeletePerExact_( region );
break;
case TTP_DELETE_WITHIN:
ok = this->DeletePerWithin_( region );
break;
case TTP_DELETE_INTERSECT:
ok = this->DeletePerIntersect_( region );
break;
case TTP_DELETE_INTERSECT_MIN:
ok = this->DeletePerIntersectMin_( region );
break;
default:
break;
}
}
else
{
ok = this->ShowInternalMessage_( TTP_MESSAGE_TILE_REGION_ILLEGAL,
"TTPT_TilePlane_c::Delete", &region );
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Delete(
const TGS_Region_c& region,
const T& data,
TTP_DeleteMode_t deleteMode )
{
bool ok = true;
if( region.IsLegal( ))
{
switch( deleteMode )
{
case TTP_DELETE_EXACT:
ok = this->DeletePerExact_( region, data );
break;
case TTP_DELETE_WITHIN:
ok = this->DeletePerWithin_( region, data );
break;
case TTP_DELETE_INTERSECT:
ok = this->DeletePerIntersect_( region, data );
break;
case TTP_DELETE_INTERSECT_MIN:
ok = this->DeletePerIntersectMin_( region, data );
break;
default:
break;
}
}
else
{
ok = this->ShowInternalMessage_( TTP_MESSAGE_TILE_REGION_ILLEGAL,
"TTPT_TilePlane_c::Delete", &region );
}
return( ok );
}
//===========================================================================//
// Method : Clear
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Clear(
void )
{
return( this->Init( this->region_ ));
}
//===========================================================================//
// Method : Find
// Purpose : Find and return a pointer to a tile based on the given
// point (x,y) location. The returned tile pointer may
// identify be either a "clear" or a "solid" tile. A null
// pointer is returned if the given point is not valid (ie.
// is not within the current tile plane's area).
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::Find(
double x,
double y,
TTPT_Tile_c< T >* ptile ) const
{
TGS_Point_c point( x, y );
return( this->Find( point, ptile ));
}
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::Find(
const TGS_Point_c& point,
TTPT_Tile_c< T >* ptile ) const
{
// Search until tile found that contains the given point
ptile = this->FindPerPoint_( point, ptile );
return( ptile );
}
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::Find(
const TGS_Region_c& region,
TTP_FindMode_t findMode,
TTP_TileMode_t tileMode ) const
{
TTPT_Tile_c< T >* ptile = 0;
switch( findMode )
{
case TTP_FIND_EXACT:
ptile = this->FindPerExact_( region, tileMode );
break;
case TTP_FIND_WITHIN:
ptile = this->FindPerWithin_( region, tileMode );
break;
case TTP_FIND_INTERSECT:
ptile = this->FindPerIntersect_( region, tileMode );
break;
default:
break;
}
return( ptile );
}
//===========================================================================//
// Method : FindNearest
// Purpose : Find and return a pointer to the nearest "solid" tile
// found, if any, based on the given reference region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearest(
const TGS_Region_c& refRegion,
const TGS_OrientMode_t* porientMode ) const
{
// Start by finding tile based on given initial search reference region
TTPT_Tile_c< T >* ptile = this->Find( refRegion, TTP_FIND_INTERSECT );
if( ptile && ptile->IsSolid( ))
{
// Nothing to do here, found "solid" tile based on given search region
;
}
else if( ptile && ptile->IsClear( ))
{
// Need to iterate sides to determine nearest potential "solid" tile
TTPT_Tile_c< T >* psolidTile = this->FindNearestBySides_( refRegion,
*ptile,
porientMode );
if( psolidTile )
{
// Need to iterate region based on nearest potential "solid" tile
double searchDistance = psolidTile->FindDistance( refRegion );
searchDistance += this->minGrid_;
ptile = this->FindNearestByRegion_( refRegion,
searchDistance,
porientMode );
}
else
{
// Need to reset tile pointer after search for "solid" tile, if any
ptile = 0;
}
}
return( ptile );
}
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearest(
const TGS_Region_c& refRegion,
double searchDistance,
const TGS_OrientMode_t* porientMode ) const
{
// Start by finding tile based on given initial search reference region
TTPT_Tile_c< T >* ptile = this->Find( refRegion, TTP_FIND_INTERSECT );
if( ptile && ptile->IsSolid( ))
{
// Nothing to do here, found "solid" tile based on given search region
;
}
else if( ptile && ptile->IsClear( ))
{
ptile = this->FindNearestByRegion_( refRegion,
searchDistance,
porientMode );
}
return( ptile );
}
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearest(
const TGS_Region_c& refRegion,
TC_SideMode_t searchSide ) const
{
// Start by finding tile based on given initial search reference region
TGS_Region_c sideRegion;
refRegion.FindRegion( searchSide, &sideRegion );
TTPT_Tile_c< T >* ptile = this->Find( sideRegion, TTP_FIND_INTERSECT );
if( ptile && ptile->IsSolid( ))
{
// Nothing to do here, found "solid" tile based on given search region
;
}
else if( ptile && ptile->IsClear( ))
{
// Need to iterate sides to determine nearest potential "solid" tile
ptile = this->FindNearestBySide_( sideRegion, *ptile, searchSide );
}
return( ptile );
}
//===========================================================================//
// Method : FindConnected
// Purpose : Find and return all connected (ie. merge/join adjacents)
// regions based on the given region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::FindConnected(
const TGS_Region_c& region,
TTPT_TilePlane_c< T >* ptilePlane ) const
{
bool foundConnected = false;
if( ptilePlane )
{
ptilePlane->Init( this->region_ );
ptilePlane->Add( region );
TGS_Region_c findRegion( region );
TGS_Region_c mergedRegion;
if( this->MergeAdjacents( findRegion, &mergedRegion, TTP_MERGE_REGION ))
{
ptilePlane->Add( mergedRegion, TTP_ADD_MERGE );
findRegion = mergedRegion;
foundConnected = true;
}
TGS_RegionList_t joinedRegionList;
if( this->JoinAdjacents( findRegion, &joinedRegionList, TTP_JOIN_INTERSECT ))
{
for( size_t i = 0; i < joinedRegionList.GetLength( ); ++i )
{
ptilePlane->Add( *joinedRegionList[i], TTP_ADD_MERGE );
}
foundConnected = true;
}
}
return( foundConnected );
}
//===========================================================================//
// Method : FindAdjacents
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::FindAdjacents(
const TGS_Region_c& region,
TTPT_TilePlane_c< T >* ptilePlane ) const
{
TGS_Region_c searchRegion( this->region_ );
return( this->FindAdjacents( searchRegion, region, ptilePlane ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::FindAdjacents(
const TGS_Region_c& searchRegion,
const TGS_Region_c& region,
TTPT_TilePlane_c< T >* ptilePlane ) const
{
bool foundAdjacents = false;
if( ptilePlane )
{
ptilePlane->Init( this->region_ );
TGS_Region_c intersectRegion( region );
intersectRegion.ApplyIntersect( this->region_ );
ptilePlane->Add( intersectRegion );
// Iterate until no more adjacent regions found relative to tile plane
bool addedAdjacents = true;
while( addedAdjacents )
{
addedAdjacents = false;
// Iterate for each tile region in tile plane
TTPT_TilePlane_c< T > tilePlane( *ptilePlane );
TTPT_TilePlaneIter_c< T > tilePlaneIter( tilePlane, searchRegion );
TTPT_Tile_c< T >* ptile = 0;
while( tilePlaneIter.Next( &ptile, TTP_TILE_SOLID ))
{
TGS_Region_c iterRegion = ptile->GetRegion( );
// Ignore any iterate regions that fall outside search region
iterRegion.ApplyIntersect( searchRegion );
if( !iterRegion.IsValid( ))
continue;
iterRegion.ApplyScale( this->minGrid_ );
TTPT_TilePlaneIter_c< T > thisPlaneIter( *this, iterRegion );
while( thisPlaneIter.Next( &ptile, TTP_TILE_SOLID ))
{
TGS_Region_c tileRegion = ptile->GetRegion( );
// Ignore any tile regions that fall outside search region
if( !tileRegion.IsIntersecting( searchRegion ))
continue;
tileRegion.ApplyIntersect( searchRegion );
if( !tileRegion.IsValid( ))
continue;
if( ptilePlane->IsClear( TTP_IS_CLEAR_ANY, tileRegion ))
{
ptilePlane->Add( tileRegion, TTP_ADD_MERGE );
addedAdjacents = true;
foundAdjacents = true;
}
}
}
}
}
return( foundAdjacents );
}
//===========================================================================//
// Method : FindData
// Purpose : Find and return a list of zero or more "solid" tile data,
// if any, based on the given reference point or region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::FindData(
double x,
double y,
TCT_OrderedVector_c< T >* pdataList ) const
{
TGS_Point_c point( x, y );
return( this->FindData( point, pdataList ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::FindData(
const TGS_Point_c& point,
TCT_OrderedVector_c< T >* pdataList ) const
{
if( pdataList )
{
pdataList->Clear( );
const TTPT_Tile_c< T >* ptile = this->Find( point );
if( ptile && ptile->IsSolid( ))
{
for( unsigned int i = 0; i < ptile->GetCount( ); ++i )
{
const T* pdata = ptile->FindData( i );
if( pdata && !pdataList->IsMember( *pdata ))
{
pdataList->Add( *pdata );
}
}
}
}
return( pdataList && pdataList->IsValid( ) ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::FindData(
const TGS_Region_c& region,
TCT_OrderedVector_c< T >* pdataList ) const
{
if( pdataList )
{
pdataList->Clear( );
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* ptile = 0;
while( ptilePlane->tilePlaneIter_.Next( &ptile, TTP_TILE_SOLID ))
{
for( unsigned int i = 0; i < ptile->GetCount( ); ++i )
{
const T* pdata = ptile->FindData( i );
if( pdata && !pdataList->IsMember( *pdata ))
{
pdataList->Add( *pdata );
}
}
}
}
return( pdataList && pdataList->IsValid( ) ? true : false );
}
//===========================================================================//
// Method : FindCount
// Purpose : Return total number of clear or solid tiles defined
// within this tile plane. The current count is cached and
// may be valid based on whether any tiles have been added
// or deleted since the last count
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > size_t TTPT_TilePlane_c< T >::FindCount(
TTP_TileMode_t tileMode ) const
{
size_t count = 0;
this->FindCountRefresh_( );
switch( tileMode )
{
case TTP_TILE_CLEAR: count = this->count_.clear; break;
case TTP_TILE_SOLID: count = this->count_.solid; break;
default: break;
}
return( count );
}
//===========================================================================//
template< class T > size_t TTPT_TilePlane_c< T >::FindCount(
const TGS_Region_c& region,
TTP_TileMode_t tileMode ) const
{
size_t count = 0;
this->FindCountRefresh_( region );
switch( tileMode )
{
case TTP_TILE_CLEAR: count = this->count_.clear; break;
case TTP_TILE_SOLID: count = this->count_.solid; break;
default: break;
}
return( count );
}
//===========================================================================//
// Method : FindRegion
// Purpose : Return bounding region for all clear or solid tiles found
// within this tile plane.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::FindRegion(
TTP_TileMode_t tileMode,
TGS_Region_c* pregion ) const
{
if( pregion )
{
pregion->Reset( );
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this );
TTPT_Tile_c< T >* ptile = 0;
while( ptilePlane->tilePlaneIter_.Next( &ptile, tileMode ))
{
const TGS_Region_c& tileRegion = ptile->GetRegion( );
pregion->ApplyUnion( tileRegion );
}
}
}
//===========================================================================//
// Method : Split
// Purpose : Splits the given tile into two adjacent tiles based on
// the given split line. This includes updating stitch
// pointers for neighboring tiles and for the new split
// tile. This split requires the split line to be
// intersecting with the given tile.
//
// The following example illustrates splitting a tile (T)
// into two horizontally adjacent tiles (T) and (T'):
//
// rt ...............rt...
// | . | .
// +-------------*+ . +-------------*+ .
// | *-tr . | *-tr
// | (T) | . | (T') | .
// | | bl'-* rt| .
// | | . +*------------|+ .
// | | . +|------------*+ .
// | | . |lb *-tr'
// | | . | (T) | .
// bl-* | bl-* | .
// +*-------------+ . +*-------------+ .
// | |
// lb lb
//
// The following example illustrates splitting a tile (T)
// into two vertically adjacent tiles (T) and (T'):
//
// rt .....rt'.....rt...
// | | | .
// +-------------*+ +-----*++-----*+ .
// | *-tr | *-tr *-tr
// | (T) | | (T) || (T') | .
// | | | || | .
// | | | || | .
// | | | || | .
// | | | || | .
// | | | || | .
// bl-* | bl-* bl-* | .
// +*-------------+ +*-----++*-----+ .
// | | | .
// lb .lb......lb'......
//
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Split(
TTPT_Tile_c< T >* ptile,
const TGS_Line_c& line,
TGS_DirMode_t dirMode )
{
bool ok = true;
TGS_OrientMode_t orientMode = TGS_ORIENT_UNDEFINED;
if( this->IsSplitable( *ptile, line, dirMode, &orientMode ))
{
// Copy tile (T) to (T'), then split into adjacent tiles
// (ie. split tile into two horizontally or vertically adjacent tiles)
TTPT_Tile_c< T >* ptileP = this->Allocate_( *ptile );
if( ptileP )
{
// Based on split intersect orientation, update tile stitch pointers
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
// Update tile (T) y2 and (T') y1 coords and 'right_upper' & 'upper_right' stitches
this->SplitRegionCoords_( ptile, ptileP, line, dirMode, orientMode );
this->StitchToSplit_( ptile, ptileP, orientMode );
TGS_CornerMode_t cornerMode = TGS_CORNER_UPPER_RIGHT;
if( TCTF_IsLT( ptile->FindArea( ), ptileP->FindArea( )))
{
TTPT_Tile_c< T > tile( *ptile );
TTPT_Tile_c< T > tileP( *ptileP );
*ptile = tileP;
ptile->SetStitchLeftLower( ptileP );
*ptileP = tile;
ptileP->SetStitchRightUpper( ptile );
cornerMode = TGS_CORNER_LOWER_LEFT;
}
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Iterate left/right/lower sides to update neighbor tile stitches
this->StitchFromSide_( ptileP, TC_SIDE_LEFT );
this->StitchFromSide_( ptileP, TC_SIDE_RIGHT );
this->StitchFromSide_( ptileP, TC_SIDE_LOWER );
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Iterate left/right/upper sides to update neighbor tile stitches
this->StitchFromSide_( ptileP, TC_SIDE_LEFT );
this->StitchFromSide_( ptileP, TC_SIDE_RIGHT );
this->StitchFromSide_( ptileP, TC_SIDE_UPPER );
}
}
else // if( orientMode == TGS_ORIENT_VERTICAL )
{
// Update tile (T) x2 and (T') x1 coords and 'left_lower' & 'lower_left' stitches
this->SplitRegionCoords_( ptile, ptileP, line, dirMode, orientMode );
this->StitchToSplit_( ptile, ptileP, orientMode );
TGS_CornerMode_t cornerMode = TGS_CORNER_UPPER_RIGHT;
if( TCTF_IsLT( ptile->FindArea( ), ptileP->FindArea( )))
{
TTPT_Tile_c< T > tile( *ptile );
TTPT_Tile_c< T > tileP( *ptileP );
*ptile = tileP;
ptile->SetStitchLowerLeft( ptileP );
*ptileP = tile;
ptileP->SetStitchUpperRight( ptile );
cornerMode = TGS_CORNER_LOWER_LEFT;
}
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Iterate lower/upper/left sides to update neighbor tile stitches
this->StitchFromSide_( ptileP, TC_SIDE_LOWER );
this->StitchFromSide_( ptileP, TC_SIDE_UPPER );
this->StitchFromSide_( ptileP, TC_SIDE_LEFT );
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Iterate lower/upper/right sides to update neighbor tile stitches
this->StitchFromSide_( ptileP, TC_SIDE_LOWER );
this->StitchFromSide_( ptileP, TC_SIDE_UPPER );
this->StitchFromSide_( ptileP, TC_SIDE_RIGHT );
}
}
ok = true;
}
else
{
ok = false;
}
}
else
{
ok = false;
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Split(
TTPT_Tile_c< T >* ptile,
TC_SideMode_t side )
{
bool ok = true;
const TGS_Region_c& tileRegion = ptile->GetRegion( );
TTPT_Tile_c< T >* pleftTile = ptile->GetStitchLowerLeft( );
TTPT_Tile_c< T >* prightTile = ptile->GetStitchUpperRight( );
switch( side )
{
case TC_SIDE_LEFT:
// Split neighboring left tile based on vertical span formed with this tile
if( pleftTile )
{
TGS_Region_c leftRegion = pleftTile->GetRegion( );
if( TCTF_IsLT( leftRegion.y1, tileRegion.y1 ))
{
TGS_Line_c lowerIntersect( leftRegion.x1 - this->minGrid_, tileRegion.y1,
leftRegion.x2 + this->minGrid_, tileRegion.y1 );
pleftTile = ptile->GetStitchLowerLeft( );
if( pleftTile->IsClear( ))
{
ok = this->Split( pleftTile, lowerIntersect, TGS_DIR_DOWN );
}
}
if( TCTF_IsGT( leftRegion.y2, tileRegion.y2 ))
{
TGS_Line_c upperIntersect( leftRegion.x1 - this->minGrid_, tileRegion.y2,
leftRegion.x2 + this->minGrid_, tileRegion.y2 );
pleftTile = ptile->GetStitchLowerLeft( );
if( pleftTile->IsClear( ))
{
ok = this->Split( pleftTile, upperIntersect, TGS_DIR_UP );
}
}
else
{
pleftTile = this->Find( leftRegion.x2, tileRegion.y2, ptile );
if( pleftTile->IsClear( ))
{
leftRegion = pleftTile->GetRegion( );
if(( TCTF_IsGT( leftRegion.y2, tileRegion.y2 )) &&
( TCTF_IsLE( leftRegion.y1, tileRegion.y2 )))
{
TGS_Line_c upperIntersect( leftRegion.x1 - this->minGrid_, tileRegion.y2,
leftRegion.x2 + this->minGrid_, tileRegion.y2 );
ok = this->Split( pleftTile, upperIntersect, TGS_DIR_UP );
}
}
}
}
break;
case TC_SIDE_RIGHT:
// Split neighboring right tile based on vertical span formed with this tile
if(( prightTile ) &&
( prightTile->GetMode( ) == ptile->GetMode( )))
{
TGS_Region_c rightRegion = prightTile->GetRegion( );
if( TCTF_IsLT( rightRegion.y1, tileRegion.y1 ))
{
TGS_Line_c lowerIntersect( rightRegion.x1 - this->minGrid_, tileRegion.y1,
rightRegion.x2 + this->minGrid_, tileRegion.y1 );
prightTile = ptile->GetStitchUpperRight( );
if( prightTile->IsClear( ))
{
ok = this->Split( prightTile, lowerIntersect, TGS_DIR_DOWN );
}
}
if( TCTF_IsGT( rightRegion.y2, tileRegion.y2 ))
{
TGS_Line_c upperIntersect( rightRegion.x1 - this->minGrid_, tileRegion.y2,
rightRegion.x2 + this->minGrid_, tileRegion.y2 );
prightTile = ptile->GetStitchUpperRight( );
if( prightTile->IsClear( ))
{
ok = this->Split( prightTile, upperIntersect, TGS_DIR_UP );
}
}
else
{
prightTile = this->Find( rightRegion.x1, tileRegion.y2, ptile );
if( prightTile->IsClear( ))
{
rightRegion = prightTile->GetRegion( );
if(( TCTF_IsGT( rightRegion.y2, tileRegion.y2 )) &&
( TCTF_IsLE( rightRegion.y1, tileRegion.y2 )))
{
TGS_Line_c upperIntersect( rightRegion.x1 - this->minGrid_, tileRegion.y2,
rightRegion.x2 + this->minGrid_, tileRegion.y2 );
ok = this->Split( prightTile, upperIntersect, TGS_DIR_UP );
}
}
}
}
break;
case TC_SIDE_LOWER:
case TC_SIDE_UPPER:
// No action taken since split by neighboring lower/upper tile is nonsense
break;
default:
break;
}
return( ok );
}
//===========================================================================//
// Method : Merge
// Purpose : Merges the given two tiles into a single larger tile.
// This includes updating stitch pointers for neighboring
// tiles on three sides. This merge requires both tiles be
// adjacent and have the same width/height.
//
// The following example illustrates merging two
// horizontally adjacent tiles (T) and (T') into a single
// tile T:
//
// rt ...............rt...
// | . | .
// +-------------*+ . +-------------*+ .
// | *-tr . | *-tr
// | (T') | . | (T) | .
// bl-* rt| . | | .
// +*------------|+ . | | .
// +|------------*+ . | | .
// |lb *-tr . | | .
// | (T) | . | | .
// bl-* | bl-* | .
// +*-------------+ . +*-------------+ .
// | |
// lb lb
//
// The following example illustrates merging two
// vertically adjacent tiles T and T' into a single tile T:
//
// rt rt .............rt...
// | | | .
// +-----*++-----*+ +-------------*+ .
// | *-tr *-tr | *-tr
// | (T) || (T') | | (T) | .
// | || | | | .
// | || | | | .
// | || | | | .
// | || | | | .
// | || | | | .
// bl-* bl-* | bl-* | .
// +*-----++*-----+ +*-------------+ .
// | | | .
// lb lb .lb...............
//
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Merge(
TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB )
{
bool ok = true;
TGS_OrientMode_t orientMode = TGS_ORIENT_UNDEFINED;
if( this->IsMergable( *ptileA, *ptileB, &orientMode ))
{
// Found two horizontally or vertically adjacent tiles...
// now decide less than/greater than tiles (T) and (T')
TGS_OrientMode_t altOrient = ( orientMode == TGS_ORIENT_HORIZONTAL ?
TGS_ORIENT_VERTICAL : TGS_ORIENT_HORIZONTAL );
TTPT_Tile_c< T >* ptile = ptileA->FindLessThan( ptileB, altOrient );
TTPT_Tile_c< T >* ptileP = ptileA->FindGreaterThan( ptileB, altOrient );
TGS_CornerMode_t cornerMode = TGS_CORNER_UPPER_RIGHT;
if( TCTF_IsLT( ptile->FindArea( ), ptileP->FindArea( )))
{
ptile = ptileA->FindGreaterThan( ptileB, altOrient );
ptileP = ptileA->FindLessThan( ptileB, altOrient );
cornerMode = TGS_CORNER_LOWER_LEFT;
}
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Update tile (T) per tile (T') y1 coord and 'left_lower' & 'lower_left' stitches
this->MergeRegionCoords_( ptile, ptileP, orientMode, cornerMode );
this->StitchToMerge_( ptile, ptileP, orientMode, cornerMode );
// Iterate left, right, and lower sides to update neighbor tile stitches
this->StitchFromSide_( ptile, TC_SIDE_LEFT, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_RIGHT, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_LOWER );
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Update tile (T) per tile (T') y2 coord and 'right_upper' & 'upper_right' stitches
this->MergeRegionCoords_( ptile, ptileP, orientMode, cornerMode );
this->StitchToMerge_( ptile, ptileP, orientMode, cornerMode );
// Iterate left, right, and upper sides to update neighbor tile stitches
this->StitchFromSide_( ptile, TC_SIDE_LEFT, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_RIGHT, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_UPPER );
}
}
else // if( orientMode == TGS_ORIENT_VERTICAL )
{
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Update tile (T) per tile (T') x1 coord and 'left_lower' & 'lower_left' stitches
this->MergeRegionCoords_( ptile, ptileP, orientMode, cornerMode );
this->StitchToMerge_( ptile, ptileP, orientMode, cornerMode );
// Iterate lower, upper, and left sides to update neighbor tile stitches
this->StitchFromSide_( ptile, TC_SIDE_LOWER, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_UPPER, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_LEFT );
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Update tile (T) per tile (T') x2 coord and 'right_upper' & 'upper_right' stitches
this->MergeRegionCoords_( ptile, ptileP, orientMode, cornerMode );
this->StitchToMerge_( ptile, ptileP, orientMode, cornerMode );
// Iterate lower, upper, and right sides to update neighbor tile stitches
this->StitchFromSide_( ptile, TC_SIDE_LOWER, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_UPPER, ptileP );
this->StitchFromSide_( ptile, TC_SIDE_RIGHT );
}
}
// Deallocate the merged tile (T') after merge complete
this->Deallocate_( ptileP );
ok = true;
}
else
{
ok = false;
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::Merge(
TTPT_Tile_c< T >* ptile,
TC_SideMode_t side )
{
bool ok = true;
TTPT_Tile_c< T >* pleftTile = ptile->GetStitchLowerLeft( );
TTPT_Tile_c< T >* prightTile = ptile->GetStitchUpperRight( );
TTPT_Tile_c< T >* plowerTile = ptile->GetStitchLeftLower( );
TTPT_Tile_c< T >* pupperTile = ptile->GetStitchRightUpper( );
TGS_OrientMode_t orientMode = TGS_ORIENT_UNDEFINED;
switch( side )
{
case TC_SIDE_LEFT:
// Merge neighboring left tile with this reference tile, if possible
if(( pleftTile && this->IsMergable( *pleftTile, *ptile, &orientMode )) &&
( orientMode == TGS_ORIENT_VERTICAL ))
{
ok = this->Merge( pleftTile, ptile );
}
break;
case TC_SIDE_RIGHT:
// Merge neighboring right tile with this reference tile, if possible
if(( prightTile && this->IsMergable( *prightTile, *ptile, &orientMode )) &&
( orientMode == TGS_ORIENT_VERTICAL ))
{
ok = this->Merge( prightTile, ptile );
}
break;
case TC_SIDE_LOWER:
// Merge neighboring lower tile with this reference tile, if possible
if(( plowerTile && this->IsMergable( *plowerTile, *ptile, &orientMode )) &&
( orientMode == TGS_ORIENT_HORIZONTAL ))
{
ok = this->Merge( plowerTile, ptile );
}
break;
case TC_SIDE_UPPER:
// Merge neighboring upper tile with this reference tile, if possible
if(( pupperTile && this->IsMergable( *pupperTile, *ptile, &orientMode )) &&
( orientMode == TGS_ORIENT_HORIZONTAL ))
{
ok = this->Merge( pupperTile, ptile );
}
break;
default:
break;
}
return( ok );
}
//===========================================================================//
// Method : MergeAdjacents
// Purpose : Returns a merged region based on the given tile and any
// neighboring tiles. A merged region is the largest
// possible region that can be constructed that completely
// includes the given tile's region.
//
// For example, given the following two tiles T and T'
// shown below on the right the tile T will be merged with
// T' to return the region shown on the left.
//
// +-----++------+ +-------------+
// | (T) || (T') | | |
// | || | ==> | |
// +-----+| | +-------------+
// | | . .
// +------+ ........
//
// For example, given the following three tiles T, T', and
// T" shown below on the right the tile T will be merged
// with T' to return the region shown on the left.
//
// +---------+ ....+----+
// | (T') | . | |
// +---------+ ....| |
// +-----+ | |
// | (T) | ==> | |
// +-----+ | |
// +----------+ | |.....
// | (T") | | | .
// +----------+ +----+.....
//
// Merging the tiles T and T' shown below on the right
// will be merged into the larger tile on the left based
// on the fully overlapping common edge between T and T'.
//
// +-----+ +-----+
// | (T) | | |
// +-----+ ==> | |
// +--------+ | |...
// | (T') | | | .
// +--------+ +-----+...
//
// Merging the tiles T and T' shown below on the right
// will not be merged since the two tiles do not have a
// fully overlapping common edge between T and T'.
//
// +-----+ +-----+
// | (T) | | |
// +-----+ ==> +-----+
// +--------+ +--------+
// | (T') | | |
// +--------+ +--------+
//
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacents(
const TGS_Point_c& point,
TGS_Region_c* pregion,
TGS_OrientMode_t orientMode,
TTP_MergeMode_t mergeMode,
TTP_TileMode_t tileMode ) const
{
bool mergedAdjacents = false;
const TTPT_Tile_c< T >* ptile = this->Find( point );
if( ptile )
{
mergedAdjacents = this->MergeAdjacents( *ptile, pregion,
mergeMode, orientMode, tileMode );
}
return( mergedAdjacents );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacents(
const TGS_Region_c& region,
TGS_Region_c* pregion,
TGS_OrientMode_t orientMode,
TTP_MergeMode_t mergeMode,
TTP_TileMode_t tileMode ) const
{
bool mergedAdjacents = false;
const TTPT_Tile_c< T >* ptile = 0;
ptile = this->Find( region, TTP_FIND_EXACT, tileMode );
if( !ptile )
{
ptile = this->Find( region, TTP_FIND_WITHIN, tileMode );
}
if( !ptile )
{
TTPT_TilePlaneIter_c< T > thisIter( *this, region );
TTPT_Tile_c< T >* pmergeTile = 0;
while( thisIter.Next( &pmergeTile, tileMode ))
{
TGS_Region_c mergeRegion;
if( this->MergeAdjacents( *pmergeTile, &mergeRegion,
mergeMode, orientMode ) &&
mergeRegion.IsWithin( region ))
{
ptile = pmergeTile;
break;
}
}
}
if( ptile )
{
mergedAdjacents = this->MergeAdjacents( *ptile, pregion,
mergeMode, orientMode );
}
return( mergedAdjacents );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacents(
const TTPT_Tile_c< T >& tile,
TGS_Region_c* pregion,
TGS_OrientMode_t orientMode,
TTP_MergeMode_t mergeMode ) const
{
bool mergedAdjacents = false;
unsigned int tileCount = tile.GetCount( );
const T* ptileData = tile.GetData( );
TTP_TileMode_t tileMode = tile.GetMode( );
const TGS_Region_c& tileRegion = tile.GetRegion( );
TGS_Region_c mergedRegion( tileRegion );
TGS_OrientMode_t defOrient = ( orientMode != TGS_ORIENT_VERTICAL ?
TGS_ORIENT_HORIZONTAL : TGS_ORIENT_VERTICAL );
TGS_OrientMode_t altOrient = ( orientMode == TGS_ORIENT_VERTICAL ?
TGS_ORIENT_HORIZONTAL : TGS_ORIENT_VERTICAL );
if( !mergedAdjacents )
{
TGS_Region_c mergedHorzMaxRegion( tileRegion );
this->MergeAdjacentsByExtent_( defOrient, tileCount, ptileData, tileMode,
mergeMode, &mergedHorzMaxRegion );
if( TCTF_IsGT( mergedHorzMaxRegion.FindArea( ), mergedRegion.FindArea( )))
{
mergedRegion = mergedHorzMaxRegion;
}
else if( TCTF_IsEQ( mergedHorzMaxRegion.FindArea( ), mergedRegion.FindArea( )) &&
TCTF_IsEQ( mergedHorzMaxRegion.FindArea( ), 0.0 ) &&
TCTF_IsGT( mergedHorzMaxRegion.FindMax( ), mergedRegion.FindMax( )))
{
mergedRegion = mergedHorzMaxRegion;
}
if( tileRegion != mergedRegion )
{
mergedAdjacents = true;
}
}
if( mergedAdjacents )
{
TGS_Region_c mergedVertMaxRegion( tileRegion );
this->MergeAdjacentsByExtent_( altOrient, tileCount, ptileData, tileMode,
mergeMode, &mergedVertMaxRegion );
if( TCTF_IsGT( mergedVertMaxRegion.FindArea( ), mergedRegion.FindArea( )))
{
mergedRegion = mergedVertMaxRegion;
}
else if( TCTF_IsEQ( mergedVertMaxRegion.FindArea( ), mergedRegion.FindArea( )) &&
TCTF_IsEQ( mergedVertMaxRegion.FindArea( ), 0.0 ) &&
TCTF_IsGT( mergedVertMaxRegion.FindMax( ), mergedRegion.FindMax( )))
{
mergedRegion = mergedVertMaxRegion;
}
}
if( pregion )
{
*pregion = mergedRegion;
}
return( mergedAdjacents );
}
//===========================================================================//
// Method : JoinAdjacents
// Purpose : Returns a list of joined regions based on the given tile
// and any neighboring tiles. A joined region is the common
// region that can be constructed that joins or connects the
// given tile's region.
//
// For example, given the following two tiles T and T' shown
// below on the right the tile T will be joined with T' to
// return the region shown on the left based on their common
// overlapping edge.
//
// +-----+ ...+--+
// | (T) | . | |
// +-----+ ==> ...| |
// +------+ | |....
// | (T') | | | .
// +------+ +--+....
//
// For example, given the following three tiles T, T', and
// T" shown below on the right the tile T will be joined
// with T' and with T" to return the two regions shown on
// the left based on their common overlapping edges.
//
// +------+ +----+ +------+ +----+
// | (T') | |(T")| | | | |
// +------+ +----+ ==> | | | |
// +--------------------+ ..| |...| |...
// | (T) | . | | | | .
// | | . | | | | .
// +--------------------+ ..+------+...+----+...
//
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::JoinAdjacents(
const TGS_Point_c& point,
TGS_RegionList_t* pregionList ) const
{
bool joinedAdjacents = false;
const TTPT_Tile_c< T >* ptile = this->Find( point );
if( ptile )
{
joinedAdjacents = this->JoinAdjacents( *ptile, pregionList );
}
return( joinedAdjacents );
}
//===========================================================================//
// Method : JoinAdjacents
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::JoinAdjacents(
const TGS_Region_c& region,
TGS_RegionList_t* pregionList,
TTP_JoinMode_t joinMode ) const
{
bool joinedAdjacents = false;
if( joinMode == TTP_JOIN_EXACT )
{
joinedAdjacents = this->JoinAdjacentsPerExact_( region, pregionList );
}
else if( joinMode == TTP_JOIN_INTERSECT )
{
joinedAdjacents = this->JoinAdjacentsPerIntersect_( region, pregionList );
}
return( joinedAdjacents );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::JoinAdjacents(
const TTPT_Tile_c< T >& tile,
TGS_RegionList_t* pregionList ) const
{
bool joinAdjacents = false;
TGS_Region_c joinRegion;
TGS_Region_c region = tile.GetRegion( );
unsigned int count = tile.GetCount( );
const T* pdata = tile.GetData( );
TTP_TileMode_t tileMode = tile.GetMode( );
for( TTPT_Tile_c< T >* pleftTile = tile.GetStitchLowerLeft( );
pleftTile;
pleftTile = pleftTile->GetStitchRightUpper( ))
{
if( TCTF_IsGT( pleftTile->GetRegion( ).y1, region.y2 ))
break;
if(( pleftTile->GetMode( ) == tileMode ) &&
( pleftTile->IsEqualData( count, pdata )))
{
joinRegion.ApplyAdjacent( pleftTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
joinAdjacents = this->JoinAdjacentsBySide_( TC_SIDE_LEFT, joinRegion,
count, pdata, tileMode,
pregionList );
if( !joinAdjacents )
{
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
for( TTPT_Tile_c< T >* prightTile = tile.GetStitchUpperRight( );
prightTile;
prightTile = prightTile->GetStitchLeftLower( ))
{
if( TCTF_IsLT( prightTile->GetRegion( ).y2, region.y1 ))
break;
if(( prightTile->GetMode( ) == tileMode ) &&
( prightTile->IsEqualData( count, pdata )))
{
joinRegion.ApplyAdjacent( prightTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
joinAdjacents = this->JoinAdjacentsBySide_( TC_SIDE_RIGHT, joinRegion,
count, pdata, tileMode,
pregionList );
if( !joinAdjacents )
{
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
for( TTPT_Tile_c< T >* plowerTile = tile.GetStitchLeftLower( );
plowerTile;
plowerTile = plowerTile->GetStitchUpperRight( ))
{
if( TCTF_IsGT( plowerTile->GetRegion( ).x1, region.x2 ))
break;
if(( plowerTile->GetMode( ) == tileMode ) &&
( plowerTile->IsEqualData( count, pdata )))
{
joinRegion.ApplyAdjacent( plowerTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
joinAdjacents = this->JoinAdjacentsBySide_( TC_SIDE_LOWER, joinRegion,
count, pdata, tileMode,
pregionList );
if( !joinAdjacents )
{
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
for( TTPT_Tile_c< T >* pupperTile = tile.GetStitchRightUpper( );
pupperTile;
pupperTile = pupperTile->GetStitchLowerLeft( ))
{
if( TCTF_IsLT( pupperTile->GetRegion( ).x2, region.x1 ))
break;
if(( pupperTile->GetMode( ) == tileMode ) &&
( pupperTile->IsEqualData( count, pdata )))
{
joinRegion.ApplyAdjacent( pupperTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
joinAdjacents = this->JoinAdjacentsBySide_( TC_SIDE_UPPER, joinRegion,
count, pdata, tileMode,
pregionList );
if( !joinAdjacents )
{
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
return( joinAdjacents );
}
//===========================================================================//
// Method : HasAdjacents
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::HasAdjacents(
const TGS_Region_c& region ) const
{
bool hasAdjacents = true;
const TTPT_Tile_c< T >* ptile = this->Find( region );
if( ptile )
{
TTP_TileMode_t tileMode = ptile->GetMode( );
hasAdjacents = false;
TGS_Point_c leftPoint( region.x1 - this->minGrid_, region.y1 );
while( !hasAdjacents && TCTF_IsLE( leftPoint.y, region.y2 ))
{
TTPT_Tile_c< T >* pleftTile = this->Find( leftPoint );
if( !pleftTile )
break;
hasAdjacents = ( pleftTile->GetMode( ) == tileMode ? true : false );
leftPoint.y = pleftTile->GetRegion( ).y2 + this->minGrid_;
}
TGS_Point_c rightPoint( region.x2 + this->minGrid_, region.y2 );
while( !hasAdjacents && TCTF_IsGE( rightPoint.y, region.y1 ))
{
TTPT_Tile_c< T >* prightTile = this->Find( rightPoint );
if( !prightTile )
break;
hasAdjacents = ( prightTile->GetMode( ) == tileMode ? true : false );
rightPoint.y = prightTile->GetRegion( ).y1 - this->minGrid_;
}
TGS_Point_c lowerPoint( region.x1, region.y1 - this->minGrid_ );
while( !hasAdjacents && TCTF_IsLE( lowerPoint.x, region.x2 ))
{
TTPT_Tile_c< T >* plowerTile = this->Find( lowerPoint );
if( !plowerTile )
break;
hasAdjacents = ( plowerTile->GetMode( ) == tileMode ? true : false );
lowerPoint.x = plowerTile->GetRegion( ).x2 + this->minGrid_;
}
TGS_Point_c upperPoint( region.x2, region.y2 + this->minGrid_ );
while( !hasAdjacents && TCTF_IsGE( upperPoint.x, region.x1 ))
{
TTPT_Tile_c< T >* pupperTile = this->Find( upperPoint );
if( !pupperTile )
break;
hasAdjacents = ( pupperTile->GetMode( ) == tileMode ? true : false );
upperPoint.x = pupperTile->GetRegion( ).x1 - this->minGrid_;
}
}
return( hasAdjacents );
}
//===========================================================================//
// Method : HasNeighbor
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::HasNeighbor(
const TGS_Region_c& region,
double minDistance ) const
{
bool hasNeighbor = false;
TTPT_Tile_c< T >* ptile = this->Find( region, TTP_FIND_EXACT );
if( ptile && ptile->IsSolid( ))
{
hasNeighbor = this->HasNeighbor( *ptile, minDistance );
}
else
{
hasNeighbor = true;
}
return( hasNeighbor );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::HasNeighbor(
const TTPT_Tile_c< T >& tile,
double minDistance ) const
{
bool hasNeighbor = false;
const TGS_Region_c& tileRegion = tile.GetRegion( );
if( !hasNeighbor )
{
const TTPT_Tile_c< T >* plowerTile = tile.GetStitchLeftLower( );
if( plowerTile && plowerTile->IsSolid( ))
{
hasNeighbor = true;
}
else if( plowerTile && plowerTile->IsClear( ))
{
const TGS_Region_c& lowerRegion = plowerTile->GetRegion( );
if( TCTF_IsGT( lowerRegion.x1, tileRegion.x1 - minDistance ) ||
TCTF_IsLT( lowerRegion.x2, tileRegion.x2 + minDistance ) ||
TCTF_IsGT( lowerRegion.y1, tileRegion.y1 - minDistance ))
{
TGS_Region_c searchRegion( tileRegion.x1 - minDistance,
tileRegion.y1 - minDistance,
tileRegion.x2 + minDistance,
lowerRegion.y1 - this->minGrid_ );
hasNeighbor = this->IsSolid( TTP_IS_SOLID_ANY, searchRegion );
}
}
}
if( !hasNeighbor )
{
const TTPT_Tile_c< T >* pupperTile = tile.GetStitchRightUpper( );
if( pupperTile && pupperTile->IsSolid( ))
{
hasNeighbor = true;
}
else if( pupperTile && pupperTile->IsClear( ))
{
const TGS_Region_c& upperRegion = pupperTile->GetRegion( );
if( TCTF_IsGT( upperRegion.x1, tileRegion.x1 - minDistance ) ||
TCTF_IsLT( upperRegion.x2, tileRegion.x2 + minDistance ) ||
TCTF_IsLT( upperRegion.y2, tileRegion.y2 + minDistance ))
{
TGS_Region_c searchRegion( tileRegion.x1 - minDistance,
upperRegion.y2 + this->minGrid_,
tileRegion.x2 + minDistance,
tileRegion.y2 + minDistance );
hasNeighbor = this->IsSolid( TTP_IS_SOLID_ANY, searchRegion );
}
}
}
if( !hasNeighbor )
{
for( TTPT_Tile_c< T >* pleftTile = tile.GetStitchLowerLeft( );
pleftTile;
pleftTile = pleftTile->GetStitchRightUpper( ))
{
const TGS_Region_c& leftRegion = pleftTile->GetRegion( );
if( TCTF_IsGT( leftRegion.y1, tileRegion.y2 ))
break;
if( pleftTile->IsSolid( ))
{
hasNeighbor = true;
}
else if( pleftTile->IsClear( ))
{
if( TCTF_IsGT( leftRegion.x1, tileRegion.x1 - minDistance ))
{
hasNeighbor = true;
}
}
if( hasNeighbor )
break;
}
}
if( !hasNeighbor )
{
for( TTPT_Tile_c< T >* prightTile = tile.GetStitchUpperRight( );
prightTile;
prightTile = prightTile->GetStitchLeftLower( ))
{
const TGS_Region_c& rightRegion = prightTile->GetRegion( );
if( TCTF_IsLT( rightRegion.y2, tileRegion.y1 ))
break;
if( prightTile->IsSolid( ))
{
hasNeighbor = true;
}
else if( prightTile->IsClear( ))
{
if( TCTF_IsLT( rightRegion.x2, tileRegion.x2 + minDistance ))
{
hasNeighbor = true;
}
}
if( hasNeighbor )
break;
}
}
return( hasNeighbor );
}
//===========================================================================//
// Method : IsClear
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClear(
void ) const
{
bool isClear = false;
if( this->ptileLL_ &&
this->ptileLL_->IsClear( ) &&
!this->ptileLL_->GetStitchLowerLeft( ) &&
!this->ptileLL_->GetStitchLeftLower( ) &&
!this->ptileLL_->GetStitchRightUpper( ) &&
!this->ptileLL_->GetStitchUpperRight( ))
{
isClear = true;
}
return( isClear );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClear(
double x,
double y ) const
{
TGS_Point_c point( x, y );
return( this->IsClear( point ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClear(
const TGS_Point_c& point ) const
{
return( this->IsClearMatch_( point ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClear(
const TGS_Region_c& region ) const
{
return( this->IsClearMatch_( region ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClear(
TTP_IsClearMode_t isClearMode,
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile ) const
{
bool isClear = false;
switch( isClearMode )
{
case TTP_IS_CLEAR_MATCH:
isClear = this->IsClearMatch_( region, ppclearTile );
break;
case TTP_IS_CLEAR_ANY:
isClear = this->IsClearAny_( region, ppclearTile );
break;
case TTP_IS_CLEAR_ALL:
isClear = this->IsClearAll_( region, ppclearTile );
break;
default:
break;
}
return( isClear );
}
//===========================================================================//
// Method : IsSolid
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
double x,
double y ) const
{
TGS_Point_c point( x, y );
return( this->IsSolid( point ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
const TGS_Point_c& point ) const
{
return( this->IsSolidMatch_( point ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
const TGS_Point_c& point,
const T& data ) const
{
return( this->IsSolidMatch_( point, 1, &data ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const
{
return( this->IsSolidMatch_( point, count, pdata ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
const TGS_Region_c& region ) const
{
return( this->IsSolidMatch_( region ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
const TGS_Region_c& region,
const T& data ) const
{
return( this->IsSolidMatch_( region, 1, &data ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
const TGS_Region_c& region,
unsigned int count,
const T* pdata ) const
{
return( this->IsSolidMatch_( region, count, pdata ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
TTP_IsSolidMode_t isSolidMode,
TTPT_Tile_c< T >** ppsolidTile ) const
{
const TGS_Region_c& region = this->GetRegion( );
return( this->IsSolid( isSolidMode, region, ppsolidTile ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile ) const
{
bool isSolid = false;
switch( isSolidMode )
{
case TTP_IS_SOLID_MATCH:
isSolid = this->IsSolidMatch_( region, ppsolidTile );
break;
case TTP_IS_SOLID_ANY:
isSolid = this->IsSolidAny_( region, ppsolidTile );
break;
case TTP_IS_SOLID_ALL:
isSolid = this->IsSolidAll_( region, ppsolidTile );
break;
case TTP_IS_SOLID_MAX:
isSolid = this->IsSolidMax_( region, ppsolidTile );
break;
default:
break;
}
return( isSolid );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
const T& data,
TTPT_Tile_c< T >** ppsolidTile ) const
{
bool isSolid = false;
switch( isSolidMode )
{
case TTP_IS_SOLID_MATCH:
isSolid = this->IsSolidMatch_( region, 1, &data, ppsolidTile );
break;
case TTP_IS_SOLID_ANY:
isSolid = this->IsSolidAny_( region, 1, &data, ppsolidTile );
break;
case TTP_IS_SOLID_ALL:
isSolid = this->IsSolidAll_( region, 1, &data, ppsolidTile );
break;
default:
break;
}
return( isSolid );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolid(
TTP_IsSolidMode_t isSolidMode,
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile ) const
{
bool isSolid = false;
switch( isSolidMode )
{
case TTP_IS_SOLID_MATCH:
isSolid = this->IsSolidMatch_( region, count, pdata, ppsolidTile );
break;
case TTP_IS_SOLID_ANY:
isSolid = this->IsSolidAny_( region, count, pdata, ppsolidTile );
break;
case TTP_IS_SOLID_ALL:
isSolid = this->IsSolidAll_( region, count, pdata, ppsolidTile );
break;
default:
break;
}
return( isSolid );
}
//===========================================================================//
// Method : IsSolidNot
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNot(
const TGS_Point_c& point,
const T& data ) const
{
return( this->IsSolidNotMatch_( point, 1, &data ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNot(
const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const
{
return( this->IsSolidNotMatch_( point, count, pdata ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNot(
const TGS_Region_c& region,
const T& data ) const
{
return( this->IsSolidNotMatch_( region, 1, &data ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNot(
const TGS_Region_c& region,
unsigned int count,
const T* pdata ) const
{
return( this->IsSolidNotMatch_( region, count, pdata ));
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNot(
TTP_IsSolidMode_t isSolidNotMode,
const TGS_Region_c& region,
const T& data,
TTPT_Tile_c< T >** ppSolidNotTile ) const
{
bool isSolidNot = false;
switch( isSolidNotMode )
{
case TTP_IS_SOLID_MATCH:
isSolidNot = this->IsSolidNotMatch_( region, 1, &data, ppSolidNotTile );
break;
case TTP_IS_SOLID_ANY:
isSolidNot = this->IsSolidNotAny_( region, 1, &data, ppSolidNotTile );
break;
case TTP_IS_SOLID_ALL:
isSolidNot = this->IsSolidNotAll_( region, 1, &data, ppSolidNotTile );
break;
default:
break;
}
return( isSolidNot );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNot(
TTP_IsSolidMode_t isSolidNotMode,
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppSolidNotTile ) const
{
bool isSolidNot = false;
switch( isSolidNotMode )
{
case TTP_IS_SOLID_MATCH:
isSolidNot = this->IsSolidNotMatch_( region, count, pdata, ppSolidNotTile );
break;
case TTP_IS_SOLID_ANY:
isSolidNot = this->IsSolidNotAny_( region, count, pdata, ppSolidNotTile );
break;
case TTP_IS_SOLID_ALL:
isSolidNot = this->IsSolidNotAll_( region, count, pdata, ppSolidNotTile );
break;
default:
break;
}
return( isSolidNot );
}
//===========================================================================//
// Method : IsIntersecting
// Purpose : Returns true if the given tile region is intersecting.
// Optionally returns the first intersecting tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsIntersecting(
const TGS_Region_c& region,
TGS_Region_c* pintersectRegion,
TTP_TileMode_t tileMode ) const
{
bool isIntersecting = false;
TTPT_Tile_c< T >* ptile = this->FindPerIntersect_( region, tileMode );
if( ptile )
{
isIntersecting = true;
if( pintersectRegion )
{
*pintersectRegion = ptile->GetRegion( );
}
}
return( isIntersecting );
}
//===========================================================================//
// Method : IsAdjacent
// Purpose : Returns true if the given tile regions are adjacent.
// Optionally returns the first tile's adjacent side with
// respect to the second tile.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsAdjacent(
const TGS_Region_c& regionA,
const TGS_Region_c& regionB,
TC_SideMode_t* pside ) const
{
TC_SideMode_t side = TC_SIDE_UNDEFINED;
if( TCTF_IsEQ( regionA.x1, regionB.x2 + this->minGrid_ ))
{
side = TC_SIDE_LEFT;
}
else if( TCTF_IsEQ( regionA.x2, regionB.x1 - this->minGrid_ ))
{
side = TC_SIDE_RIGHT;
}
if( TCTF_IsEQ( regionA.y1, regionB.y2 + this->minGrid_ ))
{
side = TC_SIDE_LOWER;
}
else if( TCTF_IsEQ( regionA.y2, regionB.y1 - this->minGrid_ ))
{
side = TC_SIDE_UPPER;
}
if( pside )
{
*pside = side;
}
return( side != TC_SIDE_UNDEFINED ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsAdjacent(
const TTPT_Tile_c< T >& tileA,
const TTPT_Tile_c< T >& tileB,
TC_SideMode_t* pside ) const
{
const TGS_Region_c& regionA = tileA.GetRegion( );
const TGS_Region_c& regionB = tileB.GetRegion( );
return( this->IsAdjacent( regionA, regionB, pside ));
}
//===========================================================================//
// Method : IsMergable
// Purpose : Returns true if the given two tiles can be merged into a
// single tile. Optionally returns the merge orientation of
// the first tile with respect to the second tile.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsMergable(
const TTPT_Tile_c< T >& tileA,
const TTPT_Tile_c< T >& tileB,
TGS_OrientMode_t* porientMode ) const
{
TGS_OrientMode_t orientMode = TGS_ORIENT_UNDEFINED;
TC_SideMode_t side = TC_SIDE_UNDEFINED;
if( this->IsAdjacent( tileA, tileB, &side ))
{
const TGS_Region_c& regionA = tileA.GetRegion( );
const TGS_Region_c& regionB = tileB.GetRegion( );
switch( side )
{
case TC_SIDE_LEFT:
case TC_SIDE_RIGHT:
if( TCTF_IsEQ( regionA.y1, regionB.y1 ) &&
TCTF_IsEQ( regionA.y2, regionB.y2 ))
{
if( tileA.IsClear( ) && tileB.IsClear( ))
{
orientMode = TGS_ORIENT_VERTICAL;
}
else if( tileA.IsSolid( ) && tileB.IsSolid( ) &&
tileA.IsEqualData( tileB ))
{
orientMode = TGS_ORIENT_VERTICAL;
}
}
break;
case TC_SIDE_LOWER:
case TC_SIDE_UPPER:
if( TCTF_IsEQ( regionA.x1, regionB.x1 ) &&
TCTF_IsEQ( regionA.x2, regionB.x2 ))
{
if( tileA.IsClear( ) && tileB.IsClear( ))
{
orientMode = TGS_ORIENT_HORIZONTAL;
}
else if( tileA.IsSolid( ) && tileB.IsSolid( ) &&
tileA.IsEqualData( tileB ))
{
orientMode = TGS_ORIENT_HORIZONTAL;
}
}
break;
default:
break;
}
}
if( porientMode )
{
*porientMode = orientMode;
}
return( orientMode != TGS_ORIENT_UNDEFINED ? true : false );
}
//===========================================================================//
// Method : IsSplitable
// Purpose : Returns true if the given single tile can be split into
// two adjacent tiles based on the given intersect line.
// Optionally returns the split orientation if the first
// tile with respect to the second tile.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSplitable(
const TTPT_Tile_c< T >& tile,
const TGS_Line_c& intersectLine,
TGS_DirMode_t dirMode,
TGS_OrientMode_t* porientMode ) const
{
TTP_TileMode_t tileMode = tile.GetMode( );
const TGS_Region_c& tileRegion = tile.GetRegion( );
TGS_OrientMode_t orientMode = intersectLine.FindOrient( );
if( orientMode == TGS_ORIENT_UNDEFINED )
{
orientMode = tileRegion.FindOrient( TGS_ORIENT_ALTERNATE );
}
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
if( TCTF_IsLT( tileRegion.GetDy( ), this->minGrid_ ))
{
orientMode = TGS_ORIENT_UNDEFINED;
}
}
if( orientMode == TGS_ORIENT_VERTICAL )
{
if( TCTF_IsLT( tileRegion.GetDx( ), this->minGrid_ ))
{
orientMode = TGS_ORIENT_UNDEFINED;
}
}
TGS_Region_c intersectRegion( tileRegion );
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
intersectRegion.y1 += this->minGrid_;
intersectRegion.y2 -= this->minGrid_;
}
if( orientMode == TGS_ORIENT_VERTICAL )
{
intersectRegion.x1 += this->minGrid_;
intersectRegion.x2 -= this->minGrid_;
}
if(( orientMode == TGS_ORIENT_HORIZONTAL ) ||
( orientMode == TGS_ORIENT_VERTICAL ))
{
switch( dirMode )
{
case TGS_DIR_LEFT:
if( TCTF_IsEQ( tileRegion.x2, intersectLine.x2 ))
{
intersectRegion.x2 += this->minGrid_;
}
break;
case TGS_DIR_RIGHT:
if( TCTF_IsEQ( tileRegion.x1, intersectLine.x1 ))
{
intersectRegion.x1 -= this->minGrid_;
}
break;
case TGS_DIR_DOWN:
if( TCTF_IsEQ( tileRegion.y2, intersectLine.y2 ))
{
intersectRegion.y2 += this->minGrid_;
}
break;
case TGS_DIR_UP:
if( TCTF_IsEQ( tileRegion.y1, intersectLine.y1 ))
{
intersectRegion.y1 -= this->minGrid_;
}
break;
default:
break;
}
TTPT_Tile_c< T > intersectTile( tileMode, intersectRegion );
if(( !TCTF_IsLE( intersectRegion.x1, intersectRegion.x2 )) ||
( !TCTF_IsLE( intersectRegion.y1, intersectRegion.y2 )) ||
( !intersectTile.IsIntersecting( intersectLine )))
{
orientMode = TGS_ORIENT_UNDEFINED;
}
}
if( porientMode )
{
*porientMode = orientMode;
}
return( orientMode != TGS_ORIENT_UNDEFINED ? true : false );
}
//===========================================================================//
// Method : IsLegal
// Purpose : Returns true if the current tile plane is legal according
// to the tile plane's strip property (ie. does not have any
// horizontally adjacent clear tiles).
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsLegal(
void ) const
{
bool isLegal = true;
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this );
TTPT_Tile_c< T >* ptile = 0;
while( ptilePlane->tilePlaneIter_.Next( &ptile ))
{
const TGS_Region_c& tileRegion = ptile->GetRegion( );
if(( TCTF_IsGT( tileRegion.x1, tileRegion.x2 )) ||
( TCTF_IsGT( tileRegion.y1, tileRegion.y2 )))
{
isLegal = this->ShowInternalMessage_( TTP_MESSAGE_IS_LEGAL_INVALID_REGION,
"TTPT_TilePlane_c::IsLegal",
&tileRegion );
}
if(( ptile->IsClear( )) &&
( ptile->GetStitchUpperRight( )) &&
( ptile->GetStitchUpperRight( )->IsClear( )))
{
const TGS_Region_c& nextRegion = ptile->GetStitchUpperRight( )->GetRegion( );
isLegal = this->ShowInternalMessage_( TTP_MESSAGE_IS_LEGAL_INVALID_REGION,
"TTPT_TilePlane_c::IsLegal",
&tileRegion, &nextRegion );
}
}
return( isLegal );
}
//===========================================================================//
// Method : AddPerRegion_
// Purpose : Adds or inserts a new solid tile into the current tile
// plane.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerRegion_(
const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient )
{
bool ok = true;
const TGS_Region_c& addRegion = addTile.GetRegion( );
unsigned int addCount = addTile.GetCount( );
const T* paddData = addTile.GetData( );
if( this->IsWithin( addRegion ))
{
// Find clear tile containing new tile's upper side, split into two tiles
if( ok )
{
ok = AddPerUpperSideSplit_( addRegion );
}
// Find clear tile containing new tile's lower side, split into two tiles
if( ok )
{
ok = AddPerLowerSideSplit_( addRegion );
}
// Iterate new tile's region, splitting and merging left/center/right tiles
if( ok )
{
ok = AddPerCenterSideSplits_( addRegion );
}
// After iteration, attempt to merge new tile with neighboring tiles
// (ie. merge with left/right/upper solid tiles, if possible)
if( ok )
{
// Find solid tile based on upper-right corner of region
TTPT_Tile_c< T >* psolidTile = this->Find( addRegion.x2, addRegion.y2 );
psolidTile->MakeSolid( addCount, paddData );
ok = AddPerSolidTileMerges_( addRegion );
}
// After merging with neighboring tiles, attempt to re-merge aligned tiles
// (ie. re-merge with lower/upper vertically aligned solid tiles, if any)
if( ok )
{
// Find solid tile based on upper-right corner of region
TTPT_Tile_c< T >* psolidTile = this->Find( addRegion.x2, addRegion.y2 );
TGS_Region_c solidRegion = psolidTile->GetRegion( );
addOrient = ( addOrient != TGS_ORIENT_UNDEFINED ?
addOrient : TGS_ORIENT_VERTICAL );
ok = AddPerSolidTileCorners_( solidRegion, addOrient );
}
}
return( ok );
}
//===========================================================================//
// Method : AddPerNew_
// Purpose : Adds or inserts a new solid tile into the current tile
// plane. This method adds the new solid tile if and only
// if there are no solid tiles in the desired area.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerNew_(
const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient )
{
bool ok = true;
const TGS_Region_c& addRegion = addTile.GetRegion( );
TTPT_Tile_c< T >* pintersectTile = 0;
if( this->IsWithin( addRegion ) &&
!this->IsSolid( TTP_IS_SOLID_ANY, addRegion, &pintersectTile ))
{
ok = this->AddPerRegion_( addTile, addOrient );
}
else if( !this->IsWithin( addRegion ))
{
// Report message: new tile region not within this tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_ADD_PER_NEW_INVALID,
"TTPT_TilePlane_c::AddPerNew_",
&addRegion, &tilePlaneRegion );
}
else if( this->IsSolid( TTP_IS_SOLID_ANY, addRegion, &pintersectTile ))
{
// Report message: new tile region intersects existing solid tile
const TGS_Region_c& existsRegion = pintersectTile->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_ADD_PER_NEW_EXISTS,
"TTPT_TilePlane_c::AddPerNew_",
&addRegion, &existsRegion );
}
return( ok );
}
//===========================================================================//
// Method : AddPerMerge_
// Purpose : Adds or inserts a new solid tile into the current tile
// plane. If the new solid tile overlaps with one or more
// existing solid tiles, then the new solid tile is merged
// with the existing solid tiles.
//
// For example, merging the two (A) (ie. "same") data tiles
// shown below on the left results in the set of three (A)
// (ie. "same") data tiles shown below on the right.
//
// +-------------+ +-------------+
// | | | |
// | | | (A) |
// | (A) | | |
// | | +-------------+
// | +-----|----+ +------------------+
// | | | | | (A) |
// +-------|-----+ | +------------------+
// | (A) | +----------+
// | | | (A) |
// +----------+ +----------+
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerMerge_(
const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode )
{
bool ok = true;
const TGS_Region_c& addRegion = addTile.GetRegion( );
unsigned int addCount = addTile.GetCount( );
const T* paddData = addTile.GetData( );
TTPT_Tile_c< T >* pintersectTile = 0;
bool isWithin = this->IsWithin( addRegion );
bool isSolidAll = isWithin ?
this->IsSolid( TTP_IS_SOLID_ALL, addRegion, addCount, paddData ) :
false;
bool isSolidNotAny = isWithin ?
this->IsSolidNot( TTP_IS_SOLID_ANY, addRegion, addCount, paddData, &pintersectTile ) :
false;
if( isWithin && !isSolidAll && !isSolidNotAny )
{
// Merge existing tile with new tile and add adjacent solid regions
ok = this->AddPerMergeNew_( addTile, addOrient, addMode );
}
else if( !isWithin )
{
// Report message: new tile region not within this tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_ADD_PER_MERGE_INVALID,
"TTPT_TilePlane_c::AddPerMerge_",
&addRegion, &tilePlaneRegion );
}
else if( isSolidNotAny )
{
// Report message: new tile region intersects existing solid tile
const TGS_Region_c& existsRegion = pintersectTile->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_ADD_PER_MERGE_EXISTS,
"TTPT_TilePlane_c::AddPerMerge_",
&addRegion, &existsRegion );
}
else if( isSolidAll )
{
// Nothing to do since solid tile(s) already exists per new region
}
return( ok );
}
//===========================================================================//
// Method : AddPerMergeNew_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerMergeNew_(
const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode )
{
bool ok = true;
const TGS_Region_c& addRegion = addTile.GetRegion( );
unsigned int addCount = addTile.GetCount( );
const T* paddData = addTile.GetData( );
bool addPerDifference = false;
TTPT_Tile_c< T >* psolidTile = 0;
if( this->IsSolid( TTP_IS_SOLID_ANY, addRegion, addCount, paddData, &psolidTile ) &&
this->IsSolid( TTP_IS_SOLID_MAX, addRegion, addCount, paddData, &psolidTile ))
{
const TGS_Region_c& solidRegion = psolidTile->GetRegion( );
if( TCTF_IsLE( addRegion.FindArea( ), solidRegion.FindArea( )))
{
addPerDifference = true;
}
if( addRegion.IsCrossed( solidRegion, this->minGrid_ ))
{
addPerDifference = this->HasAspectRatio_( addRegion, solidRegion );
}
if( addRegion.IsCorner( solidRegion ))
{
addPerDifference = true;
}
if( addMode == TTP_ADD_DIFFERENCE )
{
addPerDifference = true;
}
}
if( addPerDifference )
{
// Decide (or override) orient based on user-defined tile orient mode
addOrient = ( addRegion.IsWide( ) ?
TGS_ORIENT_VERTICAL : TGS_ORIENT_HORIZONTAL );
// Ready to iterate over region, adding any non-intersecting solid regions
const TGS_Region_c& solidRegion = psolidTile->GetRegion( );
TGS_RegionList_t subRegionList( 4 );
addRegion.FindDifference( solidRegion, addOrient,
&subRegionList, this->minGrid_ );
for( size_t i = 0; i < subRegionList.GetLength( ); ++i )
{
TTPT_Tile_c< T > subTile( TTP_TILE_SOLID, *subRegionList[i],
addCount, paddData );
ok = this->AddPerMerge_( subTile, addOrient, addMode );
if( !ok )
break;
}
}
else
{
// First, iterate over region, deleting any intersecting solid regions
TTPT_Tile_c< T >* pwithinTile = 0;
while( this->IsSolid( TTP_IS_SOLID_ANY, addRegion, addCount, paddData, &psolidTile ))
{
if( psolidTile->IsWithin( addRegion ))
{
pwithinTile = psolidTile;
break;
}
TTPT_Tile_c< T > solidTile( *psolidTile );
const TGS_Region_c& solidRegion = solidTile.GetRegion( );
unsigned int solidCount = solidTile.GetCount( );
const T* psolidData = solidTile.GetData( );
ok = this->Delete( psolidTile );
if( !ok )
break;
// Decide (or override) orient based on user-defined tile orient mode
addOrient = ( addRegion.IsWide( ) ?
TGS_ORIENT_VERTICAL : TGS_ORIENT_HORIZONTAL );
TGS_RegionList_t subRegionList( 4 );
solidRegion.FindDifference( addRegion, addOrient,
&subRegionList, this->minGrid_ );
for( size_t i = 0; i < subRegionList.GetLength( ); ++i )
{
TTPT_Tile_c< T > subTile( TTP_TILE_SOLID, *subRegionList[i],
solidCount, psolidData );
ok = this->AddPerNew_( subTile, addOrient );
if( !ok )
break;
}
if( !ok )
break;
}
// Second, add a new solid tile adjacent to any existing solid regions
if( ok && !pwithinTile )
{
ok = this->AddPerNew_( addTile, addOrient );
}
}
return( ok );
}
//===========================================================================//
// Method : AddPerOverlap_
// Purpose : Adds or inserts a new solid tile into the current tile
// existing solid tiles with non-compatible data, then the
// new and existing tile intersects are defined based on
// the union of the non-compatible data.
//
// For example, overlapping the two (A) and (B) (ie.
// "different") data tiles shown below on the left results
// in the set of (A) and (B) (ie. "same" and "different")
// data tiles shown below on the right, including the
// combined (A,B) data tile.
//
// +-------------+ +-------------+
// | | | |
// | | | (A) |
// | (A) | | |
// | | +-------------+
// | +-----|----+ +------++-----++---+
// | | | | | (A) ||(A,B)||(B)|
// +-------|-----+ | +------++-----++---+
// | (B) | +----------+
// | | | (B) |
// +----------+ +----------+
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerOverlap_(
const TTPT_Tile_c< T >& addTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode )
{
bool ok = true;
const TGS_Region_c& addRegion = addTile.GetRegion( );
unsigned int addCount = addTile.GetCount( );
const T* paddData = addTile.GetData( );
TTPT_Tile_c< T >* pintersectTile = 0;
bool isWithin = this->IsWithin( addRegion );
bool isSolidNotAny = isWithin ?
this->IsSolidNot( TTP_IS_SOLID_ANY,
addRegion, addCount, paddData,
&pintersectTile ) : false;
if( isWithin && isSolidNotAny )
{
// Add "different" data tile by using add-by-overlap insertion method
if( !pintersectTile->IsWithin( addRegion ) ||
!pintersectTile->IsEqualData( addCount, paddData ))
{
const TTPT_Tile_c< T >* poverlapTile = pintersectTile;
ok = this->AddPerOverlap_( addTile, poverlapTile, addOrient, addMode );
}
}
else if( isWithin && !isSolidNotAny )
{
// Defer adding "same" data tile by using add-by-merge insertion method
ok = this->AddPerMergeNew_( addTile, addOrient, addMode );
}
else if( !isWithin )
{
// Report message: new tile region not within this tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_ADD_PER_OVERLAP_INVALID,
"TTPT_TilePlane_c::AddPerOverlap_",
&addRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerOverlap_(
const TTPT_Tile_c< T >& addTile,
const TTPT_Tile_c< T >* poverlapTile,
TGS_OrientMode_t addOrient,
TTP_AddMode_t addMode )
{
bool ok = true;
TTPT_Tile_c< T > addTile_( addTile );
const TGS_Region_c& addRegion = addTile_.GetRegion( );
unsigned int addCount = addTile_.GetCount( );
const T* paddData = addTile_.GetData( );
TTPT_Tile_c< T > overlapTile_( *poverlapTile );
TGS_Region_c overlapRegion = overlapTile_.GetRegion( );
unsigned int overlapCount = overlapTile_.GetCount( );
const T* poverlapData = overlapTile_.GetData( );
// Start by deleting the existing overlap tile
ok = this->Delete( overlapRegion );
// Build an intersect tile based on add and overlap tile regions and data
TGS_Region_c intersectRegion;
intersectRegion.ApplyIntersect( addRegion, overlapRegion );
TTPT_Tile_c< T > intersectTile( TTP_TILE_SOLID, intersectRegion );
if( ok )
{
ok = intersectTile.AddData( addCount, paddData );
}
if( ok )
{
for( unsigned int i = 0; i < overlapCount; ++i )
{
const T* poverlapData_i = ( poverlapData + i );
bool isMemberOverlapData_i = false;
for( unsigned int j = 0; j < addCount; ++j )
{
const T* paddData_j = ( paddData + j );
if( *poverlapData_i == *paddData_j )
{
isMemberOverlapData_i = true;
break;
}
}
if( !isMemberOverlapData_i )
{
ok = intersectTile.AddData( 1, poverlapData_i );
}
}
}
// First, add the intersect tile with both add and overlap tile data
if( ok )
{
ok = this->AddPerNew_( intersectTile, addOrient );
}
// Decide difference from overlap to intersect tiles and add difference
if( ok )
{
// Decide (or override) orient based on user-defined tile orient mode
addOrient = ( addRegion.IsWide( ) ?
TGS_ORIENT_VERTICAL : TGS_ORIENT_HORIZONTAL );
TGS_RegionList_t overlapSubRegionList( 4 );
overlapRegion.FindDifference( intersectRegion, addOrient,
&overlapSubRegionList, this->minGrid_ );
for( size_t i = 0; i < overlapSubRegionList.GetLength( ); ++i )
{
TTPT_Tile_c< T > overlapSubTile( TTP_TILE_SOLID, *overlapSubRegionList[i],
overlapCount, poverlapData );
ok = this->AddPerNew_( overlapSubTile, addOrient );
if( !ok )
break;
}
}
// Decide difference from add to intersect tiles and add difference
// Note: difference tiles are added recursively to handle multiple overlaps
if( ok )
{
TGS_RegionList_t addSubRegionList( 4 );
addRegion.FindDifference( intersectRegion, addOrient,
&addSubRegionList, this->minGrid_ );
for( size_t i = 0; i < addSubRegionList.GetLength( ); ++i )
{
const TGS_Region_c& addSubRegion = *addSubRegionList[i];
TTPT_Tile_c< T > addSubTile( TTP_TILE_SOLID, addSubRegion,
addCount, paddData );
ok = this->AddPerOverlap_( addSubTile, addOrient, addMode );
if( !ok )
break;
}
}
return( ok );
}
//===========================================================================//
// Method : AddPerUpperSideSplit_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerUpperSideSplit_(
const TGS_Region_c& addRegion )
{
bool ok = true;
// Find the clear tile containing the upper side of the given new tile region
// (Clear tiles cover entire upper side due to tile plane's strip property)
TTPT_Tile_c< T >* pupperTile = this->Find( addRegion.x2, addRegion.y2 );
// Split clear tile horizontally into two tiles per given tile's upper side
const TGS_Region_c& upperRegion = pupperTile->GetRegion( );
TGS_Line_c upperIntersect( upperRegion.x1 - this->minGrid_, addRegion.y2,
upperRegion.x2 + this->minGrid_, addRegion.y2 );
if( this->IsSplitable( *pupperTile, upperIntersect, TGS_DIR_UP ))
{
ok = this->Split( pupperTile, upperIntersect, TGS_DIR_UP );
}
return( ok );
}
//===========================================================================//
// Method : AddPerLowerSideSplit_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerLowerSideSplit_(
const TGS_Region_c& addRegion )
{
bool ok = true;
// Find clear tile containing lower side of the given new tile region
// (Clear tiles cover entire lower side due to tile plane's strip property)
TTPT_Tile_c< T >* plowerTile = this->Find( addRegion.x1, addRegion.y1 );
// Split clear tile horizontally into two tiles per given tile's lower side
const TGS_Region_c& lowerRegion = plowerTile->GetRegion( );
TGS_Line_c lowerIntersect( lowerRegion.x1 - this->minGrid_, addRegion.y1,
lowerRegion.x2 + this->minGrid_, addRegion.y1 );
if( this->IsSplitable( *plowerTile, lowerIntersect, TGS_DIR_DOWN ))
{
ok = this->Split( plowerTile, lowerIntersect, TGS_DIR_DOWN );
}
return( ok );
}
//===========================================================================//
// Method : AddPerCenterSideSplits_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerCenterSideSplits_(
const TGS_Region_c& addRegion )
{
bool ok = true;
// Iterate new tile's region, splitting and merging left/center/right tiles
// (iteration direction is assumed from new tile's upper to lower region)
TGS_Region_c iterRegion( addRegion );
while( ok && TCTF_IsGE( iterRegion.y2, iterRegion.y1 ))
{
// Split clear tile into left clear, center solid, and right clear tiles
// (Clear tile has at least solid tile due to tile plane's strip property)
TTPT_Tile_c< T >* pleftCenterTile = this->Find( iterRegion.x2, iterRegion.y2 );
const TGS_Region_c& leftCenterRegion = pleftCenterTile->GetRegion( );
if( TCTF_IsLT( leftCenterRegion.x1, iterRegion.x1 ))
{
TGS_Line_c leftIntersect( iterRegion.x1, iterRegion.y1 - this->minGrid_,
iterRegion.x1, iterRegion.y2 + this->minGrid_ );
ok = this->Split( pleftCenterTile, leftIntersect, TGS_DIR_LEFT );
if( !ok )
break;
// And merge left clear tile with upper clear tile, if possible
TGS_Point_c leftPoint( iterRegion.x1 - this->minGrid_, iterRegion.y2 );
TTPT_Tile_c< T >* pleftTile = this->Find( leftPoint );
ok = this->Merge( pleftTile, TC_SIDE_UPPER );
if( !ok )
break;
}
TTPT_Tile_c< T >* prightCenterTile = this->Find( iterRegion.x2, iterRegion.y2 );
const TGS_Region_c& rightCenterRegion = prightCenterTile->GetRegion( );
if( TCTF_IsGT( rightCenterRegion.x2, iterRegion.x2 ))
{
TGS_Line_c rightIntersect( iterRegion.x2, iterRegion.y1 - this->minGrid_,
iterRegion.x2, iterRegion.y2 + this->minGrid_ );
ok = this->Split( prightCenterTile, rightIntersect, TGS_DIR_RIGHT );
if( !ok )
break;
// And merge right clear tile with upper clear tile, if possible
TGS_Point_c rightPoint( iterRegion.x2 + this->minGrid_, iterRegion.y2 );
TTPT_Tile_c< T >* prightTile = this->Find( rightPoint );
ok = this->Merge( prightTile, TC_SIDE_UPPER );
if( !ok )
break;
}
// And merge right clear tile with upper clear tile, if possible
TTPT_Tile_c< T >* pcenterTile = this->Find( iterRegion.x2, iterRegion.y2 );
if( TCTF_IsLT( iterRegion.y2, addRegion.y2 ))
{
ok = this->Merge( pcenterTile, TC_SIDE_UPPER );
if( !ok )
break;
pcenterTile = this->Find( iterRegion.x2, iterRegion.y2 );
}
const TGS_Region_c& centerRegion = pcenterTile->GetRegion( );
iterRegion.y2 = centerRegion.y1 - this->minGrid_;
}
return( ok );
}
//===========================================================================//
// Method : AddPerSolidTileMerges_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerSolidTileMerges_(
const TGS_Region_c& addRegion )
{
bool ok = true;
TGS_Point_c upperLeft( addRegion.x1, addRegion.y2 );
while( ok )
{
const TTPT_Tile_c< T >& solidTile = *this->Find( upperLeft );
TGS_Region_c solidRegion = solidTile.GetRegion( );
// Attempt to merge new solid tile with neighbor solid tiles, if possible
if( ok )
{
TTPT_Tile_c< T >* psolidTile = this->Find( upperLeft );
ok = this->Merge( psolidTile, TC_SIDE_LEFT );
}
if( ok )
{
TTPT_Tile_c< T >* psolidTile = this->Find( upperLeft );
ok = this->Merge( psolidTile, TC_SIDE_RIGHT );
}
if( ok )
{
TTPT_Tile_c< T >* psolidTile = this->Find( upperLeft );
ok = this->Merge( psolidTile, TC_SIDE_LOWER );
}
if( ok )
{
TTPT_Tile_c< T >* psolidTile = this->Find( upperLeft );
ok = this->Merge( psolidTile, TC_SIDE_UPPER );
}
const TTPT_Tile_c< T >& mergedTile = *this->Find( upperLeft );
const TGS_Region_c& mergedRegion = mergedTile.GetRegion( );
if( mergedRegion == solidRegion )
break;
}
return( ok );
}
//===========================================================================//
// Method : AddPerSolidTileCorners_
// Purpose : Re-merges the given solid tiles with vertically aligned,
// but partially mergable neighboring solid tiles in each
// of four possible corners. These merges are required to
// maintain the tile plane's strip property whereby all
// clear tiles are separated by solid tiles only. The
// following examples illustrate corner merges whereby the
// common vertically aligned neighboring solid tiles are
// re-merged:
//
// +----------+ +-----++---+
// | | | || |
// | | | || |
// +----------+ ==> | |+---+
// +-----+ | |
// | | | |
// +-----+ +-----+
//
// +---+ +---+
// | | | |
// +---+ | |
// +--------+ ==> +---+| |
// | | | || |
// | | | || |
// +--------+ +---++---+
//
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerSolidTileCorners_(
const TGS_Region_c& addRegion,
TGS_OrientMode_t addOrient )
{
bool ok = true;
// Build a set of 4 corner points based on given add tile region
TGS_Point_c lowerLeft;
TGS_Point_c lowerRight;
TGS_Point_c upperLeft;
TGS_Point_c upperRight;
if( addOrient == TGS_ORIENT_VERTICAL )
{
lowerLeft.Set( addRegion.x1, addRegion.y1 - this->minGrid_ );
lowerRight.Set( addRegion.x2, addRegion.y1 - this->minGrid_ );
upperLeft.Set( addRegion.x1, addRegion.y2 + this->minGrid_ );
upperRight.Set( addRegion.x2, addRegion.y2 + this->minGrid_ );
}
if( addOrient == TGS_ORIENT_HORIZONTAL )
{
lowerLeft.Set( addRegion.x1 - this->minGrid_, addRegion.y1 );
lowerRight.Set( addRegion.x2 + this->minGrid_, addRegion.y1 );
upperLeft.Set( addRegion.x1 - this->minGrid_, addRegion.y2 );
upperRight.Set( addRegion.x2 + this->minGrid_, addRegion.y2 );
}
// For each of 4 corner points, test for vertically aligned solid tiles
if( ok )
{
ok = this->AddPerSolidTileCorner_( addRegion, lowerLeft, addOrient );
}
if( ok )
{
ok = this->AddPerSolidTileCorner_( addRegion, lowerRight, addOrient );
}
if( ok )
{
ok = this->AddPerSolidTileCorner_( addRegion, upperLeft, addOrient );
}
if( ok )
{
ok = this->AddPerSolidTileCorner_( addRegion, upperRight, addOrient );
}
return( ok );
}
//===========================================================================//
// Method : AddPerSolidTileCorner_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::AddPerSolidTileCorner_(
const TGS_Region_c& addRegion,
const TGS_Point_c& cornerPoint,
TGS_OrientMode_t addOrient )
{
bool ok = true;
TTPT_Tile_c< T >* psolidTile = this->Find( addRegion.x1, addRegion.y2 );
if( psolidTile )
{
if( this->IsSolid( cornerPoint, psolidTile->GetCount( ), psolidTile->GetData( )))
{
TTPT_Tile_c< T >* pcornerTile = this->Find( cornerPoint );
TGS_Region_c solidRegion, cornerRegion;
if( this->CornerRegionCoords_( psolidTile->GetRegion( ),
pcornerTile->GetRegion( ),
&solidRegion, &cornerRegion, addOrient ))
{
ok = this->CornerTileRemerge_( psolidTile, pcornerTile,
solidRegion, cornerRegion, addOrient );
}
}
}
return( ok );
}
//===========================================================================//
// Method : DeletePerExact_
// Purpose : Deletes or removes existing solid tiles from the current
// tile plane based on matching exactly the given region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerExact_(
const TGS_Region_c& deleteRegion )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
TTPT_Tile_c< T >* pdeleteTile = this->Find( deleteRegion.x1, deleteRegion.y1 );
if( pdeleteTile &&
pdeleteTile->IsSolid( ) &&
pdeleteTile->GetRegion( ) == deleteRegion )
{
// Delete solid region (no iteration needed single is only region)
ok = this->Delete( pdeleteTile );
}
else
{
// Iterate over region, deleting a solid region matching given region
TTPT_TilePlaneIter_c< T > thisIter( *this, deleteRegion );
TTPT_Tile_c< T >* psolidTile = 0;
while( ok && thisIter.Next( &psolidTile, TTP_TILE_SOLID ))
{
if( psolidTile->GetRegion( ) != deleteRegion )
continue;
ok = this->Delete( psolidTile );
if( !ok )
break;
thisIter.Init( *this, deleteRegion );
}
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_EXACT_INVALID,
"TTPT_TilePlane_c::DeletePerExact_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerExact_(
const TGS_Region_c& deleteRegion,
const T& deleteData )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
// Iterate over region, deleting a solid region matching given region
TTPT_TilePlaneIter_c< T > thisIter( *this, deleteRegion );
TTPT_Tile_c< T >* psolidTile = 0;
while( ok && thisIter.Next( &psolidTile, TTP_TILE_SOLID ))
{
if( psolidTile->GetRegion( ) != deleteRegion )
continue;
if( !psolidTile->FindData( deleteData ))
continue;
TTPT_Tile_c< T > replaceTile( *psolidTile );
ok = replaceTile.DeleteData( deleteData );
if( !ok )
break;
ok = this->Delete( psolidTile );
if( !ok )
break;
if( replaceTile.IsValid( ) && replaceTile.HasData( ))
{
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( replaceTile, addOrient );
if( !ok )
break;
}
thisIter.Init( *this, deleteRegion );
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_EXACT_INVALID,
"TTPT_TilePlane_c::DeletePerExact_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
// Method : DeletePerWithin_
// Purpose : Deletes or removes existing solid tiles from the current
// tile plane based on membership within the given region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerWithin_(
const TGS_Region_c& deleteRegion )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
// Iterate over region, deleting any solid regions within given region
TTPT_TilePlaneIter_c< T > thisIter( *this, deleteRegion );
TTPT_Tile_c< T >* psolidTile = 0;
while( ok && thisIter.Next( &psolidTile, TTP_TILE_SOLID ))
{
if( !psolidTile->IsWithin( deleteRegion ))
continue;
ok = this->Delete( psolidTile );
if( !ok )
break;
thisIter.Init( *this, deleteRegion );
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_WITHIN_INVALID,
"TTPT_TilePlane_c::DeletePerWithin_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerWithin_(
const TGS_Region_c& deleteRegion,
const T& deleteData )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
// Iterate over region, deleting any solid regions within given region
TTPT_TilePlaneIter_c< T > thisIter( *this, deleteRegion );
TTPT_Tile_c< T >* psolidTile = 0;
while( ok && thisIter.Next( &psolidTile, TTP_TILE_SOLID ))
{
if( !psolidTile->IsWithin( deleteRegion ))
continue;
if( !psolidTile->FindData( deleteData ))
continue;
TTPT_Tile_c< T > replaceTile( *psolidTile );
ok = replaceTile.DeleteData( deleteData );
if( !ok )
break;
ok = this->Delete( psolidTile );
if( !ok )
break;
if( replaceTile.IsValid( ) && replaceTile.HasData( ))
{
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( replaceTile, addOrient );
if( !ok )
break;
}
thisIter.Init( *this, deleteRegion );
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_WITHIN_INVALID,
"TTPT_TilePlane_c::DeletePerWithin_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
// Method : DeletePerIntersect_
// Purpose : Deletes or removes existing solid tiles from the current
// tile plane based on membership intersecting with given
// region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerIntersect_(
const TGS_Region_c& deleteRegion )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
// Iterate over region, deleting any solid regions intersecting region
TTPT_Tile_c< T >* psolidTile = 0;
while( this->IsSolid( TTP_IS_SOLID_ANY, deleteRegion, &psolidTile ))
{
TTPT_Tile_c< T > solidTile( *psolidTile );
const TGS_Region_c& solidRegion = solidTile.GetRegion( );
unsigned int solidCount = solidTile.GetCount( );
const T* psolidData = solidTile.GetData( );
if( solidRegion.IsWithin( deleteRegion ))
{
if( solidRegion == deleteRegion )
{
this->Delete( psolidTile );
}
else if( TCTF_IsGT( deleteRegion.x1, solidRegion.x1 ))
{
TGS_Line_c leftEdge( deleteRegion.x1 - this->minGrid_, solidRegion.y1,
deleteRegion.x1 - this->minGrid_, solidRegion.y2 );
this->Split( psolidTile, leftEdge, TGS_DIR_RIGHT );
ok = this->DeletePerIntersect_( deleteRegion );
}
else if( TCTF_IsLT( deleteRegion.x2, solidRegion.x2 ))
{
TGS_Line_c rightEdge( deleteRegion.x2 + this->minGrid_, solidRegion.y1,
deleteRegion.x2 + this->minGrid_, solidRegion.y2 );
this->Split( psolidTile, rightEdge, TGS_DIR_LEFT );
ok = this->DeletePerIntersect_( deleteRegion );
}
else if( TCTF_IsGT( deleteRegion.y1, solidRegion.y1 ))
{
TGS_Line_c lowerEdge( solidRegion.x1, deleteRegion.y1 - this->minGrid_,
solidRegion.x2, deleteRegion.y1 - this->minGrid_ );
this->Split( psolidTile, lowerEdge, TGS_DIR_UP );
ok = this->DeletePerIntersect_( deleteRegion );
}
else if( TCTF_IsLT( deleteRegion.y2, solidRegion.y2 ))
{
TGS_Line_c upperEdge( solidRegion.x1, deleteRegion.y2 + this->minGrid_,
solidRegion.x2, deleteRegion.y2 + this->minGrid_ );
this->Split( psolidTile, upperEdge, TGS_DIR_DOWN );
ok = this->DeletePerIntersect_( deleteRegion );
}
}
else
{
ok = this->Delete( psolidTile );
if( !ok )
break;
TGS_RegionList_t subRegionList( 4 );
solidRegion.FindDifference( deleteRegion, TGS_ORIENT_VERTICAL,
&subRegionList, this->minGrid_ );
for( size_t i = 0; i < subRegionList.GetLength( ); ++i )
{
TTPT_Tile_c< T > subTile( TTP_TILE_SOLID, *subRegionList[i],
solidCount, psolidData );
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( subTile, addOrient );
if( !ok )
break;
}
if( !ok )
break;
}
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_INTERSECT_INVALID,
"TTPT_TilePlane_c::DeletePerIntersect_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerIntersect_(
const TGS_Region_c& deleteRegion,
const T& deleteData )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
// Iterate over region, deleting any solid regions intersecting region
TTPT_Tile_c< T >* psolidTile = 0;
while( this->IsSolid( TTP_IS_SOLID_ANY, deleteRegion, deleteData, &psolidTile ))
{
TTPT_Tile_c< T > solidTile( *psolidTile );
const TGS_Region_c& solidRegion = solidTile.GetRegion( );
unsigned int solidCount = solidTile.GetCount( );
const T* psolidData = solidTile.GetData( );
if( !psolidTile->FindData( deleteData ))
continue;
TTPT_Tile_c< T > replaceTile( *psolidTile );
ok = replaceTile.DeleteData( deleteData );
if( !ok )
break;
ok = this->Delete( psolidTile );
if( !ok )
break;
TGS_RegionList_t subRegionList( 4 );
solidRegion.FindDifference( deleteRegion, TGS_ORIENT_VERTICAL,
&subRegionList, this->minGrid_ );
for( size_t i = 0; i < subRegionList.GetLength( ); ++i )
{
TTPT_Tile_c< T > subTile( TTP_TILE_SOLID, *subRegionList[i],
solidCount, psolidData );
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( subTile, addOrient );
if( !ok )
break;
}
if( !ok )
break;
if( replaceTile.IsValid( ) && replaceTile.HasData( ))
{
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( replaceTile, addOrient );
if( !ok )
break;
}
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_INTERSECT_INVALID,
"TTPT_TilePlane_c::DeletePerIntersect_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
// Method : DeletePerIntersectMin_
// Purpose : Deletes or removes existing solid tiles from the current
// tile plane based on membership intersecting with given
// region. In addition, this method reduces the given
// region by the current min grid before deleting.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerIntersectMin_(
const TGS_Region_c& deleteRegion )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
TGS_Region_c deleteMinRegion( deleteRegion, -1.0 * this->minGrid_ );
// Iterate over region, deleting any solid regions intersecting region
TTPT_Tile_c< T >* psolidTile = 0;
while( this->IsSolid( TTP_IS_SOLID_ANY, deleteMinRegion, &psolidTile ))
{
TTPT_Tile_c< T > solidTile( *psolidTile );
const TGS_Region_c& solidRegion = solidTile.GetRegion( );
unsigned int solidCount = solidTile.GetCount( );
const T* psolidData = solidTile.GetData( );
ok = this->Delete( psolidTile );
if( !ok )
break;
TGS_RegionList_t subRegionList( 4 );
solidRegion.FindDifference( deleteMinRegion, TGS_ORIENT_VERTICAL,
&subRegionList, this->minGrid_, this->minGrid_ );
for( size_t i = 0; i < subRegionList.GetLength( ); ++i )
{
TTPT_Tile_c< T > subTile( TTP_TILE_SOLID, *subRegionList[i],
solidCount, psolidData );
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( subTile, addOrient );
if( !ok )
break;
}
if( !ok )
break;
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_INTERSECT_INVALID,
"TTPT_TilePlane_c::DeletePerIntersectMin_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerIntersectMin_(
const TGS_Region_c& deleteRegion,
const T& deleteData )
{
bool ok = true;
if( this->IsWithin( deleteRegion ))
{
TGS_Region_c deleteMinRegion( deleteRegion, -1.0 * this->minGrid_ );
// Iterate over region, deleting any solid regions intersecting region
TTPT_Tile_c< T >* psolidTile = 0;
while( this->IsSolid( TTP_IS_SOLID_ANY, deleteMinRegion, deleteData, &psolidTile ))
{
TTPT_Tile_c< T > solidTile( *psolidTile );
const TGS_Region_c& solidRegion = solidTile.GetRegion( );
unsigned int solidCount = solidTile.GetCount( );
const T* psolidData = solidTile.GetData( );
if( !psolidTile->FindData( deleteData ))
continue;
TTPT_Tile_c< T > replaceTile( *psolidTile );
ok = replaceTile.DeleteData( deleteData );
if( !ok )
break;
ok = this->Delete( psolidTile );
if( !ok )
break;
TGS_RegionList_t subRegionList( 4 );
solidRegion.FindDifference( deleteMinRegion, TGS_ORIENT_VERTICAL,
&subRegionList, this->minGrid_, this->minGrid_ );
for( size_t i = 0; i < subRegionList.GetLength( ); ++i )
{
TTPT_Tile_c< T > subTile( TTP_TILE_SOLID, *subRegionList[i],
solidCount, psolidData );
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( subTile, addOrient );
if( !ok )
break;
}
if( !ok )
break;
if( replaceTile.IsValid( ) && replaceTile.HasData( ))
{
TGS_OrientMode_t addOrient = TGS_ORIENT_UNDEFINED;
ok = this->AddPerNew_( replaceTile, addOrient );
if( !ok )
break;
}
}
}
else if( !this->IsWithin( deleteRegion ))
{
// Report message: delete tile region not within tile plane's region
const TGS_Region_c& tilePlaneRegion = this->GetRegion( );
ok = this->ShowInternalMessage_( TTP_MESSAGE_DELETE_PER_INTERSECT_INVALID,
"TTPT_TilePlane_c::DeletePerIntersectMin_",
&deleteRegion, &tilePlaneRegion );
}
return( ok );
}
//===========================================================================//
// Method : DeletePerRightSide_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerRightSide_(
const TTPT_Tile_c< T >& deleteTile )
{
bool ok = true;
// Iterate along right side of a "dead" delete tile from upper to lower...
// splitting and merging neighbor clear tiles, where possible
TTPT_TilePlaneIter_c< T > rightTileIter( *this, deleteTile, TC_SIDE_RIGHT );
TTPT_Tile_c< T >* prightTile = 0;
while( ok && rightTileIter.Next( &prightTile ))
{
TGS_Region_c rightRegion = prightTile->GetRegion( );
const TGS_Region_c& deleteRegion = deleteTile.GetRegion( );
TGS_Point_c clearPoint( deleteRegion.x1,
TCT_Max( deleteRegion.y1, rightRegion.y1 ));
if( prightTile->IsClear( ))
{
// Split "dead" left tile per adjacent neighbor clear right tile
ok = this->Split( prightTile, TC_SIDE_LEFT );
if( !ok )
break;
// Merge "dead" left tile (possibly split tile) with neighbor tile
ok = this->Merge( prightTile, TC_SIDE_LEFT );
if( !ok )
break;
// Test and continue merge IFF merged "dead" tile with right tile
TTPT_Tile_c< T >* pclearTile = this->Find( clearPoint );
const TGS_Region_c& clearRegion = pclearTile->GetRegion( );
if( TCTF_IsNEQ( clearRegion.x2, deleteRegion.x2 ))
{
// And merge neighbor lower tile with merged tile, if possible
pclearTile = this->Find( clearPoint );
ok = this->Merge( pclearTile, TC_SIDE_LOWER );
if( !ok )
break;
// And merge neighbor upper tile with merged tile too, if possible
pclearTile = this->Find( clearPoint );
ok = this->Merge( pclearTile, TC_SIDE_UPPER );
if( !ok )
break;
}
}
}
// Iterate along right side of a "dead" delete tile again...
// deleting (ie. splitting and merging per neighbor's left side clear tiles
TGS_Region_c deleteRegion = deleteTile.GetRegion( );
while( ok && TCTF_IsLE( deleteRegion.y1, deleteRegion.y2 ))
{
prightTile = this->Find( deleteRegion.x2 + this->minGrid_,
deleteRegion.y1 );
if( !prightTile )
break;
TGS_Region_c rightRegion = prightTile->GetRegion( );
if( prightTile->IsClear( ) &&
TCTF_IsGT( rightRegion.x1, deleteRegion.x2 ))
{
// Split and merge neighbor right tile with "dead" tile too
ok = this->DeletePerLeftSide_( *prightTile );
if( !ok )
break;
}
deleteRegion.y1 = rightRegion.y2 + this->minGrid_;
}
return( ok );
}
//===========================================================================//
// Method : DeletePerLeftSide_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerLeftSide_(
const TTPT_Tile_c< T >& deleteTile )
{
bool ok = true;
// Iterate along left side of "dead" delete tile from lower to upper...
// splitting and merging neighbor clear tiles, where possible
TGS_Region_c iterRegion( deleteTile.GetRegion( ));
while( ok && TCTF_IsLE( iterRegion.y1, iterRegion.y2 ))
{
TGS_Point_c leftPoint( iterRegion.x1 - this->minGrid_, iterRegion.y1 );
TTPT_Tile_c< T >* pleftTile = this->Find( leftPoint );
if( !pleftTile )
break;
TGS_Region_c leftRegion = pleftTile->GetRegion( );
iterRegion.y1 = leftRegion.y2 + this->minGrid_;
if( !pleftTile->IsClear( ))
continue;
// Split "dead" right tiles and/or neighbor clear left tile based ...
// on adjacent neighbor clear left tile
const TGS_Region_c& deleteRegion = deleteTile.GetRegion( );
TGS_Point_c rightPoint( deleteRegion.x1,
TCT_Max( deleteRegion.y1, leftRegion.y1 ));
// Find "dead" right tile w.r.t. current neighbor left tile's region
TTPT_Tile_c< T >* prightTile = this->Find( rightPoint );
TGS_Region_c rightRegion = prightTile->GetRegion( );
while( ok && TCTF_IsGE( leftRegion.y2, rightRegion.y2 ))
{
// Split neighbor left tile based on "dead" right tile
ok = this->Split( prightTile, TC_SIDE_LEFT );
if( !ok )
break;
// Merge neighbor left tile with "dead" right tile, if possible
ok = this->Merge( prightTile, TC_SIDE_LEFT );
if( !ok )
break;
// Test and continue merge IFF merged "dead" tile with left tile
TTPT_Tile_c< T >* pclearTile = this->Find( rightPoint );
const TGS_Region_c& clearRegion = pclearTile->GetRegion( );
if( TCTF_IsNEQ( clearRegion.x1, iterRegion.x1 ))
{
// And merge neighbor lower tile with merged tile, if possible
pclearTile = this->Find( rightPoint );
ok = this->Merge( pclearTile, TC_SIDE_LOWER );
if( !ok )
break;
// And merge neighbor upper tile with merged tile too, if possible
pclearTile = this->Find( rightPoint );
ok = this->Merge( pclearTile, TC_SIDE_UPPER );
if( !ok )
break;
}
// Continue split and merge on right tiles based on current left tile
rightPoint.y = rightRegion.y2 + this->minGrid_;
prightTile = this->Find( rightPoint );
if( !prightTile )
break;
rightRegion = prightTile->GetRegion( );
}
if( !ok )
break;
// Split "dead" right tile based on adjacent neighbor clear left tile
TGS_Region_c leftSubRegion( leftRegion );
while( ok && TCTF_IsLE( leftSubRegion.y1, leftSubRegion.y2 ))
{
pleftTile = this->Find( leftSubRegion.x2, leftSubRegion.y1 );
ok = this->Split( pleftTile, TC_SIDE_RIGHT );
if( !ok )
break;
// Merge "dead" right tile with neighbor left tile, if possible
ok = this->Merge( pleftTile, TC_SIDE_RIGHT );
if( !ok )
break;
// And merge "dead" lower tile with merged tile, if possible
pleftTile = this->Find( leftSubRegion.x2, leftSubRegion.y1 );
ok = this->Merge( pleftTile, TC_SIDE_LOWER );
if( !ok )
break;
// And merge neighbor upper tile with merged tile, if possible
pleftTile = this->Find( leftSubRegion.x2, leftSubRegion.y1 );
ok = this->Merge( pleftTile, TC_SIDE_UPPER );
if( !ok )
break;
pleftTile = this->Find( leftSubRegion.x2, leftSubRegion.y1 );
leftRegion = pleftTile->GetRegion( );
leftSubRegion.y1 = leftRegion.y2 + this->minGrid_;
}
if( !ok )
break;
}
return( ok );
}
//===========================================================================//
// Method : DeletePerLowerSide_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerLowerSide_(
const TTPT_Tile_c< T >& deleteTile )
{
bool ok = true;
// Try to merge lower side of "dead" delete tile with neighboring tile
const TGS_Region_c& deleteRegion = deleteTile.GetRegion( );
TGS_Point_c clearPoint( deleteRegion.x1, deleteRegion.y1 );
TTPT_Tile_c< T >* pclearTile = this->Find( clearPoint );
ok = this->Merge( pclearTile, TC_SIDE_LOWER );
return( ok );
}
//===========================================================================//
// Method : DeletePerUpperSide_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::DeletePerUpperSide_(
const TTPT_Tile_c< T >& deleteTile )
{
bool ok = true;
// Try to merge upper side of "dead" delete tile with neighboring tile
const TGS_Region_c& deleteRegion = deleteTile.GetRegion( );
TGS_Point_c clearPoint( deleteRegion.x1, deleteRegion.y1 );
TTPT_Tile_c< T >* pclearTile = this->Find( clearPoint );
ok = this->Merge( pclearTile, TC_SIDE_UPPER );
return( ok );
}
//===========================================================================//
// Method : FindPerPoint_
// Purpose : Find and return a pointer to a tile based on the given
// point (x,y) location. The returned tile pointer may
// identify be either a "clear" or a "solid" tile. A null
// pointer is returned if the given point is not valid (ie.
// is not within the current tile plane's area).
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindPerPoint_(
const TGS_Point_c& point,
TTPT_Tile_c< T >* ptile ) const
{
TTPT_Tile_c< T >* ptile_ = ptile;
// Search from "most-recent" tile, if possible, else from "lower-left" tile
TTPT_Tile_c< T >* ptileMR = 0;
if( this->ptileMRC_ && this->ptileMRS_ )
{
const TGS_Region_c& regionMRC = this->ptileMRC_->GetRegion( );
const TGS_Region_c& regionMRS = this->ptileMRS_->GetRegion( );
double distMRC = TCT_Min( regionMRC.FindDistance( point, TGS_CORNER_LL ),
regionMRC.FindDistance( point, TGS_CORNER_UR ));
double distMRS = TCT_Min( regionMRS.FindDistance( point, TGS_CORNER_LL ),
regionMRS.FindDistance( point, TGS_CORNER_UR ));
ptileMR = ( TCTF_IsLT( distMRC, distMRS ) ? this->ptileMRC_ : this->ptileMRS_ );
}
else if( this->ptileMRC_ )
{
ptileMR = this->ptileMRC_;
}
else if( this->ptileMRS_ )
{
ptileMR = this->ptileMRS_;
}
if( ptile && ptileMR )
{
const TGS_Region_c& region = ptile->GetRegion( );
const TGS_Region_c& regionMR = ptileMR->GetRegion( );
double dist = TCT_Min( region.FindDistance( point, TGS_CORNER_LL ),
region.FindDistance( point, TGS_CORNER_UR ));
double distMR = TCT_Min( regionMR.FindDistance( point, TGS_CORNER_LL ),
regionMR.FindDistance( point, TGS_CORNER_UR ));
ptile = ( TCTF_IsLT( dist, distMR ) ? ptile : ptileMR );
}
if( !ptile )
{
ptile = ( ptileMR ? ptileMR : this->ptileLL_ );
}
// Validate point is located somewhere within this tile plane
if( ptile && !this->IsWithin( point ))
{
ptile = 0;
}
if( ptile && !ptile->IsWithin( point ))
{
TTPT_Tile_c< T >* ptileLowerLeft = ( ptile ? ptile->GetStitchLowerLeft( ) : 0 );
TTPT_Tile_c< T >* ptileUpperRight = ( ptile ? ptile->GetStitchUpperRight( ) : 0 );
TTPT_Tile_c< T >* ptileLeftLower = ( ptile ? ptile->GetStitchLeftLower( ) : 0 );
TTPT_Tile_c< T >* ptileRightUpper = ( ptile ? ptile->GetStitchRightUpper( ) : 0 );
if( ptileLowerLeft && ptileLowerLeft->IsWithin( point ))
{
ptile = ptileLowerLeft;
}
else if( ptileUpperRight && ptileUpperRight->IsWithin( point ))
{
ptile = ptileUpperRight;
}
else if( ptileLeftLower && ptileLeftLower->IsWithin( point ))
{
ptile = ptileLeftLower;
}
else if( ptileRightUpper && ptileRightUpper->IsWithin( point ))
{
ptile = ptileRightUpper;
}
else if( ptile &&
( ptileLowerLeft || ptileRightUpper ) &&
( ptile->IsGreaterThan( point, TGS_ORIENT_HORIZONTAL ) ||
ptile->IsLessThan( point, TGS_ORIENT_VERTICAL )))
{
double distLowerLeft = ( ptileLowerLeft ? ptileLowerLeft->FindDistance( point ) : TC_FLT_MAX );
double distRightUpper = ( ptileRightUpper ? ptileRightUpper->FindDistance( point ) : TC_FLT_MAX );
ptile = ( TCTF_IsLE( distLowerLeft, distRightUpper ) ? ptileLowerLeft : ptileRightUpper );
}
else if( ptile &&
( ptileUpperRight || ptileLeftLower ) &&
( ptile->IsLessThan( point, TGS_ORIENT_HORIZONTAL ) ||
ptile->IsGreaterThan( point, TGS_ORIENT_VERTICAL )))
{
double distUpperRight = ( ptileUpperRight ? ptileUpperRight->FindDistance( point ) : TC_FLT_MAX );
double distLeftLower = ( ptileLeftLower ? ptileLeftLower->FindDistance( point ) : TC_FLT_MAX );
ptile = ( TCTF_IsLE( distUpperRight, distLeftLower ) ? ptileUpperRight : ptileLeftLower );
}
}
// Iterate until tile found that contains the given point
while( ptile && !ptile->IsWithin( point ))
{
// Iterate up/down until tile found whose vertical range has given point
size_t iterVerticalCt = 0;
while( ptile && !ptile->IsWithin( point, TGS_ORIENT_VERTICAL ))
{
if( ptile->IsLessThan( point, TGS_ORIENT_VERTICAL ))
{
// Iterate upward by following right-upper stitch
ptile = ptile->GetStitchRightUpper( );
}
else if( ptile->IsGreaterThan( point, TGS_ORIENT_VERTICAL ))
{
// Iterate downwards by following left-lower stitch
ptile = ptile->GetStitchLeftLower( );
}
// Stop vertical search effort after 'n' iterations
// (ie. go on to attempt search horizontally for 'n' iterations)
if( ++iterVerticalCt > 10 )
break;
}
// Test and update tile if up/down may be closer to given point
if( ptile && !ptile_ &&
ptile->IsGreaterThan( point, TGS_ORIENT_HORIZONTAL ) &&
ptile->GetStitchRightUpper( ))
{
TTPT_Tile_c< T >* ptileUpper = ptile->GetStitchRightUpper( );
const TGS_Region_c& regionUpper = ptileUpper->GetRegion( );
const TGS_Region_c& region = ptile->GetRegion( );
if( TCTF_IsLT( fabs( regionUpper.x1 - point.x ), fabs( region.x1 - point.x )))
{
ptile = ptile_ = ptileUpper;
}
}
else if( ptile && !ptile_ &&
ptile->IsLessThan( point, TGS_ORIENT_HORIZONTAL ) &&
ptile->GetStitchLeftLower( ))
{
TTPT_Tile_c< T >* ptileLower = ptile->GetStitchLeftLower( );
const TGS_Region_c& regionLower = ptileLower->GetRegion( );
const TGS_Region_c& region = ptile->GetRegion( );
if( TCTF_IsLT( fabs( regionLower.x2 - point.x ), fabs( region.x2 - point.x )))
{
ptile = ptile_ = ptileLower;
}
}
// Iterate left/right until tile found whose horizontal range has given point
size_t iterHorizontalCt = 0;
while( ptile && !ptile->IsWithin( point, TGS_ORIENT_HORIZONTAL ))
{
if( ptile->IsLessThan( point, TGS_ORIENT_HORIZONTAL ))
{
// Iterate to the right by following upper-right stitch
ptile = ptile->GetStitchUpperRight( );
}
else if( ptile->IsGreaterThan( point, TGS_ORIENT_HORIZONTAL ))
{
// Iterate to the left by following lower-left stitch
ptile = ptile->GetStitchLowerLeft( );
}
// Stop horizontal search effort after 'n' iterations
// (ie. go on to attempt search vertically for 'n' iterations)
if( ++iterHorizontalCt > 10 )
break;
}
}
// Update "most-recent" tile pointer based on search result
if( ptile )
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
if( ptile->IsClear( ))
{
if( !ptilePlane->ptileMRC_ )
{
ptilePlane->ptileMRC_ = const_cast< TTPT_Tile_c< T >* >( ptile );
}
else
{
const TGS_Region_c& tileRegionMRC = ptilePlane->ptileMRC_->GetRegion( );
const TGS_Region_c& tileRegion = ptile->GetRegion( );
if( !tileRegion.IsAdjacent( tileRegionMRC, this->minGrid_ ) ||
TCTF_IsNEQ( tileRegion.x1, this->region_.x1 ) ||
TCTF_IsNEQ( tileRegion.x2, this->region_.x2 ))
{
ptilePlane->ptileMRC_ = const_cast< TTPT_Tile_c< T >* >( ptile );
}
}
}
else if( ptile->IsSolid( ))
{
ptilePlane->ptileMRS_ = const_cast< TTPT_Tile_c< T >* >( ptile );
}
}
return( ptile );
}
//===========================================================================//
// Method : FindPerExact_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindPerExact_(
const TGS_Region_c& region,
TTP_TileMode_t tileMode ) const
{
TTPT_Tile_c< T >* ptile = 0;
if( this->IsWithin( region ))
{
TGS_Point_c point( region.x1, region.y1 );
ptile = this->FindPerPoint_( point );
ptile = ( ptile && ptile->GetMode( ) & tileMode ? ptile : 0 );
ptile = ( ptile && ptile->GetRegion( ) == region ? ptile : 0 );
}
return( ptile );
}
//===========================================================================//
// Method : FindPerWithin_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindPerWithin_(
const TGS_Region_c& region,
TTP_TileMode_t tileMode ) const
{
TTPT_Tile_c< T >* ptile = 0;
if( this->IsWithin( region ))
{
TGS_Point_c point( region.x1, region.y1 );
ptile = this->FindPerPoint_( point );
ptile = ( ptile && ptile->GetMode( ) & tileMode ? ptile : 0 );
ptile = ( ptile && ptile->IsWithin( region ) ? ptile : 0 );
}
return( ptile );
}
//===========================================================================//
// Method : FindPerIntersect_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindPerIntersect_(
const TGS_Region_c& region,
TTP_TileMode_t tileMode ) const
{
TTPT_Tile_c< T >* ptile = 0;
if( this->IsWithin( region ))
{
bool findOK = true;
if( !ptile && findOK )
{
TGS_Point_c point( region.x1, region.y1 );
TTPT_Tile_c< T >* ptileLL = this->FindPerPoint_( point );
if( ptileLL && ( ptileLL->GetMode( ) & tileMode ) &&
ptileLL->IsIntersecting( region ))
{
ptile = ptileLL;
}
else if( ptileLL && !( ptileLL->GetMode( ) & tileMode ) &&
ptileLL->IsWithin( region ))
{
findOK = false;
}
}
if( !ptile && findOK )
{
TGS_Point_c point( region.x2, region.y2 );
TTPT_Tile_c< T >* ptileUR = this->FindPerPoint_( point );
if( ptileUR && ( ptileUR->GetMode( ) & tileMode ) &&
ptileUR->IsIntersecting( region ))
{
ptile = ptileUR;
}
else if( ptileUR && !( ptileUR->GetMode( ) & tileMode ) &&
ptileUR->IsWithin( region ))
{
findOK = false;
}
}
if( !ptile && findOK )
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
while( ptilePlane->tilePlaneIter_.Next( &ptile, tileMode ))
{
if( ptile->IsIntersecting( region ))
break;
}
}
}
return( ptile );
}
//===========================================================================//
// Method : FindNearestBySides_
// Purpose : Find and return a pointer to the nearest "solid" tile
// found neighboring the given region, if any, based on the
// given reference region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearestBySides_(
const TGS_Region_c& refRegion,
const TTPT_Tile_c< T >& searchTile,
const TGS_OrientMode_t* porientMode ) const
{
TTPT_Tile_c< T >* pnearestTile = 0;
double nearestDistance = TC_FLT_MAX;
// Iterate sides, searching for nearest "solid" tile w.r.t given region
if( TCTF_IsGT( nearestDistance, 0.0 ))
{
TTPT_Tile_c< T >* pleftTile = this->FindNearestBySide_( refRegion,
searchTile,
TC_SIDE_LEFT );
if( pleftTile )
{
double leftDistance = pleftTile->FindDistance( refRegion );
if(( porientMode ) &&
( *porientMode != TGS_ORIENT_UNDEFINED ) &&
( *porientMode != pleftTile->FindOrient( )))
{
leftDistance = TC_FLT_MAX;
}
if( TCTF_IsGT( nearestDistance, leftDistance ))
{
nearestDistance = leftDistance;
pnearestTile = pleftTile;
}
}
}
if( TCTF_IsGT( nearestDistance, 0.0 ))
{
TTPT_Tile_c< T >* prightTile = this->FindNearestBySide_( refRegion,
searchTile,
TC_SIDE_RIGHT );
if( prightTile )
{
double rightDistance = prightTile->FindDistance( refRegion );
if(( porientMode ) &&
( *porientMode != TGS_ORIENT_UNDEFINED ) &&
( *porientMode != prightTile->FindOrient( )))
{
rightDistance = TC_FLT_MAX;
}
if( TCTF_IsGT( nearestDistance, rightDistance ))
{
nearestDistance = rightDistance;
pnearestTile = prightTile;
}
}
}
if( TCTF_IsGT( nearestDistance, 0.0 ))
{
TTPT_Tile_c< T >* plowerTile = this->FindNearestBySide_( refRegion,
searchTile,
TC_SIDE_LOWER );
if( plowerTile )
{
double lowerDistance = plowerTile->FindDistance( refRegion );
if(( porientMode ) &&
( *porientMode != TGS_ORIENT_UNDEFINED ) &&
( *porientMode != plowerTile->FindOrient( )))
{
lowerDistance = TC_FLT_MAX;
}
if( TCTF_IsGT( nearestDistance, lowerDistance ))
{
nearestDistance = lowerDistance;
pnearestTile = plowerTile;
}
}
}
if( TCTF_IsGT( nearestDistance, 0.0 ))
{
TTPT_Tile_c< T >* pupperTile = this->FindNearestBySide_( refRegion,
searchTile,
TC_SIDE_UPPER );
if( pupperTile )
{
double upperDistance = pupperTile->FindDistance( refRegion );
if(( porientMode ) &&
( *porientMode != TGS_ORIENT_UNDEFINED ) &&
( *porientMode != pupperTile->FindOrient( )))
{
upperDistance = TC_FLT_MAX;
}
if( TCTF_IsGT( nearestDistance, upperDistance ))
{
nearestDistance = upperDistance;
pnearestTile = pupperTile;
}
}
}
return( pnearestTile );
}
//===========================================================================//
// Method : FindNearestBySide_
// Purpose : Find and return a pointer to the nearest "solid" tile
// found neighboring the given region side, if any, based on
// the given reference region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearestBySide_(
const TGS_Region_c& refRegion,
const TTPT_Tile_c< T >& searchTile,
TC_SideMode_t searchSide ) const
{
TTPT_Tile_c< T >* pnearestTile = 0;
double nearestDistance = TC_FLT_MAX;
// Iterate side, searching for nearest "solid" tile w.r.t given region
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, searchTile, searchSide );
TTPT_Tile_c< T >* psolidTile = 0;
while( ptilePlane->tilePlaneIter_.Next( &psolidTile, TTP_TILE_SOLID ))
{
double solidDistance = psolidTile->FindDistance( refRegion );
if( TCTF_IsGT( nearestDistance, solidDistance ))
{
nearestDistance = solidDistance;
pnearestTile = psolidTile;
}
}
return( pnearestTile );
}
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearestBySide_(
const TGS_Region_c& refRegion,
TC_SideMode_t searchSide,
double searchDistance ) const
{
TTPT_Tile_c< T >* pnearestTile = 0;
double nearestDistance = TC_FLT_MAX;
if( searchSide == TC_SIDE_LEFT )
{
TGS_Point_c leftPoint( refRegion.x1 - this->minGrid_, refRegion.y1 );
while( TCTF_IsLE( leftPoint.y, refRegion.y2 ))
{
TTPT_Tile_c< T >* pleftTile = this->Find( leftPoint );
if( !pleftTile )
break;
if( TCTF_IsGT( refRegion.x1 - pleftTile->GetRegion( ).x2, searchDistance ))
break;
leftPoint.y = pleftTile->GetRegion( ).y2 + this->minGrid_;
TTPT_Tile_c< T >* psolidTile = 0;
if( pleftTile->IsSolid( ))
{
psolidTile = pleftTile;
}
else if( pleftTile->IsClear( ) &&
pleftTile->GetStitchLowerLeft( ))
{
psolidTile = pleftTile->GetStitchLowerLeft( );
}
if( psolidTile )
{
double solidDistance = psolidTile->FindDistance( refRegion );
if( TCTF_IsGT( nearestDistance, solidDistance ))
{
nearestDistance = solidDistance;
pnearestTile = psolidTile;
}
}
}
}
if( searchSide == TC_SIDE_RIGHT )
{
TGS_Point_c rightPoint( refRegion.x2 + this->minGrid_, refRegion.y2 );
while( TCTF_IsGE( rightPoint.y, refRegion.y1 ))
{
TTPT_Tile_c< T >* prightTile = this->Find( rightPoint );
if( !prightTile )
break;
if( TCTF_IsGT( prightTile->GetRegion( ).x1 - refRegion.x2, searchDistance ))
break;
rightPoint.y = prightTile->GetRegion( ).y1 - this->minGrid_;
TTPT_Tile_c< T >* psolidTile = 0;
if( prightTile->IsSolid( ))
{
psolidTile = prightTile;
}
else if( prightTile->IsClear( ) &&
prightTile->GetStitchUpperRight( ))
{
psolidTile = prightTile->GetStitchUpperRight( );
}
if( psolidTile )
{
double solidDistance = psolidTile->FindDistance( refRegion );
if( TCTF_IsGT( nearestDistance, solidDistance ))
{
nearestDistance = solidDistance;
pnearestTile = psolidTile;
}
}
}
}
if( searchSide == TC_SIDE_LOWER )
{
TTPT_Tile_c< T >* psolidTile = 0;
TGS_Point_c lowerPoint( refRegion.x1, refRegion.y1 - this->minGrid_ );
while( TCTF_IsLE( lowerPoint.x, refRegion.x2 ))
{
TTPT_Tile_c< T >* plowerTile = this->Find( lowerPoint );
if( !plowerTile )
break;
if( TCTF_IsGT( refRegion.y1 - plowerTile->GetRegion( ).y2, searchDistance ))
break;
lowerPoint.x = plowerTile->GetRegion( ).x2 + this->minGrid_;
if( plowerTile->IsSolid( ))
{
psolidTile = plowerTile;
break;
}
else if( plowerTile->GetRegion( ).IsWithinDx( refRegion ) &&
plowerTile->GetStitchLeftLower( ))
{
lowerPoint.x = refRegion.x1;
lowerPoint.y = plowerTile->GetRegion( ).y1 - this->minGrid_;
}
else if( plowerTile->GetRegion( ).IsWithinDx( refRegion ) &&
!plowerTile->GetStitchLeftLower( ))
{
break;
}
}
if( psolidTile )
{
pnearestTile = psolidTile;
}
}
if( searchSide == TC_SIDE_UPPER )
{
TTPT_Tile_c< T >* psolidTile = 0;
TGS_Point_c upperPoint( refRegion.x2, refRegion.y2 + this->minGrid_ );
while( TCTF_IsGE( upperPoint.x, refRegion.x1 ))
{
TTPT_Tile_c< T >* pupperTile = this->Find( upperPoint );
if( !pupperTile )
break;
if( TCTF_IsGT( pupperTile->GetRegion( ).y1 - refRegion.y2, searchDistance ))
break;
upperPoint.x = pupperTile->GetRegion( ).x1 - this->minGrid_;
if( pupperTile->IsSolid( ))
{
psolidTile = pupperTile;
break;
}
else if( pupperTile->GetRegion( ).IsWithinDx( refRegion ) &&
pupperTile->GetStitchRightUpper( ))
{
upperPoint.x = refRegion.x2;
upperPoint.y = pupperTile->GetRegion( ).y2 + this->minGrid_;
}
else if( pupperTile->GetRegion( ).IsWithinDx( refRegion ) &&
!pupperTile->GetStitchRightUpper( ))
{
break;
}
}
if( psolidTile )
{
pnearestTile = psolidTile;
}
}
return( pnearestTile );
}
//===========================================================================//
// Method : FindNearestByRegion_
// Purpose : Find and return a pointer to the nearest "solid" tile
// found within the given region, if any, based on the given
// reference region.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearestByRegion_(
const TGS_Region_c& refRegion,
const TGS_Region_c& searchRegion,
const TGS_OrientMode_t* porientMode ) const
{
TTPT_Tile_c< T >* pnearestTile = 0;
double nearestDistance = TC_FLT_MAX;
// Iterate region, searching for nearest "solid" tile w.r.t given region
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, searchRegion );
TTPT_Tile_c< T >* psolidTile = 0;
while( ptilePlane->tilePlaneIter_.Next( &psolidTile, TTP_TILE_SOLID ))
{
double solidDistance = psolidTile->FindDistance( refRegion );
if(( porientMode ) &&
( *porientMode != TGS_ORIENT_UNDEFINED ) &&
( *porientMode != psolidTile->FindOrient( )))
{
solidDistance = TC_FLT_MAX;
}
const TGS_Region_c& solidRegion = psolidTile->GetRegion( );
if( !searchRegion.IsOverlapping( solidRegion ))
{
solidDistance = TC_FLT_MAX;
}
if( TCTF_IsGT( nearestDistance, solidDistance ))
{
nearestDistance = solidDistance;
pnearestTile = psolidTile;
if( TCTF_IsEQ( nearestDistance, 0.0 ))
break;
}
}
return( pnearestTile );
}
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::FindNearestByRegion_(
const TGS_Region_c& refRegion,
double searchDistance,
const TGS_OrientMode_t* porientMode ) const
{
TTPT_Tile_c< T >* pnearestTile = 0;
double nearestDistance = TC_FLT_MAX;
TGS_Region_c searchRegion( refRegion, searchDistance + this->minGrid_,
TGS_SNAP_MIN_GRID );
// Iterate region, searching for nearest "solid" tile w.r.t given region
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, searchRegion );
TTPT_Tile_c< T >* psolidTile = 0;
while( ptilePlane->tilePlaneIter_.Next( &psolidTile, TTP_TILE_SOLID ))
{
double solidDistance = psolidTile->FindDistance( refRegion );
if(( porientMode ) &&
( *porientMode != TGS_ORIENT_UNDEFINED ) &&
( *porientMode != psolidTile->FindOrient( )))
{
solidDistance = TC_FLT_MAX;
continue;
}
if( TCTF_IsGT( nearestDistance, solidDistance ))
{
nearestDistance = solidDistance;
pnearestTile = psolidTile;
if( TCTF_IsEQ( nearestDistance, 0.0 ))
break;
}
else if( TCTF_IsGT( nearestDistance, this->minGrid_ ) &&
TCTF_IsLT( nearestDistance * TC_SQRT2 + 10.0 * this->minGrid_, solidDistance ))
{
TGS_Region_c nearestRegion( refRegion, nearestDistance + this->minGrid_,
TGS_SNAP_MIN_GRID );
ptilePlane->tilePlaneIter_.Init( *this, nearestRegion );
}
}
return( pnearestTile );
}
//===========================================================================//
// Method : FindCountRefresh_
// Purpose : Counts total number of clear or solid tiles defined
// within this tile plane. The current count is cached and
// may be valid based on whether any tiles have been added
// or deleted since the last count
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::FindCountRefresh_(
void ) const
{
if( !this->count_.isValid )
{
this->FindCountRefresh_( this->region_ );
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->count_.isValid = true;
}
}
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::FindCountRefresh_(
const TGS_Region_c& region ) const
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->count_.clear = 0;
ptilePlane->count_.solid = 0;
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* ptile = 0;
while( ptilePlane->tilePlaneIter_.Next( &ptile ))
{
if( ptile->IsClear( ))
{
++ptilePlane->count_.clear;
}
else // if( ptile->IsSolid( ))
{
++ptilePlane->count_.solid;
}
}
ptilePlane->count_.isValid = false;
}
//===========================================================================//
// Method : SplitRegionCoords_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::SplitRegionCoords_(
TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
const TGS_Line_c& line,
TGS_DirMode_t dirMode,
TGS_OrientMode_t orientMode )
{
TGS_Region_c regionA = ptileA->GetRegion( );
TGS_Region_c regionB = ptileB->GetRegion( );
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
// Update tile (T)'s y2 and (T')'s y1 region coords
if( dirMode == TGS_DIR_DOWN )
{
regionA.y2 = line.y1 - this->minGrid_;
regionB.y1 = line.y1;
}
else // if( dirMode == TGS_DIR_UP )
{
regionA.y2 = line.y2;
regionB.y1 = line.y2 + this->minGrid_;
}
}
else // if( orientMode == TGS_ORIENT_VERTICAL )
{
// Update tile (T)'s x2 and (T')'s x1 region coords
if( dirMode == TGS_DIR_LEFT )
{
regionA.x2 = line.x1 - this->minGrid_;
regionB.x1 = line.x1;
}
else // if( dirMode == TGS_DIR_RIGHT )
{
regionA.x2 = line.x2;
regionB.x1 = line.x2 + this->minGrid_;
}
}
ptileA->SetRegion( regionA );
ptileB->SetRegion( regionB );
}
//===========================================================================//
// Method : MergeRegionCoords_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::MergeRegionCoords_(
TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
TGS_OrientMode_t orientMode,
TGS_CornerMode_t cornerMode )
{
TGS_Region_c regionA = ptileA->GetRegion( );
TGS_Region_c regionB = ptileB->GetRegion( );
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Update tile (T)'s y1 per tile (T')'s y1 region coord
regionA.y1 = regionB.y1;
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Update tile (T)'s y2 per tile (T')'s y2 region coord
regionA.y2 = regionB.y2;
}
}
else // if( orientMode == TGS_ORIENT_VERTICAL )
{
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Update tile (T)'s x1 per tile (T')'s x1 region coord
regionA.x1 = regionB.x1;
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Update tile (T)'s x2 per tile (T')'s x2 region coord
regionA.x2 = regionB.x2;
}
}
ptileA->SetRegion( regionA );
ptileB->SetRegion( regionB );
}
//===========================================================================//
// Method : MergeAdjacentsByExtent_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacentsByExtent_(
TGS_OrientMode_t orientMode,
unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const
{
bool mergedAdjacents = false;
TGS_Region_c initialRegion( *pmergedRegion );
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
this->MergeAdjacentsToLeft_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
this->MergeAdjacentsToRight_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
this->MergeAdjacentsToLower_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
this->MergeAdjacentsToUpper_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
}
else // if( orientMode == TGS_ORIENT_VERTICAL )
{
this->MergeAdjacentsToLower_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
this->MergeAdjacentsToUpper_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
this->MergeAdjacentsToLeft_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
this->MergeAdjacentsToRight_( tileCount, ptileData, tileMode,
mergeMode, pmergedRegion );
}
if( initialRegion != *pmergedRegion )
{
mergedAdjacents = true;
}
return( mergedAdjacents );
}
//===========================================================================//
// Method : MergeAdjacentsToLeft_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacentsToLeft_(
unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const
{
bool mergedAdjacents = false;
while( true )
{
TTPT_Tile_c< T >* pleftTile = this->Find( pmergedRegion->x1 - this->minGrid_,
pmergedRegion->y1 );
if(( pleftTile ) &&
( pleftTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( pleftTile->GetRegion( ).y1, pmergedRegion->y1 )) &&
( TCTF_IsGE( pleftTile->GetRegion( ).y2, pmergedRegion->y2 )))
{
if( mergeMode == TTP_MERGE_REGION )
{
pmergedRegion->x1 = pleftTile->GetRegion( ).x1;
mergedAdjacents = true;
}
else if(( mergeMode == TTP_MERGE_EXACT ) &&
( pleftTile->IsEqualData( tileCount, ptileData )))
{
pmergedRegion->x1 = pleftTile->GetRegion( ).x1;
mergedAdjacents = true;
}
else
{
break;
}
}
else if(( pleftTile ) &&
( pleftTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( pleftTile->GetRegion( ).y1, pmergedRegion->y1 )) &&
( TCTF_IsLT( pleftTile->GetRegion( ).y2, pmergedRegion->y2 )))
{
double x1 = pleftTile->GetRegion( ).x1;
double y2 = pleftTile->GetRegion( ).y2;
TTPT_Tile_c< T >* pneighborTile = this->Find( pmergedRegion->x1 - this->minGrid_,
pleftTile->GetRegion( ).y2 + this->minGrid_ );
while(( pneighborTile ) &&
( pneighborTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( pneighborTile->GetRegion( ).y1, pmergedRegion->y2 )))
{
x1 = TCT_Max( x1, pneighborTile->GetRegion( ).x1 );
y2 = pneighborTile->GetRegion( ).y2;
pneighborTile = this->Find( pmergedRegion->x1 - this->minGrid_,
pneighborTile->GetRegion( ).y2 + this->minGrid_ );
}
if(( mergeMode == TTP_MERGE_REGION ) &&
( TCTF_IsGE( y2, pmergedRegion->y2 )))
{
pmergedRegion->x1 = x1;
mergedAdjacents = true;
}
else
{
break;
}
}
else
{
break;
}
}
return( mergedAdjacents );
}
//===========================================================================//
// Method : MergeAdjacentsToRight_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacentsToRight_(
unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const
{
bool mergedAdjacents = false;
while( true )
{
TTPT_Tile_c< T >* prightTile = this->Find( pmergedRegion->x2 + this->minGrid_,
pmergedRegion->y2 );
if(( prightTile ) &&
( prightTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( prightTile->GetRegion( ).y1, pmergedRegion->y1 )) &&
( TCTF_IsGE( prightTile->GetRegion( ).y2, pmergedRegion->y2 )))
{
if( mergeMode == TTP_MERGE_REGION )
{
pmergedRegion->x2 = prightTile->GetRegion( ).x2;
mergedAdjacents = true;
}
else if(( mergeMode == TTP_MERGE_EXACT ) &&
( prightTile->IsEqualData( tileCount, ptileData )))
{
pmergedRegion->x2 = prightTile->GetRegion( ).x2;
mergedAdjacents = true;
}
else
{
break;
}
}
else if(( prightTile ) &&
( prightTile->GetMode( ) == tileMode ) &&
( TCTF_IsGT( prightTile->GetRegion( ).y1, pmergedRegion->y1 )) &&
( TCTF_IsGE( prightTile->GetRegion( ).y2, pmergedRegion->y2 )))
{
double x2 = prightTile->GetRegion( ).x2;
double y1 = prightTile->GetRegion( ).y1;
TTPT_Tile_c< T >* pneighborTile = this->Find( pmergedRegion->x2 + this->minGrid_,
prightTile->GetRegion( ).y1 - this->minGrid_ );
while(( pneighborTile ) &&
( pneighborTile->GetMode( ) == tileMode ) &&
( TCTF_IsGE( pneighborTile->GetRegion( ).y2, pmergedRegion->y1 )))
{
x2 = TCT_Min( x2, pneighborTile->GetRegion( ).x2 );
y1 = pneighborTile->GetRegion( ).y1;
pneighborTile = this->Find( pmergedRegion->x2 + this->minGrid_,
pneighborTile->GetRegion( ).y1 - this->minGrid_ );
}
if(( mergeMode == TTP_MERGE_REGION ) &&
( TCTF_IsLE( y1, pmergedRegion->y1 )))
{
pmergedRegion->x2 = x2;
mergedAdjacents = true;
}
else
{
break;
}
}
else
{
break;
}
}
return( mergedAdjacents );
}
//===========================================================================//
// Method : MergeAdjacentsToLower_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacentsToLower_(
unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const
{
bool mergedAdjacents = false;
while( true )
{
TTPT_Tile_c< T >* plowerTile = this->Find( pmergedRegion->x1,
pmergedRegion->y1 - this->minGrid_ );
if(( plowerTile ) &&
( plowerTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( plowerTile->GetRegion( ).x1, pmergedRegion->x1 )) &&
( TCTF_IsGE( plowerTile->GetRegion( ).x2, pmergedRegion->x2 )))
{
if( mergeMode == TTP_MERGE_REGION )
{
pmergedRegion->y1 = plowerTile->GetRegion( ).y1;
mergedAdjacents = true;
}
else if(( mergeMode == TTP_MERGE_EXACT ) &&
( plowerTile->IsEqualData( tileCount, ptileData )))
{
pmergedRegion->y1 = plowerTile->GetRegion( ).y1;
mergedAdjacents = true;
}
else
{
break;
}
}
else if(( plowerTile ) &&
( plowerTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( plowerTile->GetRegion( ).x1, pmergedRegion->x1 )) &&
( TCTF_IsLT( plowerTile->GetRegion( ).x2, pmergedRegion->x2 )))
{
double y1 = plowerTile->GetRegion( ).y1;
double x2 = plowerTile->GetRegion( ).x2;
TTPT_Tile_c< T >* pneighborTile = this->Find( plowerTile->GetRegion( ).x2 + this->minGrid_,
pmergedRegion->y1 - this->minGrid_ );
while(( pneighborTile ) &&
( pneighborTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( pneighborTile->GetRegion( ).x1, pmergedRegion->x2 )))
{
y1 = TCT_Max( y1, pneighborTile->GetRegion( ).y1 );
x2 = pneighborTile->GetRegion( ).x2;
pneighborTile = this->Find( pneighborTile->GetRegion( ).x2 + this->minGrid_,
pmergedRegion->y1 - this->minGrid_ );
}
if(( mergeMode == TTP_MERGE_REGION ) &&
( TCTF_IsGE( x2, pmergedRegion->x2 )))
{
pmergedRegion->y1 = y1;
mergedAdjacents = true;
}
else
{
break;
}
}
else
{
break;
}
}
return( mergedAdjacents );
}
//===========================================================================//
// Method : MergeAdjacentsToUpper_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::MergeAdjacentsToUpper_(
unsigned int tileCount,
const T* ptileData,
TTP_TileMode_t tileMode,
TTP_MergeMode_t mergeMode,
TGS_Region_c* pmergedRegion ) const
{
bool mergedAdjacents = false;
while( true )
{
TTPT_Tile_c< T >* pupperTile = this->Find( pmergedRegion->x2,
pmergedRegion->y2 + this->minGrid_ );
if(( pupperTile ) &&
( pupperTile->GetMode( ) == tileMode ) &&
( TCTF_IsLE( pupperTile->GetRegion( ).x1, pmergedRegion->x1 )) &&
( TCTF_IsGE( pupperTile->GetRegion( ).x2, pmergedRegion->x2 )))
{
if( mergeMode == TTP_MERGE_REGION )
{
pmergedRegion->y2 = pupperTile->GetRegion( ).y2;
mergedAdjacents = true;
}
else if(( mergeMode == TTP_MERGE_EXACT ) &&
( pupperTile->IsEqualData( tileCount, ptileData )))
{
pmergedRegion->y2 = pupperTile->GetRegion( ).y2;
mergedAdjacents = true;
}
else
{
break;
}
}
else if(( pupperTile ) &&
( pupperTile->GetMode( ) == tileMode ) &&
( TCTF_IsGT( pupperTile->GetRegion( ).x1, pmergedRegion->x1 )) &&
( TCTF_IsGE( pupperTile->GetRegion( ).x2, pmergedRegion->x2 )))
{
double y2 = pupperTile->GetRegion( ).y2;
double x1 = pupperTile->GetRegion( ).x1;
TTPT_Tile_c< T >* pneighborTile = this->Find( pupperTile->GetRegion( ).x1 - this->minGrid_,
pmergedRegion->y2 + this->minGrid_ );
while(( pneighborTile ) &&
( pneighborTile->GetMode( ) == tileMode ) &&
( TCTF_IsGE( pneighborTile->GetRegion( ).x2, pmergedRegion->x1 )))
{
y2 = TCT_Min( y2, pneighborTile->GetRegion( ).y2 );
x1 = pneighborTile->GetRegion( ).x1;
pneighborTile = this->Find( pneighborTile->GetRegion( ).x1 - this->minGrid_,
pmergedRegion->y2 + this->minGrid_ );
}
if(( mergeMode == TTP_MERGE_REGION ) &&
( TCTF_IsLE( x1, pmergedRegion->x1 )))
{
pmergedRegion->y2 = y2;
mergedAdjacents = true;
}
else
{
break;
}
}
else
{
break;
}
}
return( mergedAdjacents );
}
//===========================================================================//
// Method : JoinAdjacentsPerExact
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::JoinAdjacentsPerExact_(
const TGS_Region_c& region,
TGS_RegionList_t* pregionList ) const
{
bool joinAdjacents = false;
const TTPT_Tile_c< T >* ptile = 0;
ptile = this->Find( region, TTP_FIND_EXACT, TTP_TILE_SOLID );
if( !ptile )
{
ptile = this->Find( region, TTP_FIND_WITHIN, TTP_TILE_SOLID );
}
if( ptile )
{
joinAdjacents = this->JoinAdjacents( *ptile, pregionList );
}
return( joinAdjacents );
}
//===========================================================================//
// Method : JoinAdjacentsPerIntersect
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::JoinAdjacentsPerIntersect_(
const TGS_Region_c& region,
TGS_RegionList_t* pregionList ) const
{
bool joinAdjacents = false;
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* ptile = 0;
while( ptilePlane->tilePlaneIter_.Next( &ptile, TTP_TILE_SOLID ))
{
const TGS_Region_c& tileRegion = ptile->GetRegion( );
if( region != tileRegion )
{
pregionList->Add( tileRegion );
joinAdjacents = true;
}
TGS_RegionList_t regionList;
if( this->JoinAdjacents( *ptile, &regionList ))
{
for( size_t i = 0; i < regionList.GetLength( ); ++i )
{
if( pregionList->IsMember( *regionList[i] ))
continue;
pregionList->Add( *regionList[i] );
joinAdjacents = true;
}
}
}
return( joinAdjacents );
}
//===========================================================================//
// Method : JoinAdjacentsBySide_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::JoinAdjacentsBySide_(
TC_SideMode_t side,
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTP_TileMode_t tileMode,
TGS_RegionList_t* pregionList ) const
{
bool joinAdjacents = false;
if( side == TC_SIDE_LEFT )
{
TGS_Point_c leftPoint( region.x1 - this->minGrid_, region.y1 );
while( TCTF_IsLE( leftPoint.y, region.y2 ))
{
TTPT_Tile_c< T >* pleftTile = this->Find( leftPoint );
if( !pleftTile )
break;
leftPoint.y = pleftTile->GetRegion( ).y2 + this->minGrid_;
if(( pleftTile->GetMode( ) == tileMode ) &&
( pleftTile->IsEqualData( count, pdata )))
{
TGS_Region_c joinRegion;
if( TCTF_IsLE( pleftTile->GetRegion( ).y1, region.y1 ) &&
TCTF_IsGE( pleftTile->GetRegion( ).y2, region.y2 ))
{
joinRegion.ApplyAdjacent( pleftTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( this->JoinAdjacentsBySide_( TC_SIDE_LEFT, joinRegion,
count, pdata, tileMode,
pregionList ))
{
joinAdjacents = true;
continue;
}
}
else
{
joinRegion.ApplyAdjacent( pleftTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( !this->JoinAdjacentsBySide_( TC_SIDE_LEFT, joinRegion,
count, pdata, tileMode,
pregionList ))
{
pregionList->Add( joinRegion );
}
joinRegion = region;
}
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
if( side == TC_SIDE_RIGHT )
{
TGS_Point_c rightPoint( region.x2 + this->minGrid_, region.y2 );
while( TCTF_IsGE( rightPoint.y, region.y1 ))
{
TTPT_Tile_c< T >* prightTile = this->Find( rightPoint );
if( !prightTile )
break;
rightPoint.y = prightTile->GetRegion( ).y1 - this->minGrid_;
if(( prightTile->GetMode( ) == tileMode ) &&
( prightTile->IsEqualData( count, pdata )))
{
TGS_Region_c joinRegion;
if( TCTF_IsLE( prightTile->GetRegion( ).y1, region.y1 ) &&
TCTF_IsGE( prightTile->GetRegion( ).y2, region.y2 ))
{
joinRegion.ApplyAdjacent( prightTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( this->JoinAdjacentsBySide_( TC_SIDE_RIGHT, joinRegion,
count, pdata, tileMode,
pregionList ))
{
joinAdjacents = true;
continue;
}
}
else
{
joinRegion.ApplyAdjacent( prightTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( !this->JoinAdjacentsBySide_( TC_SIDE_RIGHT, joinRegion,
count, pdata, tileMode,
pregionList ))
{
pregionList->Add( joinRegion );
}
joinRegion = region;
}
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
if( side == TC_SIDE_LOWER )
{
TGS_Point_c lowerPoint( region.x1, region.y1 - this->minGrid_ );
while( TCTF_IsLE( lowerPoint.x, region.x2 ))
{
TTPT_Tile_c< T >* plowerTile = this->Find( lowerPoint );
if( !plowerTile )
break;
lowerPoint.x = plowerTile->GetRegion( ).x2 + this->minGrid_;
if(( plowerTile->GetMode( ) == tileMode ) &&
( plowerTile->IsEqualData( count, pdata )))
{
TGS_Region_c joinRegion;
if( TCTF_IsLE( plowerTile->GetRegion( ).x1, region.x1 ) &&
TCTF_IsGE( plowerTile->GetRegion( ).x2, region.x2 ))
{
joinRegion.ApplyAdjacent( plowerTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( this->JoinAdjacentsBySide_( TC_SIDE_LOWER, joinRegion,
count, pdata, tileMode,
pregionList ))
{
joinAdjacents = true;
continue;
}
}
else
{
joinRegion.ApplyAdjacent( plowerTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( !this->JoinAdjacentsBySide_( TC_SIDE_LOWER, joinRegion,
count, pdata, tileMode,
pregionList ))
{
pregionList->Add( joinRegion );
}
joinRegion = region;
}
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
if( side == TC_SIDE_UPPER )
{
TGS_Point_c upperPoint( region.x2, region.y2 + this->minGrid_ );
while( TCTF_IsGE( upperPoint.x, region.x1 ))
{
TTPT_Tile_c< T >* pupperTile = this->Find( upperPoint );
if( !pupperTile )
break;
upperPoint.x = pupperTile->GetRegion( ).x1 - this->minGrid_;
if(( pupperTile->GetMode( ) == tileMode ) &&
( pupperTile->IsEqualData( count, pdata )))
{
TGS_Region_c joinRegion;
if( TCTF_IsLE( pupperTile->GetRegion( ).x1, region.x1 ) &&
TCTF_IsGE( pupperTile->GetRegion( ).x2, region.x2 ))
{
joinRegion.ApplyAdjacent( pupperTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( this->JoinAdjacentsBySide_( TC_SIDE_UPPER, joinRegion,
count, pdata, tileMode,
pregionList ))
{
joinAdjacents = true;
continue;
}
}
else
{
joinRegion.ApplyAdjacent( pupperTile->GetRegion( ), region, this->minGrid_ );
if( !joinRegion.IsValid( ))
continue;
if( !this->JoinAdjacentsBySide_( TC_SIDE_UPPER, joinRegion,
count, pdata, tileMode,
pregionList ))
{
pregionList->Add( joinRegion );
}
joinRegion = region;
}
if( !pregionList->IsMember( joinRegion ))
{
pregionList->Add( joinRegion );
}
joinAdjacents = true;
}
}
}
return( joinAdjacents );
}
//===========================================================================//
// Method : CornerRegionCoords_
// Purpose : Updates and returns a pair of region coordinates based on
// the given two vertically aligned, but partially mergable
// regions.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::CornerRegionCoords_(
const TGS_Region_c& regionA,
const TGS_Region_c& regionB,
TGS_Region_c* pregionA,
TGS_Region_c* pregionB,
TGS_OrientMode_t addOrient )
{
if( pregionA && pregionB )
{
pregionA->Reset( );
pregionB->Reset( );
TC_SideMode_t side = TC_SIDE_UNDEFINED;
if(( addOrient == TGS_ORIENT_VERTICAL ) &&
( this->IsAdjacent( regionA, regionB, &side )))
{
if(( side == TC_SIDE_UPPER ) ||
( side == TC_SIDE_LOWER ))
{
if( TCTF_IsEQ( regionA.x1, regionB.x1 ) &&
TCTF_IsEQ( regionA.x2, regionB.x2 ))
{
*pregionA = regionA;
*pregionB = regionB;
pregionA->y1 = TCT_Min( regionA.y1, regionB.y1 );
pregionA->y2 = TCT_Max( regionA.y2, regionB.y2 );
pregionB->y1 = TCT_Min( regionA.y1, regionB.y1 );
pregionB->y2 = TCT_Max( regionA.y2, regionB.y2 );
}
else if( TCTF_IsEQ( regionA.x1, regionB.x1 ))
{
*pregionA = regionA;
*pregionB = regionB;
if( TCTF_IsGT( regionA.GetDx( ), regionB.GetDx( )))
{
pregionA->x1 = regionB.x2 + this->minGrid_;
pregionB->y1 = TCT_Min( regionA.y1, regionB.y1 );
pregionB->y2 = TCT_Max( regionA.y2, regionB.y2 );
}
else if( TCTF_IsLT( regionA.GetDx( ), regionB.GetDx( )))
{
pregionB->x1 = regionA.x2 + this->minGrid_;
pregionA->y1 = TCT_Min( regionA.y1, regionB.y1 );
pregionA->y2 = TCT_Max( regionA.y2, regionB.y2 );
}
}
else if( TCTF_IsEQ( regionA.x2, regionB.x2 ))
{
*pregionA = regionA;
*pregionB = regionB;
if( TCTF_IsGT( regionA.GetDx( ), regionB.GetDx( )))
{
pregionA->x2 = regionB.x1 - this->minGrid_;
pregionB->y1 = TCT_Min( regionA.y1, regionB.y1 );
pregionB->y2 = TCT_Max( regionA.y2, regionB.y2 );
}
else if( TCTF_IsLT( regionA.GetDx( ), regionB.GetDx( )))
{
pregionB->x2 = regionA.x1 - this->minGrid_;
pregionA->y1 = TCT_Min( regionA.y1, regionB.y1 );
pregionA->y2 = TCT_Max( regionA.y2, regionB.y2 );
}
}
}
}
if(( addOrient == TGS_ORIENT_HORIZONTAL ) &&
( this->IsAdjacent( regionA, regionB, &side )))
{
if(( side == TC_SIDE_LEFT ) ||
( side == TC_SIDE_RIGHT ))
{
if( TCTF_IsEQ( regionA.y1, regionB.y1 ) &&
TCTF_IsEQ( regionA.y2, regionB.y2 ))
{
*pregionA = regionA;
*pregionB = regionB;
pregionA->x1 = TCT_Min( regionA.x1, regionB.x1 );
pregionA->x2 = TCT_Max( regionA.x2, regionB.x2 );
pregionB->x1 = TCT_Min( regionA.x1, regionB.x1 );
pregionB->x2 = TCT_Max( regionA.x2, regionB.x2 );
}
else if( TCTF_IsEQ( regionA.y1, regionB.y1 ))
{
*pregionA = regionA;
*pregionB = regionB;
if( TCTF_IsGT( regionA.GetDy( ), regionB.GetDy( )))
{
pregionA->y1 = regionB.y2 + this->minGrid_;
pregionB->x1 = TCT_Min( regionA.x1, regionB.x1 );
pregionB->x2 = TCT_Max( regionA.x2, regionB.x2 );
}
else if( TCTF_IsLT( regionA.GetDy( ), regionB.GetDy( )))
{
pregionB->y1 = regionA.y2 + this->minGrid_;
pregionA->x1 = TCT_Min( regionA.x1, regionB.x1 );
pregionA->x2 = TCT_Max( regionA.x2, regionB.x2 );
}
}
else if( TCTF_IsEQ( regionA.y2, regionB.y2 ))
{
*pregionA = regionA;
*pregionB = regionB;
if( TCTF_IsGT( regionA.GetDy( ), regionB.GetDy( )))
{
pregionA->y2 = regionB.y1 - this->minGrid_;
pregionB->x1 = TCT_Min( regionA.x1, regionB.x1 );
pregionB->x2 = TCT_Max( regionA.x2, regionB.x2 );
}
else if( TCTF_IsLT( regionA.GetDy( ), regionB.GetDy( )))
{
pregionB->y2 = regionA.y1 - this->minGrid_;
pregionA->x1 = TCT_Min( regionA.x1, regionB.x1 );
pregionA->x2 = TCT_Max( regionA.x2, regionB.x2 );
}
}
}
}
}
return(( pregionA && pregionB ) &&
( pregionA->IsValid( ) && pregionB->IsValid( )) ?
true : false );
}
//===========================================================================//
// Method : CornerTileRemerge_
// Purpose : Re-merges the given two vertically aligned, but partially
// mergable solid tiles. This re-merge involves deleting
// the existing tiles, then adding the re-merged solid
// tiles.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::CornerTileRemerge_(
TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
const TGS_Region_c& regionA,
const TGS_Region_c& regionB,
TGS_OrientMode_t addOrient )
{
bool ok = true;
TTPT_Tile_c< T > tileA( *ptileA );
TTPT_Tile_c< T > tileB( *ptileB );
if( addOrient == TGS_ORIENT_VERTICAL )
{
if( TCTF_IsEQ( regionA.GetDy( ), regionB.GetDy( )))
{
tileA.SetRegion( regionA );
tileB.SetMode( TTP_TILE_UNDEFINED );
}
else if( TCTF_IsGT( regionA.GetDy( ), regionB.GetDy( )))
{
tileA.SetRegion( regionA );
tileB.SetRegion( regionB );
}
else // if( TCTF_IsLT( regionA.GetDy( ), regionB.GetDy( )))
{
tileA.SetRegion( regionB );
tileB.SetRegion( regionA );
}
}
if( addOrient == TGS_ORIENT_HORIZONTAL )
{
if( TCTF_IsEQ( regionA.GetDx( ), regionB.GetDx( )))
{
tileA.SetRegion( regionA );
tileB.SetMode( TTP_TILE_UNDEFINED );
}
else if( TCTF_IsGT( regionA.GetDx( ), regionB.GetDx( )))
{
tileA.SetRegion( regionA );
tileB.SetRegion( regionB );
}
else // if( TCTF_IsLT( regionA.GetDx( ), regionB.GetDx( )))
{
tileA.SetRegion( regionB );
tileB.SetRegion( regionA );
}
}
if( ok && ptileA->IsValid( ))
{
ok = this->Delete( ptileA );
}
if( ok && ptileB->IsValid( ))
{
ok = this->Delete( ptileB );
}
if( ok && tileA.IsValid( ))
{
ok = this->AddPerNew_( tileA, addOrient );
}
if( ok && tileB.IsValid( ))
{
ok = this->AddPerNew_( tileB, addOrient );
}
return( ok );
}
//===========================================================================//
// Method : StitchToSplit_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::StitchToSplit_(
TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
TGS_OrientMode_t orientMode )
{
const TGS_Region_c& regionA = ptileA->GetRegion( );
const TGS_Region_c& regionB = ptileB->GetRegion( );
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
// Update tile (T) and (T')'s 'right_upper' & 'upper_right' stitches
ptileA->SetStitchRightUpper( ptileB );
ptileB->SetStitchLeftLower( ptileA );
// Update tile (T')'s 'lower_left' stitch based on neighboring tile
TGS_Point_c pointLowerLeft( regionB.x1 - this->minGrid_, regionB.y1 );
TTPT_Tile_c< T >* ptileLowerLeft = this->Find( pointLowerLeft );
ptileB->SetStitchLowerLeft( ptileLowerLeft );
// Update tile (T)'s 'upper_right' stitch based on neighboring tile
TGS_Point_c pointUpperRight( regionA.x2 + this->minGrid_, regionA.y2 );
TTPT_Tile_c< T >* ptileUpperRight = this->Find( pointUpperRight );
ptileA->SetStitchUpperRight( ptileUpperRight );
}
else // if( orientMode == TGS_ORIENT_VERTICAL )
{
// Update tile (T) and (T')'s 'upper_right' & 'lower_left' stitches
ptileA->SetStitchUpperRight( ptileB );
ptileB->SetStitchLowerLeft( ptileA );
// Update tile (T')'s 'left_lower' stitch based on neighboring tile
TGS_Point_c pointLeftLower( regionB.x1, regionB.y1 - this->minGrid_ );
TTPT_Tile_c< T >* ptileLeftLower = this->Find( pointLeftLower );
ptileB->SetStitchLeftLower( ptileLeftLower );
// Update tile (T)'s 'right_upper' stitch based on neighboring tile
TGS_Point_c pointRightUpper( regionA.x2, regionA.y2 + this->minGrid_ );
TTPT_Tile_c< T >* ptileRightUpper = this->Find( pointRightUpper );
ptileA->SetStitchRightUpper( ptileRightUpper );
}
}
//===========================================================================//
// Method : StitchToMerge_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::StitchToMerge_(
TTPT_Tile_c< T >* ptileA,
TTPT_Tile_c< T >* ptileB,
TGS_OrientMode_t orientMode,
TGS_CornerMode_t cornerMode )
{
if( orientMode == TGS_ORIENT_HORIZONTAL )
{
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Update tile (T) per tile (T') 'left_lower' & 'lower_left' stitches
ptileA->SetStitchLeftLower( ptileB->GetStitchLeftLower( ));
ptileA->SetStitchLowerLeft( ptileB->GetStitchLowerLeft( ));
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Update tile (T) per tile (T') 'right_upper' & 'upper_right' stitches
ptileA->SetStitchRightUpper( ptileB->GetStitchRightUpper( ));
ptileA->SetStitchUpperRight( ptileB->GetStitchUpperRight( ));
}
}
else // if( orientMode == TGS_ORIENT_VERTICAL )
{
if( cornerMode == TGS_CORNER_LOWER_LEFT )
{
// Update tile (T) per tile (T') 'left_lower' & 'lower_left' stitches
ptileA->SetStitchLeftLower( ptileB->GetStitchLeftLower( ));
ptileA->SetStitchLowerLeft( ptileB->GetStitchLowerLeft( ));
}
if( cornerMode == TGS_CORNER_UPPER_RIGHT )
{
// Update tile (T) per tile (T') 'right_upper' & 'upper_right' stitches
ptileA->SetStitchRightUpper( ptileB->GetStitchRightUpper( ));
ptileA->SetStitchUpperRight( ptileB->GetStitchUpperRight( ));
}
}
}
//===========================================================================//
// Method : StitchFromSide_
// Purpose : Updates the given tile's neighboring tile stitch pointers
// based on the given tile side. This may require iterating
// over multiple neighboring tiles in order to completely
// span the given tile side.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::StitchFromSide_(
TTPT_Tile_c< T >* ptile,
TC_SideMode_t side,
TTPT_Tile_c< T >* ptileP )
{
if( side != TC_SIDE_UNDEFINED )
{
const TGS_Region_c& tileRegion = ptile->GetRegion( );
bool iterateSide = false;
if( side == TC_SIDE_LEFT )
{
TTPT_Tile_c< T >* pleftTile = ptile->GetStitchLowerLeft( );
if( pleftTile )
{
const TGS_Region_c& leftRegion = pleftTile->GetRegion( );
if( TCTF_IsGT( leftRegion.y2, tileRegion.y2 ))
{
; // No need to iterate over side
}
else if( TCTF_IsEQ( leftRegion.y2, tileRegion.y2 ))
{
pleftTile->SetStitchUpperRight( ptile ); // No need to iterate over side
}
else // if( TCTF_IsLT( leftRegion.y2, tileRegion.y2 ))
{
iterateSide = true; // Need to iterate over side
}
}
}
if( side == TC_SIDE_RIGHT )
{
TTPT_Tile_c< T >* prightTile = ptile->GetStitchUpperRight( );
if( prightTile )
{
const TGS_Region_c& rightRegion = prightTile->GetRegion( );
if( TCTF_IsLT( rightRegion.y1, tileRegion.y1 ))
{
; // No need to iterate over side
}
else if( TCTF_IsEQ( rightRegion.y1, tileRegion.y1 ))
{
prightTile->SetStitchLowerLeft( ptile ); // No need to iterate over side
}
else // if( TCTF_IsGT( rightRegion.y1, tileRegion.y1 ))
{
iterateSide = true; // Need to iterate over side
}
}
}
if( side == TC_SIDE_LOWER )
{
TTPT_Tile_c< T >* plowerTile = ptile->GetStitchLeftLower( );
if( plowerTile )
{
const TGS_Region_c& lowerRegion = plowerTile->GetRegion( );
if( TCTF_IsGT( lowerRegion.x2, tileRegion.x2 ))
{
; // No need to iterate over side
}
else if( TCTF_IsEQ( lowerRegion.x2, tileRegion.x2 ))
{
plowerTile->SetStitchRightUpper( ptile ); // No need to iterate over side
}
else // if( TCTF_IsLT( lowerRegion.x2, tileRegion.x2 ))
{
iterateSide = true; // Need to iterate over side
}
}
}
if( side == TC_SIDE_UPPER )
{
TTPT_Tile_c< T >* pupperTile = ptile->GetStitchRightUpper( );
if( pupperTile )
{
const TGS_Region_c& upperRegion = pupperTile->GetRegion( );
if( TCTF_IsLT( upperRegion.x1, tileRegion.x1 ))
{
; // No need to iterate over side
}
else if( TCTF_IsEQ( upperRegion.x1, tileRegion.x1 ))
{
pupperTile->SetStitchLeftLower( ptile ); // No need to iterate over side
}
else // if( TCTF_IsGT( upperRegion.x1, tileRegion.x1 ))
{
iterateSide = true; // Need to iterate over side
}
}
}
if( iterateSide )
{
TTPT_Tile_c< T >* piterTile = ( ptileP ? ptileP : ptile );
this->tilePlaneIter_.Init( *this, *piterTile, side );
TTPT_Tile_c< T >* pneighbor = 0;
while( this->tilePlaneIter_.Next( &pneighbor ))
{
const TGS_Region_c& neighborRegion = pneighbor->GetRegion( );
if( side == TC_SIDE_LEFT )
{
if( TCTF_IsLE( neighborRegion.y2, tileRegion.y2 ))
{
pneighbor->SetStitchUpperRight( ptile );
}
}
if( side == TC_SIDE_RIGHT )
{
if( TCTF_IsGE( neighborRegion.y1, tileRegion.y1 ))
{
pneighbor->SetStitchLowerLeft( ptile );
}
}
if( side == TC_SIDE_LOWER )
{
if( TCTF_IsLE( neighborRegion.x2, tileRegion.x2 ))
{
pneighbor->SetStitchRightUpper( ptile );
}
}
if( side == TC_SIDE_UPPER )
{
if( TCTF_IsGE( neighborRegion.x1, tileRegion.x1 ))
{
pneighbor->SetStitchLeftLower( ptile );
}
}
}
}
}
}
//===========================================================================//
// Method : LoadTileList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::LoadTileList_(
TTPT_Tile_c< T >* ptile,
TCT_OrderedVector_c< TTPT_Tile_c< T >* >* ptileList )
{
if( ptile &&
ptile->IsValid( ))
{
ptile->SetMode( TTP_TILE_UNDEFINED );
if( ptile->GetStitchLowerLeft( ))
{
TTPT_Tile_c< T >* ptileLowerLeft = ptile->GetStitchLowerLeft( );
ptile->SetStitchLowerLeft( 0 );
if( ptileLowerLeft->GetStitchUpperRight( ) == ptile )
{
ptileLowerLeft->SetStitchUpperRight( 0 );
}
this->LoadTileList_( ptileLowerLeft, ptileList );
}
if( ptile->GetStitchUpperRight( ))
{
TTPT_Tile_c< T >* ptileUpperRight = ptile->GetStitchUpperRight( );
ptile->SetStitchUpperRight( 0 );
if( ptileUpperRight->GetStitchLowerLeft( ) == ptile )
{
ptileUpperRight->SetStitchLowerLeft( 0 );
}
this->LoadTileList_( ptileUpperRight, ptileList );
}
if( ptile->GetStitchLeftLower( ))
{
TTPT_Tile_c< T >* ptileLeftLower = ptile->GetStitchLeftLower( );
ptile->SetStitchLeftLower( 0 );
if( ptileLeftLower->GetStitchRightUpper( ) == ptile )
{
ptileLeftLower->SetStitchRightUpper( 0 );
}
this->LoadTileList_( ptileLeftLower, ptileList );
}
if( ptile->GetStitchRightUpper( ))
{
TTPT_Tile_c< T >* ptileRightUpper = ptile->GetStitchRightUpper( );
ptile->SetStitchRightUpper( 0 );
if( ptileRightUpper->GetStitchLeftLower( ) == ptile )
{
ptileRightUpper->SetStitchLeftLower( 0 );
}
this->LoadTileList_( ptileRightUpper, ptileList );
}
ptileList->Add( ptile );
}
}
//===========================================================================//
// Method : EstAspectRatio_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::EstAspectRatio_(
const TGS_Region_c& newRegion,
const TGS_Region_c& curRegion,
double* pminAspectRatio,
double* pmaxAspectRatio ) const
{
TGS_Region_c maxRegion;
if(( TCTF_IsLT( newRegion.x1, curRegion.x1 ) &&
TCTF_IsGT( newRegion.x2, curRegion.x2 )) ||
( TCTF_IsLT( newRegion.y1, curRegion.y1 ) &&
TCTF_IsGT( newRegion.y2, curRegion.y2 )))
{
maxRegion.Set( newRegion );
}
else if( TCTF_IsGE( newRegion.x1, curRegion.x1 ) &&
TCTF_IsLE( newRegion.x2, curRegion.x2 ))
{
maxRegion.Set( newRegion.x1, TCT_Min( newRegion.y1, curRegion.y1 ),
newRegion.x2, TCT_Max( newRegion.y2, curRegion.y2 ));
}
else if( TCTF_IsGE( newRegion.y1, curRegion.y1 ) &&
TCTF_IsLE( newRegion.y2, curRegion.y2 ))
{
maxRegion.Set( TCT_Min( newRegion.x1, curRegion.x1 ), newRegion.y1,
TCT_Max( newRegion.x2, curRegion.x2 ), newRegion.y2 );
}
else
{
maxRegion.Set( newRegion );
}
TGS_Region_c minRegionLL;
if( TCTF_IsGE( curRegion.x1, maxRegion.x1 ) &&
TCTF_IsGE( curRegion.y1, maxRegion.y1 ))
{
minRegionLL.Reset( );
}
else if( TCTF_IsLT( curRegion.x1, maxRegion.x1 ))
{
minRegionLL.Set( curRegion.x1, curRegion.y1, maxRegion.x1, curRegion.y2 );
}
else if( TCTF_IsLT( curRegion.y1, maxRegion.y1 ))
{
minRegionLL.Set( curRegion.x1, curRegion.y1, curRegion.x2, maxRegion.y1 );
}
else
{
minRegionLL.Reset( );
}
TGS_Region_c minRegionUR;
if( TCTF_IsLE( curRegion.x2, maxRegion.x2 ) &&
TCTF_IsLE( curRegion.y2, maxRegion.y2 ))
{
minRegionUR.Reset( );
}
else if( TCTF_IsGT( curRegion.x2, maxRegion.x2 ))
{
minRegionUR.Set( maxRegion.x2, curRegion.y1, curRegion.x2, curRegion.y2 );
}
else if( TCTF_IsGT( curRegion.y2, maxRegion.y2 ))
{
minRegionUR.Set( curRegion.x1, maxRegion.y2, curRegion.x2, curRegion.y2 );
}
else
{
minRegionUR.Reset( );
}
double maxRatio = ( maxRegion.HasArea( ) ?
maxRegion.FindMax( ) / maxRegion.FindMin( ) : 0.0 );
double minRatioLL = ( minRegionLL.HasArea( ) ?
minRegionLL.FindMax( ) / minRegionLL.FindMin( ) : 0.0 );
double minRatioUR = ( minRegionUR.HasArea( ) ?
minRegionUR.FindMax( ) / minRegionUR.FindMin( ) : 0.0 );
if( pminAspectRatio )
{
*pminAspectRatio = TCT_Max( maxRatio, TCT_Min( minRatioLL, minRatioUR ));
}
if( pmaxAspectRatio )
{
*pmaxAspectRatio = TCT_Max( maxRatio, minRatioLL, minRatioUR );
}
}
//===========================================================================//
// Method : HasAspectRatio_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::HasAspectRatio_(
const TGS_Region_c& newRegion,
const TGS_Region_c& curRegion ) const
{
double newRatioMin, newRatioMax;
this->EstAspectRatio_( newRegion, curRegion, &newRatioMin, &newRatioMax );
double curRatioMin, curRatioMax;
this->EstAspectRatio_( curRegion, newRegion, &curRatioMin, &curRatioMax );
bool hasAspectRatio = ( TCTF_IsGE( newRatioMax, curRatioMax ) ? true : false );
if( !hasAspectRatio )
{
double regionMax = this->region_.FindMax( );
double estRatioMin = ( TCTF_IsLT( regionMax, static_cast< double >( INT_MAX )) ?
regionMax / 100.0 : 1000.0 );
if( TCTF_IsLT( newRatioMin, estRatioMin ))
{
hasAspectRatio = true;
}
}
return( hasAspectRatio );
}
//===========================================================================//
// Method : IsClearMatch_
// Purpose : Return true if the given point or exact region is clear.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClearMatch_(
const TGS_Point_c& point ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( point );
if( pfind && pfind->IsClear( ))
{
ptile = pfind;
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClearMatch_(
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( region,
TTP_FIND_EXACT, TTP_TILE_CLEAR );
if( pfind && pfind->IsClear( ))
{
ptile = pfind;
}
if( ppclearTile )
{
*ppclearTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsClearAny_
// Purpose : Return true if any clear tiles are found within the given
// tile plane search region. Optionally, returns a pointer
// to the first clear tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClearAny_(
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsClear( ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsSolid( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if( pnext->IsClear( ))
{
ptile = pnext;
break;
}
}
}
if( ppclearTile )
{
*ppclearTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsClearAll_
// Purpose : Return true if only clear tiles are found within the
// given tile plane search region. Optionally, returns a
// pointer to the last clear tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsClearAll_(
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppclearTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsClear( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsClear( ) &&
!this->IsSolidAny_( region ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsSolid( ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if( pnext->IsClear( ))
{
ptile = pnext;
}
else
{
ptile = 0;
break;
}
}
}
if( ppclearTile )
{
*ppclearTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsSolidMatch_
// Purpose : Return true if the given point or exact region is solid
// and matches the given optional data.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidMatch_(
const TGS_Point_c& point ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( point );
if( pfind && pfind->IsSolid( ))
{
ptile = pfind;
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidMatch_(
const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( point );
if( pfind && pfind->IsSolid( ) && pfind->IsEqualData( count, pdata ))
{
ptile = pfind;
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidMatch_(
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( region,
TTP_FIND_EXACT, TTP_TILE_SOLID );
if( pfind && pfind->IsSolid( ))
{
ptile = pfind;
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidMatch_(
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( region,
TTP_FIND_EXACT, TTP_TILE_SOLID );
if( pfind && pfind->IsSolid( ) && pfind->IsEqualData( count, pdata ))
{
ptile = pfind;
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsSolidAny_
// Purpose : Return true if any solid tiles are found within the given
// tile plane search region and matches the optional given
// data. Optionally, returns a pointer to the first solid
// tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidAny_(
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
// Apply validate to force search region within this tile plane's region
TGS_Region_c iterRegion( region );
iterRegion.ApplyIntersect( this->region_ );
if( iterRegion.IsValid( ))
{
// Start with first tile found in upper-left corner of iteration region
ptile = this->Find( iterRegion.x1, iterRegion.y2 );
// Iterate until searched entire region (upper to lower) for a solid tile
while( ptile && !ptile->IsSolid( ))
{
// Test for neighboring solid tile when search tile is within region
// (Clear tiles cover left to right due to tile plane's strip property)
const TGS_Region_c& clearRegion = ptile->GetRegion( );
if( TCTF_IsLT( clearRegion.x2, iterRegion.x2 ))
{
ptile = this->Find( clearRegion.x2 + this->minGrid_, iterRegion.y2 );
break;
}
// Iterate to next tile found within iteration search region
iterRegion.y2 = clearRegion.y1 - this->minGrid_;
if( TCTF_IsGE( iterRegion.y2, iterRegion.y1 ))
{
// Continue with next file found in upper-left corner of region
ptile = this->Find( iterRegion.x1, iterRegion.y2 );
}
else
{
ptile = 0;
}
}
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidAny_(
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsSolid( ) &&
ptileLL->IsEqualData( count, pdata ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsClear( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if(( pnext->IsSolid( )) &&
( pnext->IsEqualData( count, pdata )))
{
ptile = pnext;
break;
}
}
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsSolidAll_
// Purpose : Return true if only solid tiles are found within the
// given tile plane search region and matches the optional
// given data. Optionally, returns a pointer to the last
// solid tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidAll_(
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsSolid( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsClear( ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if( pnext->IsSolid( ))
{
ptile = pnext;
}
else
{
ptile = 0;
break;
}
}
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidAll_(
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsSolid( ) &&
ptileLL->IsEqualData( count, pdata ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsClear( ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if(( pnext->IsSolid( )) &&
( pnext->IsEqualData( count, pdata )))
{
ptile = pnext;
}
else
{
ptile = 0;
break;
}
}
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsSolidMax_
// Purpose : Return true if any solid tiles are found within the given
// tile plane search region and matches the optional given
// data. Optionally, returns a pointer to the largest solid
// tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidMax_(
const TGS_Region_c& region,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsSolid( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsClear( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if( pnext->IsSolid( ))
{
if( !ptile )
{
ptile = pnext;
}
else if( TCTF_IsLT( ptile->FindArea( ), pnext->FindArea( )))
{
ptile = pnext;
}
}
}
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidMax_(
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsSolid( ) &&
ptileLL->GetRegion( ).IsWithin( region ) &&
ptileLL->IsEqualData( count, pdata ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsClear( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if(( pnext->IsSolid( )) &&
( pnext->IsEqualData( count, pdata )))
{
if( !ptile )
{
ptile = pnext;
}
else if( TCTF_IsLT( ptile->FindArea( ), pnext->FindArea( )))
{
ptile = pnext;
}
}
}
}
if( ppsolidTile )
{
*ppsolidTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsSolidNotMatch_
// Purpose : Return true if the given point or exact region is solid
// and does not match the given data.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNotMatch_(
const TGS_Point_c& point,
unsigned int count,
const T* pdata ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( point );
if( pfind && pfind->IsSolid( ) && !pfind->IsEqualData( count, pdata ))
{
ptile = pfind;
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNotMatch_(
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidNotTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* pfind = this->Find( region,
TTP_FIND_EXACT, TTP_TILE_SOLID );
if( pfind && pfind->IsSolid( ) && !pfind->IsEqualData( count, pdata ))
{
ptile = pfind;
}
if( ppsolidNotTile )
{
*ppsolidNotTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsSolidNotAny_
// Purpose : Return true if any solid tiles are found within the given
// tile plane search region that do not match the given
// data. Optionally, returns a pointer to the first solid
// not tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNotAny_(
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidNotTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsSolid( ) &&
!ptileLL->IsEqualData( count, pdata ))
{
ptile = ptileLL;
}
else if( ptileLL &&
ptileLL->IsClear( ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = 0;
}
else if( ptileLL &&
ptileLL->IsClear( ) &&
this->IsSolidNotAny_( region ))
{
ptile = 0;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if(( pnext->IsSolid( )) &&
( !pnext->IsEqualData( count, pdata )))
{
ptile = pnext;
break;
}
}
}
if( ppsolidNotTile )
{
*ppsolidNotTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNotAny_(
const TGS_Region_c& region ) const
{
TTPT_Tile_c< T >* ptile = this->Find( region.x1, region.y1 );
if( ptile )
{
if( !ptile->IsClear( ) ||
!ptile->GetRegion( ).IsWithinDx( region ))
{
ptile = 0;
}
}
while( ptile )
{
const TGS_Region_c& tileRegion = ptile->GetRegion( );
if( TCTF_IsGE( tileRegion.y2, region.y2 ))
break;
ptile = this->Find( region.x1, tileRegion.y2 + this->minGrid_ );
if( !ptile->IsClear( ) ||
!ptile->GetRegion( ).IsWithinDx( region ))
{
ptile = 0;
}
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : IsSolidNotAll_
// Purpose : Return true if only solid tiles found within the given
// tile plane search region that do not match the given
// data. Optionally, returns a pointer to the last solid
// not tile found.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::IsSolidNotAll_(
const TGS_Region_c& region,
unsigned int count,
const T* pdata,
TTPT_Tile_c< T >** ppsolidNotTile ) const
{
TTPT_Tile_c< T >* ptile = 0;
TTPT_Tile_c< T >* ptileLL = this->Find( region.x1, region.y1 );
if( ptileLL &&
ptileLL->IsSolid( ) &&
!ptileLL->IsEqualData( count, pdata ) &&
ptileLL->GetRegion( ).IsWithin( region ))
{
ptile = ptileLL;
}
else
{
TTPT_TilePlane_c< T >* ptilePlane = const_cast< TTPT_TilePlane_c< T >* >( this );
ptilePlane->tilePlaneIter_.Init( *this, region );
TTPT_Tile_c< T >* pnext = 0;
while( ptilePlane->tilePlaneIter_.Next( &pnext ))
{
if(( pnext->IsSolid( )) &&
( !pnext->IsEqualData( count, pdata )))
{
ptile = pnext;
break;
}
else
{
ptile = 0;
break;
}
}
}
if( ppsolidNotTile )
{
*ppsolidNotTile = ( ptile ? ptile : 0 );
}
return( ptile ? true : false );
}
//===========================================================================//
// Method : Allocate_
// Purpose : Builds and returns a new tile, based on the given tile.
// This method allocates memory asso. with the tile and
// updates the global tile plane pointers, has needed.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > TTPT_Tile_c< T >* TTPT_TilePlane_c< T >::Allocate_(
const TTPT_Tile_c< T >& tile )
{
TTPT_Tile_c< T >* ptile = new TC_NOTHROW TTPT_Tile_c< T >( tile );
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
if( printHandler.IsValidNew( ptile,
sizeof( TTPT_Tile_c< T > ),
"TTPT_TilePlane_c::Allocate_" ))
{
const TGS_Region_c& tileRegion = ptile->GetRegion( );
const TGS_Region_c& thisRegion = this->GetRegion( );
if( TCTF_IsEQ( tileRegion.x1, thisRegion.x1 ) &&
TCTF_IsEQ( tileRegion.y1, thisRegion.y1 ))
{
this->ptileLL_ = ptile;
}
}
return( ptile );
}
//===========================================================================//
// Method : Deallocate_
// Purpose : Deallocates the given tile. This method releases memory
// asso. with the given tile and updates the global tile
// plane pointers, as needed.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > void TTPT_TilePlane_c< T >::Deallocate_(
TTPT_Tile_c< T >* ptile )
{
if( this->ptileLL_ == ptile )
{
const TGS_Region_c& region = this->region_;
this->ptileLL_ = this->Find( region.x1, region.y1 );
}
if( this->ptileLL_ == ptile )
{
const TGS_Region_c& region = this->region_;
this->ptileLL_ = this->Find( region.x1, region.y2 );
}
if( this->ptileLL_ == ptile )
{
const TGS_Region_c& region = this->region_;
this->ptileLL_ = this->Find( region.x2, region.y2 );
}
if( this->ptileLL_ == ptile )
{
const TGS_Region_c& region = this->region_;
this->ptileLL_ = this->Find( region.x2, region.y1 );
}
if( this->ptileMRC_ == ptile )
{
TTPT_Tile_c< T >* ptileLowerLeft = ptile->GetStitchLowerLeft( );
TTPT_Tile_c< T >* ptileLeftLower = ptile->GetStitchLeftLower( );
TTPT_Tile_c< T >* ptileRightUpper = ptile->GetStitchRightUpper( );
TTPT_Tile_c< T >* ptileUpperRight = ptile->GetStitchUpperRight( );
if( ptileLowerLeft && ptileLowerLeft->IsClear( ))
{
this->ptileMRC_ = ptileLowerLeft;
}
else if( ptileLeftLower && ptileLeftLower->IsClear( ))
{
this->ptileMRC_ = ptileLeftLower;
}
else if( ptileRightUpper && ptileRightUpper->IsClear( ))
{
this->ptileMRC_ = ptileRightUpper;
}
else if( ptileUpperRight && ptileUpperRight->IsClear( ))
{
this->ptileMRC_ = ptileUpperRight;
}
else
{
this->ptileMRC_ = this->ptileLL_;
}
}
if( this->ptileMRS_ == ptile )
{
TTPT_Tile_c< T >* ptileLowerLeft = ptile->GetStitchLowerLeft( );
TTPT_Tile_c< T >* ptileLeftLower = ptile->GetStitchLeftLower( );
TTPT_Tile_c< T >* ptileRightUpper = ptile->GetStitchRightUpper( );
TTPT_Tile_c< T >* ptileUpperRight = ptile->GetStitchUpperRight( );
if( ptileLowerLeft && ptileLowerLeft->IsSolid( ))
{
this->ptileMRS_ = ptileLowerLeft;
}
else if( ptileLeftLower && ptileLeftLower->IsSolid( ))
{
this->ptileMRS_ = ptileLeftLower;
}
else if( ptileRightUpper && ptileRightUpper->IsSolid( ))
{
this->ptileMRS_ = ptileRightUpper;
}
else if( ptileUpperRight && ptileUpperRight->IsSolid( ))
{
this->ptileMRS_ = ptileUpperRight;
}
else
{
this->ptileMRS_ = this->ptileLL_;
}
}
delete ptile;
}
//===========================================================================//
// Method : ShowInternalMessage_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 05/30/12 jeffr : Original
//===========================================================================//
template< class T > bool TTPT_TilePlane_c< T >::ShowInternalMessage_(
TTP_MessageType_t messageType,
const char* pszSourceMethod,
const TGS_Region_c* ptileRegion,
const TGS_Region_c* pnextRegion ) const
{
bool ok = true;
string srTileRegion;
if( ptileRegion )
{
ptileRegion->ExtractString( &srTileRegion );
}
string srNextRegion;
if( pnextRegion )
{
pnextRegion->ExtractString( &srNextRegion );
}
string srThisRegion;
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
switch( messageType )
{
case TTP_MESSAGE_IS_LEGAL_INVALID_REGION:
ok = printHandler.Internal( pszSourceMethod,
"Detected corrupted tile plane due to invalid tile region at (%s).\n",
TIO_SR_STR( srTileRegion ));
break;
case TTP_MESSAGE_IS_LEGAL_ADJACENT_CLEAR_TILE:
ok = printHandler.Internal( pszSourceMethod,
"Detected corrupted tile plane due to adjacent clear tiles at (%s) and (%s).\n",
TIO_SR_STR( srTileRegion ),
TIO_SR_STR( srNextRegion ));
break;
case TTP_MESSAGE_TILE_REGION_ILLEGAL:
ok = printHandler.Internal( pszSourceMethod,
"Detected illegal tile plane region coordinates (%s).\n",
TIO_SR_STR( srTileRegion ));
break;
case TTP_MESSAGE_ADD_PER_NEW_INVALID:
ok = printHandler.Internal( pszSourceMethod,
"Can't add new tile region (%s).\n"
"%sRegion intersects with existing tile region (%s).\n",
TIO_SR_STR( srTileRegion ),
TIO_PREFIX_INTERNAL_SPACE,
TIO_SR_STR( srThisRegion ));
break;
case TTP_MESSAGE_ADD_PER_NEW_EXISTS:
ok = printHandler.Internal( pszSourceMethod,
"Can't add new tile region (%s).\n"
"%sRegion intersects with existing tile region (%s).\n",
TIO_SR_STR( srTileRegion ),
TIO_PREFIX_INTERNAL_SPACE,
TIO_SR_STR( srNextRegion ));
break;
case TTP_MESSAGE_ADD_PER_MERGE_INVALID:
ok = printHandler.Internal( pszSourceMethod,
"Can't add merge tile region (%s).\n"
"%sRegion is not within tile plane's region (%s).\n",
TIO_SR_STR( srTileRegion ),
TIO_PREFIX_INTERNAL_SPACE,
TIO_SR_STR( srThisRegion ));
break;
case TTP_MESSAGE_ADD_PER_MERGE_EXISTS:
ok = printHandler.Internal( pszSourceMethod,
"Can't add merge tile region (%s).\n"
"%sRegion intersects with existing tile region (%s).\n",
TIO_SR_STR( srTileRegion ),
TIO_PREFIX_INTERNAL_SPACE,
TIO_SR_STR( srNextRegion ));
break;
case TTP_MESSAGE_ADD_PER_OVERLAP_INVALID:
this->region_.ExtractString( &srThisRegion );
ok = printHandler.Internal( pszSourceMethod,
"Can't add overlap tile region (%s).\n"
"%sRegion is not within tile plane's region (%s).\n",
TIO_SR_STR( srTileRegion ),
TIO_PREFIX_INTERNAL_SPACE,
TIO_SR_STR( srThisRegion ));
break;
case TTP_MESSAGE_DELETE_PER_EXACT_INVALID:
case TTP_MESSAGE_DELETE_PER_WITHIN_INVALID:
case TTP_MESSAGE_DELETE_PER_INTERSECT_INVALID:
this->region_.ExtractString( &srThisRegion );
ok = printHandler.Internal( pszSourceMethod,
"Can't delete existing tile region (%s).\n"
"%sRegion is not within tile plane's region (%s).\n",
TIO_SR_STR( srTileRegion ),
TIO_PREFIX_INTERNAL_SPACE,
TIO_SR_STR( srThisRegion ));
break;
default:
break;
}
return( ok );
}
#endif