示例#1
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));
        }
示例#2
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);
        }
示例#3
0
        public override void EndSelection(Vector2[] corners)
        {
            if (_selectionData == null)
            {
                return;
            }

            _selectionLines = FieldAnalysis.WriteGraphToSun(_selectionData, new Vector3(_selection.X, _selection.Y, SliceTimeMain));
            WriteGraph(_currentFileName + "Selection", _selectedCore, _selectionData, _selectionLines);

            Renderer.Singleton.Remove(_mouseCloud);
            _mouseCircle = null;
        }
        public PathlineLengthMapper(VectorFieldUnsteady velocity, Plane plane) : base(plane, velocity.Size.ToInt2())
        {
            Velocity = velocity;

            Mapping = ShowPaths;
            Plane   = plane;

            int time = velocity.Size.T;

            _intersectTimeSlices    = new PointSet <EndPoint> [time];
            _pathlineSegments       = new LineSet[time - 1];
            _intersectTimeSlices[0] = FieldAnalysis.ValidDataPoints <EndPoint>(velocity.GetTimeSlice(0));//FieldAnalysis.SomePoints2D<EndPoint>(velocity, 100);//
            _points    = new PointCloud[velocity.Size.T];
            _points[0] = new PointCloud(Plane, _intersectTimeSlices[0].ToBasicSet());
            _fieldPositionOfValidCell = new int[_intersectTimeSlices[0].Length];
            for (int i = 0; i < _fieldPositionOfValidCell.Length; ++i)
            {
                Vector3 pos = _intersectTimeSlices[0].Points[i].Position;
                _fieldPositionOfValidCell[i] = (int)(pos.X + 0.5) + (int)(pos.Y + 0.5) * Velocity.Size[0];
            }
        }
示例#5
0
        public List <Renderable> EditorMap()
        {
            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;

            // Recompute lines if necessary.
            if (numLines > 0 && (
                    _lastSetting == null ||
                    NumLinesChanged ||
                    OffsetRadiusChanged ||
                    _selectionChanged ||
                    SliceTimeMainChanged ||
                    DiffusionMeasureChanged))
            {
                switch (DiffusionMeasure)
                {
                case RedSea.DiffusionMeasure.FTLE:
                    _currentFileName = "FTLE";
                    _rangeGraphData  = 0.095f;
                    break;

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

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

                _graph = null;
                // Load computed data.
                if (LoadGraph(_currentFileName, out _dataGraph))
                {
                    // Is there a drawing saved? If not, make a new empty graph.
                    if (!LoadGraph(_currentFileName + "Selection", _selectedCore, out _selectionData, out _selectionLines))
                    {
                        if (_selectionData == null || _selectionData.Length != _dataGraph.Length)
                        {
                            _selectionData = new Graph2D[_dataGraph.Length];
                        }

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

                        //_selectionLines = FieldAnalysis.WriteGraphToSun(_selectionData, new Vector3(_selection.X, _selection.Y, SliceTimeMain));
                    }

                    // Some weird things happening, maybe this solves offset drawing...
                    _graphData = FieldAnalysis.WriteGraphToSun(_dataGraph, new Vector3(_selection.X, _selection.Y, SliceTimeMain));


                    var dataRange = _graphData.GetRange(2);
                    //_rangeGraphData = dataRange.Item2 - SliceTimeMain;
                    _minGraphData = SliceTimeMain;

                    MaskOnData();
                }

                _selectionChanged = false;
                rebuilt           = true;
            }

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

            return(renderables);
        }
示例#6
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);
        }
示例#7
0
        protected void IntegrateLines()
        {
            LineSet seeds = FieldAnalysis.WriteGraphToSun(_coherency, new Vector3(_selection.X, _selection.Y, SliceTimeMain));

            _stencilPathlines = new List <LineSet>(8);

            // ~~~~~~~~~~~~~~~~~~~~~~~~ Integrate Pathlines and Adapt ~~~~~~~~~~~~~~~~~~~~~~~~ \\
            // Setup integrator.
            Integrator pathlineIntegrator = Integrator.CreateIntegrator(null, IntegrationType, _cores[_selectedCore], _repulsion);

            pathlineIntegrator.Direction = Sign.POSITIVE;
            pathlineIntegrator.StepSize  = StepSize;

            // Count out the runs for debugging.
            int run = 0;

            // ~~~~~~~~~~~~~~~~~~~~~~~~ Integrate Pathlines  ~~~~~~~~~~~~~~~~~~~~~~~~ \\
            #region IntegratePathlines
            // Do we need to load a field first?
            if (_velocity.TimeOrigin > 0 || _velocity.TimeOrigin + _velocity.Size.T < 11)
            {
                LoadField(0, MemberMain, 11);
            }

            // Integrate first few steps.
            pathlineIntegrator.Field = _velocity;
            _stencilPathlines.Add(pathlineIntegrator.Integrate(seeds.ToPointSet(), false)[0]);

            //List<Tuple<Int2, Line>> indexedPathlines = new List<Tuple<Int2, Line>>();
            List <Int2> pathlineIndices = new List <Int2>();
            for (int a = 0; a < _coherency.Length; a++)
            {
                for (int r = 0; r < _coherency[0].Length; r++)
                {
                    pathlineIndices.Add(new Int2(a, r));
                }
            }

            // ~~~~~~~~~~~~~~~~~~~~~~~~ Filter and Repeat ~~~~~~~~~~~~~~~~~~~~~~~~ \\

            Graph2D[] interimSlice;
            for (int toTime = 10; toTime <= 80; toTime += 10)
            {
                if (!LoadGraph(_currentFileName + "Selection", _selectedCore, out interimSlice, out _graphData, toTime))
                {
                    continue;
                }

                Vector3 corePoint = (Vector3)_cores.Lines[_selectedCore].SampleZ(toTime);

                // ~~~~~~~~~~~~~~~~~~~~~~~~ Keep Only Those Inside ~~~~~~~~~~~~~~~~~~~~~~~~ \\
                List <Line> shrunkenLineSet  = new List <Line>();
                List <Int2> shrunkenIndexSet = new List <Int2>();

                Line[] lastLines = _stencilPathlines[_stencilPathlines.Count - 1].Lines;
                for (int lineIdx = 0; lineIdx < lastLines.Length; ++lineIdx)
                {
                    Line pathLine = lastLines[lineIdx];
                    Int2 lineIdx2 = pathlineIndices[lineIdx];
                    if (pathLine.Length < 1)
                    {
                        continue;
                    }

                    Vector2 endPos     = new Vector2(pathLine.Last.X, pathLine.Last.Y);
                    Int2    indexInSun = GetClosestIndex(interimSlice, new Vector2(corePoint.X, corePoint.Y), endPos);

                    if (indexInSun.X < 0 || indexInSun.X >= interimSlice.Length ||
                        indexInSun.Y < 0 || indexInSun.Y >= interimSlice[0].Length)
                    {
                        continue;
                    }

                    // Check against stencil data.
                    if (interimSlice[indexInSun.X].Fx[indexInSun.Y] != 1)
                    {
                        continue;
                    }

                    // Keep this pathline.
                    shrunkenLineSet.Add(pathLine);
                    shrunkenIndexSet.Add(lineIdx2);

                    // Update coherency map. Use max in case we ever add more in-between slices.
                    //Vector2 startPos = new Vector2(pathLine[0].X, pathLine[0].Y);
                    //indexInSun = GetClosestIndex(interimSlice, _selection, startPos);
                    //_coherency[indexInSun.X].Fx[indexInSun.Y] = Math.Max(_coherency[indexInSun.X].Fx[indexInSun.Y], toTime);
                    _coherency[lineIdx2.X].Fx[lineIdx2.Y] = Math.Max(_coherency[lineIdx2.X].Fx[lineIdx2.Y], toTime);
                }

                // Replace last line set in list with new, filtered version.
                _stencilPathlines[_stencilPathlines.Count - 1] = new LineSet(shrunkenLineSet.ToArray());
                pathlineIndices = shrunkenIndexSet;

                string pathlineName = RedSea.Singleton.DiskFileName + _currentFileName + string.Format("Pathlines_{0}_{1}.pathlines", SliceTimeMain, toTime);
                GeometryWriter.WriteToFile(pathlineName, _stencilPathlines[_stencilPathlines.Count - 1]);

                if (toTime == 80)
                {
                    break;
                }

                // Append integrated lines of next loaded vectorfield time slices.
                LoadField(toTime, MemberMain, 11);

                // Integrate further.
                pathlineIntegrator.Field = _velocity;
                _stencilPathlines.Add(new LineSet(_stencilPathlines[_stencilPathlines.Count - 1]));
                pathlineIntegrator.IntegrateFurther(_stencilPathlines[_stencilPathlines.Count - 1]);

                #endregion IntegratePathlines
            }

            // ~~~~~~~~~~~~~~~~~~~~~~~~ Write New Coherency Map to Disk ~~~~~~~~~~~~~~~~~~~~~~~~ \\
            LineSet coherencyLines = FieldAnalysis.WriteGraphToSun(_coherency, new Vector3(_selection, SliceTimeMain));
            WriteGraph(_currentFileName + "Coherency", _selectedCore, _coherency, coherencyLines);
        }
示例#8
0
 public float SquaredError(FieldAnalysis.StraightLine line, int? length = null)
 {
     int end = length ?? Length;
     float sum = 0;
     for (int x = 0; x < end; ++x)
     {
         float diff = line[_x[x]] - _fx[x];
         sum += diff * diff;
     }
     sum /= end;
     return sum;
 }
示例#9
0
        public List <Renderable> ComputeStatistics()
        {
            List <Renderable> result = new List <Renderable>(200);

            result.Add(new FieldPlane(Plane, Velocity.GetTimeSlice(_currentSetting.SliceTimeMain), _currentSetting.Shader, _currentSetting.Colormap));

            if (!_initialized)
            {
                return(result);
            }



            result.Add(new LineBall(Plane, new LineSet(new Line[] { new Line()
                                                                    {
                                                                        Positions = new Vector3[] { _startSelection, _endSelection }
                                                                    } })));


            bool completelyNew = false;

            // ~~~~~~~~~~~~~~ Get new Start Points ~~~~~~~~~~~~~~ //
            if (_lastSetting == null ||
                SliceTimeMainChanged ||
                LineXChanged ||
                _selectionChanged)
            {
                int     numPoints   = _startSelection == null ? 0 : Math.Max(2, _currentSetting.LineX + 1);
                Point[] startPoints = new Point[numPoints];

                // Compute point positions (linear interpolation).
                for (int x = 0; x < numPoints; ++x)
                {
                    float t = (float)x / (numPoints - 1);
                    startPoints[x] = new Point()
                    {
                        Position = _startSelection * (1.0f - t) + _endSelection * t
                    };
                }
                _linePoints = new PointSet <Point>(startPoints);
                _values     = new float[_linePoints.Length];

                completelyNew = true;
            }

            // ~~~~~~~~~~~~ Compute Selected Measure ~~~~~~~~~~~~ //
            if (completelyNew ||
                MeasureChanged ||
                FlatChanged ||
                IntegrationTimeChanged ||
                IntegrationTypeChanged ||
                StepSizeChanged)
            {
                // ~~~~~~~~~~~~~ Compute Scalar FIeld ~~~~~~~~~~~~~~~ //
                ScalarField measure = null;
                switch (_currentSetting.Measure)
                {
                // Velocity Length / Pathline Length.
                case RedSea.Measure.VELOCITY:
                    measure = new VectorField(Velocity.GetTimeSlice(_currentSetting.SliceTimeMain), FieldAnalysis.VFLength, 1).Scalars[0] as ScalarField;
                    break;

                case RedSea.Measure.SURFACE_HEIGHT:
                    break;

                case RedSea.Measure.SALINITY:
                    break;

                case RedSea.Measure.TEMPERATURE:
                    break;

                case RedSea.Measure.DIVERGENCE:
                    measure = new VectorField(Velocity.GetTimeSlice(_currentSetting.SliceTimeMain), FieldAnalysis.Divergence, 1).Scalars[0] as ScalarField;
                    break;

                // Closeness of Pathline.
                case RedSea.Measure.DIVERGENCE_2D:
                    break;

                case RedSea.Measure.VORTICITY:
                    measure = new VectorField(Velocity.GetTimeSlice(_currentSetting.SliceTimeMain), FieldAnalysis.Vorticity, 1).Scalars[0] as ScalarField;
                    break;

                case RedSea.Measure.SHEAR:
                    measure = new VectorField(Velocity.GetTimeSlice(_currentSetting.SliceTimeMain), FieldAnalysis.Shear, 1).Scalars[0] as ScalarField;
                    break;
                }

                // ~~~~~~~~~~~~~~~~ Sample Field ~~~~~~~~~~~~~~~~~~~ //
                switch (_currentSetting.Measure)
                {
                // Velocity Length / Pathline Length.
                case RedSea.Measure.VELOCITY:
                    if (_currentSetting.IntegrationTime == 0)
                    {
                        for (int index = 0; index < _values.Length; ++index)
                        {
                            _values[index] = measure.Sample(((Vec3)_linePoints.Points[index].Position).ToVec2());
                        }
                    }
                    else
                    {
                        VectorField.Integrator integrator = VectorField.Integrator.CreateIntegrator(Velocity, _currentSetting.IntegrationType);
                        integrator.Direction = Sign.POSITIVE;
                        integrator.StepSize  = _currentSetting.StepSize;

                        LineSet line = integrator.Integrate(_linePoints, _currentSetting.Flat, _currentSetting.IntegrationTime)[0];
                        for (int index = 0; index < _values.Length; ++index)
                        {
                            _values[index] = line.Lines[index].LineLength;
                        }
                        result.Add(new LineBall(Plane, line));
                    }
                    break;

                // Simply sample a field.
                case RedSea.Measure.SURFACE_HEIGHT:
                case RedSea.Measure.SALINITY:
                case RedSea.Measure.TEMPERATURE:
                case RedSea.Measure.DIVERGENCE:
                case RedSea.Measure.VORTICITY:
                case RedSea.Measure.SHEAR:
                    for (int index = 0; index < _values.Length; ++index)
                    {
                        _values[index] = measure.Sample(((Vec3)_linePoints.Points[index].Position).ToVec2());
                    }
                    break;

                // Closeness of Pathline.
                case RedSea.Measure.DIVERGENCE_2D:

                    break;
                }
                completelyNew = true;
            }

            //if (completelyNew ||
            //    AlphaStableChanged ||
            //    LineSettingChanged)
            //{
            // ~~~~~~~~~~~~~~~~ Display the Graph ~~~~~~~~~~~~~~~ //
            result.Add(FieldAnalysis.BuildGraph(Plane, _linePoints, _values, _currentSetting.AlphaStable, _currentSetting.LineSetting));
            //}
            _selectionChanged = false;
            return(result);
        }
示例#10
0
        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);
                }
            }
        }
示例#11
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);
        }