Example #1
0
        private void AddEndIntercept(XYZ point, List <XYZS> intercepts, double station)
        {
            if (!Index.CalculateIndexOfCellContainingPosition(point.X, point.Y, out int cellX, out int cellY))
            {
                Log.LogWarning($"No cell address computable for end point location {point.X}:{point.Y}");
                return;
            }

            var subGrid = Index.LocateSubGridContaining(cellX, cellY);

            if (subGrid == null) // No triangles in this 'node' sub grid
            {
                return;
            }

            if (!(subGrid is TriangleArrayReferenceSubGrid referenceSubGrid))
            {
                Log.LogCritical($"Sub grid is not a TriangleArrayReferenceSubGrid, is is a {subGrid.GetType()}");
                return;
            }

            // Get the cell representing a leaf sub grid and determine if there is a triangle at the point location
            subGrid.GetSubGridCellIndex(cellX, cellY, out byte subGridX, out byte subGridY);

            TriangleArrayReference referenceList = referenceSubGrid.Items[subGridX, subGridY];

            int endIndex = referenceList.TriangleArrayIndex + referenceList.Count;

            for (int i = referenceList.TriangleArrayIndex; i < endIndex; i++)
            {
                double height = XYZ.GetTriangleHeightEx
                                    (ref TTM.Vertices.Items[TTM.Triangles.Items[Indices[i]].Vertex0],
                                    ref TTM.Vertices.Items[TTM.Triangles.Items[Indices[i]].Vertex1],
                                    ref TTM.Vertices.Items[TTM.Triangles.Items[Indices[i]].Vertex2], point.X, point.Y);

                if (height != Common.Consts.NullDouble)
                {
                    intercepts.Add(new XYZS(point.X, point.Y, height, station, Indices[i]));
                    return;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Computes a profile line across the TIN surface between two points
        /// </summary>
        /// <param name="startPoint"></param>
        /// <param name="endPoint"></param>
        /// <param name="startStation"></param>
        /// <returns></returns>
        private List <XYZS> Compute(XYZ startPoint, XYZ endPoint, double startStation)
        {
            // 1. Determine the set of sub grids the profile line cross using the same logic used to
            // compute cell cross by production data profiling

            // ...
            var cellProfileBuilder = new OptimisedTTMCellProfileBuilder(Index.CellSize, true);

            if (!cellProfileBuilder.Build(new [] { startPoint, endPoint }, startStation))
            {
                return(null);
            }

            // 2. Iterate across each sub grid in turn locating all triangles in that sub grid
            // that intersect the line and sorting them according to the distance of the closest
            // intercept from the start of the line

            // Get the resulting vertical and horizontal intercept list
            var VtHzIntercepts = cellProfileBuilder.VtHzIntercepts;

            // Iterate through the intercepts looking for ones that hit a sub grid in the TTM
            // spatial index that contains triangles

            var intercepts = new List <XYZS>();
            var plane      = new Plane();

            // Add an initial intercept if the start point is located within a triangle
            AddEndIntercept(startPoint, intercepts, startStation);

            int prevCellX = int.MinValue, preCellY = int.MinValue;

            for (int interceptIndex = 0; interceptIndex < VtHzIntercepts.Count; interceptIndex++)
            {
                InterceptRec intercept = VtHzIntercepts.Items[interceptIndex];

                if (!Index.CalculateIndexOfCellContainingPosition(intercept.MidPointX, intercept.MidPointY, out int cellX, out int cellY))
                {
                    Log.LogWarning($"No cell address computable for location {intercept.MidPointX}:{intercept.MidPointY}");
                    continue;
                }

                // Make sure we are not repeating a sub grid (can happen as a result of how the initial HZ/Vt intersects are constructed
                if (prevCellX == cellX && preCellY == cellY)
                {
                    // This sub grid has just been processed...
                    continue;
                }

                prevCellX = cellX;
                preCellY  = cellY;

                var subGrid = Index.LocateSubGridContaining(cellX, cellY);

                if (subGrid == null)
                {
                    // No triangles are present in this 'node' sub grid. Move to the next sub grid, the implicit gap will be
                    // picked up when triangle intercepts are aggregated together to form the final profile line
                    continue;
                }

                if (!(subGrid is TriangleArrayReferenceSubGrid referenceSubGrid))
                {
                    Log.LogCritical($"Sub grid is not a TriangleArrayReferenceSubGrid, is is a {subGrid.GetType()}");
                    continue;
                }

                subGrid.GetSubGridCellIndex(cellX, cellY, out byte subGridX, out byte subGridY);

                TriangleArrayReference referenceList = referenceSubGrid.Items[subGridX, subGridY];

                if (referenceList.Count == 0)
                {
                    // There are no triangles in this 'leaf' sub grid
                    continue;
                }

                // Locate all triangles in this sub grid that intersect the profile line
                var endIndex = referenceList.TriangleArrayIndex + referenceList.Count;
                for (int i = referenceList.TriangleArrayIndex; i < endIndex; i++)
                {
                    int      triIndex = Indices[i];
                    Triangle tri      = TTM.Triangles.Items[triIndex];

                    // Does this triangle intersect the line?
                    XYZ v0 = TTM.Vertices.Items[tri.Vertex0];
                    XYZ v1 = TTM.Vertices.Items[tri.Vertex1];
                    XYZ v2 = TTM.Vertices.Items[tri.Vertex2];

                    bool planeInited = false;

                    if (LineIntersection.LinesIntersect(startPoint.X, startPoint.Y, endPoint.X, endPoint.Y, v0.X, v0.Y, v1.X, v1.Y, out double intersectX, out double intersectY, true, out bool linesAreColinear))
                    {
                        // If the lines are co-linear there is nothing more to do. The two vertices need to be added and no more checking is required
                        if (linesAreColinear)
                        {
                            intercepts.Add(new XYZS(v0.X, v0.Y, v0.Z, startStation + MathUtilities.Hypot(startPoint.X - v0.X, startPoint.Y - v0.Y), triIndex));
                            intercepts.Add(new XYZS(v1.X, v1.Y, v1.Z, startStation + MathUtilities.Hypot(startPoint.X - v1.X, startPoint.Y - v1.Y), triIndex));
                            continue;
                        }

                        planeInited = true;
                        plane.Init(v0, v1, v2);

                        // Otherwise, add the intercept location to the list
                        intercepts.Add(new XYZS(intersectX, intersectY, plane.Evaluate(intersectX, intersectY), startStation + MathUtilities.Hypot(startPoint.X - intersectX, startPoint.Y - intersectY), triIndex));
                    }

                    if (LineIntersection.LinesIntersect(startPoint.X, startPoint.Y, endPoint.X, endPoint.Y, v0.X, v0.Y, v2.X, v2.Y, out intersectX, out intersectY, true, out linesAreColinear))
                    {
                        // If the lines are co-linear there is nothing more to do. The two vertices need to be added and no more checking is required
                        if (linesAreColinear)
                        {
                            intercepts.Add(new XYZS(v0.X, v0.Y, v0.Z, startStation + MathUtilities.Hypot(startPoint.X - v0.X, startPoint.Y - v0.Y), triIndex));
                            intercepts.Add(new XYZS(v2.X, v2.Y, v2.Z, startStation + MathUtilities.Hypot(startPoint.X - v2.X, startPoint.Y - v2.Y), triIndex));
                            continue;
                        }

                        if (!planeInited)
                        {
                            planeInited = true;
                            plane.Init(v0, v1, v2);
                        }

                        // Otherwise, add the intercept location to the list
                        intercepts.Add(new XYZS(intersectX, intersectY, plane.Evaluate(intersectX, intersectY), startStation + MathUtilities.Hypot(startPoint.X - intersectX, startPoint.Y - intersectY), triIndex));
                    }

                    if (LineIntersection.LinesIntersect(startPoint.X, startPoint.Y, endPoint.X, endPoint.Y, v1.X, v1.Y, v2.X, v2.Y, out intersectX, out intersectY, true, out linesAreColinear))
                    {
                        // If the lines are co-linear there is nothing more to do. The two vertices need to be added and no more checking is required
                        if (linesAreColinear)
                        {
                            intercepts.Add(new XYZS(v1.X, v1.Y, v1.Z, startStation + MathUtilities.Hypot(startPoint.X - v1.X, startPoint.Y - v1.Y), triIndex));
                            intercepts.Add(new XYZS(v2.X, v2.Y, v2.Z, startStation + MathUtilities.Hypot(startPoint.X - v2.X, startPoint.Y - v2.Y), triIndex));
                            continue;
                        }

                        if (!planeInited)
                        {
                            plane.Init(v0, v1, v2);
                        }

                        // Otherwise, add the intercept location to the list
                        intercepts.Add(new XYZS(intersectX, intersectY, plane.Evaluate(intersectX, intersectY), startStation + MathUtilities.Hypot(startPoint.X - intersectX, startPoint.Y - intersectY), triIndex));
                    }
                }
            }

            // Add an end intercept if the start point is located within a triangle
            AddEndIntercept(endPoint, intercepts, startStation + MathUtilities.Hypot(startPoint.X - endPoint.X, startPoint.Y - endPoint.Y));

            return(intercepts);
        }