예제 #1
0
        protected override void FindBoundary()
        {
            bool output = false;

            //float acceptanceRatio = 0.9f;
            //float maxTimeDistance = 0.5f;

            // ~~~~~~~~~~~ Variable Initializations ~~~~~~~~~~~~~ \\

            // Find out: Where do we want the boundary to be?
            // "One day": Take Okubo etc as predictor.
            int preferredBoundaryTime = SliceTimeMain + (24 * RedSea.Singleton.NumSubsteps) / _everyNthTimestep;
            float maxTimeDistance = 1.0f;
            float maxRadius = 12;
            float minRadius = 1;
            float radiusGrowth = StepSize * 3;
            float stepSizeStreamlines = StepSize;

            PointSet<Point> boundaryOW = OkuboBoundary(preferredBoundaryTime);

            // At which point did we find the Boundary?
            int[] boundaryIndices, boundaryIndicesLast;
            // At which point did we find the Boundary last time? Initalize 0.
            boundaryIndicesLast = new int[LineX];
            for (int i = 0; i < boundaryIndicesLast.Length; i++)
                boundaryIndicesLast[i] = int.MaxValue;

            // Keep the chosen lines in here.
            LineSet chosenPathlines = new LineSet(new Line[LineX]);
            // These are lines that do not fullfill the criteria, but are the best ones we got so far.
            Line[] bestPathlines = new Line[LineX];
            float[] bestTimeDistance = new float[LineX];
            for (int i = 0; i < bestTimeDistance.Length; i++)
                bestTimeDistance[i] = float.MaxValue;

            // ~~~~~~~~~~~~ Inner Circle ~~~~~~~~~~~~~~~~~~~~~~~~ \\

            //for (float offsetInnerCircle = 7; offsetInnerCircle < 10; offsetInnerCircle += 0.1f)
            float offsetInnerCircle = AlphaStable;
            {
                chosenPathlines = new LineSet(new Line[LineX]);

                Console.WriteLine("Current offset: {0}", offsetInnerCircle);
                //      float offsetInnerCircle = AlphaStable;

                // Save where to transit steady -> unsteady integration.
                float[] offsetSeeds = new float[LineX];
                for (int i = 0; i < offsetSeeds.Length; i++)
                    offsetSeeds[i] = offsetInnerCircle;
                // Create small circle around selection.
                Point[] circle = new Point[LineX];

                // Seeds for pathlines.
                PointSet<Point> seeds = boundaryOW; //new PointSet<Point>(circle);

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

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

                //while (seeds.Length > 0)
                //{
                //   if (output)
                Console.WriteLine("Starting run {0}, {1} seeds left.", run++, seeds.Length);

                // ~~~~~~~~~~~~ Integrate Pathlines  ~~~~~~~~~~~~~~~~~~~~~~~~ \\
                #region IntegratePathlines
                // Do we need to load a field first?
                if (_velocity.TimeOrigin > preferredBoundaryTime - 1 || _velocity.TimeOrigin + _velocity.Size.T < preferredBoundaryTime + 1)
                    LoadField(Math.Max(preferredBoundaryTime - STEPS_IN_MEMORY / 2, 0), MemberMain, STEPS_IN_MEMORY);
                int startStep = (int)_velocity.TimeOrigin;

                // Integrate first few steps.
                pathlineIntegrator.Field = _velocity;
                pathlineIntegrator.Direction = Sign.POSITIVE;
                LineSet[] pathlines = pathlineIntegrator.Integrate(seeds, true);

                // Append integrated lines of next loaded vectorfield time slices.
                float timeLength = RedSea.Singleton.NumSubstepsTotal / _everyNthTimestep; //preferredBoundaryTime * 2;
                while (_currentEndStep + 1 < timeLength)
                {
                    // Don't load more steps than we need to!
                    int numSteps = (int)Math.Min(timeLength - _currentEndStep, STEPS_IN_MEMORY);
                    pathlineIntegrator.Field = null;
                    LoadField(_currentEndStep, MemberMain, numSteps);

                    // Integrate further.
                    pathlineIntegrator.Field = _velocity;
                    pathlineIntegrator.IntegrateFurther(pathlines[0]);
                }

                // Now, integrate backwards.
                pathlineIntegrator.Direction = Sign.NEGATIVE;
                while (startStep > 0)
                {
                    // Don't load more steps than we need to!
                    int numSteps = (int)Math.Min(startStep + 1, STEPS_IN_MEMORY);
                    pathlineIntegrator.Field = null;
                    LoadField(startStep - numSteps + 1, MemberMain, numSteps);
                    startStep = (int)_velocity.TimeOrigin;

                    // Integrate further.
                    pathlineIntegrator.Field = _velocity;
                    pathlineIntegrator.IntegrateFurther(pathlines[1]);
                }

                pathlines[1].Reverse();
                pathlines[1].Append(pathlines[0]);

                chosenPathlines = pathlines[1];
                #endregion IntegratePathlines

                //        // ~~~~~~~~~~~~ Get Boundary ~~~~~~~~~~~~~~~~~~~~~~~~ \\
                //        #region GetBoundary
                //        // The two needes functions.
                //        Line[] distances = FieldAnalysis.GetGraph(_cores[_selectedCore], _selection, pathlines[0], StepSize, _everyNthTimestep, true);
                //        Line[] angles = FieldAnalysis.GetGraph(_cores[_selectedCore], _selection, pathlines[0], StepSize, _everyNthTimestep, false);

                //        // Find the boundary based on angle and distance.
                //        FieldAnalysis.FindBoundaryFromDistanceAngleDonut(distances, angles, out boundaryIndices);
                //        #endregion GetBoundary

                //        // ~~~~~~~~~~~~ Chose or Offset Pathlines ~~~~~~~~~~~~ \\
                //        int numNewSeeds = 0;
                //        int numPathlines = 0;
                //        float avgTimeDistance = 0;
                //        // Recompute start points.
                //        for (int idx = 0; idx < LineX; ++idx)
                //        {
                //            // We already have an optimal line here. Continue.
                //            if (chosenPathlines[idx] != null)
                //                continue;

                //            // Should we save this line?

                //            Vector3 pos;
                //            // Save this point
                //            if (boundaryIndices[numPathlines] >= 0)
                //            {
                //                pos = pathlines[numPathlines][boundaryIndices[numPathlines]];
                //                _allBoundaryPoints.Add(new Point(pos) { Color = new Vector3(0.1f, pos.Z * _everyNthTimestep / RedSea.Singleton.NumSubstepsTotal, 0.1f) });
                //            }
                //            // Finally found it?
                //            // TODOD: DEBUG!!!!!!!!!!!!!!!!111!!!!!!!!!!!!!!!!!!elf!!!!!!!!!!!!!!!!
                //            float timeDistance = Math.Abs((boundaryIndices[numPathlines] * StepSize) - preferredBoundaryTime);
                //            avgTimeDistance += timeDistance;
                //            if (timeDistance < maxTimeDistance || run >= 100) // We reached the spot! Take this line!
                //            {
                //                chosenPathlines[idx] = pathlines[numPathlines];
                //                if (output)
                //                    Console.WriteLine("Line {0} was chosen because it is perfect!", idx);
                //            }
                //            else
                //            {
                //                // Add new seed to seed list.
                //                float scale = boundaryIndices[numPathlines] / preferredBoundaryTime;
                //                float newOffset = offsetSeeds[numPathlines] + ((scale > 1) ? radiusGrowth : -radiusGrowth);
                //                newOffset = Math.Max(minRadius, newOffset);
                //                newOffset = Math.Min(maxRadius, newOffset);

                //                // We are stuck. Take best value we reached so far and go on.
                //                if (newOffset == offsetSeeds[numPathlines] && bestPathlines[idx] != null)
                //                {
                //                    chosenPathlines[idx] = bestPathlines[idx];
                //                    continue;
                //                }
                //                if (timeDistance < bestTimeDistance[idx])
                //                {
                //                    bestPathlines[idx] = pathlines[numPathlines];
                //                    bestTimeDistance[idx] = timeDistance;
                //                }

                //                offsetSeeds[numPathlines] = newOffset;

                //                // Recompute position on circle.
                //                float x = (float)(Math.Sin(angleDiff * idx + Math.PI / 2));
                //                float y = (float)(Math.Cos(angleDiff * idx + Math.PI / 2));

                //                // Take the selection as center.
                //                seeds.Points[numNewSeeds] = new Point() { Position = new Vector3(_selection.X + x * offsetSeeds[numNewSeeds], _selection.Y + y * offsetSeeds[numNewSeeds], SliceTimeMain) };

                //                // Count up number of new seeds.
                //                numNewSeeds++;
                //            }

                //            // We do not count up this value if there is a chosen pathline at this index already.
                //            numPathlines++;
                //        }

                //        // We maybe need less seeds now?
                //        if (numNewSeeds < seeds.Length)
                //            Array.Resize(ref seeds.Points, numNewSeeds);

                //        Console.WriteLine("Average time distance: {0}", avgTimeDistance / numPathlines);
                //    }
            }
            // ~~~~~~~~~~~~ Get Boundary for Rendering~~~~~~~~~~~~~~~~~~~~~~~~ \\

            // The two needes functions.
            _coreDistanceGraph = FieldAnalysis.GetGraph(_cores[_selectedCore], _selection, chosenPathlines, StepSize, _everyNthTimestep, true);
            _coreAngleGraph = FieldAnalysis.GetGraph(_cores[_selectedCore], _selection, chosenPathlines, StepSize, _everyNthTimestep, false);

            // Find the boundary based on angle and distance.
            _boundaryBallFunction = new LineBall(_linePlane, new LineSet(new Line[] { FieldAnalysis.FindBoundaryFromDistanceAngleDonut(_coreDistanceGraph, _coreAngleGraph, out boundaryIndices) }));

            // Find the boundary in space-time.
            int time = SliceTimeMain;
            _boundariesSpacetime[time] = new Line() { Positions = new Vector3[LineX + 1] };
            for (int l = 0; l < LineX; ++l)
            {
                Vector3 pos = chosenPathlines[l][boundaryIndices[l]];
                _allBoundaryPoints.Add(new Point(pos) { Color = Vector3.UnitY * pos.Z / RedSea.Singleton.NumSubstepsTotal * _everyNthTimestep });
                _allBoundaryPoints.Add(boundaryOW.Points[l]);
                _boundariesSpacetime[time][l] = pos;
            }
            _boundariesSpacetime[time][LineX] = _boundariesSpacetime[time][0];
            _boundaryBallSpacetime = new LineBall(_linePlane, _boundariesSpacetime, LineBall.RenderEffect.HEIGHT, Colormap);

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

            Console.WriteLine("Khalas. Boundary indices:");
            float sumTime = 0;
            for (int i = 0; i < chosenPathlines.Length; i++)
            {
                float atTime = chosenPathlines[i][boundaryIndices[i]].Z;
                sumTime += atTime;
                Console.WriteLine("\tTime at {0}: {1}", i, atTime);
            }
            Console.WriteLine("Average time: {0}", sumTime / chosenPathlines.Length);

            _boundaryCloud = new PointCloud(_linePlane, new PointSet<Point>(_allBoundaryPoints.ToArray()));

            LineSet set = new LineSet(_coreAngleGraph);
            GeometryWriter.WriteHeightCSV(RedSea.Singleton.DonutFileName + "Angle.csv", set);
            GeometryWriter.WriteToFile(RedSea.Singleton.DonutFileName + ".angle", set);

            set = new LineSet(_coreDistanceGraph);
            GeometryWriter.WriteHeightCSV(RedSea.Singleton.DonutFileName + "Distance.csv", set);
            GeometryWriter.WriteToFile(RedSea.Singleton.DonutFileName + ".distance", set);
        }
예제 #2
0
        protected void BuildGraph()
        {
            // Compute ftle.
            if (LineX == 0)
                return;
            //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] = float.MaxValue;
            //            x[e] = _distanceDistance[index].Offset;
            //        }
            //        else
            //        {
            //            fx[e] = _distanceDistance[index].RelativeSumOver(IntegrationTime);// / _distanceDistance[index].Length;
            //            x[e] = _distanceDistance[index].Offset;
            //        }
            //    }

            //    _errorGraph[seed] = new Graph2D(x, fx);
            //    int errorBound = FieldAnalysis.FindBoundaryInError(_errorGraph[seed]);
            //    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);

            //_boundaryCloud = new PointCloud(_graphPlane, new PointSet<Point>(_allBoundaryPoints.ToArray()));
            ////int errorBound = FieldAnalysis.FindBoundaryInError(_errorGraph[0]);
            ////_pathlinesTime.Cut(errorBound);
            //// ~~~~~~~~~~~~ Get Boundary for Rendering ~~~~~~~~~~~~ \\
            //_pathlinesTime.Thickness *= 0.1f;
            //_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(_ftle, new Vector3(_selection.X, _selection.Y, 0)), LineBall.RenderEffect.HEIGHT, Colormap, Flat);

            _rebuilt = false;
        }
예제 #3
0
        protected override void UpdateBoundary()
        {
            if (_lastSetting != null && (_rebuilt || FlatChanged || GraphChanged) && _errorGraph != null) // && (Flat && !Graph))
            {
                //Graph2D[] dist = FieldAnalysis.GraphDifferenceForward(_distanceTauGraph);
                //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) };
        }
예제 #4
0
        protected List<Renderable> Map()
        {
            List<Renderable> output = new List<Renderable>(2);

            bool update = false;
            if (_lastSetting == null ||
                SliceTimeMainChanged)
            {

                GeometryWriter.ReadFromFile(RedSea.Singleton.DonutFileName + ".angle", out _loadedAngle);
                GeometryWriter.ReadFromFile(RedSea.Singleton.DonutFileName + ".distance", out _loadedDistance);
                _loadedBall = new LineBall(Plane, _loadedAngle, LineBall.RenderEffect.HEIGHT);

                int[] indices;
                _boundaryLoaded = FieldAnalysis.FindBoundaryFromDistanceAngleDonut(_loadedDistance.Lines, _loadedAngle.Lines, out indices);

                _blockData = FieldAnalysis.PlotLines2D(_loadedAngle);
                _boundaryBlock = FieldAnalysis.FindBoundaryFromDistanceDonut(_blockData.Lines);

                update = true;
            }

            if (update ||
                FlatChanged)
            {
                _loadedBall = new LineBall(Plane, _loadedAngle, LineBall.RenderEffect.HEIGHT, Colormap, Flat);
                _boundaryLoadedBall = new LineBall(_fightPlane, new LineSet(new Line[] { _boundaryLoaded }) { Thickness = 0.2f }, LineBall.RenderEffect.HEIGHT, Colormap, Flat);

                _blockBall = new LineBall(Plane, _blockData, LineBall.RenderEffect.HEIGHT, Colormap, Flat);
                _boundaryBlockBall = new LineBall(_fightPlane, new LineSet(new Line[] { _boundaryBlock }) { Thickness = 0.2f }, LineBall.RenderEffect.HEIGHT, Colormap, Flat);

                update = true;
            }
            if (_lastSetting == null ||
                WindowStartChanged ||
                WindowWidthChanged ||
                ColormapChanged ||
                update)
            {
                _loadedBall.LowerBound = WindowStart;
                _loadedBall.UpperBound = WindowWidth + WindowStart;
                _loadedBall.UsedMap = Colormap;

                _blockBall.LowerBound = WindowStart;
                _blockBall.UpperBound = WindowWidth + WindowStart;
                _blockBall.UsedMap = Colormap;

                _boundaryBlockBall.LowerBound = WindowStart;
                _boundaryBlockBall.UpperBound = WindowWidth + WindowStart;
                _boundaryBlockBall.UsedMap = ColorMapping.GetComplementary(Colormap);

                _boundaryLoadedBall.LowerBound = WindowStart;
                _boundaryLoadedBall.UpperBound = WindowWidth + WindowStart;
                _boundaryLoadedBall.UsedMap = ColorMapping.GetComplementary(Colormap);
            }

            output.Add(Graph ? _blockBall : _loadedBall);
            output.Add(Graph ? _boundaryBlockBall : _boundaryLoadedBall);

            return output;
        }
예제 #5
0
        protected void BuildGraph()
        {
            float cutValue = 2000.0f;

            // Compute error.
            if (LineX == 0)
                return;
            _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)
                {
                    if (_lineDistance[seed][e].Length <= 1)
                    {
                        fx[e] = float.MaxValue;
                        x[e] = _lineDistance[seed][e].Offset;
                    }
                    else
                    {
                        fx[e] = _lineDistance[seed][e].RelativeSumOver(IntegrationTime);// / _distanceDistance[index].Length;
                        x[e] = _lineDistance[seed][e].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);

                //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);

            _rebuilt = false;
        }