1172 lines · 40.7 KB · C#
RawDownload
//******************************************************************************************************//  GraphLines.cs - Gbtc////  Copyright © 2015, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this//  file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  11/29/2012 - J. Ritchie Carroll//       Generated original version of source code.////****************************************************************************************************** using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Data;using System.IO;using System.Text;using System.Threading;using GSF;using GSF.TimeSeries;using GSF.TimeSeries.Transport;using UnityEngine;using Vectrosity; // ReSharper disable once CheckNamespace// ReSharper disable UnusedMember.Local// ReSharper disable IntroduceOptionalParameters.Localpublic class GraphLines : MonoBehaviour{    #region [ Members ]     // Nested Types     // Defines a common set of methods for a line    private interface ILine    {        Guid ID        {            get;        }        void Stop();    }     private class Scale    {        private const float ShrinkStartThreshold = 0.5F;        private const float ShrinkStopThreshold = 0.9F;        private const float ShrinkDelay = 1.0F;         private readonly List<DataLine> m_lines;         private float m_scaleMin = float.NaN;        private float m_scaleMax = float.NaN;        private readonly float m_graphScale;        private readonly bool m_autoShrinkScale;        private float m_timeUntilShrink;         public Scale(float graphScale, bool autoShrinkScale)        {            m_graphScale = graphScale;            m_autoShrinkScale = autoShrinkScale;            m_lines = new List<DataLine>();            m_timeUntilShrink = ShrinkDelay;        }         public void Add(DataLine line)        {            m_lines.Add(line);        }         public void Update()        {            float displayMin = float.NaN;            float displayMax = float.NaN;             foreach (DataLine line in m_lines)            {                foreach (float value in line.UnscaledData)                {                    if (float.IsNaN(displayMin) || value < displayMin)                        displayMin = value;                     if (float.IsNaN(displayMax) || value > displayMax)                        displayMax = value;                }            }             if (float.IsNaN(m_scaleMin) || displayMin < m_scaleMin)            {                m_scaleMin = displayMin;                m_timeUntilShrink = ShrinkDelay;            }             if (float.IsNaN(m_scaleMax) || displayMax > m_scaleMax)            {                m_scaleMax = displayMax;                m_timeUntilShrink = ShrinkDelay;            }             if (m_autoShrinkScale)            {                if (m_timeUntilShrink > 0.0F)                {                    if ((m_scaleMax - m_scaleMin) * ShrinkStartThreshold >= (displayMax - displayMin))                        m_timeUntilShrink -= Time.deltaTime;                    else                        m_timeUntilShrink = ShrinkDelay;                }                 if (m_timeUntilShrink <= 0.0F)                {                    m_scaleMin += (displayMin - m_scaleMin) * Time.deltaTime * 5.0F;                    m_scaleMax -= (m_scaleMax - displayMax) * Time.deltaTime * 5.0F;                     if ((m_scaleMax - m_scaleMin) * ShrinkStopThreshold <= (displayMax - displayMin))                        m_timeUntilShrink = ShrinkDelay;                }            }             ScaleLinePoints();        }         private void ScaleLinePoints()        {            float unscaledValue;            Vector3 point;             foreach (DataLine line in m_lines)            {                for (int x = 0; x < line.UnscaledData.Length; x++)                {                    unscaledValue = line.UnscaledData[x];                     if (float.IsNaN(unscaledValue))                        unscaledValue = MidPoint;                     point = line.LinePoints[x];                    point.z = -ScaleValue(unscaledValue);                    line.LinePoints[x] = point;                }            }        }         private float ScaleValue(float value)        {            return (value - m_scaleMin) * (m_graphScale * 2.0F) / Range - m_graphScale;        }         private float Range        {            get            {                return m_scaleMax - m_scaleMin;            }        }         private float MidPoint        {            get            {                return m_scaleMin + Range / 2.0F;            }        }    }     // Creates a dynamically scaled 3D line using Vectrosity asset to draw line for data    private class DataLine : ILine    {        private readonly Guid m_id;        private readonly int m_index;        private readonly float[] m_unscaledData;        private VectorLine m_vector;         public DataLine(GraphLines parent, Guid id, int index)        {            m_id = id;            m_index = index;             m_unscaledData = new float[parent.m_pointsInLine];             m_vector = new VectorLine("DataLine" + index, new Vector3[parent.m_pointsInLine], parent.m_lineMaterial, parent.m_lineWidth, LineType.Continuous);            m_vector.color = parent.m_lineColors[index % parent.m_lineColors.Length];            m_vector.drawTransform = parent.m_target;            m_vector.Draw3DAuto();             for (int x = 0; x < m_vector.points3.Count; x++)            {                m_unscaledData[x] = float.NaN;                m_vector.points3[x] = new Vector3(Mathf.Lerp(-5.0F, 5.0F, x / (float)m_vector.points3.Count), -((index + 1) * parent.m_lineDepthOffset + 0.05F), 0.0F);            }        }         public Guid ID        {            get            {                return m_id;            }        }         public int Index        {            get            {                return m_index;            }        }         public Color VectorColor        {            get            {                return m_vector.color;            }            set            {                m_vector.color = value;            }        }         public float[] UnscaledData        {            get            {                return m_unscaledData;            }        }         public List<Vector3> LinePoints        {            get            {                return m_vector.points3; // m_linePoints;            }        }         public void Stop()        {            if ((object)m_vector != null)            {                m_vector.StopDrawing3DAuto();                VectorLine.Destroy(ref m_vector);            }        }         public void UpdateValue(float newValue)        {            int x;             // Move y position of all points to the left by one            for (x = 0; x < m_vector.points3.Count - 1; x++)                m_unscaledData[x] = m_unscaledData[x + 1];             m_unscaledData[x] = newValue;        }    }     // Creates a fixed 3D line using Vectrosity asset to draw line for legend    private class LegendLine : ILine    {        private readonly Guid m_id;        private VectorLine m_vector;         public LegendLine(GraphLines parent, Guid id, int index, Color color)        {            Transform transform = parent.m_legendMesh.transform;            Vector3 position = transform.position;             m_id = id;            m_vector = new VectorLine("LegendLine" + index, new Vector3[2], parent.m_lineMaterial, parent.m_lineWidth, LineType.Discrete);            m_vector.color = color;            m_vector.drawTransform = transform;            m_vector.Draw3DAuto();             float spacing = parent.m_legendMesh.characterSize * 1.5F;             // Position legend line relative to text descriptions            Vector3 point1 = new Vector3(-2.0F, -(spacing / 2.0F + index * spacing), -position.z);            Vector3 point2 = new Vector3(-0.5F, point1.y, point1.z);             m_vector.points3[0] = point1;            m_vector.points3[1] = point2;        }         public Guid ID        {            get            {                return m_id;            }        }         public void Stop()        {            if ((object)m_vector != null)            {                m_vector.StopDrawing3DAuto();                VectorLine.Destroy(ref m_vector);            }        }    }     // Exposes DataRow field value in a string.Format expression    private class RowFormatProvider : IFormattable    {        private readonly DataRow m_row;         public RowFormatProvider(DataRow row)        {            m_row = row;        }         public string ToString(string format, IFormatProvider provider)        {            if (m_row.Table.Columns.Contains(format))                return m_row[format].ToString();             return "<" + format + ">";        }    }     // Constants    private const string IniFileName = "GraphLines.ini";    private const int ControlWindowActiveHeight = 130;    private const int ControlWindowMinimizedHeight = 20;     // Fields    private ConcurrentDictionary<string, Scale> m_scales;    private ConcurrentDictionary<Guid, DataLine> m_dataLines;    private ConcurrentQueue<ICollection<IMeasurement>> m_dataQueue;    private DataSubscriber m_subscriber;    private DataTable m_measurementMetadata;    private List<LegendLine> m_legendLines;    private String[] m_statusText;    private System.Timers.Timer m_hideStatusTimer;    private MouseOrbit m_mouseOrbitScript;    private WaitHandle m_linesInitializedWaitHandle;    private bool m_subscribed;     // Subscriber control window variables    private Texture2D m_controlWindowTexture;    private Rect m_controlWindowActiveLocation;    private Rect m_controlWindowMinimizedLocation;    private bool m_controlWindowMinimized = true;    private int m_lastScreenHeight = -1;    private int m_lastScreenWidth = -1;    private string m_startTime = "*-5M";    private string m_stopTime = "*";    private int m_processInterval = 33;    private bool m_historicalSubscription;    private Vector2 m_scrollPosition;    private int m_guiSize = 1;     // Public fields exposed to Unity UI interface    public string m_title = "Gateway Exchange Protocol Subscription Tester";    public string m_connectionString = "server=localhost:6165;";    public string m_filterExpression = "FILTER ActiveMeasurements WHERE SignalType='FREQ' OR SignalType LIKE 'VPH*'";    public Material m_lineMaterial;    public int m_lineWidth = 4;    public float m_lineDepthOffset = 0.75F;    public int m_pointsInLine = 50;    public Transform m_target;    public float m_graphScale = 5.0F;    public Color[] m_lineColors = { Color.blue, Color.yellow, Color.red, Color.white, Color.cyan, Color.magenta, Color.black, Color.gray };    public TextMesh m_legendMesh;    public TextMesh m_statusMesh;    public int m_statusRows = 4;    public double m_statusDisplayInterval = 10000.0D;    public string m_legendFormat = "{0:SignalAcronym}: {0:Description} [{0:PointTag}]";     #endregion     #region [ Methods ]     #region [ Unity Event Handlers ]     protected void Awake()    {        string defaultIniPath = Application.dataPath + "/" + IniFileName;        string userIniPath = Application.persistentDataPath + "/" + IniFileName;         // Copy INI file with default settings to user INI file if one doesn't exist        if (File.Exists(defaultIniPath) && !File.Exists(userIniPath))            File.Copy(defaultIniPath, userIniPath);         // Load settings from INI file        IniFile iniFile = new IniFile(userIniPath);         m_title = iniFile["Settings", "Title", m_title];        m_connectionString = iniFile["Settings", "ConnectionString", m_connectionString];        m_filterExpression = iniFile["Settings", "FilterExpression", m_filterExpression];        m_lineWidth = int.Parse(iniFile["Settings", "LineWidth", m_lineWidth.ToString()]);        m_lineDepthOffset = float.Parse(iniFile["Settings", "LineDepthOffset", m_lineDepthOffset.ToString()]);        m_pointsInLine = int.Parse(iniFile["Settings", "PointsInLine", m_pointsInLine.ToString()]);        m_legendFormat = iniFile["Settings", "LegendFormat", m_legendFormat];        m_statusRows = int.Parse(iniFile["Settings", "StatusRows", m_statusRows.ToString()]);        m_statusDisplayInterval = double.Parse(iniFile["Settings", "StatusDisplayInterval", m_statusDisplayInterval.ToString()]);        m_startTime = iniFile["Settings", "StartTime", m_startTime];        m_stopTime = iniFile["Settings", "StopTime", m_stopTime];         // Attempt to save INI file updates (e.g., to restore any missing settings)        try        {            iniFile.Save();        }        catch (Exception ex)        {            Debug.Log("ERROR: " + ex.Message);        }         // Attempt to reference active mouse orbit script        m_mouseOrbitScript = GetComponent<MouseOrbit>();         // Create line dictionary and data queue        m_scales = new ConcurrentDictionary<string, Scale>();        m_dataLines = new ConcurrentDictionary<Guid, DataLine>();        m_dataQueue = new ConcurrentQueue<ICollection<IMeasurement>>();        m_legendLines = new List<LegendLine>();         // Initialize status rows and timer to hide status after a period of no updates        m_statusText = new string[m_statusRows];         for (int i = 0; i < m_statusRows; i++)        {            m_statusText[i] = "";        }         m_hideStatusTimer = new System.Timers.Timer();        m_hideStatusTimer.AutoReset = false;        m_hideStatusTimer.Interval = m_statusDisplayInterval;        m_hideStatusTimer.Elapsed += m_hideStatusTimer_Elapsed;         // For mobile applications we use a larger GUI font size.        // Other deployments might benefit from this as well - larger        // size modes may work also but are not tested        switch (Application.platform)        {            case RuntimePlatform.Android:            case RuntimePlatform.IPhonePlayer:                if (Screen.height <= 720)                    m_guiSize = 2;	// 720P                else                    m_guiSize = 3;	// 1080P or higher                break;        }         // Create a solid background for the control window        m_controlWindowTexture = new Texture2D(1, 1);        m_controlWindowTexture.SetPixel(0, 0, new Color32(10, 25, 70, 255));        m_controlWindowTexture.Apply();         VectorLine.SetCanvasCamera(Camera.main);        VectorLine.canvas3D.hideFlags = HideFlags.HideInHierarchy;    }     protected void Start()    {        // Attempt to update title        GameObject titleObject = GameObject.Find("Title");         if ((object)titleObject != null)        {            TextMesh titleMesh = titleObject.GetComponent<TextMesh>();             if ((object)titleMesh != null)                titleMesh.text = m_title;        }         // If 3D text legend mesh property was not defined, attempt to look it up by name        if ((object)m_legendMesh == null)        {            GameObject legendObject = GameObject.Find("Legend");             if ((object)legendObject != null)                m_legendMesh = legendObject.GetComponent<TextMesh>();        }         // If 3D text status mesh property was not defined, attempt to look it up by name        if ((object)m_statusMesh == null)        {            GameObject statusObject = GameObject.Find("Status");             if ((object)statusObject != null)                m_statusMesh = statusObject.GetComponent<TextMesh>();        }         InitiateConnection();    }

Lines 1–500 of 1172.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t