protected int graphValue(GraphItem ev, int index) { // the Server Availability graph requires interpolated (stepped) line; // others require peaks where the data actually is: if(ev == null) { // no data at this point. switch(m_graphMode) { case GRAPH_MODE_STEPPED: ev = m_lastItem; // may be null too break; } } int value; if(ev == null || (index+1) > ev.nValues()) { value = m_yZeroMark; } else { double evValue = ev.values(m_format)[index]; if(m_format == Project.FORMAT_EARTHQUAKES_STRONGEST && evValue == 0.0d) { evValue = 0.5d; // quakes with unknown magnitude will be small bumps on the graph } value = m_yZeroMark - (int)(evValue * m_valueFactor); } m_lastItem = ev; return value; }
private void rebuildGraph() { if(m_track == null) { m_allItems = null; m_graphItems = null; this.Invalidate(); return; } Cursor.Current = Cursors.WaitCursor; m_elevMax = -100000.0d; // feet m_elevMin = 100000.0d; m_speedMax = -1000.0d; SortedList graphItems = new SortedList(); Waypoint prevWpt = null; double odometer = 0.0d; // meters for(int i=0; i < m_track.Trackpoints.Count ;i++) { Waypoint wpt = (Waypoint)m_track.Trackpoints.GetByIndex(i); Speed speed = null; Distance leg = null; double dSpeedCurrentUnits = 0.0d; if(prevWpt != null) { // compute odometer and speed: TimeSpan dt = wpt.DateTime - prevWpt.DateTime; leg = wpt.Location.distanceFrom(prevWpt.Location); // meters double legMeters = leg.Meters; odometer += legMeters; double legMetersPerHour = legMeters * 36000000000.0d / dt.Ticks; // meters per hour if(!m_track.isRoute && legMetersPerHour > 1000.0d && legMetersPerHour < 330.0d * 3600.0d) // sanity check - speed of sound, m/hr { speed = new Speed(legMetersPerHour); dSpeedCurrentUnits = speed.ToDouble(); } } odometer = (float)odometer; long id = (long)i; double elevCurrentUnits = new Distance(wpt.Location.Elev).ToDoubleCompl(); string properties = wpt.toTableString(); m_elevMax = Math.Max(elevCurrentUnits, m_elevMax); m_elevMin = Math.Min(elevCurrentUnits, m_elevMin); m_speedMax = Math.Max(dSpeedCurrentUnits, m_speedMax); long[] ids = new long[2]; ids[0] = id; ids[1] = id; double[] values = new double[2]; values[0] = elevCurrentUnits; values[1] = dSpeedCurrentUnits; string[] sValues = new string[2]; sValues[0] = properties; sValues[1] = ""; GraphItem ev = new GraphItem(odometer, wpt, values, sValues, ids, 2); while(true) { try { graphItems.Add(odometer, ev); break; } catch { odometer += 0.01d; } } prevWpt = wpt; } if(m_elevMax > 0.0d && m_speedMax > 0.0d) { // make speed graph match the elevation: double speedFactor = 0.6d * m_elevMax / m_speedMax; foreach(GraphItem ev in graphItems.Values) { double[] values = ev.values(Project.FORMAT_TRACK_ELEVATION); values[1] = Math.Round(values[1] * speedFactor); } } string selHint = "Click into grey area to see selected interval"; StringById dZoomById = new StringById(zoomById); StringById dDescrById = new StringById(descrById); double rounder = 200.0d; if(this.m_elevMax > 10000.0d) { rounder = 2000.0d; } else if(this.m_elevMax > 1000.0d) { rounder = 1000.0d; } else if(this.m_elevMax <= 50.0d) { this.m_elevMax = 50.0d; rounder = 100.0d; } double graphGridMaxValue = Math.Ceiling(this.m_elevMax / rounder) * rounder; int steps = (int) (graphGridMaxValue / rounder); this.MaxValueY = graphGridMaxValue; this.MinKeyDblMargin = 100.0d; this.StepY = graphGridMaxValue / steps; this.MarginLeft = 45; this.MarginRight = 30; this.initialHint = "Click on graph to see details. Use arrow keys. Drag mouse to select a " + (m_track.isRoute ? "route" : "track") + " segment, click into it to zoom."; this.init(this.enableDisable, "", "", selHint, dDescrById, dZoomById, dBrowseById, new MethodInvoker(showSelected)); this.setGraphData(graphItems, Project.FORMAT_TRACK_ELEVATION, 2, false); this.SelectItemByObject(m_trkpt); this.resetLegends(); this.setLegend(0, "elevation"); this.setLegend(1, "speed"); this.Invalidate(); Cursor.Current = Cursors.Default; }