示例#1
0
 /// <summary>
 /// Constructs an alignment master geometry result from supplied vertices and labels
 /// </summary>
 /// <param name="requestResult"></param>
 /// <param name="vertices"></param>
 /// <param name="labels"></param>
 public AlignmentDesignGeometryResponse(DesignProfilerRequestResult requestResult, double[][][] vertices, AlignmentGeometryResponseArc[] arcs, AlignmentGeometryResponseLabel[] labels)
 {
     RequestResult = requestResult;
     Vertices      = vertices;
     Arcs          = arcs;
     Labels        = labels;
 }
示例#2
0
        /// <summary>
        /// Performs the donkey work of the elevation patch calculation
        /// </summary>
        /// <returns>The computed elevation of the given design at the spot location, or NullDouble if the location does not lie on the design</returns>
        private double Calc(ISiteModelBase siteModel, DesignOffset referenceDesign, double spotX, double spotY,
                            out DesignProfilerRequestResult calcResult)
        {
            calcResult = DesignProfilerRequestResult.UnknownError;

            var design = _designs.Lock(referenceDesign.DesignID, siteModel, SubGridTreeConsts.DefaultCellSize, out var lockResult);

            if (design == null)
            {
                _log.LogWarning($"Failed to read design file for design {referenceDesign.DesignID}");
                calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile;
                return(Common.Consts.NullDouble);
            }

            try
            {
                var hint = -1;
                if (design.InterpolateHeight(ref hint, spotX, spotY, referenceDesign.Offset, out var z))
                {
                    calcResult = DesignProfilerRequestResult.OK;
                }
                else
                {
                    calcResult = DesignProfilerRequestResult.NoElevationsInRequestedPatch;
                    z          = Common.Consts.NullDouble;
                }

                return(z);
            }
示例#3
0
        /// <summary>
        /// Performs the donkey work of the boundary calculation
        /// </summary>
        private List <Fence> Calc(DesignBoundaryArgument arg, out DesignProfilerRequestResult calcResult)
        {
            calcResult = DesignProfilerRequestResult.UnknownError;

            var siteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(arg.ProjectID, false);

            if (siteModel == null)
            {
                calcResult = DesignProfilerRequestResult.NoSelectedSiteModel;
                Log.LogError($"Site model {arg.ProjectID} not found");
                return(null);
            }

            var design = Designs.Lock(arg.ReferenceDesign.DesignID, siteModel, siteModel.CellSize, out var lockResult);

            if (design == null)
            {
                Log.LogWarning($"Failed to read file for design {arg.ReferenceDesign.DesignID}");
                calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile;
                return(null);
            }

            try
            {
                var result = design.GetBoundary();

                calcResult = result != null ? DesignProfilerRequestResult.OK : DesignProfilerRequestResult.FailedToCalculateBoundary;

                return(result);
            }
            finally
            {
                Designs.UnLock(arg.ReferenceDesign.DesignID, design);
            }
        }
示例#4
0
        public bool DetermineBoundary(out DesignProfilerRequestResult calcResult, out Fence fence)
        {
            // Todo InterlockedIncrement64(DesignProfilerRequestStats.NumAlignmentFilterBoundariesComputed);

            // Walk the alignment and construct a boundary as per the SVO algorithm for road design boundary construction
            CalculateRoadSubsetFence(out calcResult, out fence);

            return(calcResult == DesignProfilerRequestResult.OK && fence.NumVertices > 2);
        }
示例#5
0
        public override void InternalFromBinary(IBinaryRawReader reader)
        {
            var version = VersionSerializationHelper.CheckVersionByte(reader, VERSION_NUMBER);

            if (version == 1)
            {
                RequestResult = (DesignProfilerRequestResult)reader.ReadByte();
            }
        }
示例#6
0
        private void CalculateRoadSubsetFence(out DesignProfilerRequestResult calcResult, out Fence fence)
        // Run down the road from start to end chainage in steps the size of which is
        // determined by the default cross section interval, computing the
        // left and right offset coordinates OffsetLeft & OffsetRight meters from the centerline and add these to
        // the fence point list
        {
            fence = new Fence();

            double SubsetStartStation = Math.Max(Alignment.StartStation, StartStation);
            double SubsetEndStation   = Math.Min(Alignment.EndStation, EndStation);

            if (SubsetEndStation <= SubsetStartStation)
            {
                calcResult = DesignProfilerRequestResult.InvalidStationValues;
                return;
            }

            double CurrentPos = SubsetStartStation;
            double Interval   = Math.Max(MinimumStationIntervalForSVLFilterBoundaryGeneration,
                                         Math.Min(Math.Abs(OffsetLeft), Math.Abs(OffsetRight)) / 4);

            var RHSProfile = new Fence();

            // Calculate all the offset points
            while (true)
            {
                AddOffsetPoints(fence, RHSProfile, CurrentPos, false);
                CurrentPos = CurrentPos + Interval;
                if (CurrentPos >= SubsetEndStation)
                {
                    AddOffsetPoints(fence, RHSProfile, SubsetEndStation, true);
                    break;
                }
            }

            // Now lets smooth each size if the fence, removing all points forming the apex of corners
            // smaller than MinimumRoadFenceAngle degrees;

            if (fence.NumVertices > 2)
            {
                SmoothFenceLine(fence, 1, 1, fence.NumVertices - 1);
            }
            if (RHSProfile.NumVertices > 2)
            {
                SmoothFenceLine(RHSProfile, RHSProfile.NumVertices - 2, -1, 0);
            }

            // Now copy the RHS profile fence points over to the fence
            for (int I = RHSProfile.NumVertices - 1; I >= 0; I--)
            {
                fence.Points.Add(RHSProfile[I]);
            }

            calcResult = DesignProfilerRequestResult.OK;
        }
示例#7
0
        /// <summary>
        /// Performs execution business logic for this executor.
        /// </summary>
        public List <Fence> Execute(DesignBoundaryArgument arg, out DesignProfilerRequestResult calcResult)
        {
            // Perform the design boundary calculation
            var result = Calc(arg, out calcResult);

            if (result == null)
            {
                Log.LogInformation($"Unable to calculate a design boundary result for {arg}");
                result = new List <Fence>();
            }

            return(result);
        }
示例#8
0
        /// <summary>
        /// Performs execution business logic for this executor
        /// </summary>
        public List <XYZS> Execute(CalculateDesignProfileArgument args, out DesignProfilerRequestResult calcResult)
        {
            // Perform the design profile calculation
            var result = Calc(args, out calcResult);

            if (result == null)
            {
                Log.LogInformation($"Unable to calculate a design profiler result for {args}");
                result = new List <XYZS>();
            }

            return(result);
        }
示例#9
0
        public bool ConstructSVLCenterlineAlignmentGeometry(NFFGuidableAlignmentEntity alignment)
        {
            if ((CalcResult = Validate(alignment)) != DesignProfilerRequestResult.OK)
            {
                return(false);
            }

            // Run through the entities in the alignment and add them to the geometry
            for (var I = 0; I < alignment.Entities.Count; I++)
            {
                AddEntityToGeometry(alignment.Entities[I]);
            }
            MoveWorkingVerticesToVertices();

            // Construct the stationing text entities along the alignment
            var StationIncrement = AlignmentLabelingInterval;
            var CurrentStation   = alignment.StartStation;

            while (CurrentStation <= alignment.EndStation + 0.001)
            {
                alignment.ComputeXY(CurrentStation, 0, out var X1, out var Y1);
                alignment.ComputeXY(CurrentStation, -1, out var X2, out var Y2);

                GeometryUtils.RectToPolar(Y1, X1, Y2, X2, out var textOrientation, out _);

                // Create an instance of the response label with the lat/lon coordinate set to the Y/X grid coordinates
                // which will be converted later by the caller
                Labels.Add(new AlignmentGeometryResponseLabel(CurrentStation, X1, Y1, Math.PI / 2 - textOrientation));

                if (CurrentStation + StationIncrement <= alignment.EndStation)
                {
                    CurrentStation += StationIncrement;
                }
                else if (CurrentStation > alignment.EndStation - 0.001)
                {
                    break;
                }
                else
                {
                    CurrentStation = alignment.EndStation;
                }
            }

            foreach (var vertices in Vertices)
            {
                vertices.FillInStationValues();
            }

            CalcResult = DesignProfilerRequestResult.OK;
            return(true);
        }
示例#10
0
        public bool ConstructSVLCenterlineDXFAlignment(NFFGuidableAlignmentEntity alignment,
                                                       out DesignProfilerRequestResult calcResult, out MemoryStream ms)
        {
            ms = null;
            if ((calcResult = Validate(alignment)) != DesignProfilerRequestResult.OK)
            {
                return(false);
            }

            DXF = new DXFFile();
            DXF.Layers.Add("B");

            // Run through the entities in the alignment and add them to the DXF file
            for (var I = 0; I < alignment.Entities.Count; I++)
            {
                AddEntityToDXF(alignment.Entities[I]);
            }

            // Construct the stationing text entities along the alignment
            var StationIncrement = AlignmentLabelingInterval;
            var CurrentStation   = alignment.StartStation;

            while (CurrentStation <= alignment.EndStation + 0.001)
            {
                alignment.ComputeXY(CurrentStation, 0, out var X1, out var Y1);
                alignment.ComputeXY(CurrentStation, -1, out var X2, out var Y2);

                GeometryUtils.RectToPolar(Y1, X1, Y2, X2, out var textOrientation, out _);

                DXF.Entities.Add(new DXFTextEntity("B",
                                                   kAlignmentCenterLineColor,
                                                   X1, Y1, Consts.NullDouble,
                                                   $"{CurrentStation / UnitUtils.DistToMeters(Units):F2}",
                                                   textOrientation - (Math.PI / 2),
                                                   2,
                                                   "Arial",
                                                   //[],
                                                   //0,
                                                   0, 0));

                if (CurrentStation + StationIncrement <= alignment.EndStation)
                {
                    CurrentStation = CurrentStation + StationIncrement;
                }
                else if (CurrentStation > alignment.EndStation - 0.001)
                {
                    break;
                }
                else
                {
                    CurrentStation = alignment.EndStation;
                }
            }

            if (DXF.Entities.Count > 0)
            {
                ms = new MemoryStream();
                using var writer = new StreamWriter(ms);
                DXF.SaveToFile(writer);
            }

            calcResult = DesignProfilerRequestResult.OK;

            return(true);
        }
示例#11
0
        /// <summary>
        /// Constructs a vector of cells in profileCells along the path of the profile geometry containing in nEECoords
        /// </summary>
        public bool Build(XYZ[] nEECoords, List <T> profileCells)
        {
            NEECoords    = nEECoords;
            ProfileCells = profileCells;

            CellSize = SiteModel.CellSize;

            CurrStationPos = 0;

            CurrentSubgridOrigin  = new SubGridCellAddress(int.MaxValue, int.MaxValue);
            ReturnDesignElevation = CutFillDesignWrapper?.Design != null;
            DesignElevations      = null;

            // Obtain the primary partition map to allow this request to determine the elements it needs to process
            bool[] primaryPartitionMap = ImmutableSpatialAffinityPartitionMap.Instance().PrimaryPartitions();

            for (int loopBound = NEECoords.Length - 1, I = 0; I < loopBound; I++)
            {
                StartX       = NEECoords[I].X;
                StartY       = NEECoords[I].Y;
                StartStation = NEECoords[I].Z;

                EndX       = NEECoords[I + 1].X;
                EndY       = NEECoords[I + 1].Y;
                EndStation = NEECoords[I + 1].Z;

                if (I == 0)                                               // Add start point of profile line to intercept list
                {
                    CurrStationPos = SlicerToolUsed ? 0 : NEECoords[I].Z; // alignment profiles pass in station for more accuracy
                    VtHzIntercepts.AddPoint(StartX, StartY, CurrStationPos);
                }

                Distance = SlicerToolUsed
          ? MathUtilities.Hypot(EndX - StartX, EndY - StartY) // station is not passed so compute
          : EndStation - StartStation;                        // use precise station passed

                if (Distance == 0)                            // if we have two points the same
                {
                    continue;
                }

                // Get all intercepts between profile line and cell boundaries for this segment
                CalculateHorizontalIntercepts(CurrStationPos); // pass the distance down alignment this segment starts
                CalculateVerticalIntercepts(CurrStationPos);

                CurrStationPos += Distance; // add distance to current station
            }

            // Merge vertical and horizontal cell boundary/profile line intercepts
            VtHzIntercepts.MergeInterceptLists(VtIntercepts, HzIntercepts);

            // Add end point of profile line to intercept list
            VtHzIntercepts.AddPoint(EndX, EndY, CurrStationPos);

            // Update each intercept with it's midpoint and intercept length
            // i.e. the midpoint on the line between one intercept and the next one
            // and the length between those intercepts
            VtHzIntercepts.UpdateMergedListInterceptMidPoints();

            if (VtHzIntercepts.Count > ProfileCells.Capacity)
            {
                ProfileCells.Capacity = VtHzIntercepts.Count;
            }

            // Iterate over all intercepts calculating the results for each cell that lies in
            // a subgrid handled by this node
            for (int i = 0; i < VtHzIntercepts.Count; i++)
            {
                if (Aborted)
                {
                    return(false);
                }

                // Determine the on-the-ground cell underneath the midpoint of each intercept line
                SiteModel.Grid.CalculateIndexOfCellContainingPosition(VtHzIntercepts.Items[i].MidPointX,
                                                                      VtHzIntercepts.Items[i].MidPointY, out OTGCellX, out OTGCellY);

                ThisSubgridOrigin = new SubGridCellAddress(OTGCellX & ~SubGridTreeConsts.SubGridLocalKeyMask, OTGCellY & ~SubGridTreeConsts.SubGridLocalKeyMask);

                if (!CurrentSubgridOrigin.Equals(ThisSubgridOrigin))
                {
                    if (!primaryPartitionMap[ThisSubgridOrigin.ToSpatialPartitionDescriptor()])
                    {
                        continue;
                    }

                    CurrentSubgridOrigin = ThisSubgridOrigin;

                    if (!ProfileFilterMask.ConstructSubGridCellFilterMask(SiteModel, CurrentSubgridOrigin, VtHzIntercepts, i, FilterMask, CellFilter,
                                                                          SurfaceDesignMaskDesign))
                    {
                        continue;
                    }

                    if (ReturnDesignElevation && CutFillDesignWrapper?.Design != null) // cut fill profile request then get elevation at same spot along design
                    {
                        var getDesignHeightsResult = CutFillDesignWrapper.Design.GetDesignHeightsViaLocalCompute(SiteModel, CutFillDesignWrapper.Offset, new SubGridCellAddress(OTGCellX, OTGCellY), CellSize);

                        DesignElevations = getDesignHeightsResult.designHeights;
                        DesignResult     = getDesignHeightsResult.errorCode;

                        if (DesignResult != DesignProfilerRequestResult.OK &&
                            DesignResult != DesignProfilerRequestResult.NoElevationsInRequestedPatch)
                        {
                            continue;
                        }

                        if (DesignResult == DesignProfilerRequestResult.NoElevationsInRequestedPatch)
                        {
                            DesignElevations = null; // force a null height to be written
                        }
                    }
                }

                if (FilterMask.BitSet(OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask, OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask))
                {
                    AddCellPassesDataToList(OTGCellX, OTGCellY, VtHzIntercepts.Items[i].ProfileItemIndex, VtHzIntercepts.Items[i].InterceptLength);
                }
            }

            Log.LogInformation($"CellProfileBuilder constructed a vector of {VtHzIntercepts.Count} vertices");

            return(true);
        }
示例#12
0
        /// <summary>
        /// Returns a list of coordinates traced over the alignment within the station range specified.
        ///  This coordinate list is then typically used to produce a station offset report
        /// </summary>
        public List <StationOffsetPoint> GetOffsetPointsInNEE(double crossSectionInterval, double startStation, double endStation, double[] offsets, out DesignProfilerRequestResult calcResult)
        {
            var result = new List <StationOffsetPoint>(1000);

            double lastX = -1, lastY = -1;

            var subsetStartStation = Math.Max(_data.StartStation, startStation);
            var subsetEndStation   = Math.Min(_data.EndStation, endStation);
            var currentStation     = subsetStartStation;

            void AddCoord(double x, double y, double station, double offset)
            {
                if (lastX == x && lastY == y)
                {
                    return; // don't wont duplicates
                }
                result.Add(new StationOffsetPoint(station, offset, x, y));
                lastX = x;
                lastY = y;
            }

            void AddPointAtStation(double x, double y, double station, double offset, bool rangeTestRequired)
            {
                if (rangeTestRequired) // test for end of range
                {
                    if (startStation >= subsetStartStation && station <= subsetEndStation)
                    {
                        AddCoord(x, y, station, offset); // add station if we have it
                    }
                }
                else
                {
                    AddCoord(x, y, station, offset);
                }
            }

            void AddSpotPointsFromElement(NFFStationedLineworkEntity element)
            {
                while (currentStation <= element.EndStation)
                {
                    foreach (var offset in offsets)
                    {
                        element.ComputeXY(currentStation, offset, out var ptX, out var ptY); // get x y at current position
                        AddPointAtStation(ptX, ptY, currentStation, offset, rangeTestRequired: false);
                    }

                    if (currentStation + crossSectionInterval > subsetEndStation && currentStation < subsetEndStation)
                    {
                        currentStation = subsetEndStation; // making sure last point is picked up
                    }
                    else
                    {
                        currentStation += crossSectionInterval;
                    }
                }
            }

            // Run down the centre line from start to end station and add these vertices to the point list
            // Pattern of coords returned will be in order of left to right e.g. -2, -1, 0 (center line) , 1 ,2

            calcResult = DesignProfilerRequestResult.UnknownError;

            if (endStation <= startStation)
            {
                calcResult = DesignProfilerRequestResult.InvalidStationValues;
                return(null);
            }

            // loop through all elements and add vertices where in range
            foreach (var currentElement in _data.Entities)
            {
                if (currentElement.EndStation < subsetStartStation) // ignore any early elements
                {
                    continue;
                }

                if (currentElement.StartStation > subsetEndStation) // are we pass end of range
                {
                    break;
                }

                AddSpotPointsFromElement(currentElement);
            }

            calcResult = DesignProfilerRequestResult.OK; // Made it this far so flag OK
            return(result);
        }
示例#13
0
        /// <summary>
        /// Performs the donkey work of the elevation patch calculation
        /// </summary>
        private IClientHeightLeafSubGrid Calc(ISiteModelBase siteModel, DesignOffset referenceDesign, double cellSize, int originX, int originY,
                                              out DesignProfilerRequestResult calcResult)
        {
            calcResult = DesignProfilerRequestResult.UnknownError;

            if (_isTraceLoggingEnabled)
            {
                _log.LogTrace("About to lock design");
            }

            var design = Designs.Lock(referenceDesign.DesignID, siteModel, cellSize, out var lockResult);

            if (design == null)
            {
                _log.LogWarning($"Failed to read design file for design {referenceDesign.DesignID}");

                calcResult = lockResult == DesignLoadResult.DesignDoesNotExist
                ? DesignProfilerRequestResult.DesignDoesNotExist
                : DesignProfilerRequestResult.FailedToLoadDesignFile;

                return(null);
            }

            try
            {
                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Computing sub grid elevation patch");
                }

                // Check to see if this sub grid has any design surface underlying it
                // from which to calculate an elevation patch. If not, don't bother...
                if (!design.HasElevationDataForSubGridPatch(originX >> SubGridTreeConsts.SubGridIndexBitsPerLevel,
                                                            originY >> SubGridTreeConsts.SubGridIndexBitsPerLevel))
                {
                    calcResult = DesignProfilerRequestResult.NoElevationsInRequestedPatch;
                    return(null);
                }

                var result = new ClientHeightLeafSubGrid(null, null, SubGridTreeConsts.SubGridTreeLevels, cellSize, SubGridTreeConsts.DefaultIndexOriginOffset);

                result.SetAbsoluteOriginPosition(originX & ~SubGridTreeConsts.SubGridLocalKeyMask,
                                                 originY & ~SubGridTreeConsts.SubGridLocalKeyMask);
                result.CalculateWorldOrigin(out var worldOriginX, out var worldOriginY);

                calcResult = design.InterpolateHeights(result.Cells, worldOriginX, worldOriginY, cellSize, referenceDesign.Offset)
                  ? DesignProfilerRequestResult.OK
                  : DesignProfilerRequestResult.NoElevationsInRequestedPatch;

                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Computed sub grid elevation patch");
                }

                return(result);
            }
            finally
            {
                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Unlocking design");
                }

                Designs.UnLock(referenceDesign.DesignID, design);

                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Completed calculating design elevations");
                }
            }
        }
示例#14
0
        /// <summary>
        /// Performs execution business logic for this executor
        /// </summary>
        public IClientHeightLeafSubGrid Execute(ISiteModelBase siteModel, DesignOffset referenceDesign, double cellSize, int originX, int originY, out DesignProfilerRequestResult calcResult)
        {
            // Perform the design elevation patch calculation
            try
            {
                /* Test code to force all sub grids to have 0 elevations from a design
                 * ClientHeightLeafSubGrid test = new ClientHeightLeafSubGrid(null, null, 6, 0.34, SubGridTreeConsts.DefaultIndexOriginOffset);
                 * test.SetToZeroHeight();
                 * return test;
                 */

                // Calculate the patch of elevations and return it
                return(Calc(siteModel, referenceDesign, cellSize, originX, originY, out calcResult));
            }
            finally
            {
                //if Debug_PerformDPServiceRequestHighRateLogging then
                //Log.LogInformation($"#Out# {nameof(CalculateDesignElevationPatch)}.Execute #Result# {calcResult}");
            }
        }
示例#15
0
        /// <summary>
        /// Performs the donkey work of the profile calculation
        /// </summary>
        private List <XYZS> Calc(CalculateDesignProfileArgument arg, out DesignProfilerRequestResult calcResult)
        {
            calcResult = DesignProfilerRequestResult.UnknownError;

            var siteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(arg.ProjectID);

            var Design = Designs.Lock(arg.ReferenceDesign.DesignID, siteModel, arg.CellSize, out DesignLoadResult LockResult);

            var arg2 = new CalculateDesignProfileArgument_ClusterCompute
            {
                ProjectID       = arg.ProjectID,
                CellSize        = arg.CellSize,
                ReferenceDesign = arg.ReferenceDesign,
            };

            if (arg.PositionsAreGrid)
            {
                arg2.ProfilePathNEE = new[] { arg.StartPoint, arg.EndPoint }.Select(x => new XYZ(x.Lon, x.Lat)).ToArray();
            }
            else
            {
                if (siteModel != null)
                {
                    arg2.ProfilePathNEE = DIContext.Obtain <ICoreXWrapper>().WGS84ToCalibration(
                        siteModel.CSIB(),
                        new[] { arg.StartPoint, arg.EndPoint }
                        .ToCoreX_WGS84Point(),
                        CoreX.Types.InputAs.Radians)
                                          .ToTRex_XYZ();
                }
            }



            if (Design == null)
            {
                Log.LogWarning($"Failed to read file for design {arg.ReferenceDesign.DesignID} lock result was {LockResult}");
                calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile;
                return(null);
            }

            try
            {
                var result = Design.ComputeProfile(arg2.ProfilePathNEE, arg.CellSize);
                //Apply any offset to the profile
                if (arg.ReferenceDesign.Offset != 0)
                {
                    for (var i = 0; i < result.Count; i++)
                    {
                        result[i] = new XYZS(result[i].X, result[i].Y, result[i].Z + arg.ReferenceDesign.Offset, result[i].Station, result[i].TriIndex);
                    }
                }
                calcResult = DesignProfilerRequestResult.OK;

                return(result);
            }
            finally
            {
                Designs.UnLock(arg.ReferenceDesign.DesignID, Design);
            }
        }