Пример #1
0
            static public IsohypseMovement GetOppositeMovement(IsohypseMovement movement)
            {
                switch (movement)
                {
                case IsohypseMovement.East:
                    return(IsohypseMovement.West);

                case IsohypseMovement.North:
                    return(IsohypseMovement.South);

                case IsohypseMovement.South:
                    return(IsohypseMovement.North);

                case IsohypseMovement.West:
                    return(IsohypseMovement.East);

                default:
                    return(IsohypseMovement.None);
                }
            }
Пример #2
0
        private IsohypseMovements ExtractIsohypseMovements(
            IRasterDigitalElevationModel dem,
            double isohypseElevation,
            Array2 <IsohypseMovement> movements,
            Array2 <byte> flags,
            int startingX,
            int startingY)
        {
            IsohypseMovements isohypseMovements = new IsohypseMovements(isohypseElevation);

            isohypseMovements.StartingX = startingX;
            isohypseMovements.StartingY = startingY;

            int x = isohypseMovements.StartingX;
            int y = isohypseMovements.StartingY;
            int lastX = 0, lastY = 0;
            IsohypseMovement lastMovement = IsohypseMovement.None;

            bool foundOneEnd = false;

            while (true)
            {
                // if we reached the end of the grid
                if (x < 0 || y < 0 || x >= dem.LonLength - 1 || y >= dem.LatLength - 1)
                {
                    // have we already found one end of the segment?
                    if (false == foundOneEnd)
                    {
                        // we haven't...
                        foundOneEnd = true;

                        // ... so reverse the segment and start moving from the other end
                        int oldStartingX = isohypseMovements.StartingX;
                        int oldStartingY = isohypseMovements.StartingY;

                        isohypseMovements.ReverseIsohypseMovements(x, y);

                        x = oldStartingX;
                        y = oldStartingY;
                    }
                    else
                    {
                        // we have, so we can exit
                        break;
                    }
                }

                if (x == isohypseMovements.StartingX &&
                    y == isohypseMovements.StartingY &&
                    isohypseMovements.Movements.Count > 0)
                {
                    // we found the starting point, this is a closed polygon
                    isohypseMovements.IsClosed = true;
                    break;
                }

                IsohypseMovement currentCellMovement = movements.GetValue(x, y);

                bool movementFound = false;

                for (int i = 0; i < 4; i++)
                {
                    IsohypseMovement movementConsidered = (IsohypseMovement)(1 << i);

                    if (0 != (currentCellMovement & movementConsidered))
                    {
                        int nextX = x, nextY = y;
                        switch (movementConsidered)
                        {
                        case IsohypseMovement.East:
                            nextX++;
                            break;

                        case IsohypseMovement.North:
                            nextY--;
                            break;

                        case IsohypseMovement.South:
                            nextY++;
                            break;

                        case IsohypseMovement.West:
                            nextX--;
                            break;

                        default:
                            throw new NotImplementedException();
                        }

                        // find the opposite movement of the last movement
                        IsohypseMovement oppositeMovement = IsohypseMovements.GetOppositeMovement(lastMovement);

                        if (lastMovement != IsohypseMovement.None)
                        {
                            // check that we haven't moved back
                            if (nextX == lastX && nextY == lastY)
                            {
                                continue;
                            }

                            // special case when all movements are possible
                            if ((((int)currentCellMovement) & 0xf) == 0xf)
                            {
                                IsohypseMovement movementCombination = movementConsidered | oppositeMovement;

                                // check that we haven't moved in such a way as to make the polygon cross itself
                                if ((movementCombination & (IsohypseMovement.North | IsohypseMovement.South))
                                    == (IsohypseMovement.North | IsohypseMovement.South))
                                {
                                    continue;
                                }

                                // check that we haven't moved in such a way as to make the polygon cross itself
                                if ((movementCombination & (IsohypseMovement.West | IsohypseMovement.East))
                                    == (IsohypseMovement.West | IsohypseMovement.East))
                                {
                                    continue;
                                }

                                // check that the movement is the right one in regards to cells elevations
                                if (flags.GetValue(x, y) == 5)
                                {
                                    if (movementCombination == (IsohypseMovement.South | IsohypseMovement.East) ||
                                        movementCombination == (IsohypseMovement.North | IsohypseMovement.West))
                                    {
                                        continue;
                                    }
                                }
                                else if (flags.GetValue(x, y) == 10)
                                {
                                    if (movementCombination == (IsohypseMovement.South | IsohypseMovement.West) ||
                                        movementCombination == (IsohypseMovement.North | IsohypseMovement.East))
                                    {
                                        continue;
                                    }
                                }
                                else
                                {
                                    throw new NotImplementedException();
                                }
                            }
                        }

                        isohypseMovements.Movements.Add(movementConsidered);

                        // remove the used movement from the array
                        movements.SetValue(movements.GetValue(x, y) & ~movementConsidered, x, y);

                        // remove this opposite movement from the array
                        movements.SetValue(movements.GetValue(x, y) & ~oppositeMovement, x, y);

                        lastX        = x;
                        lastY        = y;
                        lastMovement = movementConsidered;
                        x            = nextX;
                        y            = nextY;

                        movementFound = true;

                        break;
                    }
                }

                if (movementFound == false)
                {
                    throw new NotImplementedException();
                }
            }

            return(isohypseMovements);
        }