private void DrawCache(IGraphValueList graph, ref GraphCache cache) { Effect.Parameters["Color"].SetValue( new Vector4( graph.Color.R / 255.0f, graph.Color.G / 255.0f, graph.Color.B / 255.0f, (float)graph.PlaneAlpha)); GraphicsDevice.Indices = cache.IndexAreaBuffer; GraphicsDevice.SetVertexBuffer(cache.VertexAreaBuffer); foreach (EffectPass pass in Effect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, cache.VertexAreaBuffer.VertexCount, 0, cache.IndexAreaBuffer.IndexCount / 3); } Effect.Parameters["Color"].SetValue( new Vector4( graph.Color.R / 255.0f, graph.Color.G / 255.0f, graph.Color.B / 255.0f, (float)graph.GraphAlpha)); GraphicsDevice.SetVertexBuffer(cache.VertexLineBuffer); foreach (EffectPass pass in Effect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, cache.VertexLineBuffer.VertexCount, 0, cache.IndexAreaBuffer.IndexCount / 3); } }
private void DrawGraph(IGraphValueList graph) { if (graph.Count <= 1) { return; } GraphCache cache; bool needsRedraw = true; //if (graphCaches.TryGetValue(graph, out cache)) //{ // if (cache.NumElements == graph.Count) // { // needsRedraw = false; // } //} if (needsRedraw) { WaitCallback worker = (state) => { try { CreateCache(graph); } catch (Exception) { } }; ThreadPool.QueueUserWorkItem(worker); } lock (this) { if (graphCaches.TryGetValue(graph, out cache)) { DrawCache(graph, ref cache); } } }
public void Add(string name, IGraphValueList list) { graphs.Add(name, list); }
private void CreateCache(IGraphValueList graph) { GraphCache cache; int CurrentVertexIndex = 0; int graphCount = graph.Count; int startIndex = 0; int elementCount = graphCount - startIndex; if (elementCount <= 0) { return; } Func <IGraphValue, decimal> GetY = (value) => { return(value.DisplayValue); }; Func <IGraphValue, decimal> GetX = (value) => { return(value.DisplayPosition); }; decimal maxY = graph[startIndex].DisplayValue; decimal minY = graph[startIndex].DisplayValue; decimal maxX = graph[startIndex].DisplayPosition; decimal minX = graph[startIndex].DisplayPosition; for (int elementIndex = startIndex; elementIndex < graphCount; elementIndex++) { maxY = Math.Max(maxY, graph[elementIndex].DisplayValue); minY = Math.Min(minY, graph[elementIndex].DisplayValue); maxX = Math.Max(maxX, graph[elementIndex].DisplayPosition); minX = Math.Min(minX, graph[elementIndex].DisplayPosition); } Func <decimal, float> GetRelativeY = (decimal alpha) => { if (minY == maxY) { return(0.0f); } return(((float)((alpha - minY) / (maxY - minY)) - 0.5f) * 2.0f); }; Func <decimal, float> GetRelativeX = (decimal alpha) => { return(((float)((alpha - minX) / (maxX - minX)) - 0.5f) * 2.0f); }; VertexPosition2 upperPoint = new VertexPosition2(); VertexPosition2 lowerPoint = new VertexPosition2(); upperPoint.Position = new Vector2(-1, GetRelativeY(graph.ElementAt(0).DisplayValue)); lowerPoint.Position = new Vector2(-1, -1); VertexPosition2[] vertexAreaBufferData = new VertexPosition2[((graphCount - startIndex) + 1) * 2]; VertexPosition2[] vertexLineBufferData = new VertexPosition2[((graphCount - startIndex) + 1) * 2]; int[] indexBufferData = new int[((graphCount - startIndex)) * 6]; int CurrentIndexBufferIndex = 0; vertexAreaBufferData[CurrentVertexIndex] = upperPoint; vertexAreaBufferData[CurrentVertexIndex + 1] = lowerPoint; float lineWidth = (5.0f / Height) / 2.0f; Vector2 lineWidthOffset = new Vector2(0.0f, lineWidth / 2.0f); vertexLineBufferData[CurrentVertexIndex] = new VertexPosition2(upperPoint.Position + lineWidthOffset); vertexLineBufferData[CurrentVertexIndex + 1] = new VertexPosition2(upperPoint.Position - lineWidthOffset); CurrentVertexIndex = 2; Vector2 lastUpperPoint; for (int GraphIndex = startIndex; GraphIndex < graphCount; GraphIndex++) { float x = GetRelativeX(graph.ElementAt(GraphIndex).DisplayPosition); float y = GetRelativeY(graph.ElementAt(GraphIndex).DisplayValue); lastUpperPoint = upperPoint.Position; upperPoint.Position = new Vector2(x, y); lowerPoint.Position = new Vector2(x, -1); vertexAreaBufferData[CurrentVertexIndex] = upperPoint; vertexAreaBufferData[CurrentVertexIndex + 1] = lowerPoint; // Calculate orthogonal vector of direction from last point to this one, // so the line keeps its thickness along slopes // Without this sloped graphs would get very thin Vector2 dirFromLastPoint = upperPoint.Position - lastUpperPoint; if (GraphIndex + 1 < graphCount) { dirFromLastPoint += new Vector2( GetRelativeX(graph.ElementAt(GraphIndex + 1).DisplayPosition), GetRelativeY(graph.ElementAt(GraphIndex + 1).DisplayValue)) - upperPoint.Position; dirFromLastPoint /= 2; } dirFromLastPoint.Normalize(); Vector2 orthogonalDir = new Vector2(-dirFromLastPoint.Y, dirFromLastPoint.X); vertexLineBufferData[CurrentVertexIndex] = (new VertexPosition2(upperPoint.Position + orthogonalDir * lineWidth)); vertexLineBufferData[CurrentVertexIndex + 1] = (new VertexPosition2(upperPoint.Position - orthogonalDir * lineWidth)); // Counter Clockwise Tris get culled in our current setting // So draw 2 triangles in clockwise order // -2---+0 // | /| // | / | // | / | // |/ | // -1---+1 int LastUpperPoint = CurrentVertexIndex - 2; int LastLowerPoint = CurrentVertexIndex - 1; int CurrentUpperPoint = CurrentVertexIndex; int CurrentLowerPoint = CurrentVertexIndex + 1; indexBufferData[CurrentIndexBufferIndex] = LastUpperPoint; indexBufferData[CurrentIndexBufferIndex + 1] = CurrentUpperPoint; indexBufferData[CurrentIndexBufferIndex + 2] = LastLowerPoint; indexBufferData[CurrentIndexBufferIndex + 3] = LastLowerPoint; indexBufferData[CurrentIndexBufferIndex + 4] = CurrentUpperPoint; indexBufferData[CurrentIndexBufferIndex + 5] = CurrentLowerPoint; CurrentIndexBufferIndex += 6; CurrentVertexIndex += 2; } cache.VertexLineBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPosition2), CurrentVertexIndex, BufferUsage.WriteOnly); cache.VertexLineBuffer.SetData(vertexLineBufferData); cache.VertexAreaBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPosition2), CurrentVertexIndex, BufferUsage.WriteOnly); cache.VertexAreaBuffer.SetData(vertexAreaBufferData); cache.IndexAreaBuffer = new IndexBuffer(GraphicsDevice, IndexElementSize.ThirtyTwoBits, indexBufferData.Length, BufferUsage.WriteOnly); cache.IndexAreaBuffer.SetData(indexBufferData); cache.NumElements = graphCount; GraphCache oldCache; lock (this) { if (graphCaches.TryGetValue(graph, out oldCache)) { graphCaches.Remove(graph); oldCache.IndexAreaBuffer?.Dispose(); oldCache.VertexAreaBuffer?.Dispose(); oldCache.VertexLineBuffer?.Dispose(); } graphCaches[graph] = cache; } }