示例#1
0
文件: IDMap.cs 项目: And-G/Magellan
        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;
        }