Exemplo n.º 1
0
        private Lightmap( int zoom, ProvinceList provinces, AdjacencyTable adjacent, IDMap idmap )
        {
            if ( zoom < 0 ) throw new InvalidZoomFactorException( zoom );
            this.zoom = zoom;
            this.provinces = provinces;
            this.adjacent = adjacent;
            this.idmap = idmap;
            this.volatiledecompression = false;

            Size sz = CoordMap.ActualToZoomedBlocks( BaseSize );
            blocks = new GenericMapBlock[sz.Width*sz.Height];
        }
Exemplo n.º 2
0
        public AdjacencyTable BuildAdjacencyTable( Rectangle region, ProvinceList provinces )
        {
            const int Offset = 2; // 1 is too small, it seems...
            AdjacencyTable table = new AdjacencyTable();

            // Build a matrix of provinces by walking over the map and marking each adjacency in the matrix.
            int[,] matrix = new int[Province.InternalCount,Province.InternalCount];
            int[,] rivers = new int[Province.InternalCount,Province.InternalCount];

            // Fix region
            if ( region.Right > Lightmap.BaseWidth ) region.Width =  Lightmap.BaseWidth - region.X;
            if ( region.Bottom > Lightmap.BaseHeight ) region.Height =  Lightmap.BaseHeight - region.Y;

            ushort[] histogram = null;

            // Enlarge region (only if it's not encompassing the whole map).
            // This is necessary to detect changed on the border of the region specified...
            if ( region.X != 0 || region.Y != 0 || region.Width < Lightmap.BaseWidth || region.Width < Lightmap.BaseHeight ) {
                // Need to enlarge the region so that it *completely* encompasses all provinces in the original region

                // First, Get a map of all the IDs in the original region
                histogram = GetHistogram( region );

                // Get all ids in the region
                ushort[] ids = GetIDs( region, false );
                ProvinceBoundBox[] boxes = CalculateBoundBoxes();
                for ( int i=0; i<ids.Length; ++i ) {
                    region = Rectangle.Union( region, boxes[ids[i]].Box );
                }

                // Fix region, again.
                if ( region.Right > Lightmap.BaseWidth ) region.Width =  Lightmap.BaseWidth - region.X;
                if ( region.Bottom > Lightmap.BaseHeight ) region.Height =  Lightmap.BaseHeight - region.Y;
            }

            int id1, id2;
            int[] places = new int[] { Offset*2, 0, 0, -Offset*2,
                                       Offset*4, -Offset*2, Offset*2, -Offset*4,
                                       Offset*6, -Offset*4, Offset*4, -Offset*6,
                                       Offset*8, -Offset*6, Offset*6, -Offset*8 };
            for ( int y=region.Top; y<region.Bottom; ++y ) {
                // Walk over zones on this row
                int zleft = lines[y].LookupZoneIndex( region.Left );
                int zright = lines[y].LookupZoneIndex( region.Right );

                for ( int z=zleft; z<=zright; ++z ) {
                    // Skip if we're TI
                    if ( lines[y].GetZone( z ).ID == Province.TerraIncognitaID ) continue;

                    // Process this zone.
                    int left = lines[y].GetZone( z ).X;
                    int right = left + lines[y].GetZoneLength( z );
                    for ( int x=left; x<right; ++x ) {
                        #region Left/Right check
                        // -- Left/right check first
                        id1 = this[x-Offset,y];
                        id2 = this[x+Offset,y];

                        if ( id1 != Province.TerraIncognitaID && id2 != Province.TerraIncognitaID ) {
                            if ( provinces[id2].IsRiver() ) {
                                // The right one is a river...
                                ++matrix[id1,id2];
                                ++matrix[id2,id1];

                                // Look for land...
                                for ( int i=0; i<places.Length; i+=2 ) {
                                    id2 = this[x+places[i],y+places[i+1]];
                                    if ( provinces[id2].IsLand() ) {
                                        ++matrix[id1,id2];
                                        ++matrix[id2,id1];
                                        // Also mark river adjacency
                                        ++rivers[id1,id2];
                                        ++rivers[id2,id1];
                                        break;
                                    }
                                }

                                // If not found, don't mark a thing
                            }
                            else {
                                ++matrix[id1,id2];
                                ++matrix[id2,id1];
                            }
                        }
                        #endregion

                        #region Up/down check
                        // -- Up/down check next
                        id1 = this[x,y-Offset];
                        id2 = this[x,y+Offset];

                        if ( id1 != 0 && id2 != 0 ) {
                            if ( provinces[id2].IsRiver() ) {
                                // The bottom one is a river...
                                ++matrix[id1,id2];
                                ++matrix[id2,id1];

                                // Look further down for land...
                                for ( int i=0; i<places.Length; i+=2 ) {
                                    id2 = this[x+(-places[i+1]),y+places[i]];
                                    if ( provinces[id2].IsLand() ) {
                                        ++matrix[id1,id2];
                                        ++matrix[id2,id1];
                                        // Also mark river adjacency
                                        ++rivers[id1,id2];
                                        ++rivers[id2,id1];
                                        break;
                                    }
                                }

                                // If not found, don't mark a thing
                            }
                            else {
                                ++matrix[id1,id2];
                                ++matrix[id2,id1];
                            }
                        }
                        #endregion
                    }
                }
            }

            // Walk over the matrix, and build an actual list of adjacencies for each province.
            const int Threshold = 8; // we need a certain amount of matches to have adjacency...

            // Start iterating at 1, no need to incorporate TI...
            for ( ushort ph=1; ph<Province.Count; ++ph ) {
                // Skip ids not present in the original region
                if ( histogram != null && histogram[ph] <= 0 ) continue;

                // Do "normal" adjacencies first
                for ( ushort pv=1; pv<Province.Count; ++pv ) {
                    if ( ph == pv || provinces[pv].IsRiver() ) continue;
                    // Check for the threshold
                    if ( matrix[ph,pv] <= Threshold ) continue;

                    table.Add( ph, new Adjacent( pv, rivers[ph,pv] == matrix[ph,pv] ? AdjacencyType.River : AdjacencyType.Normal ) );
                }

                // Do "river" adjacencies next
                for ( ushort pv=1; pv<Province.Count; ++pv ) {
                    if ( ph == pv || !provinces[pv].IsRiver() ) continue;
                    // Check for the threshold
                    if ( matrix[ph,pv] <= Threshold ) continue;

                    table.Add( ph, new Adjacent( pv, AdjacencyType.Normal ) );
                }
            }

            return table;
        }
Exemplo n.º 3
0
        public ushort FindClosestLand( int x, int y, ushort skipid, int range, ProvinceList provinces, AdjacencyTable adjacent )
        {
            int halfwidth = (range >> 1);
            int halfheight = (range >> 1);

            ushort closest_id = skipid;

            // -- Build a bitmap around this point
            x = Lightmap.BaseNormalizeX( x );

            int max_distance = MaxDistance;
            ushort[,] map = ExportBitmapGrid( x-halfwidth, y-halfheight, range, range );
            for ( int my=0; my<range; ++my ) {
                for ( int mx=0; mx<range; ++mx ) {
                    // -- Skip for TI and pixels belonging to this province
                    if ( map[mx,my] == Province.TerraIncognitaID || map[mx,my] == skipid ) continue;
                    if ( !provinces[map[mx,my]].IsLandNoTI() ) continue; // Only land

                    // Also check if adjacency exists
                    if ( adjacent != null && skipid != 0 ) {
                        int adj = adjacent.GetAdjacencyIndex( skipid, map[mx,my] );
                        if ( adj < 0 || adj >= 16 ) continue;
                    }

                    // -- This pixel qualifies: check the distance.
                    // Normally, we should need a sqrt() too, but it doesn't really matter here,
                    // as we just want "the smallest" and not how small it actually is.
                    int distance = ((mx-halfwidth)*(mx-halfwidth)) + ((my-halfheight)*(my-halfheight));
                    if ( distance < max_distance ) {
                        max_distance = distance;
                        closest_id = map[mx,my];
                    }
                }
            }

            return closest_id;
        }
Exemplo n.º 4
0
 public ushort FindClosestLand( int x, int y, ushort skipid, ProvinceList provinces, AdjacencyTable adjacent )
 {
     return FindClosestLand( x, y, skipid, Lightmap.BlockSize, provinces, adjacent);
 }
Exemplo n.º 5
0
 public ushort[] BuildAdjacencyTable( AdjacencyTable mergeWith, Rectangle region, ProvinceList provinces )
 {
     return mergeWith.Merge( BuildAdjacencyTable( region, provinces ) );
 }
Exemplo n.º 6
0
 private Lightmap( int zoom, ProvinceList provinces, AdjacencyTable adjacent, IDMap idmap, BinaryReader reader )
     : this(zoom, provinces, adjacent, idmap)
 {
     ReadFrom( reader );
 }
Exemplo n.º 7
0
 public void Attach( ProvinceList provinces, AdjacencyTable adjacent, IDMap idmap )
 {
     this.provinces = provinces;
     this.adjacent = adjacent;
     this.idmap = idmap;
 }
Exemplo n.º 8
0
 public static Lightmap FromStream( int zoom, ProvinceList provinces, AdjacencyTable adjacent, IDMap idmap, BinaryReader reader )
 {
     return new Lightmap( zoom, provinces, adjacent, idmap, reader );
 }
Exemplo n.º 9
0
 public static Lightmap FromFile( int zoom, ProvinceList provinces, AdjacencyTable adjacent, IDMap idmap, string path )
 {
     FileStream stream = null;
     try {
         stream = new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read );
         return new Lightmap( zoom, provinces, adjacent, idmap, new BinaryReader( stream ) );
     }
     finally {
         if ( stream != null ) stream.Close();
     }
 }
Exemplo n.º 10
0
 public static Lightmap CreateEmpty( int zoom, ProvinceList provinces, AdjacencyTable adjacent, IDMap idmap )
 {
     Lightmap result = new Lightmap( zoom, provinces, adjacent, idmap );
     for ( int i=0; i<result.blocks.Length; ++i ) result.blocks[i] = new MapBlock();
     return result;
 }
Exemplo n.º 11
0
        public ushort[] Merge( AdjacencyTable other )
        {
            int[] tagged = new int[Province.InternalCount];

            for ( int fromId=1; fromId<other.table.Length; ++fromId ) {
                if ( other.table[fromId] == null || other.table[fromId].Length == 0 ) continue;

                ++tagged[fromId];
                table[fromId] = new Adjacent[other.table[fromId].Length];
                other.table[fromId].CopyTo( table[fromId], 0 );

                for ( int t=0; t<table[fromId].Length; ++t )
                    ++tagged[table[fromId][t].ID];
            }

            // Count affected ids
            int count = 0;
            for ( ushort i=0; i<tagged.Length; ++i ) {
                if ( tagged[i] > 0 ) count++;
            }

            ushort[] affected = new ushort[count];
            count = 0;
            for ( ushort i=0; i<tagged.Length; ++i ) {
                if ( tagged[i] > 0 ) affected[count++] = i;
            }

            return affected;
        }