예제 #1
0
        public void Isoplete(IRasterDigitalElevationModel dem, double elevationStep, NewIsohypseCallback callback)
        {
            DigitalElevationModelStatistics statistics = dem.CalculateStatistics();

            double minElevation = Math.Floor(statistics.MinElevation / elevationStep) * elevationStep;
            double maxElevation = Math.Floor(statistics.MaxElevation / elevationStep) * elevationStep;

            //if (visualizer != null)
            //{
            //    GeoPosition geoPosMin = dem.GetGeoPosition (0, 0, false);
            //    GeoPosition geoPosMax = dem.GetGeoPosition (dem.LonLength, dem.LatLength, false);

            //    visualizer.Initialize (geoPosMin.Longitude, geoPosMin.Latitude,
            //        geoPosMax.Longitude, geoPosMax.Latitude);
            //}

            Array2 <byte>             flags     = new Array2 <byte> (dem.LonLength - 1, dem.LatLength - 1);
            Array2 <IsohypseMovement> movements = new Array2 <IsohypseMovement> (dem.LonLength - 1, dem.LatLength - 1);

            int[,] adjacentCells = new int[, ] {
                { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
            };

            // foreach elevation step
            for (double isoElev = minElevation; isoElev <= maxElevation; isoElev += elevationStep)
            {
                activityLogger.Log(ActivityLogLevel.Normal, String.Format(System.Globalization.CultureInfo.InvariantCulture,
                                                                          "Analyzing elevation {0}", isoElev));

                //if (visualizer != null)
                //{
                //    GeoPosition geoPosMin = dem.GetGeoPosition (0, 0, false);
                //    GeoPosition geoPosMax = dem.GetGeoPosition (dem.LongLength, dem.LatLength, false);

                //    visualizer.Initialize (geoPosMin.Longitude, geoPosMin.Latitude,
                //        geoPosMax.Longitude, geoPosMax.Latitude);

                //    for (int x = 0; x < dem.LongLength; x++)
                //    {
                //        for (int y = 0; y < dem.LatLength; y++)
                //        {
                //            int elevation = dem.GetElevation (x, y);
                //            GeoPosition geoPos = dem.GetGeoPosition (x, y);

                //            string color = elevation >= isoElev ? "orange" : "yellow";

                //            visualizer.DrawPoint (color, geoPos.Longitude, geoPos.Latitude);
                //            visualizer.DrawText ("pink", geoPos.Longitude, geoPos.Latitude, elevation.ToString ());
                //        }
                //    }
                //}

                Isohypse isohypse = new Isohypse(isoElev);

                flags.Initialize(0);
                movements.Initialize(0);

                for (int x = 0; x < dem.LonLength - 1; x++)
                {
                    for (int y = 0; y < dem.LatLength - 1; y++)
                    {
                        byte cellCharacteristic = 0;

                        for (int i = 0; i < adjacentCells.GetLength(0); i++)
                        {
                            double adjacentCellElev = dem.GetElevationForDataPoint(x + adjacentCells[i, 0], y + adjacentCells[i, 1]);
                            if (adjacentCellElev >= isoElev)
                            {
                                cellCharacteristic++;
                                flags.SetValue((byte)(flags.GetValue(x, y) | (byte)(1 << i)), x, y);
                            }
                        }

                        // skip cells which are definitively not along the isohypse
                        if (cellCharacteristic == 0 || cellCharacteristic == 4)
                        {
                            continue;
                        }

                        if (cellCharacteristic == 2)
                        {
                            int maskedFlags = flags.GetValue(x, y) & 0x9;
                            if (maskedFlags == 0 || maskedFlags == 0x9)
                            {
                                movements.SetValue(IsohypseMovement.North | IsohypseMovement.South, x, y);
                            }
                            else
                            {
                                maskedFlags = flags.GetValue(x, y) & 0x3;
                                if (maskedFlags == 0 || maskedFlags == 0x3)
                                {
                                    movements.SetValue(IsohypseMovement.West | IsohypseMovement.East, x, y);
                                }

                                else
                                {
                                    movements.SetValue(
                                        IsohypseMovement.West | IsohypseMovement.East | IsohypseMovement.North | IsohypseMovement.South,
                                        x, y);
                                }
                            }
                        }
                        else
                        {
                            int maskedFlags = flags.GetValue(x, y) & 0x3;
                            if (maskedFlags != 0 && maskedFlags != 0x3)
                            {
                                movements.SetValue(movements.GetValue(x, y) | IsohypseMovement.North, x, y);
                            }

                            maskedFlags = flags.GetValue(x, y) & 0x6;
                            if (maskedFlags != 0 && maskedFlags != 0x6)
                            {
                                movements.SetValue(movements.GetValue(x, y) | IsohypseMovement.East, x, y);
                            }

                            maskedFlags = flags.GetValue(x, y) & 0xc;
                            if (maskedFlags != 0 && maskedFlags != 0xc)
                            {
                                movements.SetValue(movements.GetValue(x, y) | IsohypseMovement.South, x, y);
                            }

                            maskedFlags = flags.GetValue(x, y) & 0x9;
                            if (maskedFlags != 0 && maskedFlags != 0x9)
                            {
                                movements.SetValue(movements.GetValue(x, y) | IsohypseMovement.West, x, y);
                            }
                        }

                        //if (visualizer != null)
                        //{
                        //    if (cellCharacteristic > 0 && cellCharacteristic < 4)
                        //    {
                        //        GeoPosition geoPos = dem.GetGeoPosition (x + 0.5, y + 0.5);

                        //        if (movements.GetValue (x, y)
                        //            == (IsohypseMovement.West | IsohypseMovement.East | IsohypseMovement.North | IsohypseMovement.South))
                        //            visualizer.DrawText ("blue", geoPos.Longitude, geoPos.Latitude,
                        //                "X");

                        //        //visualizer.DrawText ("blue", geoPos.Longitude, geoPos.Latitude,
                        //        //    cellCharacteristic == 2 ? "K" : "T");

                        //        //List<Point2> points = new List<Point2> ();

                        //        //if ((movements[x, y] & IsohypseMovement.North) != 0)
                        //        //    points.Add (new Point2 (0.5, 0));
                        //        //if ((movements[x, y] & IsohypseMovement.East) != 0)
                        //        //    points.Add (new Point2 (1, 0.5));
                        //        //if ((movements[x, y] & IsohypseMovement.South) != 0)
                        //        //    points.Add (new Point2 (0.5, 1));
                        //        //if ((movements[x, y] & IsohypseMovement.West) != 0)
                        //        //    points.Add (new Point2 (0, 0.5));

                        //        //List<GeoPosition> geoPoints = new List<GeoPosition> ();

                        //        //foreach (Point2 point in points)
                        //        //    geoPoints.Add (dem.GetGeoPosition (x + point.X, y + point.Y));

                        //        //visualizer.DrawLine ("black", geoPoints[0].Longitude, geoPoints[0].Latitude,
                        //        //    geoPoints[1].Longitude, geoPoints[1].Latitude);

                        //        //if (geoPoints.Count > 2)
                        //        //    visualizer.DrawLine ("black", geoPoints[2].Longitude, geoPoints[2].Latitude,
                        //        //        geoPoints[3].Longitude, geoPoints[3].Latitude);
                        //    }
                        //}
                    }
                }

                for (int x = 0; x < dem.LonLength - 1; x++)
                {
                    for (int y = 0; y < dem.LatLength - 1; y++)
                    {
                        if (movements.GetValue(x, y) != IsohypseMovement.None)
                        {
                            IsohypseMovements isohypseMovements = ExtractIsohypseMovements(dem, isoElev, movements, flags, x, y);

                            Polyline isohypseSegment = ConstructIsohypseSegment(dem, isohypseMovements);

                            isohypseSegment.RemoveDuplicateVertices();

                            isohypse.AddSegment(isohypseSegment);

                            activityLogger.Log(ActivityLogLevel.Verbose, String.Format(System.Globalization.CultureInfo.InvariantCulture,
                                                                                       "Found segment with {0} vertices", isohypseSegment.VerticesCount));
                        }
                    }
                }

                if (isohypse.Segments.Count > 0)
                {
                    callback(isohypse);
                }

                //isoColl.AddIsohypse (isohypse);
            }
        }
예제 #2
0
        private Polyline ConstructIsohypseSegment(IRasterDigitalElevationModel dem, IsohypseMovements isohypseMovements)
        {
            Polyline polyline = new Polyline();

            polyline.IsClosed = isohypseMovements.IsClosed;

            int x = isohypseMovements.StartingX;
            int y = isohypseMovements.StartingY;

            bool checkedOrientation = false;
            bool shouldBeReversed   = false;

            foreach (IsohypseMovement movement in isohypseMovements.Movements)
            {
                int dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;

                switch (movement)
                {
                case IsohypseMovement.East:
                    x++;
                    dx1 = dx2 = x;
                    dy1 = y;
                    dy2 = y + 1;
                    break;

                case IsohypseMovement.North:
                    dx1 = x;
                    dx2 = x + 1;
                    dy1 = dy2 = y;
                    y--;
                    break;

                case IsohypseMovement.South:
                    y++;
                    dx1 = x + 1;
                    dx2 = x;
                    dy1 = dy2 = y;
                    break;

                case IsohypseMovement.West:
                    dx1 = dx2 = x;
                    dy1 = y + 1;
                    dy2 = y;
                    x--;
                    break;
                }

                double elevation1 = dem.GetElevationForDataPoint(dx1, dy1);
                double elevation2 = dem.GetElevationForDataPoint(dx2, dy2);

                // check the orientation of the isohypse
                if (false == checkedOrientation)
                {
                    // the right-side elevation should be higher
                    if (elevation2 < elevation1)
                    {
                        shouldBeReversed = true;
                    }
                }

                double factor = (isohypseMovements.IsohypseElevation - elevation1) / (elevation2 - elevation1);
                double ix, iy;
                ix = (factor * (dx2 - dx1) + dx1);
                iy = (factor * (dy2 - dy1) + dy1);
                GeoPosition     geoPos         = dem.GetGeoPosition(ix, iy);
                Point3 <double> isohypseVertex = new Point3 <double> (geoPos.Longitude, geoPos.Latitude, isohypseMovements.IsohypseElevation);

                polyline.AddVertex(isohypseVertex);
            }

            // now reverse the polyline if needed
            if (shouldBeReversed)
            {
                polyline.Reverse();
            }

            return(polyline);
        }
예제 #3
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);
        }