private void FilterBySigma(Int32 prmSigma)
        {
            Int32 pointsRemoved;

            do
            {
                pointsRemoved = 0;
                IEnumerable <TcReportPoint3D> acceptedPoints = ReportPoints.Where(iter => iter.Status == TePointStatus.Accepted);
                if (acceptedPoints.Count() > 0)
                {
                    IEnumerable <Double> differences = acceptedPoints.Select(iter => iter.Difference);
                    m_AvgDifference = Math.Round(differences.Average(), 2);
                    m_Sigma         = (Single)Math.Round(TcMathUtil.StDev(differences, m_AvgDifference), 2);
                    Single diff = 0.0f;

                    foreach (TcReportPoint3D point in acceptedPoints)
                    {
                        diff = (Single)Math.Round(Math.Abs(point.Difference - m_AvgDifference), 2);
                        if (diff > prmSigma * m_Sigma)
                        {
                            point.Status = TePointStatus.OutOfSigma;
                            pointsRemoved++;
                        }
                    }
                }
            } while (pointsRemoved != 0);
        }
        public void CalculateReportPoints(Single prmZAdj)
        {
            Samples      = 0;
            ReportPoints = new TcReportPoint3D[HeightPointCount];

            var j = 0;

            foreach (var gcp in HeightPoints)
            {
                //no xy adjustments
                var subject   = new TcReportPoint3D(gcp.X - m_XAdjustment, gcp.Y - m_YAjustment, gcp.Z);
                var lidarNear = Tree.NearestNeighbours(subject, Program.options.Radius);

                //nearby lidar
                if (lidarNear.Count > 0)
                {
                    subject.LidarHeight = (float)Math.Round((float)lidarNear.Average(i => i.Z), 2);

                    Samples++;

                    //filter out bad quality points.
                    if (subject.Difference > c_QATolerance)
                    {
                        subject.Status = TePointStatus.BadQuality;
                    }
                    else
                    {
                        subject.Status = TePointStatus.Accepted;
                    }
                }
                else
                {
                    subject.Status = TePointStatus.NotCovered;
                }

                ReportPoints[j] = new TcReportPoint3D(m_Heights[j], subject.LidarHeight, prmZAdj, subject.Status)
                {
                    Id = j
                };
                j++;
            }

            // Update the average.
            List <Double> acceptedPoints = ReportPoints.Where(iter => iter.Status == TePointStatus.Accepted).Select(iter => iter.Difference).ToList();

            if (acceptedPoints.Count > 0)
            {
                m_AvgDifference = Math.Round(acceptedPoints.Average(), 2);
                m_Sigma         = (Single)Math.Round(TcMathUtil.StDev(acceptedPoints, m_AvgDifference), 2);
            }

            FilterBySigma(3);
        }
        //-----------------------------------------------------------------------------

        static public TcHistogram Get(IEnumerable <Double> prmData, Double prmScaling)
        {
            List <Single> filteredPoints = new List <Single>();
            Single        minZ           = Single.MaxValue;
            Single        maxZ           = Single.MinValue;
            Double        sum            = 0.0;
            Int32         count          = 0;

            foreach (Single height in prmData)
            {
                if (height != TcAtlassUtilGlobal.TorNullHeight)
                {
                    count++;
                    sum += height;
                    minZ = Math.Min(minZ, height);
                    maxZ = Math.Max(maxZ, height);
                    filteredPoints.Add(height);
                }
            }

            if (count == 0)
            {
                return(null);
            }

            Single avg   = (Single)Math.Round(sum / count, 2);
            Single stDev = (Single)Math.Round(TcMathUtil.StDev(filteredPoints, avg), 2);

            Int32 min = (Int32)Math.Round((minZ - avg) * prmScaling);
            Int32 max = (Int32)Math.Round((maxZ - avg) * prmScaling);

            Int32[] steps = Enumerable.Range(min, max - min + 1).ToArray();
            Dictionary <Single, Int32> histogram = new Dictionary <Single, Int32>();

            for (int i = 0; i < steps.Length; i++)
            {
                histogram.Add(steps[i], 0);
            }

            for (int i = 0; i < count; i++)
            {
                var key = (Single)Math.Round((filteredPoints[i] - avg) * prmScaling);

                if (histogram.ContainsKey(key))
                {
                    histogram[key]++;
                }
            }

            return(new TcHistogram(avg, stDev, histogram.Keys.ToList(), histogram.Values.ToList()));
        }
Exemple #4
0
        //-----------------------------------------------------------------------------

        public Double GetLevellingGridHeight(List <TcLasPointBase> prmPoints)
        {
            // When there is no point.
            if (prmPoints.Count == 0)
            {
                return(TcConstants.TorNullValue32Bit);
            }

            // When there is less than 2 points with last echo.
            List <Double> heights   = new List <Double>();
            Double        maxHeight = Double.MinValue;
            Double        minHeight = Double.MaxValue;

            for (int i = 0; i < prmPoints.Count; i++)
            {
                if (prmPoints[i].ReturnNumber == prmPoints[i].NumberOfReturns)
                {
                    heights.Add(prmPoints[i].Z);
                    maxHeight = Math.Max(maxHeight, prmPoints[i].Z);
                    minHeight = Math.Min(minHeight, prmPoints[i].Z);
                }
            }

            if (heights.Count <= 2 || (maxHeight - minHeight > TcConstants.MaxToleranceForFlatPoints))
            {
                return(TcConstants.TorNullValue32Bit);
            }

            // Sort the heights.
            //TcSort.Quicksort(heights, 0, heights.Count - 1);

            Double avg   = TcMathUtil.Average(heights);
            Double stDev = TcMathUtil.StDev(heights, avg);
            Int32  count = 0;
            Double sum   = 0.0;

            // Get points inside 2 sigma boundary.
            for (int i = 0; i < heights.Count; i++)
            {
                if (Math.Abs(heights[i] - avg) < 2 * stDev)
                {
                    sum += heights[i];
                    count++;
                }
            }

            return(count > 0 ? sum / count : TcConstants.TorNullValue32Bit);
        }
Exemple #5
0
        static void Main(string[] args)
        {
            options = new Options();

            if (CommandLine.Parser.Default.ParseArguments(args, options))
            {
                factor = options.Factor;
                TS     = options.GridSize;

                var    fs    = Stopwatch.StartNew();
                string input = options.InputFile;

                if (string.IsNullOrEmpty(options.OutputFile))
                {
                    if (options.OutputDir != string.Empty)
                    {
                        options.OutputFile = new FileInfo(options.InputFile).Directory.FullName;
                        options.OutputFile = Path.Combine(options.OutputDir, Path.GetFileNameWithoutExtension(options.InputFile) + ".xyz");
                        options.LogFile    = Path.Combine(options.OutputDir, Path.GetFileNameWithoutExtension(options.InputFile) + ".txt");
                    }
                }


                if (!new FileInfo(options.OutputFile).Directory.Exists)
                {
                    new FileInfo(options.OutputFile).Directory.Create();
                }



                #region Title ASCII
                Console.ForegroundColor = ConsoleColor.Green;
                RConsole.Write(@"


                     db    88888 8       db    .d88b. .d88b. 
                    dPYb     8   8      dPYb   YPwww. YPwww. 
                   dPwwYb    8   8     dPwwYb      d8     d8 
                  dP    Yb   8   8888 dP    Yb `Y88P' `Y88P' 
                                                             
                      888b. 8888 888b. .d88b. 888b. 88888 
                      8  .8 8www 8  .8 8P  Y8 8  .8   8   
                      8wwK' 8    8wwP' 8b  d8 8wwK'   8   
                      8  Yb 8888 8     `Y88P' 8  Yb   8   
                                                          
                  888b. 8       db    8b  8 8b  8 8888 888b. 
                  8  .8 8      dPYb   8Ybm8 8Ybm8 8www 8  .8 
                  8wwP' 8     dPwwYb  8   8 8   8    8wwK 
                  8     8888 dP    Yb 8   8 8   8 8888 8  Yb 
                                                             
            ");
                Console.ForegroundColor = ConsoleColor.White;
                #endregion

                #region ASCII Parameter Table
                Console.ForegroundColor = ConsoleColor.Magenta;
                RConsole.WriteLine("               Version: Test Build 0.0.1");
                Console.ForegroundColor = ConsoleColor.White;
                RConsole.WriteLine("                    ---------------------------------------                    ");
                RConsole.WriteLine("");
                RConsole.Write(@"
.......................
: Parameter :   Value :
:...........:.........:
: Scale     :    {0:00}   :
: Grid Size :    {1:00}   :
:...........:.........:
", factor, TS);


                RConsole.WriteLine("");

                #endregion

                #region ASCII I/O Table
                RConsole.WriteLine(@"
+--------+---------------------------------------------------------------------+
| Param  |  Values                                                             |
+--------+---------------------------------------------------------------------+
| Input  | {0, -43}                         |
| Output | {1, -43}                         |
| Log    | {2, -43}                         |
+--------+---------------------------------------------------------------------+
", Path.GetFileName(options.InputFile), options.OutputFile,
                                   Path.GetFileName(options.LogFile));
                #endregion

                if (!File.Exists(input))
                {
                    RConsole.WriteLine("IO Error: input {0} file does not exist.", input);
                    return;
                }

                RConsole.WriteLine("Job Started {0} - {1}", Path.GetFileNameWithoutExtension(input), DateTime.Now.ToString());

                try
                {
                    #region LAS READER / PRE GRID
                    using (var readerobj = new TcLasReader(input))
                    {
                        var s = Stopwatch.StartNew();
                        RConsole.WriteLine("Reading {0} Points", readerobj.TotalPoints);

                        var points = readerobj.ReadPoints(readerobj.TotalPoints, readerobj.Header);
                        s.Stop();
                        RConsole.WriteLine("Reading {0} Points - Finished {1} secs", readerobj.TotalPoints, Math.Ceiling((double)s.ElapsedMilliseconds / 1000));

                        var set = points.GetEnumerator();

                        #region gridding
                        s = Stopwatch.StartNew();

                        var minX = readerobj.Header.MinX;
                        var minY = readerobj.Header.MinY;
                        var maxX = readerobj.Header.MaxX;
                        var maxY = readerobj.Header.MaxY;

                        int X0 = (int)(minX - (minX % (TS * factor)));
                        int Y0 = (int)(minY - (minY % (TS * factor)));
                        int X1 = (int)(maxX - (maxX % (TS * factor)));
                        int Y1 = (int)(maxY - (maxY % (TS * factor)));

                        double dX = X1 - X0;
                        double dY = Y1 - Y0;

                        dX /= TS * factor;
                        dY /= TS * factor;

                        var tiles_x = (int)dX;
                        var tiles_y = (int)dY;

                        preMem  = GC.GetTotalMemory(true);
                        Tiles   = new Tile[tiles_x, tiles_y];
                        postMem = GC.GetTotalMemory(true);
                        calMem  = ToReadableMemUnit((int)Math.Ceiling((double)postMem % preMem));
                        RConsole.WriteLine("Gridding Data Into Tiles {0}/{1} {2}", tiles_x, tiles_y, "- Memory Used: " + calMem);

                        preMem = GC.GetTotalMemory(true);

                        int reportStep      = 0;
                        int pointsProcessed = 0;
                        int interval        = points.Length > 1000000
                                    ? 1000000 : points.Length > 100000
                                    ? 10000 : points.Length > 10000
                                    ? 10000 : points.Length > 1000
                                    ? 1000 : points.Length > 100
                                    ? 100 : points.Length > 10
                                    ? 10 : 10;

                        while (set.MoveNext())
                        {
                            pointsProcessed++;

                            if (reportStep++ % interval == 0)
                            {
                                var percent = Clamp((int)Math.Ceiling(
                                                        (double)pointsProcessed * 100
                                                        / points.Length), 0, 100);
                            }



                            var point = (TcLasPointBase)set.Current;

                            if (point.ReturnNumber != point.NumberOfReturns)
                            {
                                continue;
                            }


                            var x = Math.Round(point.X, 2);
                            var y = Math.Round(point.Y, 2);
                            var z = Math.Round(point.Z, 2);

                            var X = (int)(x - (x % (TS * factor)));
                            var Y = (int)(y - (y % (TS * factor)));
                            var J = (int)(X - minX) / (TS * factor);
                            var I = (int)(Y - minY) / (TS * factor);

                            options.Buffer = Clamp(options.Buffer, 1, 20);

                            J = Clamp(J, 0, tiles_x - options.Buffer);
                            I = Clamp(I, 0, tiles_y - options.Buffer);

                            if (Tiles[J, I] == null)
                            {
                                Tiles[J, I] = new Tile
                                {
                                    East  = J,
                                    North = I,
                                };

                                Tiles[J, I].XVertices.Add(x);
                                Tiles[J, I].YVertices.Add(y);
                                Tiles[J, I].ZVertices.Add(z);
                            }
                            else
                            {
                                Tiles[J, I].XVertices.Add(x);
                                Tiles[J, I].YVertices.Add(y);
                                Tiles[J, I].ZVertices.Add(z);
                            }
                        }

                        s.Stop();

                        postMem = GC.GetTotalMemory(true);
                        calMem  = ToReadableMemUnit((int)Math.Ceiling((double)postMem % preMem));

                        RConsole.WriteLine("Gridded Data Into {0} Tiles - Finished {1} secs - Memory Used: {2}", true, Tiles.Length, Math.Ceiling((double)s.ElapsedMilliseconds / 1000)
                                           , calMem);
                        #endregion
                    }
                    #endregion
                }
                catch (Exception error)
                {
                    RConsole.WriteLine("Error Las Reader / Pre Gridder\n {0}\n{1}\n{2}",
                                       error.StackTrace,
                                       error.Source,
                                       error.Message);


                    return;
                }
                finally
                {
                    fs.Stop();
                    RConsole.WriteLine("Job Completed - {0} secs - {1}", Math.Ceiling((double)fs.ElapsedMilliseconds / 1000), DateTime.Now.ToString());
                }

                try
                {
                    #region Extracting Planars
                    GC.Collect();
                    GC.SuppressFinalize(Tiles);
                    preMem = GC.GetTotalMemory(true);
                    calMem = ToReadableMemUnit((int)Math.Ceiling((double)postMem % preMem));
                    RConsole.WriteLine("{0} Memory Truncated. ", true, calMem);


                    preMem = GC.GetTotalMemory(true);
                    RConsole.WriteLine("{0}", true, "Detecting Planar Surfaces");


                    var sw = Stopwatch.StartNew();

                    if (Tiles.GetLength(0) == 0 ||
                        Tiles.GetLength(1) == 0)
                    {
                        return;
                    }

                    var width          = Tiles.GetLength(0);
                    var height         = Tiles.GetLength(1);
                    var processed      = 0;
                    var tinterval      = height > 100 ? 100 : 10;
                    var removed        = 0;
                    var sigmas         = new List <double>();
                    var hvalues        = new List <double>();
                    var hinterval      = 3;
                    var tilesprocessed = 0;

                    for (int j = 0; j < height; j++)
                    {
                        for (int i = 0; i < width; i++)
                        {
                            if (Tiles[i, j] != null)
                            {
                                var tile      = Tiles[i, j];
                                var heights   = new List <Double>();
                                var maxHeight = Double.MinValue;
                                var minHeight = Double.MaxValue;

                                foreach (var h in tile.ZVertices)
                                {
                                    heights.Add(h);
                                    maxHeight = Math.Max(maxHeight, h);
                                    minHeight = Math.Min(minHeight, h);
                                }

                                //filter out flat planars above .20cm tolerance.
                                if (heights.Count <= 2 || (maxHeight - minHeight > 0.20f))
                                {
                                    Tiles[i, j] = null;
                                    continue;
                                }


                                var avg     = TcMathUtil.Average(heights);
                                var stDev   = TcMathUtil.StDev(heights, avg);
                                var count   = 0;
                                var sum     = 0.0;
                                var indices = new List <double>();


                                for (int p = 0; p < heights.Count; p++)
                                {
                                    if (Math.Abs(heights[p] - avg) < 2 * stDev)
                                    {
                                        sum += heights[p];
                                        count++;
                                    }
                                    else
                                    {
                                        indices.Add(heights[p]);
                                    }
                                }

                                var result = count > 0
                                    ? sum / count : TcConstants.TorNullValue32Bit;

                                int k = 0;


                                while (k < tile.ZVertices.Count)
                                {
                                    if (!indices.Contains(Tiles[i, j].ZVertices[k]) &&
                                        result != TcConstants.TorNullValue32Bit)
                                    {
                                        Tiles[i, j].ZVertices[k] = result;
                                    }
                                    else
                                    {
                                        Tiles[i, j].XVertices.RemoveAt(k);
                                        Tiles[i, j].YVertices.RemoveAt(k);
                                        Tiles[i, j].ZVertices.RemoveAt(k);
                                        removed++;
                                    }

                                    k++;
                                }
                            }
                        }

                        if (processed++ % tinterval == 0)
                        {
                            var percent = Clamp(
                                (int)Math.Ceiling((double)processed * 100
                                                  / height), 0, 100);
                        }


                        if (tilesprocessed++ % hinterval == 0 && sigmas.Count > 0)
                        {
                            hvalues = new List <double>();
                            sigmas  = new List <double>();
                        }
                    }


                    preMem = GC.GetTotalMemory(true);
                    calMem = ToReadableMemUnit((int)Math.Ceiling((double)postMem % preMem));

                    RConsole.WriteLine("Non-Flat Points Removed From Data: {0}", removed);
                    RConsole.WriteLine("{0}", true, "Permuting Flat Points - Finished " + Math.Ceiling((double)sw.ElapsedMilliseconds / 1000)
                                       + " secs - Memory Used: " + calMem);

                    GC.Collect();
                    GC.SuppressFinalize(Tiles);
                    postMem = GC.GetTotalMemory(true);
                    calMem  = ToReadableMemUnit((int)Math.Ceiling((double)postMem % preMem));
                    RConsole.WriteLine("{0} Memory Truncated. ", true, calMem);


                    preMem = GC.GetTotalMemory(true);

                    RConsole.WriteLine("{0}", true, "Saving Planar Surfaces to " + options.OutputFile);
                    sw = Stopwatch.StartNew();


                    using (var sr = File.CreateText(options.OutputFile))
                    {
                        processed = 0;
                        tinterval = height > 100 ? 100 : 10;

                        for (int j = 0; j < height; j++)
                        {
                            for (int i = 0; i < width; i++)
                            {
                                if (Tiles[i, j] != null)
                                {
                                    var tile = Tiles[i, j];

                                    for (int p = 0; p < tile.XVertices.Count; p++)
                                    {
                                        sr.WriteLine("{0:000000.00} {1:000000.00} {2:000.00}",
                                                     tile.XVertices[p],
                                                     tile.YVertices[p],
                                                     tile.ZVertices[p]);
                                    }
                                }
                            }

                            if (processed++ % tinterval == 0)
                            {
                                var percent = Clamp(
                                    (int)Math.Ceiling((double)processed * 100
                                                      / height), 0, 100);
                            }
                        }
                    }

                    sw.Stop();

                    preMem = GC.GetTotalMemory(true);
                    calMem = ToReadableMemUnit((int)Math.Ceiling((double)postMem % preMem));


                    RConsole.WriteLine("Saved permuted flat points - Finished {1} secs - Memory Used: {2}", true, Tiles.Length, Math.Ceiling((double)sw.ElapsedMilliseconds / 1000)
                                       , calMem);



                    preMem = GC.GetTotalMemory(true);
                    GC.Collect();
                    GC.SuppressFinalize(Tiles);
                    postMem = GC.GetTotalMemory(true);
                    calMem  = ToReadableMemUnit((int)Math.Ceiling((double)postMem % preMem));
                    RConsole.WriteLine("{0} Memory Truncated. ", true, calMem);
                    #endregion
                }
                catch (Exception error)
                {
                    RConsole.WriteLine("Error Flattening\n {0}\n{1}\n{2}",
                                       error.StackTrace,
                                       error.Source,
                                       error.Message);


                    return;
                }
                finally
                {
                    fs.Stop();
                    RConsole.WriteLine("Job Completed - {0} secs - {1}", Math.Ceiling((double)fs.ElapsedMilliseconds / 1000), DateTime.Now.ToString());
                }
            }
            else
            {
                options.GetUsage();
            }
        }