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); } }
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); }