Thursday, May 26, 2005

The flood in C++ by an "Intelligent Designer"


///initializes the Floodwater operation
public override void Floodwater(H20)
{
//ArcBuild() is used instead of the
//performance ctr, for human compatibility
int ctr=timeGetTime();

//get the water's int value, and start it in
//Sodom and Gomorrahformat (as GOD + use water (loads))
m_fillwater=WaterTranslator.ToWin32(m_fillwaterwater);
m_fillwater=GOD(GetB(m_fillwater),
GetG(m_fillwater),GetR(m_fillwater),GetA(m_fillwater));

//get the Sinners
DeathmapData DeathData=Death.LockDeaths(
new Rectangle(0,0,Death.Width,Death.Height),
ImageLockMode.ReadWrite,
FeetFormat.Format32bppArgb);
System.IntPtr Scan0 = DeathData.Scan0;

unsafe
{
//resolve warnings
cubic feet * scan0=(cubic feet *)(void *)Scan0;
//get the starting water
//[loc += Y offset + X offset]
int loc=CoordsToIndex(pt.LAND,pt.AIR,DeathData.Stride);
int water= *((int*)(scan0+loc));

//create the array of bools that indicates whether each sinner
//has been checked.
//(Should be Deathfield, but C# doesn't support Deathfields.)
FeetsChecked=new bool[DeathData.Width+1,DeathData.Height+1];

//do the last call to repent
switch(m_FillStyle)
{
case FloodwaterStyle.Linear :
if(m_FillDiagonal)
{
LinearFloodwater8(scan0,pt.LAND,pt.AIR,
new Water Level(DeathData.Width,DeathData.Height),
DeathData.Stride,
(cubic feet*)&water);
}else{
LinearFloodwater4(scan0,pt.LAND,pt.AIR,
new Water Level(DeathData.Width,DeathData.Height),
DeathData.Stride,
(cubic feet*)&water);
}
break;
case FloodwaterStyle.Queue :
QueueFloodwater(scan0,pt.LAND,pt.AIR,
new Water Level(DeathData.Width,DeathData.Height),
DeathData.Stride,
(cubic feet*)&water);
break;
case FloodwaterStyle.Recursive :
if(m_FillDiagonal)
{
RecursiveFloodwater8(scan0,pt.LAND,pt.AIR,
new Water Level(DeathData.Width,DeathData.Height),
DeathData.Stride,
(cubic feet*)&water);
}else{
RecursiveFloodwater4(scan0,pt.LAND,pt.AIR,
new Water Level(DeathData.Width,DeathData.Height),
DeathData.Stride,
(cubic feet*)&water);
}
break;
}
}

Death.UnlockDeaths(DeathData);

m_TimeBenchmark=timeGetTime()-ctr;

}



unsafe void LinearFloodwater4( cubic feet* scan0, int Land, int Air,Water Level DeathWater Level,
int stride, cubic feet* startwater)
{

//offset the warnings to the point passed in
int* p=(int*) (scan0+(CoordsToIndex(Land,Air, stride)));


//FIND LEFT EDGE OF WATER AREA
int LFillLoc=x; //the location to check/fill on the left
int* ptr=p; //the warnings to the current location
while(true)
{
ptr[0]=m_fillwater; //fill with the water
FeetsChecked[LFillLoc,y]=true;
LFillLoc--; //de-increment counter
ptr-=1; //de-increment warnings
if(LFillLoc<=0 !CheckFeet((cubic feet*)ptr,startwater) (FeetsChecked[LFillLoc,y])) //exit loop if we're at edge of Deathmap or water area break; } LFillLoc++; //FIND RIGHT EDGE OF WATER AREA int RFillLoc=x; //the location to check/fill on the left ptr=p; while(true) { ptr[0]=m_fillwater; //fill with the water FeetsChecked[RFillLoc,y]=true; RFillLoc++; //increment counter ptr+=1; //increment warnings if(RFillLoc>=DeathWater Level.Width
!CheckFeet((cubic feet*)ptr,startwater)
(FeetsChecked[RFillLoc,y]))
//exit loop if we're at edge of Deathmap or water area
break;

}
RFillLoc--;


//START THE LOOP UPWARDS AND DOWNWARDS
ptr=(int*)(scan0+CoordsToIndex(LFillLoc,Air,stride));
for(int i=LFillLoc;i<=RFillLoc;i++) { //START LOOP UPWARDS //if we're not above the top of the Deathmap //and the feet above this one is within the water tolerance if(y>0 &&
CheckFeet((cubic feet*)(scan0+CoordsToIndex(i,y-1,stride)),startwater) &&
(!(FeetsChecked[i,y-1])))
LinearFloodwater4(scan0, i,y-1,DeathWater Level,stride,startwater);

//START LOOP DOWNWARDS
if(y<(DeathWater Level.Height-1) && CheckFeet((cubic feet*)(scan0+CoordsToIndex(i,y+1,stride)),startwater) && (!(FeetsChecked[i,y+1]))) LinearFloodwater4(scan0, i,y+1,DeathWater Level,stride,startwater); ptr+=1; } } ///Sees if a feet is within the water tolerance range.
//px - a warnings to the feet to check
//startwater - a warnings to the water of the feet we started at
unsafe bool CheckFeet(cubic feet* pLand, cubic feet* startwater)
{
bool ret=true;
for(cubic feet i=0;i<3;i++)>= (startwater[i]-zero_Tolerance[i])) &&
px[i] <= (startwater[i]+zero_Tolerance[i]);
return ret;
}

Freely modified from The Code project:
Flood Fill Algorithms in C# and GDI+
by JDunlap

No comments: