protected override void FindBoundary()
        {
            if (LoadGraph("Okubo", out _okubo))
            {
                _graph = new LineBall(_graphPlane, _graphData, LineBall.RenderEffect.HEIGHT, Colormap, Flat, SliceTimeMain);
                return;
            }

            float angleDiff = (float)((Math.PI * 2) / _numSeeds);

            float[] radii  = new float[LineX];
            float[] angles = new float[_numSeeds];
            for (int seed = 0; seed < _numSeeds; ++seed)
            {
                float angle = seed * angleDiff;
                angles[seed] = angle;
            }
            for (int o = 0; o < LineX; ++o)
            {
                radii[o] = o * _lengthRadius / (LineX - 1);
            }

            Console.WriteLine($"=== Working on Okubo Slice {0} ===", SliceTimeMain);
            ComputeOkubo(radii, angles, out _okubo);
            //LineSet okuboLines = FieldAnalysis.WriteGraphToSun(_okubo, new Vector3(_selection, SliceTimeMain));
            _rebuilt = true;

            BuildGraph();

            WriteGraph("Okubo", _okubo);
        }
Exemple #2
0
        protected void SetupRenderer()
        {
            try
            {
                Renderable.Initialize(Device);
                FieldPlane.Initialize();
                ColorMapping.Initialize(Device);
                PointCloud.Initialize();
                LineBall.Initialize();
                Mesh.Initialize();


                Device.ImmediateContext.OutputMerger.SetTargets(_host.RenderTargetView);
                Device.ImmediateContext.Rasterizer.SetViewports(new Viewport(0, 0, _host.RenderTargetWidth, _host.RenderTargetHeight, 0.0f, 1.0f));

                _renderables = new List <Renderable>();
                Camera       = new Camera(Device, ((float)_host.RenderTargetWidth) / _host.RenderTargetHeight);
                var desc = new RasterizerStateDescription {
                    CullMode = CullMode.None, FillMode = FillMode.Solid
                };
                Device.ImmediateContext.Rasterizer.State = RasterizerState.FromDescription(Device, desc);

                SetupCuda();
                AlgorithmCuda.Initialize(ContextCuda, Device);
                FlowMapUncertain.Initialize();
                CutDiffusion.Initialize();
                LocalDiffusion.Initialize();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
Exemple #3
0
        protected void MaskOnData()
        {
            if (_coherency == null || _selectionData == null)
            {
                return;
            }

            //Renderer.Singleton.Remove(_graph);
            //float dataRange = 80;
            //float rangeOffset = dataRange * 0.5f;

            //Graph2D[] maskGraph = new Graph2D[_coherency.Length];
            //for (int angle = 0; angle < maskGraph.Length; ++angle)
            //    maskGraph[angle] = Graph2D.Operate(_coherency[angle], _selectionData[angle], (b, a) => (Math.Max(0, a + rangeOffset + 1/*b*/ * (2 * dataRange))));

            //LineSet maskedLines = FieldAnalysis.WriteGraphToSun(maskGraph, new Vector3(_selection.X, _selection.Y, SliceTimeMain));
            //_graph = new LineBall(_graphPlane, maskedLines, LineBall.RenderEffect.HEIGHT, Colormap, true, SliceTimeMain);
            //_graph.LowerBound = SliceTimeMain;
            //_graph.UpperBound = SliceTimeMain + 4 * dataRange;
            //_graph.UsedMap = Colormap.ParulaSegmentation;

            LineSet lines = FieldAnalysis.WriteGraphToSun(_coherency, new Vector3(_selection.X, _selection.Y, SliceTimeMain));

            _graph            = new LineBall(_graphPlane, lines, LineBall.RenderEffect.HEIGHT, Colormap.Parula, true, SliceTimeMain);
            _graph.LowerBound = SliceTimeMain;
            _graph.UpperBound = SliceTimeMain + 80;

            // Compute area coherency.
            float overallCoherency = ComputeCoherency(_coherency, _selectionData);

            Console.WriteLine(String.Format("=== {0} Coherency is {1} / 80 = {2}===", _currentFileName, overallCoherency, overallCoherency / 80));
        }
Exemple #4
0
        protected void MaskOnData()
        {
            if (_dataGraph == null || _selectionData == null)
            {
                return;
            }

            Renderer.Singleton.Remove(_graph);
            float rangeOffset = _rangeGraphData * 0.5f;

            Graph2D[] maskGraph = new Graph2D[_dataGraph.Length];
            for (int angle = 0; angle < maskGraph.Length; ++angle)
            {
                maskGraph[angle] = Graph2D.Operate(_dataGraph[angle], _selectionData[angle], (b, a) => (Math.Max(0, a + rangeOffset + b * (2 * _rangeGraphData))));
            }

            LineSet maskedLines = FieldAnalysis.WriteGraphToSun(maskGraph, new Vector3(_selection.X, _selection.Y, SliceTimeMain));

            _graph            = new LineBall(_graphPlane, maskedLines, LineBall.RenderEffect.HEIGHT, Colormap, true, SliceTimeMain);
            _graph.LowerBound = _minGraphData;
            _graph.UpperBound = _minGraphData + 4 * _rangeGraphData;
            _graph.UsedMap    = Colormap.ParulaSegmentation;

            Renderer.Singleton.AddRenderable(_graph);
        }
        public override void ClickSelection(Vector2 point)
        {
            if(LineX > 0)
            {
                _lastSelection = (_lastSelection + 1) % LineX;
                Vec3 vec = new Vec3((Vec2)point, 0);
                if (_velocity.Grid.InGrid(vec))
                {
                    Vector3[] line = _integrator.IntegrateLineForRendering(vec).Points.ToArray();
                    Line newLine = new Line() { Positions = line };
                    var set = new LineSet(new Line[] { newLine }) { Color = _flipColor? Vector3.UnitX : Vector3.UnitZ};

                    set.Thickness *= 3;
                    var ball = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false);
                    _selections.Add(ball);

                    if (_selections.Count > LineX)
                    {
                        _selections.RemoveAt(0);
                        _selectionsAngle.RemoveAt(0);
                        _steadySelection.RemoveAt(0);
                    }

                    Graph2D[] angle = FieldAnalysis.GetDistanceToAngle(_core, Vector2.Zero, new LineSet(new Line[] { newLine }));
                    Debug.Assert(angle.Length == 1);

                    for(int p = 0; p < newLine.Length; ++p)
                    {
                    //    if(angle[0].X[p] > _velocity.Size.T - 1)
                    //    {
                    //        newLine.Resize(p);
                    //        break;
                    //    }

                        Vector3 sph = FieldAnalysis.SphericalPosition(_core[0], (float)(angle[0].X[p] * 0.5f / Math.PI), angle[0].Fx[p]);
                        newLine[p] = new Vector3(sph.X, sph.Y, angle[0].X[p] - angle[0].X[0]);
                    }
                    set = new LineSet(new Line[] { newLine }) { Color = _flipColor ? Vector3.UnitX : Vector3.UnitZ };
                    set.Thickness *= 3;
                    ball = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false);
                    _selectionsAngle.Add(ball);

                    _integrator.Field = _steadyField;
                    _integrator.MaxNumSteps = 50;
                    line = _integrator.IntegrateLineForRendering(new Vec2(vec.X, vec.Y)).Points.ToArray();
                    newLine = new Line() { Positions = line };
                    set = new LineSet(new Line[] { newLine }) { Color = _flipColor ? Vector3.UnitX : Vector3.UnitZ };
                    set.Thickness *= 3;
                    ball = new LineBall(new Plane(Plane, Vector3.UnitZ * 0.1f), set, LineBall.RenderEffect.DEFAULT, Colormap, false);
                    _steadySelection.Add(ball);
                    _integrator.Field = _velocity;
                    _integrator.MaxNumSteps = 10000;

                    _flipColor = !_flipColor;
                    //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);
                }
            }
        }
        protected override void FindBoundary()
        {
            float[] offsets = new float[LineX];
            float[] angles = new float[LineX];
            for (int o = 0; o < offsets.Length; ++o)
            {
                offsets[o] = AlphaStable + o * IntegrationTime;
                angles[o] = 0;
            }

            IntegrateCircles(offsets, angles, out _distanceAngleGraph, SliceTimeMain);

            // ~~~~~~~~~~~~ Get Boundary for Rendering~~~~~~~~~~~~~~~~~~~~~~~~ \\
            _pathlines = new LineBall(_linePlane, _pathlinesTime, LineBall.RenderEffect.HEIGHT, ColorMapping.GetComplementary(Colormap), Flat);

            _graph = new LineBall(_graphPlane, FieldAnalysis.WriteGraphsToCircles(_distanceAngleGraph, new Vector3(_selection.X, _selection.Y, SliceTimeMain)), LineBall.RenderEffect.HEIGHT, Colormap, false);
        }
        public PlaygroundMapper(Plane plane)
            : base(new Plane(plane, 1), new Int2(NUM_CELLS))
        {
            Mapping = Map;
            _velocity = Tests.CreateBowl(new Vec2(NUM_CELLS/2, 0), NUM_CELLS, new Vec2(-10, 0), 22, 200);
            _selections = new List<LineBall>(10);
            _selectionsAngle = new List<LineBall>(10);
            _steadySelection = new List<LineBall>(10);

            // Core.
            _core = new Line() { Positions = new Vector3[] { new Vector3(50, 100, 0), new Vector3(155, 100, _velocity.Size.T-1) } };
            LineSet set = new LineSet(new Line[] { _core }) { Color = new Vector3(0.2f) };
            set.Thickness *= 3;
            _coreBall = new LineBall(plane, set, LineBall.RenderEffect.DEFAULT);

            // Straight core.
            set = new LineSet(new Line[] { new Line() { Positions = new Vector3[] { _core[0], _core[0] + Vector3.UnitZ * (_velocity.Size.T - 1) } } }) { Color = new Vector3(0.2f) };
            set.Thickness *= 3;
            _straightCoreBall = new LineBall(Plane, set);

            var center = Tests.CreatePerfect(new Vec2(0, 0), NUM_CELLS, new Vec2(0), 1, 200);
            _steadyField = center.GetTimeSlice(0); //[0] as ScalarField;
        }
        public PlaygroundMapper(Plane plane) : base(new Plane(plane, 1), new Int2(NUM_CELLS))
        {
            Mapping          = Map;
            _velocity        = Tests.CreateBowl(new Vec2(NUM_CELLS / 2, 0), NUM_CELLS, new Vec2(-10, 0), 22, 200);
            _selections      = new List <LineBall>(10);
            _selectionsAngle = new List <LineBall>(10);
            _steadySelection = new List <LineBall>(10);

            // Core.
            _core = new Line()
            {
                Positions = new Vector3[] { new Vector3(50, 100, 0), new Vector3(155, 100, _velocity.Size.T - 1) }
            };
            LineSet set = new LineSet(new Line[] { _core })
            {
                Color = new Vector3(0.2f)
            };

            set.Thickness *= 3;
            _coreBall      = new LineBall(plane, set, LineBall.RenderEffect.DEFAULT);

            // Straight core.
            set = new LineSet(new Line[] { new Line()
                                           {
                                               Positions = new Vector3[] { _core[0], _core[0] + Vector3.UnitZ * (_velocity.Size.T - 1) }
                                           } })
            {
                Color = new Vector3(0.2f)
            };
            set.Thickness    *= 3;
            _straightCoreBall = new LineBall(Plane, set);

            var center = Tests.CreatePerfect(new Vec2(0, 0), NUM_CELLS, new Vec2(0), 1, 200);

            _steadyField = center.GetTimeSlice(0); //[0] as ScalarField;
        }
Exemple #9
0
        public List <Renderable> CoherencyMap()
        {
            List <Renderable> renderables = new List <Renderable>(10);

            int numLines = LineX;

            #region BackgroundPlanes
            if (_lastSetting == null ||
                MeasureChanged ||
                SliceTimeMainChanged ||
                MemberMainChanged ||
                CoreChanged)
            {
                if (_lastSetting == null && _cores == null ||
                    CoreChanged ||
                    MemberMainChanged)
                {
                    // Trace / load cores.
                    TraceCore(MemberMain, SliceTimeMain);
                    if (_selectedCore >= 0)
                    {
                        ClickSelection(_selection);
                    }
                }

                // Computing which field to load as background.
                int totalTime = Math.Min(RedSea.Singleton.NumSubstepsTotal, SliceTimeMain);
                int time      = (totalTime * _everyNthTimestep) / RedSea.Singleton.NumSubsteps;
                int subtime   = (totalTime * _everyNthTimestep) % RedSea.Singleton.NumSubsteps;

                _timeSlice         = LoadPlane(MemberMain, time, subtime, true);
                _intersectionPlane = _timeSlice.GetIntersectionPlane();
            }

            if (_lastSetting == null || SliceTimeReferenceChanged)
            {
                // Reference slice.
                int totalTime = Math.Min(RedSea.Singleton.NumSubstepsTotal, SliceTimeReference);
                int time      = (totalTime * _everyNthTimestep) / RedSea.Singleton.NumSubsteps;
                int subtime   = (totalTime * _everyNthTimestep) % RedSea.Singleton.NumSubsteps;
                _compareSlice = LoadPlane(MemberMain, time, subtime, true);
            }

            if (_lastSetting == null ||
                ColormapChanged ||
                ShaderChanged ||
                WindowStartChanged ||
                WindowWidthChanged)
            {
                _timeSlice.SetRenderEffect(Shader);
                _timeSlice.UsedMap    = Colormap;
                _timeSlice.LowerBound = WindowStart;
                _timeSlice.UpperBound = WindowWidth + WindowStart;

                _compareSlice.SetRenderEffect(Shader);
                _compareSlice.UsedMap    = Colormap;
                _compareSlice.LowerBound = WindowStart;
                _compareSlice.UpperBound = WindowWidth + WindowStart;
            }

            // First item in list: plane.
            renderables.Add(_timeSlice);
            #endregion BackgroundPlanes

            // Add Point to indicate clicked position.
            //renderables.Add(new PointCloud(_linePlane, new PointSet<Point>(new Point[] { new Point() { Position = new Vector3(_selection, SliceTimeMain), Color = new Vector3(0.7f), Radius = 0.4f } })));
            bool rebuilt = false;

            if (_lastSetting == null ||
                DiffusionMeasureChanged)
            {
                switch (DiffusionMeasure)
                {
                case RedSea.DiffusionMeasure.FTLE:
                    _currentFileName = "FTLE";
                    break;

                case RedSea.DiffusionMeasure.Direction:
                    _currentFileName = "Okubo";
                    break;

                default:
                    _currentFileName = "Concentric";
                    break;
                }
            }

            // Recompute lines if necessary.
            if (numLines > 0 && (
                    _lastSetting == null ||
                    NumLinesChanged ||
                    _selectionChanged ||
                    SliceTimeMainChanged ||
                    DiffusionMeasureChanged))
            {
                _graph = null;
                // Load selection
                if (LoadGraph(_currentFileName + "Selection", out _selectionData))
                {
                    // Is there a drawing saved? If not, make a new empty graph.
                    if (!LoadGraph(_currentFileName + "Coherency", _selectedCore, out _coherency, out _graphData))
                    {
                        if (_coherency == null || _coherency.Length != _selectionData.Length)
                        {
                            _coherency = new Graph2D[_selectionData.Length];
                        }

                        for (int angle = 0; angle < _coherency.Length; ++angle)
                        {
                            _coherency[angle] = new Graph2D(_selectionData[angle].Length);
                            for (int rad = 0; rad < _coherency[angle].Length; ++rad)
                            {
                                _coherency[angle].X[rad]  = _selectionData[angle].X[rad];
                                _coherency[angle].Fx[rad] = 0;
                            }
                        }

                        IntegrateLines();
                    }
                    else
                    {
                        _stencilPathlines = new List <LineSet>(8);
                        for (int toTime = 10; toTime <= 80; toTime += 10)
                        {
                            string  pathlineName = RedSea.Singleton.DiskFileName + _currentFileName + string.Format("Pathlines_{0}_{1}.pathlines", SliceTimeMain, toTime);
                            LineSet paths;
                            GeometryWriter.ReadFromFile(pathlineName, out paths);
                            _stencilPathlines.Add(paths);
                        }
                    }
                    // Some weird things happening, maybe this solves offset drawing... It does.
                    LineSet coherencyLines = FieldAnalysis.WriteGraphToSun(_coherency, new Vector3(_selection.X, _selection.Y, SliceTimeMain));
                    _coherencyDisk = new LineBall(_graphPlane, coherencyLines, LineBall.RenderEffect.HEIGHT, Colormap, true, SliceTimeMain);
                    //_coherencyDisk.LowerBound = SliceTimeMain;
                    //_coherencyDisk.UpperBound = SliceTimeMain + 80;
                    MaskOnData();
                }

                _selectionChanged = false;
                rebuilt           = true;
            }

            // Recompute lines if necessary.
            if (numLines > 0 && (
                    _lastSetting == null ||
                    NumLinesChanged ||
                    FlatChanged ||
                    _selectionChanged ||
                    SliceTimeReferenceChanged ||
                    DiffusionMeasureChanged))
            {
                _selectionDistRef = null;
                // Load selection
                if (LoadGraph(_currentFileName + "Selection", _selectedCore, out _selectionDataRef, out _graphData, SliceTimeReference))
                {
                    // Some weird things happening, maybe this solves offset drawing... It does.
                    LineSet selectionLines = FieldAnalysis.WriteGraphToSun(_selectionDataRef, new Vector3(_selection.X, _selection.Y, SliceTimeReference));
                    _selectionDistRef            = new LineBall(_graphPlane, selectionLines, LineBall.RenderEffect.HEIGHT, Colormap.Gray, true, SliceTimeReference);
                    _selectionDistRef.LowerBound = SliceTimeReference;
                    _selectionDistRef.UpperBound = SliceTimeReference + 1;

                    if (SliceTimeReference % 10 == 0 && SliceTimeReference != 0)
                    {
                        _pathlinesTime        = _stencilPathlines[SliceTimeReference / 10 - 1];
                        _pathlines            = new LineBall(_graphPlane, _pathlinesTime, LineBall.RenderEffect.HEIGHT, Colormap.Heat, false);
                        _pathlines.LowerBound = SliceTimeMain;
                        _pathlines.UpperBound = 80;
                    }
                }

                _selectionChanged = false;
                rebuilt           = true;
            }

            // Add the lineball.
            if (_pathlines != null && !Flat)
            {
                renderables.Add(_pathlines);
            }
            if (_graph != null)
            {
                renderables.Add(_graph);
            }
            if (_selectionDistRef != null)
            {
                renderables.Add(_selectionDistRef);
            }
            //if (_coherencyDisk != null) // && !Graph && !Flat)
            //    renderables.Add(_coherencyDisk);
            //            if (_selectionDistRef != null && (Graph || Flat))
            //                renderables.Add(_selectionDistRef);
            //if (SliceTimeMain != SliceTimeReference)
            //    renderables.Add(_compareSlice);
            if (_selectedCore >= 0 && _coreBall != null && !Flat)
            {
                renderables.Add(_coreBall);
            }

            return(renderables);
        }
        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);
        }
        protected void TubeToRenderables()
        {
            if (_tube.Count < 1)
                return;
            _tube = _tube.OrderBy(o => o[0].Z).ToList();

            //_boundaryBallSpacetime = new LineBall(new Plane(_graphPlane, Vector3.UnitZ * 0.01f), _boundariesSpacetime, LineBall.RenderEffect.HEIGHT, ColorMapping.GetComplementary(Colormap), Flat);
            LineSet rings = new LineSet(_tube.ToArray());
            rings.Thickness *= 0.5f;
            _boundaryBallSpacetime = new LineBall(_linePlane, rings, LineBall.RenderEffect.HEIGHT, ColorMapping.GetComplementary(Colormap), false);

            //if (_tube.Count > 1)
            //    _specialObject = new Mesh(_linePlane, new TileSurface(rings), Mesh.RenderEffect.DEFAULT, Colormap);
        }
        protected Line Boundary(int timestep)
        {
            float cutValue = 2000.0f;

            // Compute error.
            if (LineX == 0)
                return null;
            _errorGraph = new Graph2D[_numSeeds];
            _allBoundaryPoints = new List<Point>();
            for (int seed = 0; seed < _numSeeds; ++seed)
            {
                // Smaller field: the difference diminishes it by one line.
                float[] fx = new float[LineX-1];
                float[] x = new float[LineX-1];
                for (int e = 0; e < fx.Length; ++e)
                {
                    // Inbetween graphs, there is one useless one.
                    int index = seed * LineX + e;
                    if (_distanceDistance[index].Length <= 1)
                    {
                        fx[e] = cutValue * 1.5f;
                        x[e] = _distanceDistance[index].Offset;
                    }
                    else
                    {
                        fx[e] = _distanceDistance[index].RelativeSumOver(IntegrationTime);// / _distanceDistance[index].Length;
                        if (float.IsNaN(fx[e]) || float.IsInfinity(fx[e]) || fx[e] == float.MaxValue)
                            fx[e] = 0;
                        x[e] = _distanceDistance[index].Offset;
                        //if (fx[e] > cutValue)
                        //{
                        //    Array.Resize(ref fx, e);
                        //    Array.Resize(ref x, e);
                        //    break;
                        //}
                    }
                }

                _errorGraph[seed] = new Graph2D(x, fx);
                _errorGraph[seed].SmoothLaplacian(0.8f);
                _errorGraph[seed].SmoothLaplacian(0.8f);
            }

            // Do whatever this methode does.
            LineSet line = FieldAnalysis.FindBoundaryInErrors3(_errorGraph, new Vector3(_selection, timestep));

            string ending = "Bound_" + _numSeeds + '_' + AlphaStable + '_' + _lengthRadius + '_' + StepSize + '_' + _methode + '_' + timestep + ".ring";

            Debug.Assert(line.Length == 1);
            // Directly rescale in Z.
            if (line[0][0].Z != timestep)
            {
                for (int p = 0; p < line[0].Length; ++p)
                {
                    line[0].Positions[p].Z = timestep;
                }
            }
            GeometryWriter.WriteToFile(RedSea.Singleton.RingFileName + ending, line);
            foreach(Line l in line.Lines)
            _tube.Add(l);
            // ~~~~~~~~~~~~ Get Boundary for Rendering ~~~~~~~~~~~~ \\

            // Show the current graph.
            _graph = new LineBall(_graphPlane, FieldAnalysis.WriteGraphToSun(_errorGraph, new Vector3(_selection.X, _selection.Y, timestep)), LineBall.RenderEffect.HEIGHT, Colormap, false);

            _rebuilt = false;

            if (line.Length != 1)
                Console.WriteLine("Not exactly one boundary!");

            if (line.Length < 1)
                return null;
            return line[0];
        }
        protected override void UpdateBoundary()
        {
            if (_lastSetting != null && (_rebuilt || FlatChanged || GraphChanged))
            {
                Graph2D[] dist = FieldAnalysis.GraphDifferenceForward(_distanceAngleGraph);
                Plane zPlane = new Plane(_graphPlane, Vector3.UnitZ * 2);
                _graph = new LineBall(_graphPlane, FieldAnalysis.WriteGraphToSun(_errorGraph, new Vector3(_selection.X, _selection.Y, 0)), LineBall.RenderEffect.HEIGHT, Colormap, Flat);
                //               _graph = new LineBall(zPlane, FieldAnalysis.WriteGraphsToCircles(dist, new Vector3(_selection.X, _selection.Y, SliceTimeMain)), LineBall.RenderEffect.HEIGHT, Colormap, false);
                _rebuilt = false;
            }
            if (_lastSetting != null && (IntegrationTimeChanged || _rebuilt || Graph && GraphChanged && Flat))
                BuildGraph();
            //_graph = new LineBall(_graphPlane, FieldAnalysis.WriteGraphToSun(_errorGraph, new Vector3(_selection.X, _selection.Y, 0)), LineBall.RenderEffect.HEIGHT, Colormap, false);
            // new LineBall(_graphPlane, FieldAnalysis.WriteGraphsToCircles(_distanceAngleGraph, new Vector3(_selection.X, _selection.Y, SliceTimeMain)), LineBall.RenderEffect.HEIGHT, Colormap, false);
            //LineSet cutLines;
            ////if (SliceTimeReference > SliceTimeMain)
            ////{
            ////    // _graph = cut version of _coreAngleGraph.
            ////    int length = SliceTimeReference - SliceTimeMain;
            ////    length = (int)((float)length / StepSize + 0.5f);
            ////    cutLines = FieldAnalysis.CutLength(new LineSet(_coreDistanceGraph), length);
            ////}
            ////else
            ////    cutLines = new LineSet(_coreDistanceGraph);

            //cutLines = new LineSet(FieldAnalysis.);

            //_graph = new LineBall[] { new LineBall(_graphPlane, cutLines, LineBall.RenderEffect.HEIGHT, Colormap) };
        }
Exemple #14
0
        public virtual void UpdateSelection()
        {
            if (_intersectionPlane == null)
                return;

            Vector2[] points = Renderer.Singleton.Camera.IntersectPlane(_intersectionPlane);
            Renderer.Singleton.Remove(_selectionRect);
            if (points == null)
                return;

            Vector3[] corners = new Vector3[5];
            corners[0] = new Vector3(points[0], 0);
            corners[1] = new Vector3(points[0].X, points[1].Y, 0);
            corners[2] = new Vector3(points[1], 0);
            corners[3] = new Vector3(points[1].X, points[0].Y, 0);
            corners[4] = corners[0];

            _selectionRect = new LineBall(_intersectionPlane, new LineSet(new Line[] { new Line() { Positions = corners } }) { Thickness = 0.2f, Color = Vector3.UnitX });
            Renderer.Singleton.AddRenderable(_selectionRect);
        }
        public override void ClickSelection(Vector2 point)
        {
            if (LineX > 0)
            {
                _lastSelection = (_lastSelection + 1) % LineX;
                Vec3 vec = new Vec3((Vec2)point, 0);
                if (_velocity.Grid.InGrid(vec))
                {
                    Vector3[] line    = _integrator.IntegrateLineForRendering(vec).Points.ToArray();
                    Line      newLine = new Line()
                    {
                        Positions = line
                    };
                    var set = new LineSet(new Line[] { newLine })
                    {
                        Color = _flipColor? Vector3.UnitX : Vector3.UnitZ
                    };

                    set.Thickness *= 3;
                    var ball = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false);
                    _selections.Add(ball);

                    if (_selections.Count > LineX)
                    {
                        _selections.RemoveAt(0);
                        _selectionsAngle.RemoveAt(0);
                        _steadySelection.RemoveAt(0);
                    }

                    Graph2D[] angle = FieldAnalysis.GetDistanceToAngle(_core, Vector2.Zero, new LineSet(new Line[] { newLine }));
                    Debug.Assert(angle.Length == 1);

                    for (int p = 0; p < newLine.Length; ++p)
                    {
                        Vector3 sph = FieldAnalysis.SphericalPosition(_core[0], (float)(angle[0].X[p] * 0.5f / Math.PI), angle[0].Fx[p]);
                        newLine[p] = new Vector3(sph.X, sph.Y, angle[0].X[p] - angle[0].X[0]);
                    }
                    set = new LineSet(new Line[] { newLine })
                    {
                        Color = _flipColor ? Vector3.UnitX : Vector3.UnitZ
                    };
                    set.Thickness *= 3;
                    ball           = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false);
                    _selectionsAngle.Add(ball);

                    _integrator.Field       = _steadyField;
                    _integrator.MaxNumSteps = 50;
                    line    = _integrator.IntegrateLineForRendering(new Vec2(vec.X, vec.Y)).Points.ToArray();
                    newLine = new Line()
                    {
                        Positions = line
                    };
                    set = new LineSet(new Line[] { newLine })
                    {
                        Color = _flipColor ? Vector3.UnitX : Vector3.UnitZ
                    };
                    set.Thickness *= 3;
                    ball           = new LineBall(new Plane(Plane, Vector3.UnitZ * 0.1f), set, LineBall.RenderEffect.DEFAULT, Colormap, false);
                    _steadySelection.Add(ball);
                    _integrator.Field       = _velocity;
                    _integrator.MaxNumSteps = 10000;

                    _flipColor = !_flipColor;
                    //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);
                }
            }
        }
Exemple #16
0
        protected void BuildGraph()
        {
            // Compute ftle.
            if (LineX == 0)
            {
                return;
            }

            _graphData        = FieldAnalysis.WriteGraphToSun(_okubo, new Vector3(_selection.X, _selection.Y, 0));
            _graph            = new LineBall(_graphPlane, _graphData, LineBall.RenderEffect.HEIGHT, Colormap, Flat, SliceTimeMain);
            _graph.LowerBound = -0.05f;
            _graph.UpperBound = 0.05f;

            _rebuilt = false;

            // Load or compute selection by floodfill.
            Graph2D[] okuboSelection;
            LineSet   okuboLines;

            if (LoadGraph("OkuboSelection", _selectedCore, out okuboSelection, out okuboLines))
            {
                return;
            }

            // Floodfill.
            int            numAngles = _okubo.Length;
            int            numRadii  = _okubo[0].Length;
            HashSet <Int2> toFlood   = new HashSet <Int2>();

            okuboSelection = new Graph2D[numAngles];
            for (int angle = 0; angle < numAngles; ++angle)
            {
                toFlood.Add(new Int2(angle, 0));

                okuboSelection[angle] = new Graph2D(numRadii);
                for (int r = 1; r < numRadii; ++r)
                {
                    okuboSelection[angle].Fx[r] = 0;
                    okuboSelection[angle].X[r]  = _okubo[angle].X[r];
                }
            }

            while (toFlood.Count > 0)
            {
                Int2 current = toFlood.Last();
                toFlood.Remove(current);
                okuboSelection[current.X].Fx[current.Y] = 1;

                // In each direction, go negative and positive.
                for (int dim = 0; dim < 2; ++dim)
                {
                    for (int sign = -1; sign <= 1; sign += 2)
                    {
                        Int2 neighbor = new Int2(current);
                        neighbor[dim] += sign;

                        // Wrap angle around.
                        neighbor[0] = (neighbor[0] + numAngles) % numAngles;
                        if (neighbor.Y >= 0 && neighbor.Y < numRadii &&
                            _okubo[neighbor.X].Fx[neighbor.Y] <= 0 &&
                            okuboSelection[neighbor.X].Fx[neighbor.Y] == 0)
                        {
                            toFlood.Add(neighbor);
                        }
                    }
                }
            }

            LineSet sun = FieldAnalysis.WriteGraphToSun(okuboSelection, new Vector3(_selection, SliceTimeMain));

            WriteGraph("OkuboSelection", _selectedCore, okuboSelection, sun);
        }
        protected void BuildGraph()
        {
            float cutValue = 2000.0f;

            // Compute error.
            if (LineX == 0)
                return;
            if(_errorGraph == null || _errorGraph.Length != _numSeeds + 1)
                _errorGraph = new Graph2D[_numSeeds];
            _allBoundaryPoints = new List<Point>();
            for (int seed = 0; seed < _numSeeds; ++seed)
            {
                // Smaller field: the difference diminishes it by one line.
                float[] fx = new float[LineX - 1];
                float[] x = new float[LineX - 1];
                for (int e = 0; e < fx.Length; ++e)
                {
                    // Inbetween graphs, there is one useless one.
                    int index = seed * LineX + e;
                    if (_distanceDistance[index].Length <= 1)
                    {
                        fx[e] = -0.01f;
                        x[e] = _distanceDistance[index].Offset;
                    }
                    else
                    {
                        fx[e] = _distanceDistance[index].RelativeSumOver(IntegrationTime);// / _distanceDistance[index].Length;
                        x[e] = _distanceDistance[index].Offset;
                        if (fx[e] > cutValue || float.IsNaN(fx[e]) || float.IsInfinity(fx[e]))
                        {
                            fx[e] = 0.01f;
                        }
                    }
                }

                _errorGraph[seed] = new Graph2D(x, fx);
                _errorGraph[seed].SmoothLaplacian(0.8f);
                _errorGraph[seed].SmoothLaplacian(0.8f);

                //var maxs = _errorGraph[seed].Maxima();
                //float angle = (float)((float)seed * Math.PI * 2 / _errorGraph.Length);
                //foreach (int p in maxs)
                //{
                //    float px = _errorGraph[seed].X[p];
                //    _allBoundaryPoints.Add(new Point(new Vector3(_selection.X + (float)(Math.Sin(angle + Math.PI / 2)) * px, _selection.Y + (float)(Math.Cos(angle + Math.PI / 2)) * px, cutValue)) { Color = Vector3.UnitX });
                //}

                //int[] errorBound = FieldAnalysis.FindBoundaryInError(_errorGraph[seed]);
                //foreach (int bound in errorBound)
                //    _allBoundaryPoints.Add(new Point(_pathlinesTime[seed * LineX + bound][0]));
            }
            //_boundariesSpacetime = FieldAnalysis.FindBoundaryInErrors(_errorGraph, new Vector3(_selection, SliceTimeMain));
            //_boundaryBallSpacetime = new LineBall(_linePlane, _boundariesSpacetime, LineBall.RenderEffect.HEIGHT, ColorMapping.GetComplementary(Colormap));

            //if (errorBound >= 0)
            //    _allBoundaryPoints.Add(new Point(_pathlinesTime[seed * LineX + errorBound][0]));
            //GeometryWriter.WriteGraphCSV(RedSea.Singleton.DonutFileName + "Error.csv", _errorGraph);
            //Console.WriteLine("Radii without boundary point: {0} of {1}", _numSeeds - _allBoundaryPoints.Count, _numSeeds);
            ////   _graphPlane.ZAxis = Plane.ZAxis * WindowWidth;
            //_boundaryCloud = new PointCloud(_graphPlane, new PointSet<Point>(_allBoundaryPoints.ToArray()));
            //LineSet lineCpy = new LineSet(_pathlinesTime);
            //lineCpy.CutAllHeight(_repulsion);
            //_pathlines = new LineBall(_linePlane, lineCpy, LineBall.RenderEffect.HEIGHT, Colormap, false);
            //int errorBound = FieldAnalysis.FindBoundaryInError(_errorGraph[0]);
            //_pathlinesTime.Cut(errorBound);
            // ~~~~~~~~~~~~ Get Boundary for Rendering ~~~~~~~~~~~~ \\

               //         _pathlines = new LineBall(_linePlane, _pathlinesTime, LineBall.RenderEffect.HEIGHT, ColorMapping.GetComplementary(Colormap), Flat);

            // _graph = new LineBall(_graphPlane, FieldAnalysis.WriteGraphsToCircles(_distanceAngleGraph, new Vector3(_selection.X, _selection.Y, SliceTimeMain)), LineBall.RenderEffect.HEIGHT, Colormap, false);
            _graph = new LineBall(_graphPlane, FieldAnalysis.WriteGraphToSun(_errorGraph, new Vector3(_selection.X, _selection.Y, 0)), LineBall.RenderEffect.HEIGHT, Colormap, Flat);
            LineSet line = FieldAnalysis.FindBoundaryInErrors3(_errorGraph, new Vector3(_selection, SliceTimeMain));
            line.Thickness *= 0.5f;
            _boundaryBallSpacetime = new LineBall(_linePlane, line, LineBall.RenderEffect.HEIGHT, Colormap, false);

            _rebuilt = false;
        }
        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;
        }