private void bgwRender_DoWork(object sender, DoWorkEventArgs e)
        {
            TimeController timeController = _timeController;
            MotionDataSet  dataSet        = _dataSet;

            if (dataSet == null || timeController == null)
            {
                Bitmap infoImage = new Bitmap(_width, _height);
                using (Graphics gfx = Graphics.FromImage(infoImage)) {
                    gfx.Clear(Color.DimGray);
                    gfx.DrawString("Error...", this.Font, Brushes.LightGray, new PointF());
                }
                setPictureImage(pictGraph, infoImage);
                return;
            }

            RangeSet <int> existAll    = null;             // 選択されたオブジェクトが被欠損なインデックス
            List <int>     clipIndices = new List <int>(); // グラフ上の各x座標のインデックスの範囲
            Collection <MotionObjectInfo> infoList;

            // メッセージを表示
            setText(labelInfo, "データ欠損情報");
            infoList = dataSet.GetSelectedObjectInfoList();
            if (infoList.Count == 0)
            {
                Bitmap infoImage = new Bitmap(_width, _height);
                using (Graphics gfx = Graphics.FromImage(infoImage)) {
                    gfx.Clear(Color.DimGray);
                    gfx.DrawString("選択オブジェクトなし", this.Font, Brushes.Ivory, new PointF());
                }
                setPictureImage(pictGraph, infoImage);
                return;
            }
            else
            {
                Bitmap infoImage = new Bitmap(_width, _height);
                using (Graphics gfx = Graphics.FromImage(infoImage)) {
                    gfx.Clear(Color.DimGray);
                    gfx.DrawString("読み込み中...", this.Font, Brushes.LightGray, new PointF());
                }
                setPictureImageImmediate(pictGraph, infoImage);
            }
            // 選択された全オブジェクトの非欠損のandを取る
            foreach (var info in infoList)
            {
                if (bgwRender.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                if (existAll == null)
                {
                    existAll = getExistenceList(info.Id);
                }
                else
                {
                    existAll = existAll.GetIntersect(getExistenceList(info.Id));
                }
            }
            // 各x座標に対応する時間に対応するフレームのインデックスを求める
            // clipIndices[0] から (clipIndices[1] - 1)には,[x=0に対応する時刻]から[x=1に対応する時刻の直前]までに含まれるインデックスが入るようにする
            for (int x = 0; x <= _width; x++)
            {
                decimal time  = positionToTime(x);
                int     index = dataSet.GetFrameIndexAt(time);
                // ちょうどtimeの値がフレームの時間と一緒のときだけ特別対応
                Motion.MotionFrame frame = dataSet.GetFrameByIndex(index);
                if (frame == null || frame.Time != time)
                {
                    index++; // 取得されたインデックスは,今回のループのx座標に対応する時間範囲に入らない
                }
                clipIndices.Add(index);
            }
            lock (_lockAccessGraphImage) {
                // グラフの作成
                _graphImage = new Bitmap(_width, _height);
                using (Graphics gfx = Graphics.FromImage(_graphImage)) {
                    gfx.Clear(Color.Black);

                    for (int x = 0; x < _width; x++)
                    {
                        // 今回のx座標に対応するフレームインデックスの範囲
                        int clipCount = clipIndices[x + 1] - clipIndices[x];
                        RangeSet <int> .Range clipRange = new RangeSet <int> .Range(clipIndices[x], clipIndices[x + 1]);

                        // 今回の範囲の被欠損情報を取得
                        RangeSet <int> existClipped = existAll.GetClipped(clipRange);
                        int            existCount   = existClipped.Total();

                        Pen pen = Pens.LightGreen;
                        if (existCount == clipCount)
                        {
                            pen = Pens.YellowGreen;
                        }
                        if (existCount > 0)
                        {
                            gfx.DrawLine(pen, new Point(x, _height - 1), new Point(x, _height - 1 - _height * existCount / clipCount));
                        }
                    }
                    // 選択範囲の欠損割合の計算
                    decimal     selectBegin      = timeController.VisibleBeginTime;
                    decimal     selectEnd        = timeController.VisibleEndTime;
                    int         selectBeginIndex = dataSet.GetFrameIndexAt(selectBegin);
                    int         selectEndIndex   = dataSet.GetFrameIndexAt(selectEnd);
                    MotionFrame selectBeginFrame = dataSet.GetFrameByIndex(selectBeginIndex);
                    MotionFrame selectEndFrame   = dataSet.GetFrameByIndex(selectEndIndex);
                    if (selectBeginFrame == null || selectBeginFrame.Time != selectBegin)
                    {
                        selectBeginIndex++; // clipIndicesを求めるときと同じ処理
                    }
                    if (selectEndFrame == null || selectEndFrame.Time != selectEnd)
                    {
                        selectEndIndex++;
                    }
                    RangeSet <int> whole            = existAll.GetClipped(new RangeSet <int> .Range(selectBeginIndex, selectEndIndex));
                    int            selectClipCount  = selectEndIndex - selectBeginIndex;
                    int            selectExistCount = whole.Total();
                    int            missingCount     = selectClipCount - selectExistCount;
                    double         percentage       = selectClipCount == 0 ? 0 : (100.0 - 100.0 * selectExistCount / selectClipCount);
                    setText(labelInfo, string.Format("欠落フレーム数: {0} (選択フレーム数 {1}, {2}% 欠損) ({3} オブジェクト)", missingCount, selectClipCount, Math.Round(percentage, 2), infoList.Count));
                }
            }
        }
 public static IList <uint> OptimizePlaneOrder(IList <MotionObjectInfo> infoList, Motion.MotionFrame frame)
 {
     return(OptimizePlaneOrder(infoList, new ReadOnlyMotionFrame(frame)));
 }