Exemple #1
0
        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;
        }
Exemple #2
0
        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();
        }
Exemple #3
0
 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;
     }
 }
Exemple #4
0
        /// <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;
        }
Exemple #5
0
 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);
        }
Exemple #7
0
        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;
        }