public ReadOnlyMotionFrame(MotionFrame frame) { if (frame == null) { throw new ArgumentNullException("frame", "'frame' cannot be null"); } _frame = frame; }
/// <summary> /// フレームデータをバイナリ形式から取得します /// </summary> /// <param name="reader"></param> /// <param name="parent"></param> /// <returns></returns> public static MotionFrame DeserializeBinary(BinaryReader reader, MotionDataSet parent) { decimal time = reader.ReadDecimal(); int count = reader.ReadInt32(); MotionFrame ret = new MotionFrame(parent, time, count); for (int i = 0; i < count; i++) { uint id = reader.ReadUInt32(); MotionObjectInfo info = parent.GetObjectInfoById(id); if (info == null) { throw new InvalidDataException(string.Format("unexpected id:{0} in frame at:{1}", id, time)); } MotionObject @object = info.GetEmptyObject(); @object.ReadBinary(reader); ret[info] = @object; } return(ret); }
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)); } } }
/// <summary> /// CreateObjectの結果に基づいてプレビューを表示します. /// </summary> protected virtual void SetPreview() { if (_operation == null) { return; } // 処理の種類を判別したい IMotionOperationCreateObject createOpe = _operation as IMotionOperationCreateObject; IMotionOperationEditObject editOpe = _operation as IMotionOperationEditObject; IMotionOperationGeneral generalOpe = _operation as IMotionOperationGeneral; IMotionOperationOutputSequence outputOpe = _operation as IMotionOperationOutputSequence; // 前回のプレビュー用オブジェクトを消しておく motionDataViewer.ClearPreviewObjects(); // 作成や編集でなければプレビューしない if (createOpe == null && editOpe == null) { panelPreview.Visible = false; return; } panelPreview.Visible = true; // 引数チェック.失敗したら表示しない string errorMessage = ""; if (!_operation.ValidateArguments(_exec.Parameters, ref errorMessage)) { return; } // フレーム取得.失敗したら表示しない MotionFrame frame = _console.MotionDataSet.GetFrameAt(TimeController.Singleton.CurrentTime); if (frame == null) { return; } // 作成/編集結果のオブジェクトと,プレビュー時のみに表示されるオブジェクトを分類する IList <MotionObject> previewObjs = null; IList <MotionObject> previewSubObjs = null; if (createOpe != null) { previewSubObjs = createOpe.CreateObjects(_targetInfoList, _exec.Parameters, new ReadOnlyMotionFrame(frame), true); previewObjs = createOpe.CreateObjects(_targetInfoList, _exec.Parameters, new ReadOnlyMotionFrame(frame), false); } else if (editOpe != null) { previewSubObjs = editOpe.EditObject(_targetInfoList, _exec.Parameters, new ReadOnlyMotionFrame(frame), true); previewObjs = editOpe.EditObject(_targetInfoList, _exec.Parameters, new ReadOnlyMotionFrame(frame), false); } if (previewObjs == null) { return; } if (previewSubObjs == null) { previewSubObjs = previewObjs; } if (previewSubObjs.Count >= previewObjs.Count) { previewSubObjs = previewSubObjs.Skip(previewObjs.Count).ToList(); } // プレビュー対象をビューに登録しつつ,重心を求める Vector3 sum = Vector3.Empty; int count = 0; if (previewObjs != null) { foreach (var @object in previewObjs) { if (@object != null) { sum += @object.GravityPoint; motionDataViewer.AddPreviewObject(@object, false); count++; } } foreach (var @object in previewSubObjs) { if (@object != null) { sum += @object.GravityPoint; motionDataViewer.AddPreviewObject(@object, true); count++; } } if (editOpe != null) { foreach (MotionObjectInfo info in _targetInfoList) { motionDataViewer.AddPreviewRemoveObject(info); } } } // ビューのカメラを重心の方に向ける if (count > 0) { sum *= 1f / count; motionDataViewer.ViewCamera.SetTarget(sum, false); } }