public static void WriteGraphCSV(string file, Graph2D graph) { try { // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Create)) { using (StreamWriter writer = new StreamWriter(fs)) { foreach (float f in graph.X) { writer.Write("{0},", f); } writer.Write('\n'); foreach (float f in graph.Fx) { if (!float.IsNaN(f)) { writer.Write("{0},", f); } } writer.Write('\n'); } } } catch (Exception e) { Console.WriteLine(e.Message); } }
public static void WriteGraphCSV(string file, Graph2D graph) { try { // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Create)) { using (StreamWriter writer = new StreamWriter(fs)) { foreach (float f in graph.X) { writer.Write("{0},", f); } writer.Write('\n'); foreach (float f in graph.Fx) { if (!float.IsNaN(f)) writer.Write("{0},", f); } writer.Write('\n'); } } } catch(Exception e) { Console.WriteLine(e.Message); } }
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 Graph2D(Graph2D cpy) { _x = new float[cpy.Length]; _fx = new float[cpy.Length]; Array.Copy(cpy._x, _x, cpy.Length); Array.Copy(cpy._fx, _fx, cpy.Length); }
public static void ReadFromFile(string file, out Graph2D[] lines) { // Open the file. using (FileStream fs = File.Open(@file, FileMode.Open)) { using (BinaryReader reader = new BinaryReader(fs)) { // Read number of lines. lines = new Graph2D[reader.ReadInt32()]; // Read line lengths in order. for (int l = 0; l < lines.Length; ++l) { lines[l] = new Graph2D(reader.ReadInt32());// { Positions = new Vector3[reader.ReadInt32()] }; } // Read positions. foreach (Graph2D line in lines) { for (int v = 0; v < line.Length; ++v) { line.X[v] = reader.ReadSingle(); line.Fx[v] = reader.ReadSingle(); } } } } }
public static void WriteGraphCSV(string file, Graph2D[] graph) { try { // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Create)) { using (StreamWriter writer = new StreamWriter(fs)) { // X values in first row. Assume equal. foreach (float f in graph[0].X) { writer.Write("{0},", f); } writer.Write('\n'); // Fx values subsequent. foreach (Graph2D g in graph) { foreach (float f in g.Fx) { writer.Write("{0},", f); } writer.Write('\n'); } } } } catch(Exception e) { Console.WriteLine(e.Message); } }
protected static Graph2D OperateBackwards(Graph2D g0, Graph2D g1, ValueOperator func) { if (g0.Length == 0 || g1.Length == 0) { return(new Graph2D(new float[0], new float[0]) { Offset = 0 }); } float[] x = new float[g0.Length + g1.Length]; float[] fx = new float[x.Length]; int p0 = 0; int p1 = 0; int pCount = 0; if (g0.X[0] > g1.X[0]) { p0 = g0.GetLastBelowX(g1.X[0]) + 1; } if (g1.X[0] > g0.X[0]) { p1 = g1.GetLastBelowX(g0.X[0]) + 1; } float maxX = Math.Min(g0.X[g0.Length - 1], g1.X[g1.Length - 1]); // Interleave while (p0 < g0.Length && p1 < g1.Length) { float v0 = p0 < g0.Length ? g0.X[p0] : float.MaxValue; float v1 = p1 < g1.Length ? g1.X[p1] : float.MaxValue; if (v0 > v1) { x[pCount] = v0; fx[pCount] = func(g1.Sample(v0), g0.Fx[p0]); p0++; } if (v0 < v1) { x[pCount] = v1; fx[pCount] = func(g1.Fx[p1], g0.Sample(v1)); p1++; } if (v0 == v1) { x[pCount] = v0; fx[pCount] = func(g1.Fx[p1], g0.Fx[p0]); p0++; p1++; } ++pCount; } if (pCount < x.Length) { Array.Resize(ref x, pCount); Array.Resize(ref fx, pCount); } return(new Graph2D(x, fx)); }
public static Graph2D Distance(Graph2D a, Graph2D b, bool forward = true) { if (forward) { return(Operate(a, b, (x, y) => ((x - y) * (x - y)))); } return(OperateBackwards(a, b, (x, y) => ((x - y) * (x - y)))); }
public static Graph2D operator *(Graph2D g, float f) { Graph2D result = new Graph2D(g); for (int x = 0; x < result.Fx.Length; ++x) { result.Fx[x] *= f; } return(result); }
public static Graph2D DistanceCutSmooth(Graph2D a, Graph2D b, bool forward = true) { Graph2D diff; if (forward) { diff = Operate(a, b, (x, y) => ((x - y) * (x - y))); } else { diff = OperateBackwards(a, b, (x, y) => ((x - y) * (x - y))); } float minXjump = -1; for (int ax = 0; ax < a.Length - 1; ++ax) { if ((forward && a.X[ax] > a.X[ax + 1]) || (!forward && a.X[ax] < a.X[ax + 1])) { minXjump = a.X[ax]; break; } } for (int bx = 0; bx < b.Length - 1 && b.X[bx] < minXjump; ++bx) { if ((forward && b.X[bx] > b.X[bx + 1]) || (!forward && b.X[bx] < b.X[bx + 1])) { minXjump = b.X[bx]; break; } } if (minXjump > 0) { //int jumpPos = diff.GetLastBelowX(minXjump); diff.CutGraph(minXjump); diff = new Graph2D(new float[0], new float[0]); } return(diff); }
protected void ComputeOkubo(float[] radii, float[] angles, out Graph2D[] okuboData) { float integrationLength = 40; // IntegrationTime; // ~~~~~~~~~~~~~~~~~~ Initialize seed points. ~~~~~~~~~~~~~~~~~~~~ \\ PointSet <Point> circle = new PointSet <Point>(new Point[radii.Length * angles.Length * 4]); okuboData = new Graph2D[angles.Length]; if (_velocity.TimeOrigin > SliceTimeMain || _velocity.TimeOrigin + _velocity.Size.T < SliceTimeMain) { LoadField(SliceTimeMain, MemberMain, 1); } VectorField okuboField = new VectorField(_velocity.GetSlice(SliceTimeMain), FieldAnalysis.OkuboWeiss, 1); float mean, fill, standardDeviation; (okuboField.Scalars[0] as ScalarField).ComputeStatistics(out fill, out mean, out _standardDeviation); Console.WriteLine("Mean: " + mean + ", SD: " + _standardDeviation + ", valid cells: " + fill); for (int angle = 0; angle < angles.Length; ++angle) { okuboData[angle] = new Graph2D(radii.Length); for (int rad = 0; rad < radii.Length; ++rad) { okuboData[angle].X[rad] = radii[rad]; float x = (float)(Math.Sin(angles[angle] + Math.PI / 2)); float y = (float)(Math.Cos(angles[angle] + Math.PI / 2)); Vec2 pos = new Vec2(_selection.X + x * radii[rad], _selection.Y + y * radii[rad]); if (!okuboField.Grid.InGrid(pos) || !okuboField.IsValid(pos)) { okuboData[angle].Fx[rad] = 1; continue; } okuboData[angle].Fx[rad] = okuboField[0].Sample(pos) + 0.2f * _standardDeviation; } } }
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 static Graph2D DistanceCutSmooth(Graph2D a, Graph2D b, bool forward = true) { Graph2D diff; if (forward) diff = Operate(a, b, (x, y) => ((x - y) * (x - y))); else diff = OperateBackwards(a, b, (x, y) => ((x - y) * (x - y))); float minXjump = -1; for(int ax = 0; ax < a.Length - 1; ++ax) { if((forward && a.X[ax] > a.X[ax+1]) || (!forward && a.X[ax] < a.X[ax+1])) { minXjump = a.X[ax]; break; } } for (int bx = 0; bx < b.Length - 1 && b.X[bx] < minXjump; ++bx) { if ((forward && b.X[bx] > b.X[bx + 1]) || (!forward && b.X[bx] < b.X[bx + 1])) { minXjump = b.X[bx]; break; } } if(minXjump > 0) { //int jumpPos = diff.GetLastBelowX(minXjump); diff.CutGraph(minXjump); diff = new Graph2D(new float[0], new float[0]); } return diff; }
public static Graph2D Distance(Graph2D a, Graph2D b, bool forward = true) { if(forward) return Operate(a, b, (x, y) => ((x - y) * (x - y))); return OperateBackwards(a, b, (x, y) => ((x - y) * (x - y))); }
protected static Graph2D OperateBackwards(Graph2D g0, Graph2D g1, ValueOperator func) { if (g0.Length == 0 || g1.Length == 0) { return new Graph2D(new float[0], new float[0]) { Offset = 0 }; } float[] x = new float[g0.Length + g1.Length]; float[] fx = new float[x.Length]; int p0 = 0; int p1 = 0; int pCount = 0; if (g0.X[0] > g1.X[0]) { p0 = g0.GetLastBelowX(g1.X[0]) + 1; } if (g1.X[0] > g0.X[0]) { p1 = g1.GetLastBelowX(g0.X[0]) + 1; } float maxX = Math.Min(g0.X[g0.Length - 1], g1.X[g1.Length - 1]); // Interleave while (p0 < g0.Length && p1 < g1.Length) { float v0 = p0 < g0.Length ? g0.X[p0] : float.MaxValue; float v1 = p1 < g1.Length ? g1.X[p1] : float.MaxValue; if (v0 > v1) { x[pCount] = v0; fx[pCount] = func(g1.Sample(v0), g0.Fx[p0]); p0++; } if (v0 < v1) { x[pCount] = v1; fx[pCount] = func(g1.Fx[p1], g0.Sample(v1)); p1++; } if (v0 == v1) { x[pCount] = v0; fx[pCount] = func(g1.Fx[p1], g0.Fx[p0]); p0++; p1++; } ++pCount; } if (pCount < x.Length) { Array.Resize(ref x, pCount); Array.Resize(ref fx, pCount); } return new Graph2D(x, fx); }
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> 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); }
//protected Line IntegrateCircle(float angle, float radius, out Graph2D graph, float time = 0) //{ //} protected LineSet IntegrateCircles(float[] radii, float[] angles, out Graph2D[] graph, int time = 0) { // ~~~~~~~~~~~~~~~~~~ Initialize seed points. ~~~~~~~~~~~~~~~~~~~~ \\ PointSet<Point> circle = new PointSet<Point>(new Point[radii.Length * angles.Length]); for (int a = 0; a < angles.Length; ++a) { float x = (float)(Math.Sin(angles[a] + Math.PI / 2)); float y = (float)(Math.Cos(angles[a] + Math.PI / 2)); for (int r = 0; r < radii.Length; ++r) { // Take the selection as center. circle[a*radii.Length + r] = new Point() { Position = new Vector3(_selection.X + x * radii[r], _selection.Y + y * radii[r], time) }; } } // ~~~~~~~~~~~~ Integrate Pathlines and Adapt ~~~~~~~~~~~~~~~~~~~~~~~~ \\ // Setup integrator. Integrator pathlineIntegrator = Integrator.CreateIntegrator(null, IntegrationType, _cores[_selectedCore], _repulsion); pathlineIntegrator.StepSize = StepSize; LineSet pathlines; // Count out the runs for debugging. int run = 0; // ~~~~~~~~~~~~ Integrate Pathlines ~~~~~~~~~~~~~~~~~~~~~~~~ \\ #region IntegratePathlines // Do we need to load a field first? if (_velocity.TimeOrigin > time || _velocity.TimeOrigin + _velocity.Size.T < time) LoadField(time, MemberMain); // Integrate first few steps. pathlineIntegrator.Field = _velocity; pathlines = pathlineIntegrator.Integrate(circle, false)[0]; // Append integrated lines of next loaded vectorfield time slices. float timeLength = STEPS_IN_MEMORY * 3 - 2/*RedSea.Singleton.NumSubstepsTotal / _everyNthTimestep / 4*/ + time; 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); } #endregion IntegratePathlines // ~~~~~~~~~~~~ Get Boundary ~~~~~~~~~~~~~~~~~~~~~~~~ \\ #region GetBoundary // The two needes functions. //Line[] distances = FieldAnalysis.GetGraph(_cores[_selectedCore], _selection, pathlines, (StepSize * _everyNthTimestep) / 24.0f, _everyNthTimestep, true); //Line[] angles = FieldAnalysis.GetGraph(_cores[_selectedCore], _selection, pathlines, (StepSize * _everyNthTimestep) / 24.0f, _everyNthTimestep, false); graph = FieldAnalysis.GetDistanceToAngle(_cores[_selectedCore], _selection, pathlines); //graph[0].CutGraph((float)(Math.PI * 2)); //Array.Resize(ref pathlines[0].Positions, graph[0].Length); FieldAnalysis.WriteXToLinesetAttribute(pathlines, graph); #endregion GetBoundary //LineSet[] subsets = new LineSet[angles.Length]; //for(int s = 0; s < subsets.Length; ++ s) //{ // subsets[s] = new LineSet(pathlines, s * radii.Length, radii.Length); //} //return subsets; return pathlines; // 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); }
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 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); }