Example #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);
        }
Example #2
0
        /// <summary>
        /// Gets kdtree path for a certain patch according to name, level and postype.
        /// </summary>
        public string GetKdTreePath(string patchName, int level, PositionsType posType)
        {
            var fileName   = GetKdTreeFileName(patchName, level, posType);
            var kdTreePath = Path.Combine(RootPatchPath, fileName);

            return(kdTreePath);
        }
        /// <summary>
        /// Takes first OPC in opcDirectory and returns its root patch info. This
        /// is typically needed to retrieve rendering offsets to prevent rounding errors.
        /// </summary>
        public static PatchFileInfo GetFirstPatchFileInfo(string opcDirectory, PositionsType posType)
        {
            var paths         = OpcFileUtils.OpcPathsFromFolder(opcDirectory);
            var rootPatchPath = OpcFileUtils.GetRootPatchPath(paths.First());

            return(PatchFileInfo.FromFile(rootPatchPath));
        }
Example #4
0
        public static string GetKdTreeFileName(string patchName, int level, PositionsType posType)
        {
            string levelSub    = level > -1 ? "-" + level : string.Empty;
            string positionSub = posType == PositionsType.V3dPositions ? string.Empty : "-2d";

            var fileName = string.Format("{0}{1}{2}.{3}", patchName, levelSub, positionSub, Identifiers.KdTreeExt);

            return(fileName);
        }
        /// <summary>
        /// Loads VertexGeometry from aara files. Beware: add Local2Global node for global space.
        /// </summary>
        /// <returns>Vertex Geometry in local OPC space.</returns>
        public static VertexGeometry LoadPatch(PatchFileInfo info, string basePath, PositionsType posType,
                                               bool loadNormals = true, bool loadTexCoords = true, bool loadDiffTex = true, bool loadHueTex = true, float maxTriangleSize = float.PositiveInfinity, bool loadAsDoubles = false)
        {
            Array  positions;
            Symbol dataType;

            return(LoadPatch(info, basePath, posType, out positions, out dataType,
                             loadNormals, loadTexCoords, loadDiffTex, loadHueTex, maxTriangleSize, loadAsDoubles));
        }
Example #6
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);
        }
 public M44d GetLocal2Global(PositionsType posType)
 {
     if (posType == PositionsType.V3dPositions)
     {
         return(Local2Global);
     }
     else
     {
         return(Local2Global2d);
     }
 }
 public Box3d GetLocalBoundingBox(PositionsType posType)
 {
     if (posType == PositionsType.V3dPositions)
     {
         return(LocalBoundingBox);
     }
     else
     {
         return(LocalBoundingBox2d);
     }
 }
        public VertexGeometry Load(PatchFileInfo info, string basePath, PositionsType posType,
                                   bool loadTextures = true, bool loadNormals = true, bool loadTexCoords = true, float maxTriangleSize = float.PositiveInfinity)
        {
            //Array positions;
            //Symbol dataType;
            bool loadDiffTex = loadTextures ? LoadDiffTex : false;
            bool loadHueTex  = loadTextures ? LoadHueTex : false;

            return(LoadPatch(info, basePath, posType, //out positions, out dataType,
                             loadNormals, loadTexCoords, loadDiffTex, loadHueTex, maxTriangleSize));
        }
Example #10
0
 public string GetPositionPath(PositionsType posType)
 {
     if (posType == PositionsType.V3dPositions)
     {
         return(Path.Combine(PatchPath, Info.Positions));
     }
     else
     {
         return(Path.Combine(PatchPath, Info.Positions2d));
     }
 }
Example #11
0
 public string GetKdTreeZeroPath(PositionsType posType)
 {
     if (posType == PositionsType.V3dPositions)
     {
         return(m_kdTreeZeroPath);
     }
     else
     {
         return(m_kdTreeZero2dPath);
     }
 }
Example #12
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));
        }
Example #13
0
        //static volatile int patchCounter = 0;

        /// <summary>
        /// Represents a single patch of ordered positions including coords, textures, etc.
        /// </summary>
        public Patch(PatchFileInfo info, string patchPath, int level, int maxLevel, PositionsType posType, bool invertZ = false, float maxTriangleSize = float.PositiveInfinity)
            : base(Identifier)
        {
            PatchFilePath   = patchPath;
            Level           = level;
            PatchFileInfo   = info;
            MaxLevel        = maxLevel;
            PositionsType   = posType;
            InvertZ         = invertZ;
            MaxTriangleSize = maxTriangleSize;
            //patchCounter++;
            //Report.Line("++" + patchCounter);
        }
Example #14
0
        /// <summary>
        /// Loads level N kdtree. If level N kdtree does not exist it is built from rootpatch.
        /// </summary>
        public static KdIntersectionTree BuildOrLoadKdTreeN(OpcPaths opcPaths, PositionsType posType, PatchFileInfo patchFileInfo)
        {
            KdIntersectionTree kdiTree = null;
            var kdTreeNPatch           = opcPaths.GetKdTreeNPath(posType);

            if (!StorageConfig.FileExists(kdTreeNPatch))
            {
                kdiTree = KdTreeUtils.BuildKdTreeForPatch(opcPaths.RootPatchName, -1, patchFileInfo, opcPaths, posType, saveTriangles: true);
                kdiTree.Save(opcPaths.RootPatchName);
            }
            else
            {
                kdiTree = Load.As <KdIntersectionTree>(opcPaths.GetKdTreeNPath(posType));
            }

            return(kdiTree);
        }
Example #15
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);
            }
        }
Example #16
0
        private static LazyKdTreeSet BuildLazyKdTreeSet(IEnumerable <PatchTree> patches, OpcPaths opcPaths,
                                                        int level, PositionsType posType, bool overrideExisting, IObserver <float> progressObserver, CancellationToken cancelToken = default(CancellationToken),
                                                        float maxTriangleSize = float.PositiveInfinity)
        {
            var placeHolders = new List <LazyKdTreeSet.KdTreePlaceHolder>();
            var progressInc  = 1f / patches.Count();

            foreach (var p in patches)
            {
                cancelToken.ThrowIfCancellationRequested();

                var kdtreePath = opcPaths.GetKdTreePath(p.Id, level, posType);
                if (overrideExisting || !StorageConfig.FileExists(kdtreePath))
                {
                    BuildKdTreeForPatch(p.Id, level, p.Info, opcPaths, posType, saveTriangles: false, saveKdTree: true, maxTriangleSize: maxTriangleSize);
                }

                // Create place holders
                placeHolders.Add(new LazyKdTreeSet.KdTreePlaceHolder()
                {
                    BoundingBox   = p.Info.GetGlobalBoundingBox(posType),
                    Affine        = p.Info.GetLocal2Global(posType),
                    Path          = opcPaths.GetKdTreePath(p.Id, level, posType),
                    ObjectSetPath = p.GetPositionPath(posType)
                });

                if (progressObserver != null)
                {
                    progressObserver.OnNext(progressInc);
                }
            }

            if (progressObserver != null)
            {
                progressObserver.OnCompleted();
            }

            return(new LazyKdTreeSet(placeHolders));
        }
Example #17
0
        /// <summary>
        /// Builds kdtree for specific patch.
        /// Kdtree is built according to specified positions type and hierarchy level.
        /// </summary>
        private static KdIntersectionTree BuildKdTreeForPatch(
            string patchName, int level, PatchFileInfo info, OpcPaths paths,
            PositionsType posType, bool saveTriangles = false, bool saveKdTree = true,
            float maxTriangleSize = float.PositiveInfinity)
        {
            var path = Path.Combine(paths.PatchesSubDir, patchName);

            var patchGeometry = new TriangleSet();

            //var patchGeometryTest = new TriangleSet();
            if ((maxTriangleSize < float.PositiveInfinity) && (maxTriangleSize > 0.000001f))
            {
                patchGeometry = PatchLoadingStrategy.LoadPatchTriangleSetWithoutOversizedTriangles(info, path, posType, maxTriangleSize);
                //patchGeometryTest = PatchLoadingStrategy.LoadPatchTriangleSet(info, path, posType);
            }
            else
            {
                patchGeometry = PatchLoadingStrategy.LoadPatchTriangleSet(info, path, posType);
            }

            KdIntersectionTree kdIntTree =
                new KdIntersectionTree(patchGeometry,
                                       KdIntersectionTree.BuildFlags.MediumIntersection |
                                       KdIntersectionTree.BuildFlags.Hierarchical);

            if (!saveTriangles)
            {
                kdIntTree.ObjectSet = null;
            }

            if (saveKdTree)
            {
                var kdTreePath = paths.GetKdTreePath(patchName, level, posType);
                kdIntTree.Save(kdTreePath);
            }

            return(kdIntTree);
        }
Example #18
0
        /// <summary>
        /// NOT TESTED
        /// </summary>
        private static KdTreeSet BuildConcreteKdTreeSet(IEnumerable <PatchTree> patches, OpcPaths opcPaths,
                                                        int level, PositionsType posType, bool overrideExisting, IObserver <float> progressObserver, CancellationToken cancelToken = default(CancellationToken),
                                                        float maxTriangleSize = float.PositiveInfinity)
        {
            var kdTrees     = new List <ConcreteKdIntersectionTree>();
            var progressInc = 1f / patches.Count();

            foreach (var p in patches)
            {
                cancelToken.ThrowIfCancellationRequested();

                KdIntersectionTree tree;
                var kdtreePath = opcPaths.GetKdTreePath(p.Id, level, posType);
                if (overrideExisting || !StorageConfig.FileExists(kdtreePath))
                {
                    tree = BuildKdTreeForPatch(p.Id, level, p.Info, opcPaths, posType, saveTriangles: true, saveKdTree: false, maxTriangleSize: maxTriangleSize);
                }
                else
                {
                    tree = Load.As <KdIntersectionTree>(kdtreePath);
                }

                kdTrees.Add(tree.ToConcreteKdIntersectionTree());

                if (progressObserver != null)
                {
                    progressObserver.OnNext(progressInc);
                }
            }

            if (progressObserver != null)
            {
                progressObserver.OnCompleted();
            }

            return(new KdTreeSet(kdTrees));
        }
Example #19
0
        //~Patch()
        //{
        //    patchCounter--;
        //    Report.Line("--" + patchCounter);
        //}

        public static Patch FromFile(string patchXmlPath, int level, int maxLevel, PositionsType posType)
        {
            return(new Patch(PatchFileInfo.FromFile(patchXmlPath), patchXmlPath, level, maxLevel, posType));
        }
        /// <summary>
        /// Loads VertexGeometry from aara files. Beware: add Local2Global node for global space.
        /// </summary>
        /// <param name="positions">Raw positions, read from aara files for possible further processing.</param>
        /// <param name="dataType">DataType of positions.</param>
        /// <returns>Vertex Geometry in local OPC space.</returns>
        public static VertexGeometry LoadPatch(PatchFileInfo info, string basePath, PositionsType posType, out Array positions, out Symbol dataType,
                                               bool loadNormals = true, bool loadTexCoords = true, bool loadDiffTex = true, bool loadHueTex = true, float maxTriangleSize = float.PositiveInfinity, bool loadAsDoubles = false)
        {
            var vg = new VertexGeometry(GeometryMode.TriangleList);

            positions = null;

            // load metadata
            var aara3dPos = AaraData.FromFile(
                Path.Combine(basePath, posType == PositionsType.V3dPositions
                ? info.Positions : info.Positions2d));

            dataType = aara3dPos.DataTypeAsSymbol;

            var resolution = new V2i(aara3dPos.Size);

            if (resolution.AnySmaller(2))
            {
                Report.Warn("ignoring patch {0} due to invalid gridresolution {1}", basePath, resolution);
                return(null);
            }

            // load positions
            positions = aara3dPos.LoadElements();
            var positions3d = loadAsDoubles ? positions : AaraData.ConvertArrayToV3fs[aara3dPos.DataTypeAsSymbol](positions);

            //var positionsV3 = loadAsDoubles ?
            //    (Array)AaraData.ConvertArrayToV3ds[aara3dPos.DataTypeAsSymbol](positions) :
            //    (Array);

            vg.Positions = positions3d;

            var p = AaraData.ConvertArrayToV3fs[aara3dPos.DataTypeAsSymbol](positions);

            // calculate indices
            var invalidPoints = OpcIndices.GetInvalidPositions(p);

            // limit triangle size
            if ((maxTriangleSize < float.PositiveInfinity) && (maxTriangleSize > 0.000001f))
            {
                vg.Indices = OpcIndices.ComputeIndexArray(resolution, invalidPoints.ToList(), p, maxTriangleSize);
            }
            else
            {
                vg.Indices = OpcIndices.ComputeIndexArray(resolution, invalidPoints.ToList());
            }

            // load normals
            if (loadNormals)
            {
                var normalPath = Path.Combine(basePath, "Normals.aara");
                if (StorageConfig.FileExists(normalPath))
                {
                    var normals   = AaraData.FromFile(normalPath);
                    var normals3d = AaraData.ConvertArrayToV3fs[normals.DataTypeAsSymbol](normals.LoadElements());
                    vg.Normals = normals3d;
                }
            }

            // load coordinates
            vg.Coordinates = new CoordinatesMap();
            if (loadTexCoords)
            {
                var coordPath   = Path.Combine(basePath, info.Coordinates.First());
                var coordinates = AaraData.FromFile(coordPath).LoadElements() as V2f[];
                vg.Coordinates[VertexGeometry.Property.DiffuseColorCoordinates] = coordinates;
            }

            // load textures
            vg.Textures = new TexturesMap();
            if (loadDiffTex)
            {
                var texFile = Path.ChangeExtension(info.Textures.First(), ".dds");
                var texPath = Path.GetFullPath(Path.Combine(basePath, @"..\..\images", texFile));

                if (StorageConfig.FileExists(texPath))
                {
                    var img = Convertible.FromFile(texPath);

                    vg.Textures[VertexGeometry.Property.DiffuseColorTexture] =
                        new Aardvark.Rendering.Texture(img)
                    {
                        ForceImmediateUpload = false
                    };
                }
            }
            if (loadHueTex)
            {
                vg.Textures[VertexGeometry.Property.LightMapTexture] =
                    new Aardvark.Rendering.Texture(Resources.HueColorMap.Convertible());
            }

            return(vg);
        }
        /// <summary>
        /// Gets Triangle Set loaded from AaraData and transformed to global space.
        /// </summary>
        public static TriangleSet LoadPatchTriangleSet(PatchFileInfo info, string basePath, PositionsType posType)
        {
            var vg = LoadPatch(info, basePath, posType, false, false, false, false, loadAsDoubles: false);

            if (vg == null)
            {
                return(new TriangleSet());
            }

            var trafo = posType == PositionsType.V3dPositions ? info.Local2Global : info.Local2Global2d;

            vg.TransformV3d(trafo);

            var triangles = vg.Triangles
                            .Where(x => !x.Point0.Position.IsNaN &&
                                   !x.Point1.Position.IsNaN &&
                                   !x.Point2.Position.IsNaN)
                            .Select(x => x.ToTriangle3d());

            return(new TriangleSet(triangles));
        }
Example #22
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));
        }
Example #23
0
        public static Subject <float> GetKdTreeProgressObserver(OpcPaths opcPaths, int level, PositionsType posType)
        {
            var   opcName       = Path.GetFileName(opcPaths.BasePath);
            float totalProgress = 0f;

            var progress = new Subject <float>();

            progress.Sample(TimeSpan.FromSeconds(1.0)).Subscribe(inc =>
            {
                totalProgress += inc;
                Report.Line("{0} - {1} - {2} - Progress {3:0.0}%",
                            opcName, level, posType.ToString(), totalProgress * 100.0);

                //Report.ProgressDelta(tup.E1);
            });

            return(progress);
        }
        /// <summary>
        /// Gets Triangle Set loaded from AaraData and transformed to global space.
        /// Triangles side length < maxTriiangleSize
        /// </summary>
        public static TriangleSet LoadPatchTriangleSetWithoutOversizedTriangles(PatchFileInfo info, string basePath, PositionsType posType, float maxTriangleSize = float.PositiveInfinity)
        {
            var vg = LoadPatch(info, basePath, posType, false, false, false, false);

            if (vg == null)
            {
                return(new TriangleSet());
            }

            vg.Transform(
                posType == PositionsType.V3dPositions ?
                info.Local2Global : info.Local2Global2d);

            var triangles = vg.Triangles
                            .Where(x => !x.Point0.Position.IsNaN &&
                                   !x.Point1.Position.IsNaN &&
                                   !x.Point2.Position.IsNaN &&
                                   (V3d.Distance(x.Point0.Position, x.Point1.Position) < maxTriangleSize) &&
                                   (V3d.Distance(x.Point0.Position, x.Point2.Position) < maxTriangleSize) &&
                                   (V3d.Distance(x.Point1.Position, x.Point2.Position) < maxTriangleSize))
                            .Select(x => x.ToTriangle3d());

            return(new TriangleSet(triangles));
        }
Example #25
0
 /// <summary>
 /// Gets the aggregate kdtree path according to the specified level and positions type. Level -1 indicates
 /// the path for a Level N kdtree
 /// </summary>
 public string GetAggKdTreePath(int level, PositionsType posType)
 {
     return(GetKdTreePath(RootPatchName, level, posType));
 }