public List<Renderable> AdvectLines() { List<Renderable> renderables = new List<Renderable>(3 + _currentSetting.LineX); int numLines = _currentSetting.LineX; // Update / create underlying plane. if (_lastSetting == null || SliceTimeMainChanged) { _timeSlice = new FieldPlane(Plane, _velocity.GetTimeSlice(_currentSetting.SliceTimeMain), _currentSetting.Shader, _currentSetting.Colormap); _intersectionPlane = new Plane(_intersectionPlane, new Vector3(0, 0, _currentSetting.SliceTimeMain - (_lastSetting?.SliceTimeMain) ?? 0)); } else if (ColormapChanged || ShaderChanged) { _timeSlice.SetRenderEffect(_currentSetting.Shader); _timeSlice.UsedMap = _currentSetting.Colormap; } // First item in list: plane. renderables.Add(_timeSlice); // Add Point to indicate clicked position. renderables.Add(new PointCloud(Plane, new PointSet<Point>(new Point[] { new Point() { Position = new Vector3(_selection, _currentSetting.SliceTimeMain + _velocity.Grid.TimeOrigin ?? 0), Color = new Vector3(1, 0, 1), Radius = 0.5f } }))); bool rebuilt = false; // Recompute lines if necessary. if (_lastSetting == null || LineXChanged || AlphaStableChanged || StepSizeChanged || IntegrationTypeChanged || IntegrationTimeChanged || FlatChanged || _selectionChanged) { if (_velocity.IsValid((Vec2)_selection)) { // Compute starting positions. Point[] circle = new Point[numLines]; float offset = _currentSetting.AlphaStable; float angleDiff = 2 * (float)(Math.PI / numLines); for (int dir = 0; dir < numLines; ++dir) { float x = (float)(Math.Sin(angleDiff * dir + Math.PI / 2)); float y = (float)(Math.Cos(angleDiff * dir + Math.PI / 2)); circle[dir] = new Point() { Position = new Vector3(_selection.X + x * offset, _selection.Y + y * offset, _currentSetting.SliceTimeMain + (_velocity.Grid.TimeOrigin ?? 0)) }; } VectorField.Integrator integrator = VectorField.Integrator.CreateIntegrator(_velocity, _currentSetting.IntegrationType); integrator.StepSize = _currentSetting.StepSize; //bool pos = _velocity.SampleDerivative(new Vec3((Vec2)_selection, _currentSetting.SliceTimeMain)).EigenvaluesReal()[0] > 0; //integrator.Direction = pos ? Sign.POSITIVE : Sign.NEGATIVE; LineSet[] lineSets = integrator.Integrate<Point>(new PointSet<Point>(circle), true); /*, _currentSetting.AlphaStable * 10); PointSet<EndPoint> ends = lineSets[0].GetEndPoints(); lineSets[0] = integrator.Integrate(ends, false)[0]; ends = lineSets[1].GetEndPoints(); lineSets[1] = integrator.Integrate(ends, false)[0];*/ // COmpute and show statistics. if (_currentSetting.Flat) { lineSets[0].FlattenLines(_currentSetting.SliceTimeMain); lineSets[1].FlattenLines(_currentSetting.SliceTimeMain); _graph = new Renderable[0]; // Compute values (distance to start point). foreach (LineSet lines in lineSets) { Line[] starLines = new Line[lines.Lines.Length]; int count = 0; float[] values = new float[lines.NumExistentPoints]; for (int l = 0; l < lines.Lines.Length; ++l) { Line line = lines.Lines[l]; // Outgoing direction. Vector3 start = line.Positions[0]; Vector3 dir = line.Positions[0] - new Vector3(_selection, line.Positions[0].Z); ; dir.Normalize(); // Scale such that step size does not scale. dir *= _currentSetting.StepSize / _velocity.Size.T * 40; // Write star coordinates here. Vector3[] starPos = new Vector3[line.Length]; for (int p = 0; p < line.Length; ++p) { values[count++] = new Vector2(line.Positions[p].X - _selection.X, line.Positions[p].Y - _selection.Y).Length(); starPos[p] = start + p * dir; } starLines[l] = new Line() { Positions = starPos }; } var graph = FieldAnalysis.BuildGraph(Plane, new LineSet(starLines), values, _currentSetting.IntegrationTime, _currentSetting.LineSetting, _currentSetting.Colormap); _graph = graph.Concat(_graph).ToArray(); } } else _graph = null; _pathlines = new LineBall[] { new LineBall(Plane, lineSets[0]), new LineBall(Plane, lineSets[1]) }; } _selectionChanged = false; rebuilt = true; } if (_graph != null && _currentSetting.LineSetting == RedSea.DisplayLines.LINE && ( _lastSetting == null || rebuilt || WindowWidthChanged || WindowStartChanged || ColormapChanged)) { foreach (Renderable ball in _graph) { (ball as LineBall).LowerBound = _currentSetting.WindowStart + _currentSetting.AlphaStable * _currentSetting.IntegrationTime + _currentSetting.SliceTimeMain; (ball as LineBall).UpperBound = _currentSetting.WindowStart + _currentSetting.AlphaStable * _currentSetting.IntegrationTime + _currentSetting.SliceTimeMain + _currentSetting.WindowWidth; (ball as LineBall).UsedMap = _currentSetting.Colormap; } } // Add the lineball. if (_pathlines != null) renderables.AddRange(_pathlines); if (_graph != null && _currentSetting.Graph) renderables = renderables.Concat(_graph.ToList()).ToList(); return renderables; }
public List<Renderable> TrackCP() { // The reference slice was changed. Update the field and its critical points. if (_lastSetting == null || SliceTimeReferenceChanged) { _slice1 = new List<Renderable>(2); _planes[0] = new FieldPlane(Plane, SlicesToRender[_currentSetting.SliceTimeReference], FieldPlane.RenderEffect.LIC); _slice1.Add(_planes[0]); _slice1.Add(new PointCloud(Plane, CP[_currentSetting.SliceTimeReference].ToBasicSet())); } // Something mayor changed. Re-integrate. bool mapLines = false; if (_lastSetting == null || AlphaStableChanged || SliceTimeMainChanged || IntegrationTypeChanged || StepSizeChanged) { if (_lastSetting == null || SliceTimeMainChanged) { // Clear the slice mapping. _slice0 = new List<Renderable>(2); // ~~~~~~~~~~~~ Field Mapping ~~~~~~~~~~~~~ \\ _planes[1] = new FieldPlane(Plane, SlicesToRender[_currentSetting.SliceTimeMain], FieldPlane.RenderEffect.LIC); _slice0.Add(_planes[1]); // ~~~~~~~~ Critical Point Mapping ~~~~~~~~ \\ _slice0.Add(new PointCloud(Plane, CP[_currentSetting.SliceTimeMain].SelectTypes(new CriticalPoint2D.TypeCP[] { CriticalPoint2D.TypeCP.ATTRACTING_FOCUS, CriticalPoint2D.TypeCP.REPELLING_FOCUS }).ToBasicSet())); } // Re-compute the feature flow field. Costly operation. if (_lastSetting == null || AlphaStableChanged) { FieldAnalysis.AlphaStableFFF = _currentSetting.AlphaStable; ForwardFFF = new VectorField(Velocity, FieldAnalysis.StableFFF, 3); BackwardFFF = new VectorField(Velocity, FieldAnalysis.StableFFFNegative, 3); } // ~~~~~~~~~~~ Line Integration ~~~~~~~~~~~ \\ // Clear the raw lines. _rawLines = new List<LineSet>(2); // Setup an integrator. VectorField.Integrator intVF = VectorField.Integrator.CreateIntegrator(ForwardFFF, _currentSetting.IntegrationType); intVF.MaxNumSteps = 10000; intVF.StepSize = _currentSetting.StepSize; intVF.NormalizeField = true; // Integrate the forward field. LineSet cpLinesPos = intVF.Integrate(CP[_currentSetting.SliceTimeMain], false)[0]; // Negative FFF integration. Reversed stabilising field. //intVF.Direction = Sign.NEGATIVE; // intVF.Field = BackwardFFF; // var cpLinesNeg = intVF.Integrate(CP[_currentSetting.SliceTimeMain], false); // cpLinesNeg.Color = new Vector3(0, 0.8f, 0); // Add the data to the list. _rawLines.Add(cpLinesPos); // _rawLines.Add(cpLinesNeg); mapLines = true; } // The line settings have changed. Create new renderables from the lines. if (mapLines || LineSettingChanged) { _lines = new List<Renderable>(_rawLines.Count); switch (_currentSetting.LineSetting) { // Map the vertices to colored points. case RedSea.DisplayLines.POINTS_2D_LENGTH: foreach (LineSet line in _rawLines) { PointSet<Point> linePoints = Velocity.ColorCodeArbitrary(line, RedSea.DisplayLineFunctions[(int)_currentSetting.LineSetting]); _lines.Add(new PointCloud(Plane, linePoints)); } break; // Render as line. default: case RedSea.DisplayLines.LINE: foreach (LineSet line in _rawLines) { _lines.Add(new LineBall(Plane, line)); } break; } } // Set mapping values. _planes[0].UpperBound = _currentSetting.WindowWidth; _planes[0].UsedMap = _currentSetting.Colormap; _planes[0].SetRenderEffect(_currentSetting.Shader); _planes[1].UpperBound = _currentSetting.WindowWidth; _planes[1].UsedMap = _currentSetting.Colormap; _planes[1].SetRenderEffect(_currentSetting.Shader); return _slice0.Concat(_slice1).Concat(_lines).ToList(); }
private void RefreshPlane() { _dataMap = new FieldPlane[1]; switch (_currentSetting.Shader) { case FieldPlane.RenderEffect.LIC: { var tmp = _velocity.GetTimeSlice(_currentSetting.SliceTimeMain); tmp.TimeSlice = null; _dataMap[0] = new FieldPlane(_subrangePlane, tmp, _currentSetting.Shader, _currentSetting.Colormap); _dataMap[0].AddScalar(_diffusionMap.Map); RefreshBoundsPlanes(); break; } case FieldPlane.RenderEffect.LIC_LENGTH: { _dataMap = new FieldPlane[2]; var tmp = _velocity.GetTimeSlice(_currentSetting.SliceTimeMain); tmp.TimeSlice = null; _dataMap[0] = new FieldPlane(_subrangePlane, tmp, _currentSetting.Shader, ColorMapping.GetComplementary(_currentSetting.Colormap)); _dataMap[0].LowerBound = 0; _dataMap[0].UpperBound = 20; _dataMap[1] = new FieldPlane(_subrangePlane, _diffusionMap.Map, (_velocity.Size).ToInt2(), 0, 0, FieldPlane.RenderEffect.OVERLAY, _currentSetting.Colormap); _dataMap[1].LowerBound = 0; _dataMap[1].UpperBound = _currentSetting.WindowWidth; //if (_currentSetting.Shader == FieldPlane.RenderEffect.LIC) // _dataMap[0].AddScalar(_diffusionMap.ReferenceMap); break; } case FieldPlane.RenderEffect.OVERLAY: default: _dataMap[0] = _diffusionMap.GetPlane(_subrangePlane); _dataMap[0].UsedMap = _currentSetting.Colormap; _dataMap[0].SetRenderEffect(_currentSetting.Shader); RefreshBoundsPlanes(); break; } }
/// <summary> /// If different planes were chosen, load new fields. /// </summary> /// <returns></returns> public List<Renderable> GetTimeSlice() { if (_lastSetting == null) Initialize(); if (_lastSetting == null || SliceTimeMainChanged) { VectorField sliceOW = _fieldOW.GetTimeSlice(_currentSetting.SliceTimeMain); _fieldSlice = new FieldPlane(Plane, sliceOW, FieldPlane.RenderEffect.COLORMAP, Colormap.Heatstep); } if (_lastSetting == null || WindowWidthChanged) { _fieldSlice.LowerBound = -0.2f * _standardDeviation - _currentSetting.WindowWidth; _fieldSlice.UpperBound = -0.2f * _standardDeviation + _currentSetting.WindowWidth; } if (_lastSetting == null || ColormapChanged || ShaderChanged) { _fieldSlice.UsedMap = _currentSetting.Colormap; _fieldSlice.SetRenderEffect(_currentSetting.Shader); } List<Renderable> list = new List<Renderable>(1); // Set mapping. // _fieldSlice.UpperBound = _currentSetting.WindowWidth; _fieldSlice.UsedMap = _currentSetting.Colormap; _fieldSlice.SetRenderEffect(_currentSetting.Shader); list.Add(_fieldSlice); return list; }
private void RefreshPlane() { switch (_currentSetting.Shader) { case FieldPlane.RenderEffect.LIC: case FieldPlane.RenderEffect.LIC_LENGTH: var tmp = _velocity.GetTimeSlice(_currentSetting.SliceTimeMain); tmp.TimeSlice = null; _currentState = new FieldPlane(_subrangePlane, tmp, _currentSetting.Shader, _currentSetting.Colormap); _currentState.AddScalar(_flowMap.FlowMap); break; default: _currentState = _flowMap.GetPlane(_subrangePlane); _currentState.UsedMap = _currentSetting.Colormap; _currentState.SetRenderEffect(_currentSetting.Shader); break; } }
public List <Renderable> Map() { List <Renderable> result = new List <Renderable>(10); #region BackgroundPlane if (_bg == null) { _bg = new FieldPlane(Plane, _velocity.GetTimeSlice(0), Shader, Colormap); _steadyBG = new FieldPlane(Plane, _steadyField, Shader, Colormap); } _bg.SetRenderEffect(Shader); _bg.UsedMap = Colormap; _bg.LowerBound = WindowStart; _bg.UpperBound = WindowStart + WindowWidth; _steadyBG.SetRenderEffect(Shader); _steadyBG.UsedMap = Colormap; _steadyBG.LowerBound = WindowStart; _steadyBG.UpperBound = WindowStart + WindowWidth; result.Add(Graph? _steadyBG : _bg); #endregion BackgroundPlane if (_lastSetting == null || IntegrationTypeChanged) { _integrator = VectorField.Integrator.CreateIntegrator(_velocity, IntegrationType); _integrator.StepSize = StepSize; } _integrator.StepSize = StepSize; if (_lastSetting != null && LineXChanged) { int diff = _selections.Count - LineX; if (diff > 0) { _selections.RemoveRange(0, diff); _selectionsAngle.RemoveRange(0, diff); //var set = new LineSet(_selections.ToArray()) { Color = _selections.Count % 2 == 0 ? Vector3.UnitX : Vector3.UnitY }; //_lines = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false); } } if (Flat) { result.AddRange(_selectionsAngle); result.Add(_straightCoreBall); } else if (!Graph) { result.AddRange(_selections); result.Add(_coreBall); } if (Graph) { result.AddRange(_steadySelection); } return(result); }
public FieldPlane GetPlane(Plane plane) { FieldPlane flowMap = new FieldPlane(plane, FlowMap, _ensembleGrid.Size.ToInt2(), 0, float.MaxValue, FieldPlane.RenderEffect.DEFAULT); return(flowMap); }
public List<Renderable> Map() { List<Renderable> result = new List<Renderable>(10); #region BackgroundPlane if (_bg == null) { _bg = new FieldPlane(Plane, _velocity.GetTimeSlice(0), Shader, Colormap); _steadyBG = new FieldPlane(Plane, _steadyField, Shader, Colormap); } _bg.SetRenderEffect(Shader); _bg.UsedMap = Colormap; _bg.LowerBound = WindowStart; _bg.UpperBound = WindowStart + WindowWidth; _steadyBG.SetRenderEffect(Shader); _steadyBG.UsedMap = Colormap; _steadyBG.LowerBound = WindowStart; _steadyBG.UpperBound = WindowStart + WindowWidth; result.Add(Graph? _steadyBG : _bg); #endregion BackgroundPlane if(_lastSetting == null || IntegrationTypeChanged) { _integrator = VectorField.Integrator.CreateIntegrator(_velocity, IntegrationType); _integrator.StepSize = StepSize; } _integrator.StepSize = StepSize; if(_lastSetting != null && LineXChanged) { int diff = _selections.Count - LineX; if (diff > 0) { _selections.RemoveRange(0, diff); _selectionsAngle.RemoveRange(0, diff); //var set = new LineSet(_selections.ToArray()) { Color = _selections.Count % 2 == 0 ? Vector3.UnitX : Vector3.UnitY }; //_lines = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false); } } if (Flat) { result.AddRange(_selectionsAngle); result.Add(_straightCoreBall); } else if(!Graph) { result.AddRange(_selections); result.Add(_coreBall); } if(Graph) { result.AddRange(_steadySelection); } return result; }
public List<Renderable> ShowPaths() { bool mapLines = false; // Setup an integrator. VectorField.Integrator intVF = VectorField.Integrator.CreateIntegrator(Velocity, _currentSetting.IntegrationType); intVF.MaxNumSteps = 10000; intVF.StepSize = _currentSetting.StepSize; if (_lastSetting == null || IntegrationTypeChanged || StepSizeChanged) { // ~~~~~~~~~~~ Line Integration ~~~~~~~~~~~ \\ // Clear the raw lines. int timeLength = Velocity.Size.T; _rawLines = new LineSet[Velocity.Size.T]; // Initialize the firth _rawLines[0] = new LineSet(new Line[0]); ScalarField[] lengths = new ScalarField[timeLength]; lengths[0] = new ScalarField(Velocity.ScalarsAsSFU[0].TimeSlices[0], (v, J) => 0); _minLength = new float[timeLength]; _maxLength = new float[timeLength]; // Integrate the path line segments between each neighboring pair of time slices. for (int time = 1; time < timeLength; ++time) { _minLength[time] = float.MaxValue; _maxLength[time] = float.MinValue; // Integrate last points until next time slice. _pathlineSegments[time-1] = intVF.Integrate(_intersectTimeSlices[time - 1], false, time)[0]; _pathlineSegments[time - 1].Color = Vector3.UnitZ * (float)time / timeLength; // if(time == timeLength - 1) _intersectTimeSlices[time] = _pathlineSegments[time - 1].GetValidEndPoints();//VectorField.Integrator.Status.BORDER); //else // _intersectTimeSlices[time] = _pathlineSegments[time - 1].GetEndPoints(VectorField.Integrator.Status.TIME_BORDER); _points[time] = new PointCloud(Plane, _intersectTimeSlices[time].ToBasicSet()); // Set all positions to 0, or invalid value. lengths[time] = new ScalarField(lengths[time-1], (s, g) => s, false); int i = 0; for (int p = 0; p < _intersectTimeSlices[time].Points.Length; ++p) { EndPoint pP = _intersectTimeSlices[time].Points[p]; ++i; // Map floating position to int position. int iPos = _fieldPositionOfValidCell[p]; float timeStepped = (pP.Position.Z - (time-1)); lengths[time][iPos] += timeStepped > 0 ? pP.LengthLine / timeStepped : 0; float tmp = lengths[time][iPos]; _minLength[time] = Math.Min(lengths[time][iPos], _minLength[time]); _maxLength[time] = Math.Max(lengths[time][iPos], _maxLength[time]); if (_minLength[time] < 0 || pP.Status != VectorField.Integrator.Status.TIME_BORDER) i += 0; //Console.WriteLine(lengths[time][iPos]); } Console.WriteLine("Integrated lines until time " + time); } lengths[0] = new VectorField(Velocity.GetTimeSlice(0), FieldAnalysis.VFLength, 1, false).Scalars[0] as ScalarField; _minLength[0] = 0; _maxLength[0] = RedSea.Singleton.NumTimeSlices; _pathLengths = new ScalarFieldUnsteady(lengths); mapLines = true; } if (_lastSetting == null || SliceTimeMainChanged|| ShaderChanged) { ScalarField f = _pathLengths.GetTimeSlice(_currentSetting.SliceTimeMain); f.TimeOrigin = 0; VectorField vecField; switch(_currentSetting.Shader) { case FieldPlane.RenderEffect.LIC: VectorField slice = Velocity.GetTimeSlice(0); slice.TimeSlice = 0; vecField = new VectorField(new Field[] { slice.Scalars[0], slice.Scalars[1], f }); break; case FieldPlane.RenderEffect.LIC_LENGTH: vecField = Velocity.GetTimeSlice(_currentSetting.SliceTimeMain); vecField.TimeSlice = 0; break; default: case FieldPlane.RenderEffect.COLORMAP: case FieldPlane.RenderEffect.DEFAULT: vecField = new VectorField(new Field[] { f }); break; } _plane = new FieldPlane(Plane, vecField /*Velocity.GetSlice(_currentSetting.SliceTimeReference)*/, _currentSetting.Shader); } // The line settings have changed. Create new renderables from the lines. if (mapLines || LineSettingChanged) { _lines = new Renderable[_pathlineSegments.Length]; switch (_currentSetting.LineSetting) { // Map the vertices to colored points. case RedSea.DisplayLines.POINTS_2D_LENGTH: for (int i = 0; i < _pathlineSegments.Length; ++i) { PointSet<Point> linePoints = Velocity.ColorCodeArbitrary(_pathlineSegments[i], RedSea.DisplayLineFunctions[(int)_currentSetting.LineSetting]); _lines[i] = new PointCloud(Plane, linePoints); } break; // Render as line. default: case RedSea.DisplayLines.LINE: for (int i = 0; i < _pathlineSegments.Length; ++i) { _lines[i] = new LineBall(Plane, _pathlineSegments[i]); } break; } } // Set mapping values. //_plane.UpperBound = 0; //= (1 + _currentSetting.WindowWidth) * (_maxLength[_currentSetting.SliceTimeMain] - _minLength[_currentSetting.SliceTimeMain]) /2 + _minLength[_currentSetting.SliceTimeMain]; _plane.UpperBound = _currentSetting.WindowWidth + _currentSetting.WindowStart; ///= _currentSetting.SliceTimeMain; //_plane.LowerBound = 0; //= (1 - _currentSetting.WindowWidth) * (_maxLength[_currentSetting.SliceTimeMain] - _minLength[_currentSetting.SliceTimeMain]) /2 + _minLength[_currentSetting.SliceTimeMain]; _plane.LowerBound = _currentSetting.WindowStart; ///= _currentSetting.SliceTimeMain; _plane.UsedMap = _currentSetting.Colormap; _plane.SetRenderEffect(_currentSetting.Shader); List<Renderable> result = new List<Renderable>(50); result.Add(_plane); switch(_currentSetting.Tracking) { case RedSea.DisplayTracking.LINE: case RedSea.DisplayTracking.LINE_POINTS: Renderable[] lines = new Renderable[_currentSetting.SliceTimeMain]; Array.Copy(_lines, lines, _currentSetting.SliceTimeMain); result = result.Concat(lines).ToList(); break; case RedSea.DisplayTracking.POINTS: result.Add(_points[_currentSetting.SliceTimeMain]); break; case RedSea.DisplayTracking.LINE_SELECTION: VectorField.StreamLine<Vector3> line = intVF.IntegrateLineForRendering(new Vec3(_startPoint.X, _startPoint.Y, 0)); LineSet set = new LineSet(new Line[] { new Line() { Positions = line.Points.ToArray() } }); if(_currentSetting.Flat) set.FlattenLines(_currentSetting.SliceTimeMain); result.Add(new LineBall(Plane, set)); break; default: break; } return result; }