void _drawSettingsWheel(CustomGraphics g) { const int outR = 6 * 18 / 16; const int inR = 4 * 18 / 16; const int inR45 = 3 * 18 / 16; const int outR45 = 4 * 18 / 16; if (mShowSettingsWheel) { if (CursorInSettingsWheel) { g.LineColor = Color.Cyan; } else { g.LineColor = Color.DarkGray; } g.SetTransform(new Matrix(1, 0, 0, 1, BoundingBox.X + 12, BoundingBox.Y + BoundingBox.Height - 16)); g.DrawCircle(new Point(), inR); g.DrawLine(-outR, 0, -inR, 0); g.DrawLine(outR, 0, inR, 0); g.DrawLine(0, -outR, 0, -inR); g.DrawLine(0, outR, 0, inR); g.DrawLine(-outR45, -outR45, -inR45, -inR45); g.DrawLine(outR45, -outR45, inR45, -inR45); g.DrawLine(-outR45, outR45, -inR45, inR45); g.DrawLine(outR45, outR45, inR45, inR45); g.ClearTransform(); } }
void _drawFFTVerticalGridLines(CustomGraphics g) { /* Draw x-grid lines and label the frequencies in the FFT that they point to. */ int prevEnd = 0; int divs = 20; double maxFrequency = 1 / (ControlPanel.TimeStep * Speed * divs * 2); g.LineColor = Color.FromArgb(0x88, 0x00, 0x00); for (int i = 0; i < divs; i++) { int x = BoundingBox.Width * i / divs; if (x < prevEnd) { continue; } string s = ((int)Math.Round(i * maxFrequency)) + "Hz"; int sWidth = (int)Math.Ceiling(g.GetTextSize(s).Width); prevEnd = x + sWidth + 4; if (i > 0) { g.DrawLine(x, 0, x, BoundingBox.Height); } g.DrawLeftText(s, x + 2, BoundingBox.Height - 12); } }
void _drawCrosshairs(CustomGraphics g) { if (CirSim.Sim.DialogIsShowing()) { return; } if (!BoundingBox.Contains(CirSim.Sim.MouseCursorX, CirSim.Sim.MouseCursorY)) { return; } if (SelectedPlot < 0 && !ShowFFT) { return; } var info = new string[4]; int ipa = mPlots[0].StartIndex(BoundingBox.Width); int ip = (CirSim.Sim.MouseCursorX - BoundingBox.X + ipa) & (mScopePointCount - 1); int ct = 0; int maxy = (BoundingBox.Height - 1) / 2; int y = maxy; if (SelectedPlot >= 0) { var plot = mVisiblePlots[SelectedPlot]; info[ct++] = plot.GetUnitText(plot.MaxValues[ip]); int maxvy = (int)(mMainGridMult * (plot.MaxValues[ip] - mMainGridMid)); g.LineColor = plot.Color; g.FillCircle(CirSim.Sim.MouseCursorX, BoundingBox.Y + y - maxvy, 2.5f); } if (ShowFFT) { double maxFrequency = 1 / (ControlPanel.TimeStep * Speed * 2); info[ct++] = Utils.UnitText(maxFrequency * (CirSim.Sim.MouseCursorX - BoundingBox.X) / BoundingBox.Width, "Hz"); } if (mVisiblePlots.Count > 0) { double t = CirSim.Sim.Time - ControlPanel.TimeStep * Speed * (BoundingBox.X + BoundingBox.Width - CirSim.Sim.MouseCursorX); info[ct++] = Utils.TimeText(t); } int szw = 0, szh = 15 * ct; for (int i = 0; i != ct; i++) { int w = (int)g.GetTextSize(info[i]).Width; if (w > szw) { szw = w; } } g.LineColor = CustomGraphics.WhiteColor; g.DrawLine(CirSim.Sim.MouseCursorX, BoundingBox.Y, CirSim.Sim.MouseCursorX, BoundingBox.Y + BoundingBox.Height); int bx = CirSim.Sim.MouseCursorX; if (bx < szw / 2) { bx = szw / 2; } g.LineColor = ControlPanel.ChkPrintable.Checked ? Color.White : Color.Black; g.FillRectangle(bx - szw / 2, BoundingBox.Y - szh, szw, szh); for (int i = 0; i != ct; i++) { int w = (int)g.GetTextSize(info[i]).Width; g.DrawLeftText(info[i], bx - w / 2, BoundingBox.Y - 2 - (ct - 1 - i) * 15); } }
void _drawFFT(CustomGraphics g) { if (mFft == null || mFft.Size != mScopePointCount) { mFft = new FFT(mScopePointCount); } var real = new double[mScopePointCount]; var imag = new double[mScopePointCount]; var plot = (mVisiblePlots.Count == 0) ? mPlots[0] : mVisiblePlots[0]; var maxV = plot.MaxValues; var minV = plot.MinValues; int ptr = plot.Pointer; for (int i = 0; i < mScopePointCount; i++) { int ii = (ptr - i + mScopePointCount) & (mScopePointCount - 1); /* need to average max and min or else it could cause average of function to be > 0, which * /* produces spike at 0 Hz that hides rest of spectrum */ real[i] = .5 * (maxV[ii] + minV[ii]); imag[i] = 0; } mFft.Exec(real, imag); double maxM = 1e-8; for (int i = 0; i < mScopePointCount / 2; i++) { double m = mFft.Magnitude(real[i], imag[i]); if (m > maxM) { maxM = m; } } int prevX = 0; g.LineColor = Color.Red; if (!LogSpectrum) { int prevHeight = 0; int y = (BoundingBox.Height - 1) - 12; for (int i = 0; i < mScopePointCount / 2; i++) { int x = 2 * i * BoundingBox.Width / mScopePointCount; /* rect.width may be greater than or less than scopePointCount/2, * so x may be greater than or equal to prevX. */ double magnitude = mFft.Magnitude(real[i], imag[i]); int height = (int)((magnitude * y) / maxM); if (x != prevX) { g.DrawLine(prevX, y - prevHeight, x, y - height); } prevHeight = height; prevX = x; } } else { int y0 = 5; int prevY = 0; double ymult = BoundingBox.Height / 10; double val0 = mScale * ymult; for (int i = 0; i < mScopePointCount / 2; i++) { int x = 2 * i * BoundingBox.Width / mScopePointCount; /* rect.width may be greater than or less than scopePointCount/2, * so x may be greater than or equal to prevX. */ var mag = mFft.Magnitude(real[i], imag[i]); if (0 == mag) { mag = 1; } double val = Math.Log(mag); int y = y0 - (int)(val * ymult - val0); if (x != prevX) { g.DrawLine(prevX, prevY, x, y); } prevY = y; prevX = x; } } }
void _drawPlot(CustomGraphics g, ScopePlot plot, bool selected) { if (plot.Elm == null) { return; } int i; int multptr = 0; int x = 0; int maxy = (BoundingBox.Height - 1) / 2; int y = maxy; var color = (mSomethingSelected) ? Color.FromArgb(0xA0, 0xA0, 0xA0) : plot.Color; if (selected || (CirSim.Sim.ScopeSelected == -1 && plot.Elm.IsMouseElm)) { color = CustomGraphics.SelectColor; } else if (ControlPanel.ChkPrintable.Checked) { color = CustomGraphics.GrayColor; } var ipa = plot.StartIndex(BoundingBox.Width); var maxV = plot.MaxValues; var minV = plot.MinValues; var gridMax = mScale; /* if we don't have overlapping scopes of different units, we can move zero around. * Put it at the bottom if the scope is never negative. */ double mx = gridMax; double mn = 0; if (mMaxScale) { /* scale is maxed out, so fix boundaries of scope at maximum and minimum. */ mx = mMaxValue; mn = mMinValue; } else if (mShowNegative || mMinValue < (mx + mn) * .5 - (mx - mn) * .55) { mn = -gridMax; mShowNegative = true; } var gridMid = (mx + mn) * .5; gridMax = (mx - mn) * .55; /* leave space at top and bottom */ double gridMult = maxy / gridMax; if (selected) { mMainGridMult = gridMult; mMainGridMid = gridMid; } int minRangeLo = -10 - (int)(gridMid * gridMult); int minRangeHi = 10 - (int)(gridMid * gridMult); mGridStepY = 1e-8; while (mGridStepY < 20 * gridMax / maxy) { mGridStepY *= MULTA[(multptr++) % 3]; } /* Horizontal gridlines */ int ll; var minorDiv = Color.FromArgb(0x30, 0x30, 0x30); var majorDiv = Color.FromArgb(0xA0, 0xA0, 0xA0); if (ControlPanel.ChkPrintable.Checked) { minorDiv = Color.FromArgb(0xD0, 0xD0, 0xD0); majorDiv = Color.FromArgb(0x80, 0x80, 0x80); } /* Vertical (T) gridlines */ double ts = ControlPanel.TimeStep * Speed; mGridStepX = CalcGridStepX(); if (mDrawGridLines) { /* horizontal gridlines */ /* don't show gridlines if lines are too close together (except for center line) */ bool showGridLines = (mGridStepY != 0); for (ll = -100; ll <= 100; ll++) { if (ll != 0 && !showGridLines) { continue; } int yl = maxy - (int)((ll * mGridStepY - gridMid) * gridMult); if (yl < 0 || yl >= BoundingBox.Height - 1) { continue; } g.LineColor = ll == 0 ? majorDiv : minorDiv; g.DrawLine(0, yl, BoundingBox.Width - 1, yl); } /* vertical gridlines */ double tstart = CirSim.Sim.Time - ControlPanel.TimeStep * Speed * BoundingBox.Width; double tx = CirSim.Sim.Time - (CirSim.Sim.Time % mGridStepX); for (ll = 0; ; ll++) { double tl = tx - mGridStepX * ll; int gx = (int)((tl - tstart) / ts); if (gx < 0) { break; } if (gx >= BoundingBox.Width) { continue; } if (tl < 0) { continue; } if (((tl + mGridStepX / 4) % (mGridStepX * 10)) < mGridStepX) { g.LineColor = majorDiv; } else { g.LineColor = minorDiv; } g.DrawLine(gx, 0, gx, BoundingBox.Height - 1); } } /* only need gridlines drawn once */ mDrawGridLines = false; g.LineColor = color; int ox = -1; int oy = -1; for (i = 0; i != BoundingBox.Width; i++) { int nx = x + i; int ip = (i + ipa) & (mScopePointCount - 1); int minvy = (int)(gridMult * (minV[ip] - gridMid)); int maxvy = (int)(gridMult * (maxV[ip] - gridMid)); if (minvy <= maxy) { if (minvy < minRangeLo || maxvy > minRangeHi) { /* we got a value outside min range, so we don't need to rescale later */ mReduceRange = false; minRangeLo = -1000; minRangeHi = 1000; /* avoid triggering this test again */ } if (ox != -1) { if (minvy == oy && maxvy == oy) { continue; } g.DrawLine(ox, y - oy, nx, y - oy); ox = oy = -1; } if (minvy == maxvy) { ox = nx; oy = minvy; continue; } g.DrawLine(nx, y - minvy, nx, y - maxvy); } } /* for (i=0...) */ if (ox != -1) { g.DrawLine(ox, y - oy, x + i, y - oy); /* Horizontal */ } }