public Node( Node original ) { //location = original.location; level = original.level; data = original.data; if ( original.IsLeaf() ) BecomeLeaf(); else BecomeBranch(); }
private Node BuildTree( int x, int y, int factor ) { // factor 0 = 1 pixel, so don't do advanced searching as it's useless. int size = 1 << factor; int topleft = source.Memory[x,y].Color << 16; int topright = source.Memory[x+size,y].Color << 16; int bottomleft = source.Memory[x,y+size].Color << 16; int bottomright = source.Memory[x+size,y+size].Color << 16; int leftystep = (bottomleft-topleft)/size; int rightystep = (bottomright-topright)/size; int blockowner = source[x,y].ID; // Walk over the blocks contents, and see if it is "uniform" or not. // if it isn't, divide it into 4 subblocks and do the subprocessing of each block. for ( int cy=0, leftcolor=topleft, rightcolor=topright; cy<size; ++cy, leftcolor+=leftystep, rightcolor+=rightystep ) { int xstep = (rightcolor-leftcolor) / size; for ( int cx=0, color = leftcolor; cx<size; ++cx, color+=xstep ) { Pixel mem = source[x+cx,y+cy]; if ( mem.ID != blockowner || mem.IsBorder() || Math.Abs( mem.Color - ((color + 0x008000)>>16) ) >= thresholds[factor] ) { // Need to create a branch Node node = new Node( false ); if ( --factor == 0 ) { node.BottomRightChild = new Node( source[x+1,y+1] ); node.BottomLeftChild = new Node( source[x,y+1] ); node.TopRightChild = new Node( source[x+1,y] ); node.TopLeftChild = new Node( source[x,y] ); } else { size >>= 1; // Half the size node.BottomRightChild = BuildTree( x+size, y+size, factor ); node.BottomLeftChild = BuildTree( x, y+size, factor ); node.TopRightChild = BuildTree( x+size, y, factor ); node.TopLeftChild = BuildTree( x, y, factor ); } return node; } } } // This block is "uniform" so create a leaf... return new Node( source[x,y] ); }
protected override void OnVisitNode( Node node, int x, int y ) { Bitmap vis = null; if ( node.IsBranch() && node.Level > 1 ) { // combine 4 images into a larger one Bitmap tl = (Bitmap)imagestack.Pop(); Bitmap tr = (Bitmap)imagestack.Pop(); Bitmap bl = (Bitmap)imagestack.Pop(); Bitmap br = (Bitmap)imagestack.Pop(); int width = bl.Width + br.Width; if ( tl.Width + tr.Width > width ) width = tl.Width + tr.Width; int height = tl.Height + bl.Height; if ( tr.Height + br.Height > height ) height = tr.Height + br.Height; vis = new Bitmap( width + VisPadding, height + VisPadding ); using ( Graphics g = Graphics.FromImage( vis ) ) { g.DrawImageUnscaled( tl, 0, 0 ); g.DrawImageUnscaled( tr, vis.Width-tr.Width, 0 ); g.DrawImageUnscaled( bl, 0, vis.Height-bl.Height ); g.DrawImageUnscaled( br, vis.Width-br.Width, vis.Height-br.Height ); } } else if ( node.IsBranch() ) { // Display 4 leaves on pixel level vis = new Bitmap( VisSize*2 + VisPadding, VisSize*2 + VisPadding, PixelFormat.Format32bppArgb ); using ( Graphics g = Graphics.FromImage( vis ) ) { g.DrawLine( Pens.Black, VisSize, VisSize, vis.Width-VisSize, vis.Height-VisSize ); g.DrawLine( Pens.Black, vis.Width-VisSize, VisSize, VisSize, vis.Height-VisSize ); DrawNode( node.BottomRightChild, g, vis.Width-VisSize, vis.Height-VisSize ); DrawNode( node.BottomLeftChild, g, 0, vis.Height-VisSize ); DrawNode( node.TopRightChild, g, vis.Width-VisSize, 0 ); DrawNode( node.TopLeftChild, g, 0, 0 ); } } else { // Display a leaf above pixel level vis = new Bitmap( VisSize << node.Level, VisSize << node.Level, PixelFormat.Format32bppArgb ); using ( Graphics g = Graphics.FromImage( vis ) ) { DrawNode( node, g, 0, 0 ); } } imagestack.Push( vis ); }
private static Node DecompressTree( byte[] data, ref int index ) { // Copy the tree into a bit array // We know there can be at most 43 bytes of data (1024 pixels or 668 nodes), so we copy those // first and resize it to the proper size later. int srcsize = index+45 < data.Length ? 45 : data.Length-index; byte[] srcdata = new byte[srcsize]; Array.Copy( data, index, srcdata, 0, srcsize ); BitArray srctree = new BitArray( srcdata ); srcdata = null; int nodeIndex = 0; Node tree = new Node(true); ConvertBitTree( 5, srctree, ref nodeIndex, tree ); index += (int)((nodeIndex+7) / 8); // Set proper data index //index += (int)(nodeIndex / 8); // Set proper data index return tree; }
public void Erase( ) { tree = new Node( false ); tree.BottomRightChild = new Node( Pixel.Empty ); tree.BottomLeftChild = new Node( Pixel.Empty ); tree.TopRightChild = new Node( Pixel.Empty ); tree.TopLeftChild = new Node( Pixel.Empty ); }
private static void ConvertBitTree( int level, BitArray srctree, ref int nodeIndex, Node parent ) { // Get flag, and advance node pointer bool flag = srctree[nodeIndex++]; if ( flag && level > 1 ) { parent.CreateBranches(); ConvertBitTree( level - 1, srctree, ref nodeIndex, parent.BottomRightChild ); ConvertBitTree( level - 1, srctree, ref nodeIndex, parent.BottomLeftChild ); ConvertBitTree( level - 1, srctree, ref nodeIndex, parent.TopRightChild ); ConvertBitTree( level - 1, srctree, ref nodeIndex, parent.TopLeftChild ); } else { if ( flag ) { parent.CreateLeaves(); } else { parent.BecomeLeaf(); } } }
public void Decompress( CompressedBlock compressed, AdjacencyTable adjacent ) { int index = 0; // Decompress the ID table from the data stream Pixel[] owners; int ownercount = DecompressIdTable( compressed.Data, ref index, adjacent, out owners ); // Decompress the tree from the data stream tree = DecompressTree( compressed.Data, ref index ); int leafcount = tree.CalcLeafCount(); // Create the leaf array Pixel[] leafs = new Pixel[leafcount + (leafcount % 8 == 0 ? 0 : 8-(leafcount % 8))]; // Decompress the ownership table next DecompressOwnership( compressed.Data, ref index, leafs, leafcount, owners, ownercount ); // Finally, read the color data, which contains the "color" data for each leaf. DecompressColorInfo( compressed.Data, ref index, leafs, leafcount ); // Assign the leaf data to the nodes int leafIndex = 0; PopulateNode( tree, leafs, ref leafIndex ); }
public MapBlock( Node root ) { tree = root; }
protected void WalkTreeFull( Node node, int x, int y ) { if ( node == null ) return; int size = ((1 << node.Level) >> 1); Node.ChildMaskLocation oldmask = node.ChildMask; if ( node.IsBranch() && node.Level > stopAtLevel ) { if ( visitBranches ) OnVisitNode( node, x, y ); if ( node.IsBranch() ) { WalkTreeFull( node.BottomRightChild, x+size, y+size ); WalkTreeFull( node.BottomLeftChild, x, y+size ); WalkTreeFull( node.TopRightChild, x+size, y ); WalkTreeFull( node.TopLeftChild, x, y ); } } else { OnVisitNode( node, x, y ); // OnVisitNode might have changed the node (leaf<->branch), so have to recheck if ( node.ChildMask != oldmask && node.IsBranch() ) { WalkTreeFull( node.BottomRightChild, x+size, y+size ); WalkTreeFull( node.BottomLeftChild, x, y+size ); WalkTreeFull( node.TopRightChild, x+size, y ); WalkTreeFull( node.TopLeftChild, x, y ); } } }
public static MapBlock Combine( MapBlock[,] matrix ) { Node root = new Node( false ); // Create 4 children root.BottomRightChild = new Node( false ); root.BottomLeftChild = new Node( false ); root.TopRightChild = new Node( false ); root.TopLeftChild = new Node( false ); // Add items to children root.BottomRightChild.BottomRightChild = matrix[3,3].Tree.Clone(); root.BottomRightChild.BottomLeftChild = matrix[2,3].Tree.Clone(); root.BottomRightChild.TopRightChild = matrix[3,2].Tree.Clone(); root.BottomRightChild.TopLeftChild = matrix[2,2].Tree.Clone(); root.BottomLeftChild.BottomRightChild = matrix[1,3].Tree.Clone(); root.BottomLeftChild.BottomLeftChild = matrix[0,3].Tree.Clone(); root.BottomLeftChild.TopRightChild = matrix[1,2].Tree.Clone(); root.BottomLeftChild.TopLeftChild = matrix[0,2].Tree.Clone(); root.TopRightChild.BottomRightChild = matrix[3,1].Tree.Clone(); root.TopRightChild.BottomLeftChild = matrix[2,1].Tree.Clone(); root.TopRightChild.TopRightChild = matrix[3,0].Tree.Clone(); root.TopRightChild.TopLeftChild = matrix[2,0].Tree.Clone(); root.TopLeftChild.BottomRightChild = matrix[1,1].Tree.Clone(); root.TopLeftChild.BottomLeftChild = matrix[0,1].Tree.Clone(); root.TopLeftChild.TopRightChild = matrix[1,0].Tree.Clone(); root.TopLeftChild.TopLeftChild = matrix[0,0].Tree.Clone(); root.Level = matrix[3,3].Tree.Level+2; // Use for new block MapBlock result = new MapBlock( root ); // Clip the tree result.WalkTree( new MapBlockHandling.TreeClipperDeep( ) ); result.tree.Level = 5; // Optimise the tee result.WalkTree( new MapBlockHandling.TreeOptimiser( true ) ); return result; }
private void PaintNode( Node node, int x, int y ) { int v = 0xFF - (node.Data.Color << 2); SolidBrush brush; if ( node.Data.IsBorder() ) brush = new SolidBrush( Color.FromArgb( 0xFF, v, v ) ); else brush = new SolidBrush( Color.FromArgb( v, v, v ) ); paintgraphics.FillRectangle( brush, x*20 + 1, y*20 + 1, 20*(1<<node.Level)-2, 20*(1<<node.Level)-2 ); brush.Dispose(); paintgraphics.DrawString( node.Data.ID.ToString(), lblFont.Font, node.Data.Color > 32 ? Brushes.White : Brushes.Black, x*20 + 2, y*20 + 2 ); //if ( chkDisplayColors.Checked ) paintgraphics.DrawString( node.Data.Color.ToString(), lblFont.Font, node.Data.Color > 32 ? Brushes.Yellow : Brushes.Blue, x*20 + 2, y*20 + 10 ); //else // paintgraphics.DrawString( node.Data.Full.ToString(), lblFont.Font, node.Data.Color > 32 ? Brushes.White : Brushes.Black, x*20 + 2, y*20 + 10 ); }
protected abstract void OnVisitNode( Node node, int x, int y );
public void CreateLeaves() { BecomeBranch(); children[0] = new Node( true, level-1 ); children[1] = new Node( true, level-1 ); children[2] = new Node( true, level-1 ); children[3] = new Node( true, level-1 ); }
private void PopulateNode( Node node, Pixel[] leafs, ref int index ) { if ( !node.IsLeaf() ) { PopulateNode( node.BottomRightChild, leafs, ref index ); PopulateNode( node.BottomLeftChild, leafs, ref index ); PopulateNode( node.TopRightChild, leafs, ref index ); PopulateNode( node.TopLeftChild, leafs, ref index ); } else { node.Data = leafs[index++]; } }
public void CreateBranches() { BecomeBranch(); children[0] = new Node( false, level-1 ); children[1] = new Node( false, level-1 ); children[2] = new Node( false, level-1 ); children[3] = new Node( false, level-1 ); }
public Node Clone() { Node result = new Node( IsLeaf(), level ); result.data = data; if ( IsBranch() ) { result.children[0] = children[0].Clone(); result.children[1] = children[1].Clone(); result.children[2] = children[2].Clone(); result.children[3] = children[3].Clone(); } return result; }
private void RightWalker( Node node, int x, int y ) { x += Lightmap.BlockSize; if ( node.IsBranch() ) { shadow[x,y+1] = node.BottomLeftChild.Data.Color; shadow[x,y] = node.TopLeftChild.Data.Color; } else { int size = 1 << node.Level; int topleft = node.Data.Color << 16; int bottomleft = (shadow[x, y+size]) << 16; // Do the interpolation int delta = (bottomleft - topleft) >> node.Level; int color = topleft; for ( int a = 0; a<size; a++ ) { // Loop horizontally shadow[x, y+a] = (byte)(color>>16); color += delta; } } }
private void DrawWalker( Node node, int x, int y ) { int level = node.Level; x += sx; y += sy; if ( node.IsBranch() ) { shadow[x-sx+1,y-sy+1] = (memory[(x+1),(y+1)] = node.BottomRightChild.Data).Color; shadow[x-sx,y-sy+1] = (memory[x,(y+1)] = node.BottomLeftChild.Data).Color; shadow[x-sx+1,y-sy] = (memory[(x+1),y] = node.TopRightChild.Data).Color; shadow[x-sx,y-sy] = (memory[x,y] = node.TopLeftChild.Data).Color; } else { int size = 1 << level; ushort pid = node.Data.ID; ushort rid = node.Data.RiverID; byte border = node.Data.Border; int topleft = node.Data.Color << 16; int bottomright = (shadow[x-sx+size, y-sy+size]) << 16; int topright = (shadow[x-sx+size, y-sy]) << 16; int bottomleft = (shadow[x-sx, y-sy+size]) << 16; int leftstep = (bottomleft - topleft) >> node.Level; int rightstep = (bottomright - topright) >> node.Level; int left = topleft; int right = topright; // Do the interpolation int xstep = (right - left) >> level; int light = left; for ( int a = 0; a<size; a++ ) { // Loop horizontally shadow[x-sx+a, y-sy] = (byte)(light>>16); light += xstep; } for ( int b = 0; b < size; b++ ) { // Loop vertically xstep = (left - right) >> level; light = left; shadow[x-sx, y-sy+b] = (byte)(left>>16); if ( xstep == 0 ) { for ( int a = 0; a<size; a++ ) { // Loop horizontally memory[(x+a),(y+b)].Color = (byte)((light+0x8000)>>16); memory[(x+a),(y+b)].ID = pid; memory[(x+a),(y+b)].RiverID = rid; memory[(x+a),(y+b)].Border = border; } } else if ( size == 1 ) { memory[(x),(y+b)].Color = (byte)((light+0x8000)>>16); memory[(x),(y+b)].ID = pid; memory[(x),(y+b)].RiverID = rid; memory[(x),(y+b)].Border = border; } else { int prevlight = light; int preva = 0; for ( int a = 0; a<size; a++ ) { // Loop horizontally if ( light != prevlight ) { // Do as little as decoding as possible... for ( int a2=preva; a2<a; ++a2 ) { memory[(x+a2),(y+b)].Color = (byte)((prevlight+0x8000)>>16); memory[(x+a2),(y+b)].ID = pid; memory[(x+a2),(y+b)].RiverID = rid; memory[(x+a2),(y+b)].Border = border; } preva = a; prevlight = light; } light -= xstep; } if ( preva<size ) { for ( int a2=preva; a2<size; ++a2 ) { memory[(x+a2),(y+b)].Color = (byte)((prevlight+0x8000)>>16); memory[(x+a2),(y+b)].ID = pid; memory[(x+a2),(y+b)].RiverID = rid; memory[(x+a2),(y+b)].Border = border; } } } left += leftstep; right += rightstep; } } }
private void BottomRightWalker( Node node, int x, int y ) { if ( node.IsLeaf() ) shadow[Lightmap.BlockSize,Lightmap.BlockSize] = node.Data.Color; else shadow[Lightmap.BlockSize,Lightmap.BlockSize] = node.TopLeftChild.Data.Color; }
public static MapBlock Combine( MapBlock bottomright, MapBlock bottomleft, MapBlock topright, MapBlock topleft ) { // Merge 4 trees Node root = new Node( false, bottomright.Tree.Level+1 ); root.BottomRightChild = bottomright.Tree.Clone(); root.BottomLeftChild = bottomleft.Tree.Clone(); root.TopRightChild = topright.Tree.Clone(); root.TopLeftChild = topleft.Tree.Clone(); // Use for new block MapBlock result = new MapBlock( root ); // Clip the tree result.WalkTree( new MapBlockHandling.TreeClipper() ); result.tree.Level = 5; // Optimise the tee result.WalkTree( new MapBlockHandling.TreeOptimiser( true ) ); return result; }
private void DrawNode( Node node, Graphics g, int x, int y ) { int color = shades[((rangecheck[(node.Data.Color-0+128+32)]<<6) | (int)(provinces[node.Data.ID].Terrain.Color) )]; unchecked { using ( Brush b = new SolidBrush( Color.FromArgb( (int)(0xFF000000) | color ) ) ) { g.FillRectangle( b, x, y, VisSize << node.Level, VisSize << node.Level ); } } Brush fb = node.Data.IsBorder() ? Brushes.Red : Brushes.Black; g.FillRectangle( Brushes.White, x+2, y+2, VisSize-4, 8 ); g.FillRectangle( Brushes.White, x+2, y+11, VisSize-4, 8 ); g.FillRectangle( Brushes.White, x+2, y+20, VisSize-4, 8 ); using ( StringFormat sf = new StringFormat( StringFormatFlags.NoWrap ) ) { sf.Alignment = StringAlignment.Center; using ( Font f = new Font( "Tahoma", 5.0F ) ) { g.DrawString( node.Data.ID.ToString(), f, fb, new RectangleF( x+2, y+2, VisSize-4, 8 ), sf ); g.DrawString( node.Data.RiverID.ToString(), f, fb, new RectangleF( x+2, y+11, VisSize-4, 8 ), sf ); g.DrawString( node.Data.Color.ToString(), f, fb, new RectangleF( x+2, y+20, VisSize-4, 8 ), sf ); } } }
private void PaintWalker( Node node, int x, int y ) { Pen pen; //paintgraphics.DrawRectangle( pen, x*20 + (5-node.Level), y*20 + (5-node.Level), 20*(1<<node.Level)-(5-node.Level)*2, 20*(1<<node.Level)-(5-node.Level)*2 ); if ( node.IsLeaf() ) { PaintNode( node, x, y ); pen = Pens.Red; } else { pen = Pens.Blue; PaintNode( node.BottomRightChild, x+1, y+1 ); PaintNode( node.BottomLeftChild, x, y+1 ); PaintNode( node.TopRightChild, x+1, y ); PaintNode( node.TopLeftChild, x, y ); } paintgraphics.DrawRectangle( pen, x*20 + 1, y*20 + 1, 20*(1<<node.Level)-2, 20*(1<<node.Level)-2 ); }
protected override void OnVisitNode( Node node, int x, int y ) { visitor( node, x, y ); }