Ejemplo n.º 1
0
        private async void StartReceive()
        {
            var buffer = new byte[m_PipeStream.InBufferSize];

            var cancellationToken = m_ChannelCancelToken.Token;

            while (!cancellationToken.IsCancellationRequested)
            {
                var result = await m_PipeStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);

                var processResult = m_PipeLineProcessor.Process(new ArraySegment <byte>(buffer, 0, result));

                if (processResult.State == ProcessState.Error)
                {
                    Debug.Fail("Pipeline processing failed.");
                    break;
                }
                else if (processResult.State == ProcessState.Cached)
                {
                    buffer = new byte[m_PipeStream.InBufferSize];
                }

                if (processResult.Packages != null && processResult.Packages.Count > 0)
                {
                    foreach (var item in processResult.Packages)
                    {
                        HandlePipePackage(item as PipePackageInfo);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        List <PipelineStepContainer> _pipelineSteps = new List <PipelineStepContainer>(); // Reference to all steps

        public Pipeline <TPipelineIn, TPipelineOut> AddStepAndStart <TIn, TOut>(IPipelineProcessor <TIn, TOut> processor)
        {
            var step      = new PipelineStep <TIn, TOut>(processor);
            int stepIndex = _pipelineSteps.Count;

            // Alternatively, I can store a list of the Task.Run() handlers here and then run them at a later point
            // Start the step
            Task.Run(() =>
            {
                // Cached next step
                IBufferable <TOut> nextBuffer = null;

                foreach (Item <TIn> input in step.Buffer.GetConsumingEnumerable())
                {
                    // Give us the most up-to-date status on our current position in the pipeline
                    bool isLastStep = stepIndex == _pipelineSteps.Count - 1;

                    TOut outputValue;

                    // Attempt to process value
                    try
                    {
                        outputValue = processor.Process(input.Value);
                    }
                    catch (Exception e)
                    {
                        input.TaskCompletionSource.SetException(e);
                        continue;
                    }

                    // Move to next step
                    if (isLastStep)
                    {
                        input.TaskCompletionSource.SetResult((TPipelineOut)(object)outputValue);
                    }
                    else
                    {
                        nextBuffer = nextBuffer ?? _pipelineSteps[stepIndex + 1].Value as IBufferable <TOut>;
                        try // In the case of the pipeline closing prematurely, catch the error and throw an exception to the task
                        {
                            nextBuffer.Buffer.Add(new Item <TOut>
                            {
                                Value = outputValue,
                                TaskCompletionSource = input.TaskCompletionSource
                            });
                        }
                        catch (InvalidOperationException e)
                        {
                            input.TaskCompletionSource.SetException(e);
                        }
                    }
                }
            });
            _pipelineSteps.Add(new PipelineStepContainer
            {
                Value = step,
            });
            return(this);
        }
        private void RunSubPipelines(PipelineContext pipelineContext, Pipeline subPipeline)
        {
            ILogger logger = pipelineContext.PipelineBatchContext.Logger;

            pipelineContext.CurrentPipeline = subPipeline;
            IPipelineProcessor pipelineProcessor = subPipeline.PipelineProcessor;

            if (pipelineProcessor == null)
            {
                logger.Error("Pipeline will be skipped because it does not have a processor assigned. (pipeline step: {0}, sub-pipeline: {1})", "Iterate and Run Async", (object)subPipeline.Name);
            }
            else if (!pipelineProcessor.CanProcess(subPipeline, pipelineContext))
            {
                logger.Error("Pipeline will be skipped because the processor cannot processes the sub-pipeline. (pipeline step: {0}, sub-pipeline: {1}, sub-pipeline processor: {2})", "Iterate and Run Async", (object)subPipeline.Name, (object)pipelineProcessor.GetType().FullName);
            }
            else
            {
                pipelineProcessor.Process(subPipeline, pipelineContext);
                if (pipelineContext.CriticalError)
                {
                    logger.Error("Sub pipeline processing will not abort since it's done async");
                }
            }
        }
Ejemplo n.º 4
0
 public static PipelineResult ProcessAction <TEvent>(this IPipelineProcessor processor, TEvent @event)
     where TEvent : IEvent
 {
     return(processor.Process(new Payload <TEvent>(@event)));
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Process a given payload through the stages in this pipeline using
 /// the processor in this pipeline.
 /// </summary>
 public TPayload Process(TPayload payload)
 {
     return(_processor.Process(payload, _stages));
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Executor that implements requesting and rendering grid information to create the grid rows
        /// </summary>
        /// <returns></returns>
        public async Task <bool> ExecuteAsync()
        {
            // Get the lat lon boundary from xyz tile request
            TileBoundaryLL = MapGeo.TileXYZToRectLL(TileX, TileY, TileZ, out var yFlip);
            _log.LogInformation($"#Tile#.({TileX},{TileY}) Execute Start.  DMode:{DisplayMode}, HasLighting:{HasLighting}, Zoom:{TileZ} FlipY:{yFlip}. TileBoundary:{TileBoundaryLL.ToDisplay()}, DataModel:{DataModelUid}");

            if (TileZ == 0) // Send back default root tile
            {
                MakeRootTile();
                return(true);
            }

            SiteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(DataModelUid);
            if (SiteModel == null)
            {
                ResultStatus = RequestErrorStatus.NoSuchDataModel;
                _log.LogError($"Tile.({TileX},{TileY}) Failed to obtain site model for {DataModelUid}");
                return(false);
            }

            var siteModelExtentWithSurveyedSurfaces = SiteModel.GetAdjustedDataModelSpatialExtents(null);

            _log.LogDebug($"Tile.({TileX},{TileY}) Site model extents are {siteModelExtentWithSurveyedSurfaces}. TileBoundary:{TileBoundaryLL.ToDisplay()}");
            if (!siteModelExtentWithSurveyedSurfaces.IsValidPlanExtent) // No data return empty tile
            {
                return(BuildEmptyTile());
            }

            // We will draw all missing data just below lowest elevation for site
            LowestElevation = (float)siteModelExtentWithSurveyedSurfaces.MinZ - 1F;

            Initialise();                                           // setup tile requirements

            if (TileGridSize == QMConstants.FlatResolutionGridSize) // Too far out to see detail so return empty tile
            {
                return(BuildEmptyTile());
            }

            if (DisplayMode == QMConstants.DisplayModeDemo) // development use only
            {
                return(BuildDemoTile());
            }

            try
            {
                var setupResult = await SetupPipelineTask(siteModelExtentWithSurveyedSurfaces, SiteModel.CellSize);

                if (!setupResult)
                {
                    if (ResultStatus != RequestErrorStatus.InvalidCoordinateRange)
                    {
                        _log.LogError($"Tile.({TileX},{TileY}) Unable to setup pipelinetask.");
                    }
                    return(BuildEmptyTile());
                }

                processor.Process();

                if (GriddedElevationsResponse.ResultStatus != RequestErrorStatus.OK)
                {
                    _log.LogError($"Tile.({TileX},{TileY}) Unable to obtain data for gridded data. GriddedElevationRequestResponse: {GriddedElevationsResponse.ResultStatus.ToString()}");
                    return(BuildEmptyTile());
                }

                ElevData.HasData = !float.IsPositiveInfinity(task.MinElevation); // check for data

                // Developer Debugging Only
                if (ElevData.HasData)
                {
                    OutputDebugTile("Raw");
                }

                if (!ElevData.HasData)
                {
                    return(BuildEmptyTile());
                }

                _log.LogInformation($"#Tile#.({TileX},{TileY}) Data successfully sampled. GridSize:{TileGridSize} Min:{task.MinElevation}, Max:{task.MaxElevation} FirstElev:{GriddedElevDataArray[0, 0].Elevation}, LastElev:{GriddedElevDataArray[TileGridSize - 1, TileGridSize - 1].Elevation}");

                ElevData.HasLighting = HasLighting;
                // Transform gridded data into a format the mesh builder can use
                ConvertGridToDEM(task.MinElevation, task.MaxElevation);

                // Build a quantized mesh from sampled elevations
                QMTileBuilder tileBuilder = new QMTileBuilder()
                {
                    TileData = ElevData, GridSize = TileGridSize
                };
                _log.LogInformation($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile. GridSize:{TileGridSize} Min:{ElevData.MinimumHeight}, Max:{ElevData.MaximumHeight}");
                if (!tileBuilder.BuildQuantizedMeshTile())
                {
                    _log.LogError($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile returned false with error code: {tileBuilder.BuildTileFaultCode}");
                    return(false);
                }

                QMTileResponse.data         = tileBuilder.QuantizedMeshTile; // Make tile from mesh
                ResultStatus                = RequestErrorStatus.OK;
                QMTileResponse.ResultStatus = ResultStatus;
                _log.LogDebug($"#Tile#.({TileX},{TileY}) Execute End. Returning production tile. CesiumY:{yFlip}, Zoom:{TileZ}, GridSize:{TileGridSize}");

                return(true);
            }
            catch (Exception ex)
            {
                _log.LogError(ex, $"#Tile#.({TileX},{TileY}). Exception building QuantizedMesh tile: ");
                return(false);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Perform rendering activities to produce a bitmap tile
        /// </summary>
        public RequestErrorStatus PerformRender(DisplayMode mode, IPipelineProcessor processor, IPlanViewPalette colourPalette, IFilterSet filters, ILiftParameters liftParams)
        {
            // Obtain the display responsible for rendering the thematic information for this mode
            Displayer = PVMDisplayerFactory.GetDisplayer(mode /*, FICOptions*/);

            if (Displayer == null)
            {
                processor.Response.ResultStatus = RequestErrorStatus.UnsupportedDisplayType;
                return(processor.Response.ResultStatus);
            }

            // Create and assign the colour palette logic for this mode to the displayer
            if (colourPalette == null)
            {
                if (mode == DisplayMode.CCA || mode == DisplayMode.CCASummary)
                {
                    Displayer.SetPalette(Utilities.ComputeCCAPalette(processor.SiteModel, filters.Filters[0].AttributeFilter, mode));

                    if (Displayer.GetPalette() == null)
                    {
                        processor.Response.ResultStatus = RequestErrorStatus.FailedToGetCCAMinimumPassesValue;
                        return(processor.Response.ResultStatus);
                    }
                }
                else
                {
                    Displayer.SetPalette(PVMPaletteFactory.GetPalette(processor.SiteModel, mode, processor.SpatialExtents));
                }
            }
            else
            {
                Displayer.SetPalette(colourPalette);
            }

            // Create the world coordinate display surface the displayer will render onto
            Displayer.MapView = new MapSurface
            {
                SquareAspect = IsWhollyInTermsOfGridProjection
            };

            var view = Displayer.MapView;

            // Set the world coordinate bounds of the display surface to be rendered on
            view.SetBounds(NPixelsX, NPixelsY);

            if (IsWhollyInTermsOfGridProjection)
            {
                view.FitAndSetWorldBounds(OriginX, OriginY, OriginX + Width, OriginY + Height, 0);
            }
            else
            {
                view.SetWorldBounds(OriginX, OriginY, OriginX + Width, OriginY + Height, 0);
            }

            // Provide data smoothing support to the displayer for the rendering operation being performed
            ((IProductionPVMConsistentDisplayer)Displayer).DataSmoother = DIContext.Obtain <Func <DisplayMode, IDataSmoother> >()(mode);

            // Set the rotation of the displayer rendering surface to match the tile rotation due to the project calibration rotation
            view.SetRotation(TileRotation);

            ConstructPVMTaskAccumulator(processor);

            // Displayer.ICOptions  = ICOptions;

            // Set the skip-step area control cell selection parameters for this tile render. Note that the floating point
            // skip step algorithm is requested, and a user origin is configured that offsets the sampling grid by half a pixel
            // size to matching the skip-stepping the PVM accumulator will use when transcribing cell data from sub grids into
            // the accumulator. Note that the area control set is not configured with a rotation - this is taken into account
            // through the mapview rotation configured above
            processor.Pipeline.AreaControlSet = new AreaControlSet(false,
                                                                   view.XPixelSize, view.YPixelSize,
                                                                   view.XPixelSize / 2.0, view.YPixelSize / 2.0,
                                                                   0.0);

            processor.Pipeline.LiftParams = liftParams;
            // todo PipeLine.NoChangeVolumeTolerance  = FICOptions.NoChangeVolumeTolerance;

            // Perform the sub grid query and processing to render the tile
            var pipelineProcessorStopWatch = Stopwatch.StartNew();

            processor.Process();
            _log.LogInformation($"Pipeline processor completed in {pipelineProcessorStopWatch.Elapsed}");

            if (processor.Response.ResultStatus == RequestErrorStatus.OK)
            {
                // Render the collection of data in the aggregator
                var consistentRenderStopWatch = Stopwatch.StartNew();
                (Displayer as IProductionPVMConsistentDisplayer)?.PerformConsistentRender();
                _log.LogInformation($"Consistent render complated in {consistentRenderStopWatch.Elapsed}");

                PerformAnyRequiredDebugLevelDisplay();

                if (DebugDrawDiagonalCrossOnRenderedTilesDefault)
                {
                    // Draw diagonal cross and top left corner indicators
                    view.DrawLine(view.OriginX, view.OriginY, view.LimitX, view.LimitY, Color.Red);
                    view.DrawLine(view.OriginX, view.LimitY, view.LimitX, view.OriginY, Color.Red);

                    // Draw the horizontal line a little below the world coordinate 'top' of the tile to encourage the line
                    // drawing algorithm not to clip it
                    view.DrawLine(view.OriginX, view.LimitY, view.OriginX, view.CenterY, Color.Red);
                    view.DrawLine(view.OriginX, view.LimitY - 0.01, view.CenterX, view.LimitY - 0.01, Color.Red);
                }
            }

            return(processor.Response.ResultStatus);
        }