Пример #1
0
 /// <summary>
 /// Points within given distance of a line segment (at most 1000).
 /// </summary>
 public static IEnumerable <PointsNearObject <Line3d> > QueryPointsNearLineSegment(
     this PointSet self, Line3d lineSegment, double maxDistanceToRay
     )
 => QueryPointsNearLineSegment(self.Root.Value, lineSegment, maxDistanceToRay);
Пример #2
0
 /// <summary>
 /// Count points approximately NOT within maxDistance of given plane.
 /// Result is always equal or greater than exact number.
 /// Faster than CountPointsNotNearPlane.
 /// </summary>
 public static long CountPointsApproximatelyNotNearPlane(
     this PointSet self, Plane3d plane, double maxDistance, int minCellExponent = int.MinValue
     )
 => CountPointsApproximatelyNotNearPlane(self.Root.Value, plane, maxDistance, minCellExponent);
Пример #3
0
 /// <summary>
 /// All points inside axis-aligned box (including boundary).
 /// </summary>
 public static IEnumerable <Chunk> QueryPointsInsideBox(
     this PointSet self, Box3d query, int minCellExponent = int.MinValue
     )
 => QueryPointsInsideBox(self.Root.Value, query, minCellExponent);
Пример #4
0
 /// <summary>
 /// Counts points outside axis-aligned box.
 /// </summary>
 public static long CountPointsOutsideBox(
     this PointSet self, Box3d query, int minCellExponent = int.MinValue
     )
 => CountPointsOutsideBox(self.Root.Value, query, minCellExponent);
Пример #5
0
 /// <summary>
 /// Enumerates (chunked) all points in pointset.
 /// </summary>
 public static IEnumerable <Chunk> QueryAllPoints(this PointSet self)
 => QueryAllPoints(self.Root.Value);
Пример #6
0
 /// <summary>
 /// Points within given distance of a point.
 /// </summary>
 public static PointsNearObject <V3d> QueryPointsNearPoint(
     this PointSet self, V3d query, double maxDistanceToPoint, int maxCount
     )
 => QueryPointsNearPoint(self.Root.Value, query, maxDistanceToPoint, maxCount);
Пример #7
0
 /// <summary>
 /// Count points NOT within maxDistance of given polygon.
 /// </summary>
 public static long CountPointsNotNearPolygon(
     this PointSet self, Polygon3d polygon, double maxDistance, int minCellExponent = int.MinValue
     )
 => CountPointsNotNearPolygon(self.Root.Value, polygon, maxDistance, minCellExponent);
Пример #8
0
 /// <summary>
 /// Counts points outside convex hull.
 /// </summary>
 internal static long CountPointsOutsideConvexHull(
     this PointSet self, Hull3d query, int minCellExponent = int.MinValue
     )
 => CountPointsOutsideConvexHull(self.Root.Value, query, minCellExponent);
 /// <summary>
 /// Finds deepest octree level which still contains less than given number of points within given bounds.
 /// </summary>
 public static int GetMaxOctreeLevelWithLessThanGivenPointCount(
     this PointSet self, long maxPointCount, Box3d bounds
     )
 => GetMaxOctreeLevelWithLessThanGivenPointCount(self.Root.Value, maxPointCount, bounds);
Пример #10
0
        /// <summary>
        /// Maps a sequence of point chunks to point sets, which are then reduced to one single point set.
        /// </summary>
        public static PointSet MapReduce(this IEnumerable <Chunk> chunks, ImportConfig config)
        {
            //var foo = chunks.ToArray();
            var             totalChunkCount         = 0;
            var             totalPointCountInChunks = 0L;
            Action <double> progress = x => config.ProgressCallback(x * 0.5);

            #region MAP: create one PointSet for each chunk

            var pointsets = chunks
                            .MapParallel((chunk, ct2) =>
            {
                Interlocked.Add(ref totalPointCountInChunks, chunk.Count);
                progress(Math.Sqrt(1.0 - 1.0 / Interlocked.Increment(ref totalChunkCount)));

                var builder  = InMemoryPointSet.Build(chunk, config.OctreeSplitLimit);
                var root     = builder.ToPointSetNode(config.Storage, isTemporaryImportNode: true);
                var id       = $"Aardvark.Geometry.PointSet.{Guid.NewGuid()}.json";
                var pointSet = new PointSet(config.Storage, id, root.Id, config.OctreeSplitLimit);

                return(pointSet);
            },
                                         config.MaxDegreeOfParallelism, null, config.CancellationToken
                                         )
                            .ToList()
            ;
            ;

            if (config.Verbose)
            {
                Console.WriteLine($"[MapReduce] pointsets              : {pointsets.Count}");
                Console.WriteLine($"[MapReduce] totalPointCountInChunks: {totalPointCountInChunks}");
            }

            #endregion

            #region REDUCE: pairwise octree merge until a single (final) octree remains

            progress = x => config.ProgressCallback(0.5 + x * 0.5);
            var i = 0;
            var fractionalProgress = new Dictionary <int, double>();

            var totalPointsToMerge = pointsets.Sum(x => x.PointCount);
            if (config.Verbose)
            {
                Console.WriteLine($"[MapReduce] totalPointsToMerge: {totalPointsToMerge}");
            }

            var totalPointSetsCount = pointsets.Count;
            if (totalPointSetsCount == 0)
            {
                var empty = new PointSet(config.Storage, config.Key ?? Guid.NewGuid().ToString());
                config.Storage.Add(config.Key, empty);
                return(empty);
            }

            var doneCount = 0;
            var parts     = new HashSet <PointSet>(pointsets);
            var final     = pointsets.MapReduceParallel((first, second, ct2) =>
            {
                lock (parts)
                {
                    if (!parts.Remove(first))
                    {
                        throw new InvalidOperationException("map reduce error");
                    }
                    if (!parts.Remove(second))
                    {
                        throw new InvalidOperationException("map reduce error");
                    }
                }

                var id = Interlocked.Increment(ref i);
                var firstPlusSecondPointCount = first.PointCount + second.PointCount;

                var lastN  = 0L;
                var merged = first.Merge(second,
                                         n =>
                {
                    //Console.WriteLine($"[MERGE CALLBACK][{id}] {n:N0}");
                    if (n > lastN)
                    {
                        lastN = n;
                        var p = 0.0;
                        lock (fractionalProgress)
                        {
                            fractionalProgress[id] = n / (double)firstPlusSecondPointCount;
                            p = 1.0 / (totalPointSetsCount - (doneCount + fractionalProgress.Values.Sum()));
                        }
                        progress(p);
                    }
                },
                                         config.WithCancellationToken(ct2)
                                         );

                lock (fractionalProgress)
                {
                    fractionalProgress.Remove(id);
                    Interlocked.Increment(ref doneCount);
                }

                //Console.WriteLine($"[MERGE CALLBACK][{id}] {(first.PointCount + second.PointCount) / (double)totalPointsToMerge,7:N3}");

                lock (parts)
                {
                    parts.Add(merged);
                }

                config.Storage.Add(merged.Id, merged);
                if (config.Verbose)
                {
                    Console.WriteLine($"[MapReduce] merged "
                                      + $"{formatCell(first.Root.Value.Cell)} + {formatCell(second.Root.Value.Cell)} -> {formatCell(merged.Root.Value.Cell)} "
                                      + $"({first.Root.Value.PointCountTree:N0} + {second.Root.Value.PointCountTree:N0} -> {merged.Root.Value.PointCountTree:N0})"
                                      );
                }

                if (merged.Root.Value.PointCountTree == 0)
                {
                    throw new InvalidOperationException();
                }
                return(merged);
            },
                                                        config.MaxDegreeOfParallelism
                                                        );
            if (config.Verbose)
            {
                Console.WriteLine($"[MapReduce] everything merged");
            }

            config.CancellationToken.ThrowIfCancellationRequested();

            #endregion

            config.Storage.Add(config.Key, final);
            config.ProgressCallback(1.0);
            return(final);

            string formatCell(Cell c) => c.IsCenteredAtOrigin ? $"[centered, {c.Exponent}]" : c.ToString();
        }
 /// <summary>
 /// Max tree depth.
 /// </summary>
 public static int CountOctreeLevels(this PointSet self)
 => CountOctreeLevels(self.Root.Value);
 /// <summary>
 /// Returns lod points for given octree depth/front of cells intersecting given bounds, where level 0 is the root node.
 /// Front will include leafs higher up than given level.
 /// </summary>
 public static IEnumerable <Chunk> QueryPointsInOctreeLevel(
     this PointSet self, int level, Box3d bounds
     )
 => QueryPointsInOctreeLevel(self.Root.Value, level, bounds);
 /// <summary>
 /// Gets approximate number of points at given octree level within given bounds.
 /// For cells that only partially overlap the specified bounds all points are counted anyway.
 /// For performance reasons, in order to avoid per-point bounds checks.
 /// </summary>
 public static long CountPointsInOctreeLevel(
     this PointSet self, int level, Box3d bounds
     )
 => CountPointsInOctreeLevel(self.Root.Value, level, bounds);
Пример #14
0
 /// <summary>
 /// All points NOT within maxDistance of ALL the given planes.
 /// </summary>
 public static IEnumerable <Chunk> QueryPointsNotNearPlanes(
     this PointSet self, Plane3d[] planes, double maxDistance, int minCellExponent = int.MinValue
     )
 => QueryPointsNotNearPlanes(self.Root.Value, planes, maxDistance, minCellExponent);
Пример #15
0
 /// <summary>
 /// Count points approximately NOT within maxDistance of ALL the given polygons.
 /// Result is always equal or greater than exact number.
 /// Faster than CountPointsNotNearPolygons.
 /// </summary>
 public static long CountPointsApproximatelyNotNearPolygons(
     this PointSet self, Polygon3d[] polygons, double maxDistance, int minCellExponent = int.MinValue
     )
 => CountPointsApproximatelyNotNearPolygons(self.Root.Value, polygons, maxDistance, minCellExponent);
Пример #16
0
 /// <summary>
 /// All points outside convex hull (excluding boundary).
 /// </summary>
 public static IEnumerable <Chunk> QueryPointsOutsideConvexHull(
     this PointSet self, Hull3d query, int minCellExponent = int.MinValue
     )
 => QueryPointsOutsideConvexHull(self.Root.Value, query, minCellExponent);
Пример #17
0
 /// <summary>
 /// All points NOT within maxDistance of given polygon.
 /// </summary>
 public static IEnumerable <Chunk> QueryPointsNotNearPolygon(
     this PointSet self, Polygon3d polygon, double maxDistance, int minCellExponent = int.MinValue
     )
 => QueryPointsNotNearPolygon(self.Root.Value, polygon, maxDistance, minCellExponent);
Пример #18
0
 /// <summary>
 /// Count points within maxDistance of ANY of the given planes.
 /// </summary>
 public static long CountPointsNearPlanes(
     this PointSet self, Plane3d[] planes, double maxDistance, int minCellExponent = int.MinValue
     )
 => CountPointsNearPlanes(self.Root.Value, planes, maxDistance, minCellExponent);
Пример #19
0
        /// <summary>
        /// Maps a sequence of point chunks to point sets, which are then reduced to one single point set.
        /// </summary>
        public static PointSet MapReduce(this IEnumerable <Chunk> chunks, ImportConfig config)
        {
            var             totalChunkCount         = 0;
            var             totalPointCountInChunks = 0L;
            Action <double> progress = x => config.ProgressCallback(x * 0.5);

            #region MAP: create one PointSet for each chunk

            var pointsets = chunks
                            .MapParallel((chunk, ct2) =>
            {
                Interlocked.Add(ref totalPointCountInChunks, chunk.Count);
                progress(1.0 - 1.0 / Interlocked.Increment(ref totalChunkCount));

                var builder  = InMemoryPointSet.Build(chunk, config.OctreeSplitLimit);
                var root     = builder.ToPointSetCell(config.Storage, ct: ct2);
                var id       = $"Aardvark.Geometry.PointSet.{Guid.NewGuid()}.json";
                var pointSet = new PointSet(config.Storage, id, root.Id, config.OctreeSplitLimit);

                return(pointSet);
            },
                                         config.MaxDegreeOfParallelism, null, config.CancellationToken
                                         )
                            .ToList()
            ;
            ;

            if (config.Verbose)
            {
                Console.WriteLine($"[MapReduce] pointsets              : {pointsets.Count}");
                Console.WriteLine($"[MapReduce] totalPointCountInChunks: {totalPointCountInChunks}");
            }

            #endregion

            #region REDUCE: pairwise octree merge until a single (final) octree remains

            progress = x => config.ProgressCallback(0.5 + x * 0.5);
            var i = 0;

            var totalPointsToMerge = pointsets.Sum(x => x.PointCount);
            if (config.Verbose)
            {
                Console.WriteLine($"[MapReduce] totalPointsToMerge: {totalPointsToMerge}");
            }

            var totalPointSetsCount = pointsets.Count;
            if (totalPointSetsCount == 0)
            {
                var empty = new PointSet(config.Storage, config.Key ?? Guid.NewGuid().ToString());
                config.Storage.Add(config.Key, empty, config.CancellationToken);
                return(empty);
            }
            var final = pointsets.MapReduceParallel((first, second, ct2) =>
            {
                progress(Interlocked.Increment(ref i) / (double)totalPointSetsCount);
                var merged = first.Merge(second, ct2);
                config.Storage.Add(merged.Id, merged, ct2);
                if (config.Verbose)
                {
                    Console.WriteLine($"[MapReduce] merged "
                                      + $"{first.Root.Value.Cell} + {second.Root.Value.Cell} -> {merged.Root.Value.Cell} "
                                      + $"({first.Root.Value.PointCountTree} + {second.Root.Value.PointCountTree} -> {merged.Root.Value.PointCountTree})"
                                      );
                }

                if (merged.Root.Value.PointCountTree == 0)
                {
                    throw new InvalidOperationException();
                }

                return(merged);
            },
                                                    config.MaxDegreeOfParallelism
                                                    );
            if (config.Verbose)
            {
                Console.WriteLine($"[MapReduce] everything merged");
            }

            config.CancellationToken.ThrowIfCancellationRequested();

            #endregion

            config.Storage.Add(config.Key, final, config.CancellationToken);
            config.ProgressCallback(1.0);
            return(final);
        }