Exemplo n.º 1
0
        private List <Way> processWays(QueryParameters queryParameters, int numberOfWays)
        {
            List <Way> ways = new List <Way>();

            Tag[] wayTags = this.mapFileHeader.MapFileInfo.WayTags;

            for (int elementCounter = numberOfWays; elementCounter != 0; --elementCounter)
            {
                if (this.mapFileHeader.MapFileInfo.DebugFile)
                {
                    // get and check the way signature
                    this.signatureWay = this.readBuffer.ReadUTF8Encodedstring(SIGNATURE_LENGTH_WAY);
                    if (!this.signatureWay.StartsWith("---WayStart"))
                    {
                        System.Diagnostics.Debug.WriteLine("invalid way signature: " + this.signatureWay);
                        System.Diagnostics.Debug.WriteLine(DEBUG_SIGNATURE_BLOCK + this.signatureBlock);
                        return(null);
                    }
                }

                // get the size of the way (VBE-U)
                int wayDataSize = this.readBuffer.ReadUnsignedInt();
                if (wayDataSize < 0)
                {
                    System.Diagnostics.Debug.WriteLine("invalid way data size: " + wayDataSize);
                    if (this.mapFileHeader.MapFileInfo.DebugFile)
                    {
                        System.Diagnostics.Debug.WriteLine(DEBUG_SIGNATURE_BLOCK + this.signatureBlock);
                    }
                    return(null);
                }

                if (queryParameters.useTileBitmask)
                {
                    // get the way tile bitmask (2 bytes)
                    int tileBitmask = this.readBuffer.Readshort();
                    // check if the way is inside the requested tile
                    if ((queryParameters.queryTileBitmask & tileBitmask) == 0)
                    {
                        // skip the rest of the way and continue with the next way
                        this.readBuffer.SkipBytes(wayDataSize - 2);
                        continue;
                    }
                }
                else
                {
                    // ignore the way tile bitmask (2 bytes)
                    this.readBuffer.SkipBytes(2);
                }

                // get the special byte which encodes multiple flags
                byte specialbyte = (byte)this.readBuffer.ReadByte();

                // bit 1-4 represent the layer
                byte layer = (byte)((specialbyte & WAY_LAYER_BITMASK) >> WAY_LAYER_SHIFT);
                // bit 5-8 represent the number of tag IDs
                byte numberOfTags = (byte)(specialbyte & WAY_NUMBER_OF_TAGS_BITMASK);

                List <Tag> tags = new List <Tag>();

                for (byte tagIndex = numberOfTags; tagIndex != 0; --tagIndex)
                {
                    int tagId = this.readBuffer.ReadUnsignedInt();
                    if (tagId < 0 || tagId >= wayTags.Length)
                    {
                        System.Diagnostics.Debug.WriteLine("invalid way tag ID: " + tagId);
                        return(null);
                    }
                    tags.Add(wayTags[tagId]);
                }

                // get the feature bitmask (1 byte)
                byte featurebyte = (byte)this.readBuffer.ReadByte();

                // bit 1-6 enable optional features
                bool featureName                   = (featurebyte & WAY_FEATURE_NAME) != 0;
                bool featureHouseNumber            = (featurebyte & WAY_FEATURE_HOUSE_NUMBER) != 0;
                bool featureRef                    = (featurebyte & WAY_FEATURE_REF) != 0;
                bool featureLabelPosition          = (featurebyte & WAY_FEATURE_LABEL_POSITION) != 0;
                bool featureWayDataBlocksbyte      = (featurebyte & WAY_FEATURE_DATA_BLOCKS_byte) != 0;
                bool featureWayDoubleDeltaEncoding = (featurebyte & WAY_FEATURE_DOUBLE_DELTA_ENCODING) != 0;

                // check if the way has a name
                if (featureName)
                {
                    tags.Add(new Tag(TAG_KEY_NAME, this.readBuffer.ReadUTF8Encodedstring()));
                }

                // check if the way has a house number
                if (featureHouseNumber)
                {
                    tags.Add(new Tag(TAG_KEY_HOUSE_NUMBER, this.readBuffer.ReadUTF8Encodedstring()));
                }

                // check if the way has a reference
                if (featureRef)
                {
                    tags.Add(new Tag(TAG_KEY_REF, this.readBuffer.ReadUTF8Encodedstring()));
                }

                GeoPoint labelPosition = readOptionalLabelPosition(featureLabelPosition);

                int wayDataBlocks = readOptionalWayDataBlocksbyte(featureWayDataBlocksbyte);
                if (wayDataBlocks < 1)
                {
                    System.Diagnostics.Debug.WriteLine("invalid number of way data blocks: " + wayDataBlocks);
                    return(null);
                }

                for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; ++wayDataBlock)
                {
                    GeoPointList2 wayNodes = processWayDataBlock(featureWayDoubleDeltaEncoding);
                    if (wayNodes == null)
                    {
                        return(null);
                    }

                    ways.Add(new Way(layer, tags, wayNodes, labelPosition));
                }
            }

            return(ways);
        }
Exemplo n.º 2
0
        private MapReadResult processBlocks(QueryParameters queryParameters, SubFileParameter subFileParameter)
        {
            bool queryIsWater       = true;
            bool queryReadWaterInfo = false;

            MapReadResultBuilder mapReadResultBuilder = new MapReadResultBuilder();

            // read and process all blocks from top to bottom and from left to right
            for (long row = queryParameters.fromBlockY; row <= queryParameters.toBlockY; ++row)
            {
                for (long column = queryParameters.fromBlockX; column <= queryParameters.toBlockX; ++column)
                {
                    // calculate the actual block number of the needed block in the file
                    long blockNumber = row * subFileParameter.BlocksWidth + column;

                    // get the current index entry
                    long currentBlockIndexEntry = this.databaseIndexCache.getIndexEntry(subFileParameter, blockNumber);

                    // check if the current query would still return a water tile
                    if (queryIsWater)
                    {
                        // check the water flag of the current block in its index entry
                        queryIsWater      &= (currentBlockIndexEntry & BITMASK_INDEX_WATER) != 0;
                        queryReadWaterInfo = true;
                    }

                    // get and check the current block pointer
                    long currentBlockpointer = currentBlockIndexEntry & BITMASK_INDEX_OFFSET;
                    if (currentBlockpointer < 1 || currentBlockpointer > subFileParameter.SubFileSize)
                    {
                        System.Diagnostics.Debug.WriteLine("invalid current block pointer: " + currentBlockpointer);
                        System.Diagnostics.Debug.WriteLine("subFileSize: " + subFileParameter.SubFileSize);
                        return(null);
                    }

                    long nextBlockpointer;
                    // check if the current block is the last block in the file
                    if (blockNumber + 1 == subFileParameter.NumberOfBlocks)
                    {
                        // set the next block pointer to the end of the file
                        nextBlockpointer = subFileParameter.SubFileSize;
                    }
                    else
                    {
                        // get and check the next block pointer
                        nextBlockpointer = this.databaseIndexCache.getIndexEntry(subFileParameter, blockNumber + 1)
                                           & BITMASK_INDEX_OFFSET;
                        if (nextBlockpointer > subFileParameter.SubFileSize)
                        {
                            System.Diagnostics.Debug.WriteLine("invalid next block pointer: " + nextBlockpointer);
                            System.Diagnostics.Debug.WriteLine("sub-file size: " + subFileParameter.SubFileSize);
                            return(null);
                        }
                    }

                    // calculate the size of the current block
                    int currentBlockSize = (int)(nextBlockpointer - currentBlockpointer);
                    if (currentBlockSize < 0)
                    {
                        System.Diagnostics.Debug.WriteLine("current block size must not be negative: " + currentBlockSize);
                        return(null);
                    }
                    else if (currentBlockSize == 0)
                    {
                        // the current block is empty, continue with the next block
                        continue;
                    }
                    else if (currentBlockSize > BufferStream.MAXIMUM_BUFFER_SIZE)
                    {
                        // the current block is too large, continue with the next block
                        System.Diagnostics.Debug.WriteLine("current block size too large: " + currentBlockSize);
                        continue;
                    }
                    else if (currentBlockpointer + currentBlockSize > this.fileSize)
                    {
                        System.Diagnostics.Debug.WriteLine("current block largher than file size: " + currentBlockSize);
                        return(null);
                    }

                    // seek to the current block in the map file
                    this.inputFile.Seek(subFileParameter.StartAddress + currentBlockpointer, SeekOrigin.Begin);

                    // read the current block into the buffer
                    if (!this.readBuffer.ReadFromFile(currentBlockSize))
                    {
                        // skip the current block
                        System.Diagnostics.Debug.WriteLine("reading current block has failed: " + currentBlockSize);
                        return(null);
                    }

                    // calculate the top-left coordinates of the underlying tile
                    this.tile = new Tile(
                        subFileParameter.BoundaryTileLeft + column,
                        subFileParameter.BoundaryTileTop + row,
                        subFileParameter.BaseZoomLevel,
                        Projection.TileSize
                        );
                    this.tilePosition = Projection.MappointToGeoPoint(tile.MapPoint1);

                    try {
                        NodeWayBundle nodeWayBundle = ProcessBlock(queryParameters, subFileParameter);
                        mapReadResultBuilder.Add(nodeWayBundle);
                    } catch (IndexOutOfRangeException e) {
                        System.Diagnostics.Debug.WriteLine(e.Message);
                    }
                }
            }

            // the query is finished, was the water flag set for all blocks?
            if (queryIsWater && queryReadWaterInfo)
            {
                mapReadResultBuilder.isWater = true;
            }

            return(mapReadResultBuilder.build());
        }