//构造函数 internal Channels() { nAvg = AVGCOUNT; visible = new bool[MAXCAPCITY]; enableTrace = new bool[MAXCAPCITY]; chnls = new Channel[MAXCAPCITY]; for (int i = 0; i < MAXCAPCITY; i++) { visible[i] = false; enableTrace[i] = false; chnls[i] = new Channel(); } //默认仅一个可见 visible[0] = true; }
//使用channel中的所有数据 //依X坐标,从小到大,绘制成图形曲线 internal static void Draw(Channel chnl, Graphics g, AixsVisibleArea ava, ChannelPictureArea cpa, Boolean sampling) { PointF[] p; PointF[] src; ChannelNode chNode; ChannelCurveStyle ccStyle = chnl.ccStyle; //当前段数据与上一段数据的衔接点 //当(i > 0), 将被更新(页面坐标) PointF preTail = new PointF(float.MinValue, float.MinValue); //建立画笔 Pen pn = new Pen(ccStyle.lineColor); pn.Width = ccStyle.lineWidth; //上一次有效数据段在chnl中的索引 int k = -1; //重置channel Nodes chnl.ClearNodes(); //一次将channel中,以i为索引的一段数据 //依X坐标,从小到大,绘制成图形曲线 for (int i = 0; i <= chnl.MaxIndex; i++) { src = chnl.DataOf(i); if (src == null) continue; //假设src按X递增顺序形式 if (src[0].X > src[src.Length - 1].X) continue; //不启动X轴滚动,则从src中采样数据(世界坐标) if (sampling) p = DataSampling.SamplingFrom(src, ava.xBegin, ava.xEnd, cpa.N0); //启用X轴滚动时,不采样,从src(世界坐标)复制数据 else { p = new PointF[src.Length]; for (int j = 0; j < src.Length; j++) p[j] = src[j]; } if (p == null) continue; //查找p中,具有最大、最小Y值的点 //并且设置当前数据段的最小,最大值(世界坐标) chNode = MinMaxOf(p); chnl.SetHeadNode(2, i, chNode.head); chnl.SetTailNode(2, i, chNode.tail); //对p做世界变换,页面坐标 //并且设置当前数据段绘图数据的头部点、尾部点(页面坐标) DrawingChannel.WorldTransform(p, chnl.UnitOffset, ava, cpa); chnl.SetHeadNode(0, i, p[0]); chnl.SetTailNode(0, i, p[p.Length - 1]); //计算当前数据段,与其前一数据段的连接点 //索引(i - 1)无效时,TailNodeOf返回 p(-1, -1) preTail = chnl.TailNodeOf(0, k); //绘制当前段与前一段的连接线 if ((preTail.X > float.MinValue) && (preTail != p[0])) g.DrawLine(pn, preTail, p[0]); //绘制当前数据段曲线 if (p.Length >= 2) g.DrawLines(pn, p); else g.DrawLine(pn, p[0], p[0]); //绘制曲线图标 if (ccStyle.showIcon) DrawingCurveIcon.Draw(p, g, ccStyle); //记录前一次有效数据段在chnl中的索引 k = i; } }
//在chnl的源数据中,搜索Y值最大的点 private static PointF SearchPeak(Channel chnl) { PointF temp; PointF p = new PointF(float.MinValue, float.MinValue); for (int i = 0; i <= chnl.MaxIndex; i++) { temp = chnl.TailNodeOf(2, i); if (temp.Y > p.Y) p = temp; } //使用yUnitOffset修正p的Y方向的值 p.Y = p.Y + chnl.UnitOffset; return p; }
//在chnl的源数据中,搜索MARK点 private static PointF Search2(Channel chnl, AixsVisibleArea ava, ChannelPictureArea cpa, MarkSearchType schType, float value) { int i, k; float Vcurr, Vmin; PointF pMin = new PointF(float.MinValue, float.MinValue); //获取chnl拥有的第一段数据和最后一段数据 PointF[] src1 = chnl.DataOf(0); PointF[] src2 = chnl.DataOf(chnl.MaxIndex); //chnl中包含的源数据为空 if ((src1 == null) || (src2 == null)) return pMin; //若value在chnl数据之外 if ((value < src1[0].X) || (value > src2[src2.Length - 1].X)) return pMin; //若value在坐标轴之外 if ((value < ava.xBegin) || (value > ava.xEnd)) return pMin; //查找与value最接近的段 PointF[] src; k = -1; Vmin = float.MaxValue; for (i = 0; i <= chnl.MaxIndex; i++) { src = chnl.DataOf(i); if (src == null) continue; Vcurr = Math.Min(Math.Abs(value - src[0].X), Math.Abs(src[src.Length - 1].X - value)); if (Vcurr < Vmin) { k = i; Vmin = Vcurr; } } //找不到源数据所在的数据段 if (k < 0) return pMin; //若MarkSearchType.schValue,则在chnl.DataOf(k)中搜索 //否则将对chnl.DataOf(k)进行采样,再在采样返回的点集中进行搜索 src = chnl.DataOf(k); if (schType == MarkSearchType.schPoint) src = DataSampling.SamplingFrom(src, ava.xBegin, ava.xEnd, cpa.N0); if (src == null) return pMin; //在src中,查找一个点,其X坐标与value相差最小 k = -1; Vmin = float.MaxValue; for (i = 0; i < src.Length; i++) { Vcurr = Math.Abs(src[i].X - value); if (Vcurr < Vmin) { Vmin = Vcurr; k = i; } } //使用yUnitOffset修正src的Y方向的值 src[k].Y = src[k].Y + chnl.UnitOffset; return src[k]; }