示例#1
0
        /// <summary>
        /// Insertion point
        /// </summary>
        /// <param name="region"></param>
        /// <param name="master"></param>
        public OctTree(
            BoundingBox masterRegion,
            IEnumerable <Vector3> masterColl,
            List <OctTree> baseList,
            float basesize = 0.010f)
        {
            List <Vector3> masterList = masterColl.ToList();

            if (masterList.Count.Equals(0))
            {
                return;
            }
            m_Points   = masterList;
            m_baseSize = basesize;
            //Set region's points
            m_Region = masterRegion;
            //Get dimension of master box
            Vector3 dimensions = m_Region.Max - m_Region.Min;
            //Halfway point of box
            Vector3 half = dimensions / 2f;
            //Center of box
            Vector3 center = m_Region.Min + half;

            //Smallest size box, send back to baselist
            if (dimensions.X <= m_baseSize && dimensions.Y <= m_baseSize &&
                dimensions.Z <= m_baseSize)
            {
                baseList.Add(this);
                Dims = dimensions;
            }
            else
            {
                bool firstpass = true;
                //Create set of boxes
                BoundingBox[] boxes = new BoundingBox[8];
                //Create holder for points
                List <Vector3>[] boxPoints = new List <Vector3> [8];
                m_PendingInsertion = new Queue <Vector3>(masterList);
                //Spin up all individual boxes
                boxes[0] = new BoundingBox(m_Region.Min, center);
                boxes[1] = new BoundingBox(new Vector3(center.X, m_Region.Min.Y, m_Region.Min.Z), new Vector3(m_Region.Max.X, center.Y, center.Z));
                boxes[2] = new BoundingBox(new Vector3(center.X, m_Region.Min.Y, center.Z), new Vector3(m_Region.Max.X, center.Y, m_Region.Max.Z));
                boxes[3] = new BoundingBox(new Vector3(m_Region.Min.X, m_Region.Min.Y, center.Z), new Vector3(center.X, center.Y, m_Region.Max.Z));
                boxes[4] = new BoundingBox(new Vector3(m_Region.Min.X, center.Y, m_Region.Min.Z), new Vector3(center.X, m_Region.Max.Y, center.Z));
                boxes[5] = new BoundingBox(new Vector3(center.X, center.Y, m_Region.Min.Z), new Vector3(m_Region.Max.X, m_Region.Max.Y, center.Z));
                boxes[6] = new BoundingBox(center, m_Region.Max);
                boxes[7] = new BoundingBox(new Vector3(m_Region.Min.X, center.Y, center.Z), new Vector3(center.X, m_Region.Max.Y, m_Region.Max.Z));

                while (m_PendingInsertion.Count > 0)
                {
                    Vector3 temp = m_PendingInsertion.Dequeue();
                    for (int i = 0; i < boxes.Length; i++)
                    {
                        //instantite list on first pass
                        if (firstpass)
                        {
                            boxPoints[i] = new List <Vector3>();
                        }
                        //find container box until binnable
                        if (
                            boxes[i].Contains(temp).Equals(ContainmentType.Contains) ||
                            boxes[i].Contains(temp).Equals(ContainmentType.Intersects))
                        {
                            boxPoints[i].Add(temp);
                        }
                    }
                    if (firstpass)
                    {
                        firstpass = false;
                    }
                }
                for (int i = 0; i < boxPoints.Length; i++)
                {
                    if (boxPoints[i].Count > 0)
                    {
                        //Assign child
                        m_ChildNode[i] = new OctTree(boxes[i], boxPoints[i], baseList, basesize);
                    }
                }
            }
        }
        private void Generate()
        {
            m_stopwatch.Restart();
            Vector3[] conglom = DataProcessing.conglomerateData(m_lastPointCloud, m_lastRotationAxis, 360f / m_lastScanNum);
            m_lastStats.TotalPoints = conglom.Length;
            //Dump points into octtree nodes
            List <OctTree> OctList = new List <OctTree>();
            OctTree        octTree = new OctTree(new BoundingBox(m_lastBoundingContext.Min, new Vector3(1, 1, 1)), conglom.Distinct(), OctList, (float)Pro_octreeResolution.Value);

            m_lastStats            = new Stats();
            m_lastStats.OctalNodes = OctList.Count;
            m_lastStats.OctalDim   = OctList[0].Dims;
            //Do statistical analysis of points
            double octAverage = (float)OctList.Average(x => x.m_Points.Count);
            double octSD      = OctList.Select(x => (double)x.m_Points.Count).StandardDeviation();
            double octSOM     = octSD / Math.Sqrt(OctList.Count);

            m_lastStats.Average           = octAverage;
            m_lastStats.StandardDeviation = octSD;
            //Remove all outliers
            OctList.RemoveAll(x => x.m_Points.Count < octAverage - octSD / 4);
            OctList.ForEach(x => x.m_Points = new List <Vector3>()
            {
                new Vector3(x.m_Points.Average(q => q.X), x.m_Points.Average(q => q.Y), x.m_Points.Average(q => q.Z))
            });
            //Separate octree into its layers
            var layers = (from q in OctList group q by q.m_Region.Min.Y into r select new { r.Key, List = r.Select(x => x) } into s orderby s.Key select s).ToList();
            List <IEnumerable <Vector3> > goodPoints = new List <IEnumerable <Vector3> >();

            if (Pro_fillBottomCheck.IsChecked == true)
            {
                float averageY = layers.First().List.SelectMany(x => x.m_Points).Average(x => x.Y);
                //Make a bottom layer to be culled
                List <Vector3> bottomMax = new List <Vector3>();
                for (float x = m_lastBoundingContext.Min.X; x < m_lastBoundingContext.Max.X; x += (float)Pro_octreeResolution.Value)
                {
                    for (float z = m_lastBoundingContext.Min.Z; z < m_lastBoundingContext.Max.Z; z += (float)Pro_octreeResolution.Value)
                    {
                        bottomMax.Add(new Vector3(x, averageY, z));
                    }
                }
                //Get bottom layer angle, distance and point for grid
                var botLayerDetails = (from q in bottomMax select new { Angle = DataProcessing.GetAngle(q.X, q.Z, m_lastRotationAxis.X, m_lastRotationAxis.Z), Distance = Math.Sqrt(Math.Pow(q.X - m_lastRotationAxis.X, 2) + Math.Pow(q.Z - m_lastRotationAxis.Z, 2)), Point = q, } into r orderby r.Angle select r).ToList();
                //Get bottom layer angle for
                var            bottomTrue        = layers.First().List.SelectMany(x => x.m_Points);
                var            bottomTrueDetails = (from q in bottomTrue select new { Angle = DataProcessing.GetAngle(q.X, q.Z, m_lastRotationAxis.X, m_lastRotationAxis.Z), Distance = Math.Sqrt(Math.Pow(q.X - m_lastRotationAxis.X, 2) + Math.Pow(q.Z - m_lastRotationAxis.Z, 2)), Point = q, } into r orderby r.Angle select r).ToList();
                double         lastAngle         = 0;
                List <Vector3> goodBottom        = new List <Vector3>();
                for (int i = 0; i < bottomTrueDetails.Count(); i++)
                {
                    var checker     = bottomTrueDetails[i];
                    var goodSection = from q in botLayerDetails where q.Angle > lastAngle && q.Angle <= checker.Angle && q.Distance < checker.Distance select q;
                    goodBottom.AddRange(goodSection.Select(x => x.Point));
                    lastAngle = checker.Angle;
                }

                goodPoints.Add(goodBottom);
            }
            if (Pro_fillTopCheck.IsChecked == true)
            {
                float averageY = layers.Last().List.SelectMany(x => x.m_Points).Average(x => x.Y);
                //Make a bottom layer to be culled
                List <Vector3> topMax = new List <Vector3>();
                for (float x = m_lastBoundingContext.Min.X; x < m_lastBoundingContext.Max.X; x += (float)Pro_octreeResolution.Value)
                {
                    for (float z = m_lastBoundingContext.Min.Z; z < m_lastBoundingContext.Max.Z; z += (float)Pro_octreeResolution.Value)
                    {
                        topMax.Add(new Vector3(x, averageY, z));
                    }
                }
                //Get bottom layer angle, distance and point for grid
                var topLayerDetails = (from q in topMax select new { Angle = DataProcessing.GetAngle(q.X, q.Z, m_lastRotationAxis.X, m_lastRotationAxis.Z), Distance = Math.Sqrt(Math.Pow(q.X - m_lastRotationAxis.X, 2) + Math.Pow(q.Z - m_lastRotationAxis.Z, 2)), Point = q, } into r orderby r.Angle select r).ToList();
                //Get bottom layer angle for
                var            topTrue        = layers.Last().List.SelectMany(x => x.m_Points);
                var            topTrueDetails = (from q in topTrue select new { Angle = DataProcessing.GetAngle(q.X, q.Z, m_lastRotationAxis.X, m_lastRotationAxis.Z), Distance = Math.Sqrt(Math.Pow(q.X - m_lastRotationAxis.X, 2) + Math.Pow(q.Z - m_lastRotationAxis.Z, 2)), Point = q, } into r orderby r.Angle select r).ToList();
                double         lastAngle      = 0;
                List <Vector3> goodTop        = new List <Vector3>();
                for (int i = 0; i < topTrueDetails.Count(); i++)
                {
                    var checker     = topTrueDetails[i];
                    var goodSection = from q in topLayerDetails where q.Angle > lastAngle && q.Angle <= checker.Angle && q.Distance < checker.Distance select q;
                    goodTop.AddRange(goodSection.Select(x => x.Point));
                    lastAngle = checker.Angle;
                }

                goodPoints.Add(goodTop);
            }

            goodPoints.AddRange(OctList.Select(x => x.m_Points.ToList()));
            Vector3[] final = goodPoints.SelectMany(x => x).ToArray();
            m_lastStats.ReducedPoints = final.Length;
            FileWriter writer = new FileWriter(final, "processing");

            writer.WriteToFile();
            writer.WriteToASC();

            BatchFileManager bfm = new BatchFileManager(Directory.GetCurrentDirectory());

            bfm.createBatchFile("pointcloud", Pro_samplingResolution.Value);
        }