Пример #1
0
        /// <param name="level">Selects hierarchy Level the kdtree is built of (-1 shouldn't be used, use BuildKdtreeN instead).</param>
        /// <param name="progressObserver">Reports progress in increments which sum up to 1.</param>
        public static void BuildKdTreeForLevel(
            OpcPaths opcPaths, int level, PositionsType posType,
            bool lazy = true, bool overrideExisting = false, IObserver <float> progressObserver = null,
            CancellationToken cancelToken = default(CancellationToken), PatchHierarchyInfo hierarchyInfo = null,
            float maxTriangleSize         = float.PositiveInfinity)
        {
            #region Preconditions

            if (hierarchyInfo == null)
            {
                hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths);
            }

            if (posType == PositionsType.V2dPositions && !hierarchyInfo.PatchTree.Info.Has2dData)
            {
                Report.Warn("KdTreeUtils: 2d KdTree needs 2d data to be able to get built.");
                progressObserver.OnNext(1f);
                progressObserver.OnCompleted();
                return;
            }

            opcPaths.SetRootPatchName(hierarchyInfo.RootPatch);

            var kdTreeSetPath = opcPaths.GetAggKdTreePath(level, posType);
            if (!overrideExisting && StorageConfig.FileExists(kdTreeSetPath))
            {
                progressObserver.OnNext(1f);
                progressObserver.OnCompleted();
                return;
            }

            #endregion

            hierarchyInfo.PatchTree.CreatePatchPaths(opcPaths.PatchesSubDir);

            // Get geometry patchinformations for certain level with a valid boundingbox
            var patchTrees = hierarchyInfo.RetrievePatchTreesOfLevel(level)
                             .Where(x => !x.Info.GlobalBoundingBox.IsInvalid);

            IIntersectableObjectSet kdTree;
            var buildFlags =
                KdIntersectionTree.BuildFlags.Hierarchical |
                KdIntersectionTree.BuildFlags.EmptySpaceOptimization;

            // Decide lazy or eager
            if (lazy)
            {
                kdTree      = BuildLazyKdTreeSet(patchTrees, opcPaths, level, posType, overrideExisting, progressObserver, cancelToken, maxTriangleSize);
                buildFlags |= KdIntersectionTree.BuildFlags.OptimalRaytracing;
            }
            else
            {
                kdTree      = BuildConcreteKdTreeSet(patchTrees, opcPaths, level, posType, overrideExisting, progressObserver, cancelToken, maxTriangleSize);
                buildFlags |= KdIntersectionTree.BuildFlags.MediumIntersection;
            }

            // Save Kd-Tree
            var aggrTree = new KdIntersectionTree(kdTree, buildFlags);
            aggrTree.Save(kdTreeSetPath, waitMode: WaitMode.WaitUntilFinished);
        }
Пример #2
0
        public static bool HasKdTreeForGeoResolution(OpcPaths opcPaths, double minGeometricResolution, PositionsType posType)
        {
            var hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths);
            var level         = GetLevelFromResolution(hierarchyInfo.AvgGeometrySizes, minGeometricResolution);

            return(HasKdTreeForLevel(opcPaths, level, posType, hierarchyInfo));
        }
Пример #3
0
        /// <param name="minGeometricResolution">Used to select an appropriate level in the hierarchy to meet the specified minimum resolution criterion.</param>
        /// <param name="progressObserver">Reports progress in increments which sum up to 1.</param>
        public static void BuildKdTreeForGeoResolution(
            OpcPaths opcPaths, double minGeometricResolution, PositionsType posType,
            bool lazy = true, bool overrideExisting = false, IObserver <float> progressObserver = null,
            CancellationToken cancelToken = default(CancellationToken))
        {
            var hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths);
            var level         = GetLevelFromResolution(hierarchyInfo.AvgGeometrySizes, minGeometricResolution);

            BuildKdTreeForLevel(opcPaths, level, posType, lazy, overrideExisting, progressObserver, cancelToken, hierarchyInfo);
        }
Пример #4
0
        public static bool HasKdTreeForLevel(OpcPaths opcPaths, int level, PositionsType posType, PatchHierarchyInfo hierarchyInfo = null)
        {
            if (hierarchyInfo == null)
            {
                hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths);
            }

            opcPaths.SetRootPatchName(hierarchyInfo.RootPatch);
            var kdTreeSetPath = opcPaths.GetAggKdTreePath(level, posType);

            return(StorageConfig.FileExists(kdTreeSetPath));
        }
Пример #5
0
        public static void BuildKdtreeN(OpcPaths opcPaths, PositionsType posType, bool overrideExisting = false, float maxTriangleSize = float.PositiveInfinity)
        {
            var hierarchyInfo = PatchHierarchyInfo.BuildOrLoadCache(opcPaths);
            var patchInfo     = hierarchyInfo.PatchTree.Info;

            opcPaths.SetRootPatchName(hierarchyInfo.RootPatch);

            if (posType == PositionsType.V2dPositions && !patchInfo.Has2dData)
            {
                Report.Warn("KdTreeUtils: 2d KdTreeN needs 2d data to be able to get built.");
                return;
            }

            if (overrideExisting || !StorageConfig.FileExists(opcPaths.GetKdTreeNPath(posType)))
            {
                BuildKdTreeForPatch(opcPaths.RootPatchName, -1, patchInfo, opcPaths, posType, true, true, maxTriangleSize);
            }
        }
Пример #6
0
        /// <summary>
        /// Builds look up table for profile "intersection" in 2d data.
        /// </summary>
        public static void BuildLookUpTable(OpcPaths opcPaths, bool overrideExisting = false, IObserver <Tup <float, string> > progress = null, CancellationToken cancelToken = default(CancellationToken))
        {
            if (!overrideExisting && StorageConfig.FileExists(opcPaths.ProfileLutPath))
            {
                if (progress != null)
                {
                    progress.OnNext(Tup.Create(1f, ""));
                    progress.OnCompleted();
                }
                Report.Line("LookUpTable already exists at {0}", opcPaths.ProfileLutPath);
            }

            // PatchHierarchyInfo
            var info = PatchHierarchyInfo.BuildOrLoadCache(opcPaths);

            info.PatchTree.CreatePatchPaths(opcPaths.PatchesSubDir);

            // Level 0 Patches
            var lvl0Patches =
                info.RetrievePatchTreesOfLevel(0);

            if (progress != null)
            {
                progress.OnNext(Tup.Create(.1f, ""));
            }

            // group by BB-2d: Min-X, Max-X
            var patchesGroupedByBB = lvl0Patches
                                     .GroupBy(patchTree => Tup.Create(patchTree.Info.GlobalBoundingBox2d.Min.X, patchTree.Info.GlobalBoundingBox2d.Max.X)).ToArray();

            var entries = new List <ProfileLookUpTableEntry>();

            #region Create ProfileLookUpTableEntries

            for (int index = 0; index < patchesGroupedByBB.Count(); index++)
            {
                if (cancelToken.IsCancellationRequested)
                {
                    if (progress != null)
                    {
                        progress.OnNext(Tup.Create(0f, "Building LookUpTabele cancelled."));
                    }
                    cancelToken.ThrowIfCancellationRequested();
                }

                //sort patches according to their b (sv_b_r) value
                var patchesGroupedBySvBR = patchesGroupedByBB[index]
                                           .OrderBy(k => k.Info.GlobalBoundingBox2d.Min.Y);

                var fileHandleList = new List <PatchFileHandle>();
                #region build PatchFileHandles

                foreach (var patchTree in patchesGroupedBySvBR)
                {
                    if (patchTree.Info.Positions2d.IsNullOrEmpty())
                    {
                        Report.Warn("ProfileLutCreation: Skipping Patchtree {0}, because of missing 2d positions.", patchTree.Id);
                        if (progress != null)
                        {
                            progress.OnNext(Tup.Create(0f, "ProfileLutCreation: Skipping Patchtree " + patchTree.Id + ", because of missing 2d positions."));
                        }
                        continue;
                    }
                    var pos2dPath = patchTree.GetPositionPath(PositionsType.V2dPositions);

                    //CAUTION absolute path needs to be repaired during loading
                    var file = AaraData.FromFile(pos2dPath);
                    file.SourceFileName = string.Empty;

                    fileHandleList.Add(new PatchFileHandle()
                    {
                        PatchTree  = patchTree,
                        FileLoader = file,
                    });
                }

                #endregion

                // Create ProfileLookupTableEntries
                var firstPatchBB = patchesGroupedBySvBR.First().Info.GlobalBoundingBox2d;
                entries.Add(new ProfileLookUpTableEntry()
                {
                    Index       = index,
                    SvRange     = new Range1d(firstPatchBB.Min.X, firstPatchBB.Max.X),
                    FileHandles = fileHandleList,
                });

                var progressInc = 0.8f / patchesGroupedByBB.Count();
                if (progress != null)
                {
                    progress.OnNext(Tup.Create(progressInc, ""));
                }
            }
            entries.Reverse();

            #endregion

            #region Save LUT

            var lut = new ProfileLookUpTable()
            {
                SvRange        = new Range1d(info.PatchTree.Info.GlobalBoundingBox2d.Min.X, info.PatchTree.Info.GlobalBoundingBox2d.Max.X),
                Entries        = entries,
                AvgGeomtrySize = info.AvgGeometrySizes.First()
            };

            lut.Save(opcPaths.ProfileLutPath);

            #endregion

            if (progress != null)
            {
                progress.OnNext(Tup.Create(0.1f, ""));
                progress.OnCompleted();
            }
        }