/// <summary>
 /// Points within given distance of a line segment (at most 1000).
 /// </summary>
 public static IEnumerable <PointsNearObject <Line3d> > QueryPointsNearLineSegment(
     this PointSetNode node, Line3d lineSegment, double maxDistanceToRay
     )
 {
     if (!node.BoundingBox.Intersects(lineSegment))
     {
         yield break;
     }
     else if (node.PointCount > 0)
     {
         var center = node.Center;
         var ia     = node.KdTree.Value.GetClosestToLine((V3f)(lineSegment.P0 - center), (V3f)(lineSegment.P1 - center), (float)maxDistanceToRay, 1000);
         if (ia.Count > 0)
         {
             var ps = new V3d[ia.Count];
             var cs = node.HasColors ? new C4b[ia.Count] : null;
             var ns = node.HasNormals ? new V3f[ia.Count] : null;
             var js = node.HasIntensities ? new int[ia.Count] : null;
             var ds = new double[ia.Count];
             for (var i = 0; i < ia.Count; i++)
             {
                 var index = (int)ia[i].Index;
                 ps[i] = center + (V3d)node.Positions.Value[index];
                 if (node.HasColors)
                 {
                     cs[i] = node.Colors.Value[index];
                 }
                 if (node.HasNormals)
                 {
                     ns[i] = node.Normals.Value[index];
                 }
                 ds[i] = ia[i].Dist;
             }
             var chunk = new PointsNearObject <Line3d>(lineSegment, maxDistanceToRay, ps, cs, ns, js, ds);
             yield return(chunk);
         }
     }
     else if (node.Subnodes != null)
     {
         for (var i = 0; i < 8; i++)
         {
             var n = node.Subnodes[i];
             if (n == null)
             {
                 continue;
             }
             foreach (var x in QueryPointsNearLineSegment(n.Value, lineSegment, maxDistanceToRay))
             {
                 yield return(x);
             }
         }
     }
 }
示例#2
0
        /// <summary>
        /// Points within given distance of a point.
        /// </summary>
        public static PointsNearObject <V3d> QueryPointsNearPoint(
            this IPointCloudNode node, V3d query, double maxDistanceToPoint, int maxCount
            )
        {
            if (node == null)
            {
                return(PointsNearObject <V3d> .Empty);
            }

            // if query point is farther from bounding box than maxDistanceToPoint,
            // then there cannot be a result and we are done
            var eps = node.BoundingBoxExactGlobal.Distance(query);

            if (eps > maxDistanceToPoint)
            {
                return(PointsNearObject <V3d> .Empty);
            }

            if (node.IsLeaf())
            {
                var nodePositions = node.Positions;
                #if PARANOID
                if (nodePositions.Value.Length <= 0)
                {
                    throw new InvalidOperationException();
                }
                #endif

                var center = node.Center;

                var ia = node.KdTree.Value.GetClosest((V3f)(query - center), (float)maxDistanceToPoint, maxCount);
                if (ia.Count > 0)
                {
                    var ps = new V3d[ia.Count];
                    var cs = node.HasColors ? new C4b[ia.Count] : null;
                    var ns = node.HasNormals ? new V3f[ia.Count] : null;
                    var js = node.HasIntensities ? new int[ia.Count] : null;
                    var ks = node.HasClassifications ? new byte[ia.Count] : null;
                    var ds = new double[ia.Count];
                    for (var i = 0; i < ia.Count; i++)
                    {
                        var index = (int)ia[i].Index;
                        ps[i] = center + (V3d)node.Positions.Value[index];
                        if (node.HasColors)
                        {
                            cs[i] = node.Colors.Value[index];
                        }
                        if (node.HasNormals)
                        {
                            ns[i] = node.Normals.Value[index];
                        }
                        if (node.HasIntensities)
                        {
                            js[i] = node.Intensities.Value[index];
                        }
                        if (node.HasClassifications)
                        {
                            ks[i] = node.Classifications.Value[index];
                        }
                        ds[i] = ia[i].Dist;
                    }
                    var chunk = new PointsNearObject <V3d>(query, maxDistanceToPoint, ps, cs, ns, js, ks, ds);
                    return(chunk);
                }
                else
                {
                    return(PointsNearObject <V3d> .Empty);
                }
            }
            else
            {
                // first traverse octant containing query point
                var index  = node.GetSubIndex(query);
                var n      = node.Subnodes[index];
                var result = n != null?n.Value.QueryPointsNearPoint(query, maxDistanceToPoint, maxCount) : PointsNearObject <V3d> .Empty;

                if (!result.IsEmpty && result.MaxDistance < maxDistanceToPoint)
                {
                    maxDistanceToPoint = result.MaxDistance;
                }

                // now traverse other octants
                for (var i = 0; i < 8; i++)
                {
                    if (i == index)
                    {
                        continue;
                    }
                    n = node.Subnodes[i];
                    if (n == null)
                    {
                        continue;
                    }
                    var x = n.Value.QueryPointsNearPoint(query, maxDistanceToPoint, maxCount);
                    result = result.Merge(x, maxCount);
                    if (!result.IsEmpty && result.MaxDistance < maxDistanceToPoint)
                    {
                        maxDistanceToPoint = result.MaxDistance;
                    }
                }

                return(result);
            }
        }