Esempio n. 1
0
    private void KDSearch()
    {
        KDTree <int> kd = new KDTree <int>(3);

        // clear neighbours and init tree
        int i = 0;

        foreach (BoidController bc in boids)
        {
            bc.neighbours.Clear();
            kd.AddPoint(new double[3] {
                bc.transform.position.x, bc.transform.position.y, bc.transform.position.z
            }, i);
            i++;
        }

        // search
        foreach (BoidController bc in boids)
        {
            NearestNeighbour <int> neighbours = kd.NearestNeighbors(new double[3] {
                bc.transform.position.x, bc.transform.position.y, bc.transform.position.z
            }, n, r_c2);
            while (neighbours.MoveNext())
            {
                int id = neighbours.Current;
                if (id != bc.id)
                {
                    bc.neighbours.Add(boids[id]);
                }
            }
        }
    }
Esempio n. 2
0
        public static bool Add(KDRectangle Rectangle)
        {
            if (tree.Size == 0)
            {
                tree.AddPoint(new double[] { Rectangle.LeftTop.X, Rectangle.RightBottom.X, Rectangle.LeftTop.Y, Rectangle.RightBottom.Y }, Rectangle);
                return(true);
            }
            else
            {
                NearestNeighbour <KDRectangle> pIter = tree.NearestNeighbors(new double[] { Rectangle.LeftTop.X, Rectangle.RightBottom.X, Rectangle.LeftTop.Y, Rectangle.RightBottom.Y }, 10);
                while (pIter.MoveNext())
                {
                    KDRectangle overlaper = pIter.Current;
                    if (doOverlap(Rectangle.LeftTop, Rectangle.RightBottom, overlaper.LeftTop, overlaper.RightBottom))
                    {
                        Console.WriteLine(Rectangle.Name);
                        Rectangle.Filled = true;
                        return(false);
                    }
                }

                tree.AddPoint(new double[] { Rectangle.LeftTop.X, Rectangle.RightBottom.X, Rectangle.LeftTop.Y, Rectangle.RightBottom.Y }, Rectangle);
                return(true);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// removes a list of multiple objects from the point cloud by a distance
        /// </summary>
        /// <param name="pInputPoints">the list of removable point clouds</param>
        /// <param name="pRemoveDistance">the nearest neighbour search distance</param>
        /// <returns>the amount of points removed</returns>
        public int removePointcloudsFromPointCloud(List <PointCloud> pInputPoints, float pRemoveDistance)
        {
            Object          parWork    = new Object();
            HashSet <Point> removeList = new HashSet <Point>();

            //go through list // parallel
            Parallel.ForEach(pInputPoints, pcl =>
            {
                Parallel.ForEach(pcl.pointcloud_hs, p =>
                {
                    NearestNeighbour <Point> nn = pointcloud_kd.NearestNeighbors(new double[] { p.point.X, p.point.Y, p.point.Z }, 10000, pRemoveDistance);
                    while (nn.MoveNext())
                    {
                        lock (parWork) removeList.Add(nn.Current);
                    }
                });
            });

            //remove points from pointcloud
            int removecount = 0;

            foreach (Point p in removeList)
            {
                if (this.pointcloud_hs.Remove(p))
                {
                    removecount++;
                }
            }

            resetLazyLoadingObjectsAfterUpdate();
            return(removecount);
        }
Esempio n. 4
0
        /// <summary>
        /// downsamples the pointcloud by using a downsample factor. Reduces amount of points in downsample factor distance to 1
        /// </summary>
        /// <param name="pDownsampleFactor">the downsample factor, a distance in m</param>
        public void downsamplePointcloud(float pDownsampleFactor)
        {
            //new target cloud
            HashSet <Point> newHS = new HashSet <Point>();

            //check all initial points
            foreach (Point p in pointcloud_hs)
            {
                //if not processed, add to new cloud, check neighbours and set them as processed; processed points dont get added to new pointcloud
                if (!p.processed)
                {
                    newHS.Add(p);
                    p.processed = true;

                    //check for nearest neighbours, set them processed, so they dont get added to list
                    NearestNeighbour <Point> nn = pointcloud_kd.NearestNeighbors(new double[] { p.point.X, p.point.Y, p.point.Z }, 10000, pDownsampleFactor);
                    while (nn.MoveNext())
                    {
                        if (!nn.Current.processed)
                        {
                            nn.Current.processed = true;
                        }
                    }
                }
            }

            //goes through the point list and set every point as unprocessed
            Parallel.ForEach(newHS, point => point.processed = false);

            //set downsampled cloud as new
            this.pointcloud_hs = newHS;

            //resets the objects so they represent the current data
            this.resetLazyLoadingObjectsAfterUpdate();
        }
 void Update()
 {
     if (Input.GetMouseButton(0))
     {
         ray = Camera.main.ScreenPointToRay(Input.mousePosition);
         if (groundPlane.Raycast(ray, out rayDistance))
         {
             pos   = ray.GetPoint(rayDistance);
             pIter = Collection.NearestNeighbors(new double[] { pos.x, pos.z }, MaxCount, Range);
             while (pIter.MoveNext())
             {
                 pIter.Current.Transform.localScale = Vector3.zero;
             }
         }
     }
 }
Esempio n. 6
0
        /// <summary>
        /// calculates an euclidean cluster extraction from the point cloud based on a euclidean distance. returns a list of point clouds
        /// </summary>
        /// <param name="pInputCloud">the combined point cloud</param>
        /// <param name="pConfig">the config object for the algorithms</param>
        /// <returns>a list of point clouds</returns>
        public static List <PointCloud> calculateEuclideanClusterExtraction(PointCloud pInputCloud, float pEuclideanExtractionRadius, CancellationToken pToken)
        {
            //update status
            Log.LogManager.updateAlgorithmStatus("Euclidean Cluster Extraction");
            Log.LogManager.writeLogDebug("[EuclideanClusterExtraction] Extraction Radius: " + pEuclideanExtractionRadius);

            //creates the end list to be returned
            List <PointCloud> clusters = new List <PointCloud>();

            foreach (Point p in pInputCloud.pointcloud_hs)
            {
                pToken.ThrowIfCancellationRequested();

                //checks if point has been processed already, if yes, skip
                if (p.processed)
                {
                    continue;
                }

                //create new queue
                Queue <Point> Q = new Queue <Point>();

                //add point to queue
                Q.Enqueue(p);

                //result values
                HashSet <Point> resultCloud   = new HashSet <Point>();
                PointCloud      resultCluster = new PointCloud(resultCloud);

                //while queue has points, check for neighbours and add them to queue as well, do as long there are neighbours
                while (Q.Count > 0)
                {
                    pToken.ThrowIfCancellationRequested();

                    //remove point from queue and add to current cluster, point has been processed by doing that
                    Point p2 = Q.Dequeue();
                    if (p2.processed)
                    {
                        continue;
                    }
                    resultCloud.Add(p2);
                    p2.processed = true;

                    //check all neighbour points, add them to queue if they havnt been processed yet
                    double[] tp = { p2.point.X, p2.point.Y, p2.point.Z };
                    NearestNeighbour <Point> nb = lookForNeighbours(pInputCloud.pointcloud_kd, tp, pEuclideanExtractionRadius);
                    while (nb.MoveNext())
                    {
                        if (!nb.Current.processed)
                        {
                            Q.Enqueue(nb.Current);
                        }
                    }
                }

                clusters.Add(resultCluster);
            }

            //set all points as unprocessed, so they can be used for other algorithms
            Parallel.ForEach(clusters, pointcloud => Parallel.ForEach(pointcloud.pointcloud_hs, point => point.processed = false));

            //updates the status
            Log.LogManager.updateAlgorithmStatus("Done");

            //return
            return(clusters);
        }
Esempio n. 7
0
        /**
         *	Similar to Merge vertices, expect that this method only collapses vertices within
         *	a specified distance of one another (typically epsilon).  Returns true if any action
         *  was taken, false otherwise.  Outputs indices that have been welded in the @welds var.
         */
        public static bool WeldVertices(this pb_Object pb, int[] indices, float delta, out int[] welds)
        {
            List <int> universal = pb.sharedIndices.GetUniversalIndices(indices).ToList();

            Vector3[] v = pb.vertices;

            HashSet <int> used = new HashSet <int>();
            KDTree <int>  tree = new KDTree <int>(3, 48);               // dimensions (xyz), node size

            for (int i = 0; i < universal.Count; i++)
            {
                Vector3 vert = v[pb.sharedIndices[universal[i]][0]];
                tree.AddPoint(new double[] { vert.x, vert.y, vert.z }, universal[i]);
            }

            List <List <int> > groups = new List <List <int> >();

            double[] point = new double[3] {
                0, 0, 0
            };

            int[][] si = pb.sharedIndices.ToArray();
            for (int i = 0; i < universal.Count; i++)
            {
                if (used.Contains(universal[i]))
                {
                    continue;
                }

                int tri = si[universal[i]][0];

                point[0] = v[tri].x;
                point[1] = v[tri].y;
                point[2] = v[tri].z;

                NearestNeighbour <int> neighborIterator = tree.NearestNeighbors(point, 64, delta);

                List <int> neighbors = new List <int>();

                while (neighborIterator.MoveNext())
                {
                    if (used.Contains(neighborIterator.Current))
                    {
                        continue;
                    }

                    used.Add(neighborIterator.Current);
                    neighbors.Add(neighborIterator.Current);
                }

                used.Add(universal[i]);
                groups.Add(neighbors);
            }

            pb_IntArray[] rebuilt = new pb_IntArray[groups.Count];            // + remainingCount ];
            welds = new int[groups.Count];

            for (int i = 0; i < groups.Count; i++)
            {
                rebuilt[i] = new pb_IntArray(groups[i].SelectMany(x => pb.sharedIndices[x].array).ToArray());
                welds[i]   = rebuilt[i][0];
            }

            foreach (pb_IntArray arr in rebuilt)
            {
                Vector3 avg = pb_Math.Average(pbUtil.ValuesWithIndices(v, arr.array));
                foreach (int i in arr.array)
                {
                    v[i] = avg;
                }
            }

            pb.SetVertices(v);
            // profiler.EndSample();

            pb_IntArray[] remaining = pb.sharedIndices.Where((val, index) => !used.Contains(index)).ToArray();

            rebuilt = pbUtil.Concat(rebuilt, remaining);

            pb.SetSharedIndices(rebuilt);

            return(true);
        }