/// <summary> /// 绘制UV界面 /// </summary> /// <param name="rect"></param> public void DrawPreview(Rect rect, Color color, UVIndex uvIndex, bool drawVertexColor) { DrawCheckerBoard(rect);//绘制棋盘格 if (drawVertexColor) { DrawVertexColor(rect, (int)uvIndex); //绘制顶点色 } DrawUV(rect, (int)uvIndex, color); //绘制UV ListenEvent(rect); }
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); }
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); } }