Exemplo n.º 1
0
        private async Task UpdateGraph(object sender, EventArgs e)
        {
            try
            {
                //fetch latest UV data from service and then update model
                int?LocIndex = this.arpansaModel.LocIndexValue;
                if (LocIndex == null)
                {
                    //no location has been selected. Nothing to paint.
                    return;
                }
                MeasuredLocation curLocation = this.arpansaModel.MeasureLocations[LocIndex.Value];
                CurrentLocName.Text = curLocation.SiteName;

                ArpansaUVResponse arpansaUV = await this.arpansaService.GetUVData(curLocation.SiteLongitude.Value, curLocation.SiteLatitude.Value);

                List <UVIndex> uvIndexes = arpansaService.GenerateUVIndexs();

                //update model
                ArpansaUVData graphData = new ArpansaUVData(arpansaUV);
                graphData.ReferenceUVs          = uvIndexes;
                this.arpansaModel.ArpansaUVData = graphData;
            }
            catch (Exception e1)
            {
                await DisplayAlert("Error", e1.Message, "Ok");
            }
        }
Exemplo n.º 2
0
        //util method to find the closes datapoint for a given value on the x axis
        private GraphData GetClosestDataPointAtTime(TimeSpan targetTime)
        {
            ArpansaUVData arpansaData = this.arpansaModel.ArpansaUVData;

            if (arpansaData == null)
            {
                //no data to sort through
                return(null);
            }

            GraphData[] uvData = arpansaData.GraphData;

            GraphData closestPoint = null;
            double    closestDiff  = double.PositiveInfinity;

            for (int i = 0; i < uvData.Length; i++)
            {
                TimeSpan uvTime = DateTimeStringToTime(uvData[i].Date);
                double   diff   = Math.Abs(targetTime.TotalMinutes - uvTime.TotalMinutes);
                if (diff < closestDiff)
                {
                    closestPoint = uvData[i];
                    closestDiff  = diff;
                }
            }

            return(closestPoint);
        }
Exemplo n.º 3
0
        private void DrawHorizontalDashes()
        {
            SKCanvas      graphCavnas = this.graphSurface.Canvas;
            ArpansaUVData arpansaData = this.arpansaModel.ArpansaUVData;

            if (arpansaData?.ReferenceUVs == null)
            {
                //need reference UV levels
                return;
            }

            //for each refernce UV level
            for (int i = 0; i < arpansaData.ReferenceUVs.Count; i++)
            {
                float uvValue     = arpansaData.ReferenceUVs[i].LowerValue;
                float unitsHigh   = uvValue * this.unitsPerUVLevel;
                float RefLineYPos = unitsHigh;

                SKPaint refLinePaint = new SKPaint
                {
                    Color       = arpansaData.ReferenceUVs[i].Colour.WithAlpha(0.5f),
                    Style       = SKPaintStyle.Stroke,
                    StrokeWidth = 1f,
                    PathEffect  = SKPathEffect.CreateDash(new float[] { 6f, 3f }, 0),
                    IsAntialias = true
                };

                // draw line
                graphCavnas.DrawLine(0, RefLineYPos, this.gridWidth, RefLineYPos, refLinePaint);

                // write text above each reference point
                SKPaint refTextPaint = new SKPaint
                {
                    Color       = arpansaData.ReferenceUVs[i].Colour,
                    TextAlign   = SKTextAlign.Right,
                    IsAntialias = true,
                    TextSize    = 15f
                };

                float padding  = 10f;
                float textPosX = this.gridWidth - padding;
                float textPosY = RefLineYPos + padding;

                DrawTextOnGraph(arpansaData.ReferenceUVs[i].DetailText, textPosX, textPosY, refTextPaint);
            }
        }
Exemplo n.º 4
0
        private void DrawCurrentUV()
        {
            SKCanvas      graphCanvas = this.graphSurface.Canvas;
            ArpansaUVData arpansaData = this.arpansaModel.ArpansaUVData;

            if (arpansaData?.GraphData == null || arpansaData.GraphData.Length <= 0)
            {
                //need graph data
                return;
            }
            if (arpansaData?.CurrentUVIndex == null || arpansaData?.CurrentDateTime == null)
            {
                //need current data
                return;
            }
            if (arpansaData?.ReferenceUVs == null)
            {
                //need reference UV levels
                return;
            }

            //get latest datapoint
            float curUVLevel = float.Parse(arpansaData.CurrentUVIndex);

            TimeSpan lastMeasurementTime = DateTimeStringToTime(arpansaData.CurrentDateTime);

            float currentX = (float)(lastMeasurementTime.TotalMinutes - this.minX.TotalMinutes) * this.unitsPerMinute;
            float currentY = curUVLevel * this.unitsPerUVLevel;

            string uvString = curUVLevel.ToString("F1");


            //create a paint based of the current reading
            //paint colour will be set to the current UV reference colour
            UVIndex curUVIndex = null;

            for (int i = 0; i < arpansaData.ReferenceUVs.Count; i++)
            {
                if (curUVLevel >= arpansaData.ReferenceUVs[i].LowerValue)
                {
                    curUVIndex = arpansaData.ReferenceUVs[i];
                }
            }
            SKPaint curColourAreaPaint = new SKPaint
            {
                Color       = curUVIndex.Colour.WithAlpha(0.8f),
                Style       = SKPaintStyle.Fill,
                IsAntialias = true
            };
            SKPaint curColourLinePaint = new SKPaint
            {
                Color       = curUVIndex.Colour.WithAlpha(0.4f),
                Style       = SKPaintStyle.Stroke,
                IsAntialias = true,
                StrokeWidth = 2f
            };

            //draw a nice circle on the endpoint
            float pointRadius = 3.6f;

            graphCanvas.DrawCircle(currentX, currentY, pointRadius, new SKPaint {
                Color = SKColors.White
            });
            graphCanvas.DrawCircle(currentX, currentY, pointRadius, curColourLinePaint);


            //write the current text a little up and to the right of the current point
            float textX = currentX + 12f;
            float textY = currentY + 12f;

            SKRect uvRectFrame = new SKRect();

            this.currentUVTextPaint.MeasureText(uvString, ref uvRectFrame);

            //do a check to see if current UV reading will appear off the screen
            float framePadding = 5f;

            if (textX + uvRectFrame.Width + framePadding >= this.gridWidth)
            {
                //being cut off on x axis
                GraphData closestPoint = this.GetClosestDataPointAtTime(this.maxX);

                textX = this.gridWidth - uvRectFrame.Width - framePadding - 4f;
            }
            if (textY + uvRectFrame.Height + framePadding >= this.gridHeight)
            {
                //being cut off on y axis
                textY = this.gridHeight - uvRectFrame.Height - framePadding - 4f;
            }

            uvRectFrame.Offset(textX, textY + uvRectFrame.Height);
            uvRectFrame.Inflate(framePadding, framePadding);

            graphCanvas.DrawRoundRect(uvRectFrame, 3f, 3f, curColourAreaPaint);
            this.DrawTextOnGraph(uvString, textX, textY, this.currentUVTextPaint);
        }
Exemplo n.º 5
0
        private void DrawUVPlots()
        {
            ArpansaUVData arpansaData = this.arpansaModel.ArpansaUVData;

            if (arpansaData?.GraphData == null || arpansaData.GraphData.Length <= 0)
            {
                //no graph data
                return;
            }
            if (arpansaData?.ReferenceUVs == null || arpansaData.ReferenceUVs.Count <= 0)
            {
                //need reference points for background colour
                return;
            }

            GraphData[] graphData       = arpansaData.GraphData;
            SKCanvas    graphCanvas     = this.graphSurface.Canvas;
            SKPath      approximatePath = null;
            SKPath      measuredPath    = null;

            //collect data for the UV plot lines
            TimeSpan timeValue = DateTimeStringToTime(graphData[0].Date);

            //approximate UV
            float?startForecast = graphData[0].Forecast;

            if (startForecast != null)
            {
                float approxX = (float)(timeValue.TotalMinutes - this.minX.TotalMinutes) * this.unitsPerMinute;
                float approxY = (float)startForecast * this.unitsPerUVLevel;
                approximatePath = new SKPath();
                approximatePath.MoveTo(approxX, approxY);
            }

            //measured UV
            float?startMeasured = graphData[0].Measured;

            if (startMeasured != null)
            {
                float measuredX = (float)(timeValue.TotalMinutes - this.minX.TotalMinutes) * this.unitsPerMinute;
                float measuredY = (float)graphData[0].Measured * this.unitsPerUVLevel;
                measuredPath = new SKPath();
                measuredPath.MoveTo(measuredX, measuredY);
            }

            //for each plot point
            for (int i = 1; i < graphData.Length; i++)
            {
                //get time
                TimeSpan curTimeValue = DateTimeStringToTime(graphData[i].Date);

                //approximate UV
                float?curApproxUV = graphData[i].Forecast;
                if (curApproxUV != null && approximatePath != null)
                {
                    float curApproxX = (float)(curTimeValue.TotalMinutes - this.minX.TotalMinutes) * this.unitsPerMinute;
                    float curApproxY = (float)curApproxUV * this.unitsPerUVLevel;
                    approximatePath.LineTo(curApproxX, curApproxY);
                }

                //measured UV
                float?curMeasuredUV = graphData[i].Measured;
                if (curMeasuredUV != null && measuredPath != null)
                {
                    float curMeasuredX = (float)(curTimeValue.TotalMinutes - this.minX.TotalMinutes) * this.unitsPerMinute;
                    float curMeasuredY = (float)curMeasuredUV * this.unitsPerUVLevel;
                    measuredPath.LineTo(curMeasuredX, curMeasuredY);
                }
            }

            //create an awesome rainbow shader
            SKPoint graphBottom    = new SKPoint(0.0f, 0.0f);
            UVIndex highestUVRef   = arpansaData.ReferenceUVs[arpansaData.ReferenceUVs.Count - 1];
            float   highestIVValue = highestUVRef.LowerValue;
            SKPoint highRefPoint   = new SKPoint(0.0f, highestIVValue * this.unitsPerUVLevel);

            List <SKColor> colourList = new List <SKColor>();
            List <float>   posList    = new List <float>();

            foreach (var uvInfo in arpansaData.ReferenceUVs)
            {
                colourList.Add(uvInfo.Colour.WithAlpha(0.4f));
                posList.Add(uvInfo.LowerValue / highestIVValue);
            }
            SKShader uvShader = SKShader.CreateLinearGradient(graphBottom, highRefPoint, colourList.ToArray(), posList.ToArray(), SKShaderTileMode.Clamp);

            this.measuredLinePaint.Shader = uvShader;

            ////draw approximate and measured plot lines
            if (approximatePath != null)
            {
                graphCanvas.DrawPath(approximatePath, this.predictedLinePaint);
            }
            if (measuredPath != null)
            {
                graphCanvas.DrawPath(measuredPath, this.measuredLinePaint);

                //now draw area under plot lines
                SKPoint firstMeasuredPoint = measuredPath.GetPoint(0);
                SKPoint lastMeasuredPoint  = measuredPath.GetPoint(measuredPath.PointCount - 1);
                measuredPath.LineTo(lastMeasuredPoint.X, 0);
                measuredPath.LineTo(firstMeasuredPoint.X, 0);
                measuredPath.Close();

                graphCanvas.DrawPath(measuredPath, this.measuredAreaPaint);
            }
        }