/// <summary> /// Set of lines in 3D space. /// </summary> /// <param name="origin"></param> /// <param name="xAxis"></param> /// <param name="yAxis"></param> /// <param name="scale">Scaling the field extent.</param> /// <param name="field"></param> public LineBall(Plane plane, LineSet lines, RenderEffect effect = RenderEffect.DEFAULT, Colormap colormap = Colormap.Parula, bool flatten = false) { _thickness = lines.Thickness * plane.PointSize; _color = lines.Color; this._vertexSizeBytes = Marshal.SizeOf(typeof(Vector4)); this._numVertices = lines.NumPoints * 2 - lines.Lines.Length * 2; // Linelist means, all points are there twice, minus the endpoints. if (_numVertices == 0) return; this._topology = PrimitiveTopology.LineList; // Setting up the vertex buffer. if (!flatten) GenerateGeometry(plane, lines); else GenerateGeometryFlatXY(plane, lines); //this._technique = _lineEffect.GetTechniqueByName("Render"); UsedMap = colormap; _planeNormal = plane.ZAxis; _planeNormal.Normalize(); _effect = _lineEffect; SetRenderEffect(effect); this._vertexLayout = new InputLayout(_device, _technique.GetPassByIndex(0).Description.Signature, new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), new InputElement("SCALAR", 0, Format.R32_Float, 12, 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)); }
/// <summary> /// Set of lines in 3D space. /// </summary> /// <param name="origin"></param> /// <param name="xAxis"></param> /// <param name="yAxis"></param> /// <param name="scale">Scaling the field extent.</param> /// <param name="field"></param> public LineBall(Plane plane, LineSet lines, RenderEffect effect = RenderEffect.DEFAULT, Colormap colormap = Colormap.Parula, bool flatten = false, float flattenToTime = 0) { _thickness = lines.Thickness * plane.PointSize; _color = lines.Color; this._vertexSizeBytes = Marshal.SizeOf(typeof(Vector4)); this._numVertices = lines.NumPoints * 2 - lines.Lines.Length * 2; // Linelist means, all points are there twice, minus the endpoints. if (_numVertices == 0) { return; } this._topology = PrimitiveTopology.LineList; // Setting up the vertex buffer. if (!flatten) { GenerateGeometry(plane, lines); } else { GenerateGeometryFlatXY(plane, lines, flattenToTime); } //this._technique = _lineEffect.GetTechniqueByName("Render"); UsedMap = colormap; _planeNormal = plane.ZAxis; _planeNormal.Normalize(); _effect = _lineEffect; SetRenderEffect(effect); this._vertexLayout = new InputLayout(_device, _technique.GetPassByIndex(0).Description.Signature, new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), new InputElement("SCALAR", 0, Format.R32_Float, 12, 0) }); }
protected void MaskOnData() { if (_dataGraph == null || _selectionData == null) { return; } Renderer.Singleton.Remove(_graph); float rangeOffset = _rangeGraphData * 0.5f; Graph2D[] maskGraph = new Graph2D[_dataGraph.Length]; for (int angle = 0; angle < maskGraph.Length; ++angle) { maskGraph[angle] = Graph2D.Operate(_dataGraph[angle], _selectionData[angle], (b, a) => (Math.Max(0, a + rangeOffset + b * (2 * _rangeGraphData)))); } LineSet maskedLines = FieldAnalysis.WriteGraphToSun(maskGraph, new Vector3(_selection.X, _selection.Y, SliceTimeMain)); _graph = new LineBall(_graphPlane, maskedLines, LineBall.RenderEffect.HEIGHT, Colormap, true, SliceTimeMain); _graph.LowerBound = _minGraphData; _graph.UpperBound = _minGraphData + 4 * _rangeGraphData; _graph.UsedMap = Colormap.ParulaSegmentation; Renderer.Singleton.AddRenderable(_graph); }
public static void ReadFromFile(string file, out LineSet lineset) { Line[] lines; // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Open)) { using (BinaryReader reader = new BinaryReader(fs)) { // Write number of lines. lines = new Line[reader.ReadInt32()]; // Write line lengths in order. for (int l = 0; l < lines.Length; ++l) lines[l] = new Line() { Positions = new Vector3[reader.ReadInt32()] }; // Write positions. float x, y, z; foreach (Line line in lines) { for(int v = 0; v < line.Length; ++v) { x = reader.ReadSingle(); y = reader.ReadSingle(); z = reader.ReadSingle(); line[v] = new Vector3(x, y, z); } } } } lineset = new LineSet(lines); }
public static void WriteToFile(string file, LineSet lines) { // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Create)) { using (BinaryWriter writer = new BinaryWriter(fs)) { // Write number of lines. writer.Write(lines.Length); // Write line lengths in order. foreach (Line line in lines.Lines) { writer.Write(line.Length); } // Write positions. foreach (Line line in lines.Lines) { foreach (Vector3 vec in line.Positions) { writer.Write(vec.X); writer.Write(vec.Y); writer.Write(vec.Z); } } } } }
public void IntegrateFurther(LineSet positions, float?maxTime = null) { try { Debug.Assert(Field.NumVectorDimensions <= 3); LineSet result; PointSet <EndPoint> ends = positions.GetAllEndPoints(); if (ends.Length == 0) { return; } //int validPoints = 0; for (int index = 0; index < positions.Length; ++index) { if (positions[index].Length == 0 || ends[index] == null || (ends[index].Status != Status.BORDER && ends[index].Status != Status.TIME_BORDER && ends[index].Status != Status.OK)) { continue; } StreamLine <Vector3> streamline = IntegrateLineForRendering(((Vec3)ends.Points[index].Position).ToVec(Field.NumVectorDimensions), maxTime); positions[index].Positions = positions.Lines[index].Positions.Concat(streamline.Points).ToArray(); positions[index].Status = streamline.Status; positions[index].LineLength += streamline.LineLength; //if ((index) % (positions.Length / 10) == 0) // Console.WriteLine("Further integrated {0}/{1} lines. {2}%", index, positions.Length, ((float)index*100) / positions.Length); //validPoints++; } //return new LineSet(lines) { Color = (Vector3)Direction }; } catch (Exception e) { Console.WriteLine(e.Message); } }
public override void ClickSelection(Vector2 point) { if(LineX > 0) { _lastSelection = (_lastSelection + 1) % LineX; Vec3 vec = new Vec3((Vec2)point, 0); if (_velocity.Grid.InGrid(vec)) { Vector3[] line = _integrator.IntegrateLineForRendering(vec).Points.ToArray(); Line newLine = new Line() { Positions = line }; var set = new LineSet(new Line[] { newLine }) { Color = _flipColor? Vector3.UnitX : Vector3.UnitZ}; set.Thickness *= 3; var ball = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false); _selections.Add(ball); if (_selections.Count > LineX) { _selections.RemoveAt(0); _selectionsAngle.RemoveAt(0); _steadySelection.RemoveAt(0); } Graph2D[] angle = FieldAnalysis.GetDistanceToAngle(_core, Vector2.Zero, new LineSet(new Line[] { newLine })); Debug.Assert(angle.Length == 1); for(int p = 0; p < newLine.Length; ++p) { // if(angle[0].X[p] > _velocity.Size.T - 1) // { // newLine.Resize(p); // break; // } Vector3 sph = FieldAnalysis.SphericalPosition(_core[0], (float)(angle[0].X[p] * 0.5f / Math.PI), angle[0].Fx[p]); newLine[p] = new Vector3(sph.X, sph.Y, angle[0].X[p] - angle[0].X[0]); } set = new LineSet(new Line[] { newLine }) { Color = _flipColor ? Vector3.UnitX : Vector3.UnitZ }; set.Thickness *= 3; ball = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false); _selectionsAngle.Add(ball); _integrator.Field = _steadyField; _integrator.MaxNumSteps = 50; line = _integrator.IntegrateLineForRendering(new Vec2(vec.X, vec.Y)).Points.ToArray(); newLine = new Line() { Positions = line }; set = new LineSet(new Line[] { newLine }) { Color = _flipColor ? Vector3.UnitX : Vector3.UnitZ }; set.Thickness *= 3; ball = new LineBall(new Plane(Plane, Vector3.UnitZ * 0.1f), set, LineBall.RenderEffect.DEFAULT, Colormap, false); _steadySelection.Add(ball); _integrator.Field = _velocity; _integrator.MaxNumSteps = 10000; _flipColor = !_flipColor; //var set = new LineSet(_selections.ToArray()) { Color = _selections.Count % 2 == 0 ? Vector3.UnitX : Vector3.UnitY }; //_lines = new LineBall(Plane, set, LineBall.RenderEffect.DEFAULT, Colormap, false); } } }
public LineSet(LineSet cpy, int start = 0, int length = -1) : base() { int numLines = length > 0 ? length : cpy.Length - start; this.Color = cpy.Color; this.Lines = new Line[numLines]; this.Thickness = cpy.Thickness; for (int line = 0; line < numLines; ++line) { Lines[line] = new Line(cpy.Lines[start + line]); } }
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; }
protected void GenerateGeometryFlatXY(Plane plane, LineSet lines, float toTime = 0) { // Write poition and UV-map data. var stream = new DataStream(_numVertices * _vertexSizeBytes, true, true); Vector3 zAxis = plane.ZAxis; LowerBound = lines.Lines[0].Positions[0][2]; UpperBound = LowerBound; for (int index = 0; index < lines.Lines.Length; ++index) { Line line = lines.Lines[index]; if (line.Length < 2) { continue; } Debug.Assert(line.Length == lines.Lines[index].Length); stream.Write(new Vector4(plane.Origin + (plane.XAxis * line.Positions[0][0] + plane.YAxis * line.Positions[0][1] + plane.ZAxis * toTime), line.Positions[0][2])); for (int point = 1; point < line.Positions.Length - 1; ++point) { Vector4 pos = new Vector4(plane.Origin + (plane.XAxis * line.Positions[point][0] + plane.YAxis * line.Positions[point][1] + plane.ZAxis * toTime), line.Positions[point][2]); stream.Write(pos); stream.Write(pos); LowerBound = Math.Min(LowerBound, line.Positions[point][2]); UpperBound = Math.Max(UpperBound, line.Positions[point][2]); } int end = line.Positions.Length - 1; stream.Write(new Vector4(plane.Origin + (plane.XAxis * line.Positions[end][0] + plane.YAxis * line.Positions[end][1] + plane.ZAxis * toTime), line.Positions[end][2])); } stream.Position = 0; // Create and fill buffer. _vertices = new Buffer(_device, stream, new BufferDescription() { BindFlags = BindFlags.VertexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = _numVertices * _vertexSizeBytes, Usage = ResourceUsage.Default }); stream.Dispose(); }
public static void WriteHeightCSV(string file, LineSet lines) { // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Create)) { using (StreamWriter writer = new StreamWriter(fs)) { // Write positions. foreach (Line line in lines.Lines) { foreach (Vector3 vec in line.Positions) { writer.Write("{0},", vec.Z); } writer.Write('\n'); } } } }
public TileSurface(LineSet lines) { // Assert "full" lineset. int length = lines[0].Length; #if DEBUG foreach (Line l in lines.Lines) { Debug.Assert(l.Length == length); } #endif Positions = new Vector3[length, lines.Length]; for(int l = 0; l < lines.Length; ++l) { for (int p = 0; p < lines[l].Length; ++p) Positions[p, l] = lines[l][p]; } }
public LineSet[] Integrate <P>(PointSet <P> positions, bool forwardAndBackward = false, float?maxTime = null) where P : Point { Debug.Assert(Field.NumVectorDimensions <= 3); Line[] lines = new Line[positions.Length]; Line[] linesReverse = new Line[forwardAndBackward? positions.Length : 0]; LineSet[] result = new LineSet[forwardAndBackward ? 2 : 1]; for (int index = 0; index < positions.Length; ++index) { StreamLine <Vector3> streamline = IntegrateLineForRendering(((Vec3)positions.Points[index].Position).ToVec(Field.NumVectorDimensions), maxTime); lines[index] = new Line(); lines[index].Positions = streamline.Points.ToArray(); lines[index].Status = streamline.Status; lines[index].LineLength = streamline.LineLength; //if ((index) % (positions.Length / 10) == 0) // Console.WriteLine("Integrated {0}/{1} lines. {2}%", index, positions.Length, ((float)index * 100) / positions.Length); } result[0] = new LineSet(lines) { Color = (Vector3)Direction }; if (forwardAndBackward) { Direction = !Direction; for (int index = 0; index < positions.Length; ++index) { StreamLine <Vector3> streamline = IntegrateLineForRendering((Vec3)positions.Points[index].Position, maxTime); linesReverse[index] = new Line(); linesReverse[index].Positions = streamline.Points.ToArray(); } result[1] = new LineSet(linesReverse) { Color = (Vector3)Direction }; Direction = !Direction; } return(result); }
public PointSet <Point> ColorCodeArbitrary(LineSet lines, PositionToColor func) { Point[] points; points = new Point[lines.NumExistentPoints]; int idx = 0; foreach (Line line in lines.Lines) { foreach (Vector3 pos in line.Positions) { points[idx] = new Point() { Position = pos, Color = func(this, pos), Radius = lines.Thickness }; ++idx; } } return(new PointSet <Point>(points)); }
public TileSurface(LineSet lines) { // Assert "full" lineset. int length = lines[0].Length; #if DEBUG foreach (Line l in lines.Lines) { Debug.Assert(l.Length == length); } #endif Positions = new Vector3[length, lines.Length]; for (int l = 0; l < lines.Length; ++l) { for (int p = 0; p < lines[l].Length; ++p) { Positions[p, l] = lines[l][p]; } } }
public static void ReadFromFile(string file, out LineSet lineset) { Line[] lines; // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Open)) { using (BinaryReader reader = new BinaryReader(fs)) { // Write number of lines. lines = new Line[reader.ReadInt32()]; // Write line lengths in order. for (int l = 0; l < lines.Length; ++l) { lines[l] = new Line() { Positions = new Vector3[reader.ReadInt32()] } } ; // Write positions. float x, y, z; foreach (Line line in lines) { for (int v = 0; v < line.Length; ++v) { x = reader.ReadSingle(); y = reader.ReadSingle(); z = reader.ReadSingle(); line[v] = new Vector3(x, y, z); } } } } lineset = new LineSet(lines); }
public PlaygroundMapper(Plane plane) : base(new Plane(plane, 1), new Int2(NUM_CELLS)) { Mapping = Map; _velocity = Tests.CreateBowl(new Vec2(NUM_CELLS/2, 0), NUM_CELLS, new Vec2(-10, 0), 22, 200); _selections = new List<LineBall>(10); _selectionsAngle = new List<LineBall>(10); _steadySelection = new List<LineBall>(10); // Core. _core = new Line() { Positions = new Vector3[] { new Vector3(50, 100, 0), new Vector3(155, 100, _velocity.Size.T-1) } }; LineSet set = new LineSet(new Line[] { _core }) { Color = new Vector3(0.2f) }; set.Thickness *= 3; _coreBall = new LineBall(plane, set, LineBall.RenderEffect.DEFAULT); // Straight core. set = new LineSet(new Line[] { new Line() { Positions = new Vector3[] { _core[0], _core[0] + Vector3.UnitZ * (_velocity.Size.T - 1) } } }) { Color = new Vector3(0.2f) }; set.Thickness *= 3; _straightCoreBall = new LineBall(Plane, set); var center = Tests.CreatePerfect(new Vec2(0, 0), NUM_CELLS, new Vec2(0), 1, 200); _steadyField = center.GetTimeSlice(0); //[0] as ScalarField; }
public PlaygroundMapper(Plane plane) : base(new Plane(plane, 1), new Int2(NUM_CELLS)) { Mapping = Map; _velocity = Tests.CreateBowl(new Vec2(NUM_CELLS / 2, 0), NUM_CELLS, new Vec2(-10, 0), 22, 200); _selections = new List <LineBall>(10); _selectionsAngle = new List <LineBall>(10); _steadySelection = new List <LineBall>(10); // Core. _core = new Line() { Positions = new Vector3[] { new Vector3(50, 100, 0), new Vector3(155, 100, _velocity.Size.T - 1) } }; LineSet set = new LineSet(new Line[] { _core }) { Color = new Vector3(0.2f) }; set.Thickness *= 3; _coreBall = new LineBall(plane, set, LineBall.RenderEffect.DEFAULT); // Straight core. set = new LineSet(new Line[] { new Line() { Positions = new Vector3[] { _core[0], _core[0] + Vector3.UnitZ * (_velocity.Size.T - 1) } } }) { Color = new Vector3(0.2f) }; set.Thickness *= 3; _straightCoreBall = new LineBall(Plane, set); var center = Tests.CreatePerfect(new Vec2(0, 0), NUM_CELLS, new Vec2(0), 1, 200); _steadyField = center.GetTimeSlice(0); //[0] as ScalarField; }
public static void WriteToFile(string file, LineSet lines) { // Open the file. If it already exists, overwrite. using (FileStream fs = File.Open(@file, FileMode.Create)) { using (BinaryWriter writer = new BinaryWriter(fs)) { // Write number of lines. writer.Write(lines.Length); // Write line lengths in order. foreach (Line line in lines.Lines) writer.Write(line.Length); // Write positions. foreach(Line line in lines.Lines) { foreach(Vector3 vec in line.Positions) { writer.Write(vec.X); writer.Write(vec.Y); writer.Write(vec.Z); } } } } }
public List<Renderable> ShowPaths() { bool mapLines = false; // Setup an integrator. VectorField.Integrator intVF = VectorField.Integrator.CreateIntegrator(Velocity, _currentSetting.IntegrationType); intVF.MaxNumSteps = 10000; intVF.StepSize = _currentSetting.StepSize; if (_lastSetting == null || IntegrationTypeChanged || StepSizeChanged) { // ~~~~~~~~~~~ Line Integration ~~~~~~~~~~~ \\ // Clear the raw lines. int timeLength = Velocity.Size.T; _rawLines = new LineSet[Velocity.Size.T]; // Initialize the firth _rawLines[0] = new LineSet(new Line[0]); ScalarField[] lengths = new ScalarField[timeLength]; lengths[0] = new ScalarField(Velocity.ScalarsAsSFU[0].TimeSlices[0], (v, J) => 0); _minLength = new float[timeLength]; _maxLength = new float[timeLength]; // Integrate the path line segments between each neighboring pair of time slices. for (int time = 1; time < timeLength; ++time) { _minLength[time] = float.MaxValue; _maxLength[time] = float.MinValue; // Integrate last points until next time slice. _pathlineSegments[time-1] = intVF.Integrate(_intersectTimeSlices[time - 1], false, time)[0]; _pathlineSegments[time - 1].Color = Vector3.UnitZ * (float)time / timeLength; // if(time == timeLength - 1) _intersectTimeSlices[time] = _pathlineSegments[time - 1].GetValidEndPoints();//VectorField.Integrator.Status.BORDER); //else // _intersectTimeSlices[time] = _pathlineSegments[time - 1].GetEndPoints(VectorField.Integrator.Status.TIME_BORDER); _points[time] = new PointCloud(Plane, _intersectTimeSlices[time].ToBasicSet()); // Set all positions to 0, or invalid value. lengths[time] = new ScalarField(lengths[time-1], (s, g) => s, false); int i = 0; for (int p = 0; p < _intersectTimeSlices[time].Points.Length; ++p) { EndPoint pP = _intersectTimeSlices[time].Points[p]; ++i; // Map floating position to int position. int iPos = _fieldPositionOfValidCell[p]; float timeStepped = (pP.Position.Z - (time-1)); lengths[time][iPos] += timeStepped > 0 ? pP.LengthLine / timeStepped : 0; float tmp = lengths[time][iPos]; _minLength[time] = Math.Min(lengths[time][iPos], _minLength[time]); _maxLength[time] = Math.Max(lengths[time][iPos], _maxLength[time]); if (_minLength[time] < 0 || pP.Status != VectorField.Integrator.Status.TIME_BORDER) i += 0; //Console.WriteLine(lengths[time][iPos]); } Console.WriteLine("Integrated lines until time " + time); } lengths[0] = new VectorField(Velocity.GetTimeSlice(0), FieldAnalysis.VFLength, 1, false).Scalars[0] as ScalarField; _minLength[0] = 0; _maxLength[0] = RedSea.Singleton.NumTimeSlices; _pathLengths = new ScalarFieldUnsteady(lengths); mapLines = true; } if (_lastSetting == null || SliceTimeMainChanged|| ShaderChanged) { ScalarField f = _pathLengths.GetTimeSlice(_currentSetting.SliceTimeMain); f.TimeOrigin = 0; VectorField vecField; switch(_currentSetting.Shader) { case FieldPlane.RenderEffect.LIC: VectorField slice = Velocity.GetTimeSlice(0); slice.TimeSlice = 0; vecField = new VectorField(new Field[] { slice.Scalars[0], slice.Scalars[1], f }); break; case FieldPlane.RenderEffect.LIC_LENGTH: vecField = Velocity.GetTimeSlice(_currentSetting.SliceTimeMain); vecField.TimeSlice = 0; break; default: case FieldPlane.RenderEffect.COLORMAP: case FieldPlane.RenderEffect.DEFAULT: vecField = new VectorField(new Field[] { f }); break; } _plane = new FieldPlane(Plane, vecField /*Velocity.GetSlice(_currentSetting.SliceTimeReference)*/, _currentSetting.Shader); } // The line settings have changed. Create new renderables from the lines. if (mapLines || LineSettingChanged) { _lines = new Renderable[_pathlineSegments.Length]; switch (_currentSetting.LineSetting) { // Map the vertices to colored points. case RedSea.DisplayLines.POINTS_2D_LENGTH: for (int i = 0; i < _pathlineSegments.Length; ++i) { PointSet<Point> linePoints = Velocity.ColorCodeArbitrary(_pathlineSegments[i], RedSea.DisplayLineFunctions[(int)_currentSetting.LineSetting]); _lines[i] = new PointCloud(Plane, linePoints); } break; // Render as line. default: case RedSea.DisplayLines.LINE: for (int i = 0; i < _pathlineSegments.Length; ++i) { _lines[i] = new LineBall(Plane, _pathlineSegments[i]); } break; } } // Set mapping values. //_plane.UpperBound = 0; //= (1 + _currentSetting.WindowWidth) * (_maxLength[_currentSetting.SliceTimeMain] - _minLength[_currentSetting.SliceTimeMain]) /2 + _minLength[_currentSetting.SliceTimeMain]; _plane.UpperBound = _currentSetting.WindowWidth + _currentSetting.WindowStart; ///= _currentSetting.SliceTimeMain; //_plane.LowerBound = 0; //= (1 - _currentSetting.WindowWidth) * (_maxLength[_currentSetting.SliceTimeMain] - _minLength[_currentSetting.SliceTimeMain]) /2 + _minLength[_currentSetting.SliceTimeMain]; _plane.LowerBound = _currentSetting.WindowStart; ///= _currentSetting.SliceTimeMain; _plane.UsedMap = _currentSetting.Colormap; _plane.SetRenderEffect(_currentSetting.Shader); List<Renderable> result = new List<Renderable>(50); result.Add(_plane); switch(_currentSetting.Tracking) { case RedSea.DisplayTracking.LINE: case RedSea.DisplayTracking.LINE_POINTS: Renderable[] lines = new Renderable[_currentSetting.SliceTimeMain]; Array.Copy(_lines, lines, _currentSetting.SliceTimeMain); result = result.Concat(lines).ToList(); break; case RedSea.DisplayTracking.POINTS: result.Add(_points[_currentSetting.SliceTimeMain]); break; case RedSea.DisplayTracking.LINE_SELECTION: VectorField.StreamLine<Vector3> line = intVF.IntegrateLineForRendering(new Vec3(_startPoint.X, _startPoint.Y, 0)); LineSet set = new LineSet(new Line[] { new Line() { Positions = line.Points.ToArray() } }); if(_currentSetting.Flat) set.FlattenLines(_currentSetting.SliceTimeMain); result.Add(new LineBall(Plane, set)); break; default: break; } return result; }
protected void 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); }
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); }
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); }
public List <Renderable> ShowPaths() { bool mapLines = false; // Setup an integrator. VectorField.Integrator intVF = VectorField.Integrator.CreateIntegrator(Velocity, _currentSetting.IntegrationType); intVF.MaxNumSteps = 10000; intVF.StepSize = _currentSetting.StepSize; if (_lastSetting == null || IntegrationTypeChanged || StepSizeChanged) { // ~~~~~~~~~~~ Line Integration ~~~~~~~~~~~ \\ // Clear the raw lines. int timeLength = Velocity.Size.T; _rawLines = new LineSet[Velocity.Size.T]; // Initialize the firth _rawLines[0] = new LineSet(new Line[0]); ScalarField[] lengths = new ScalarField[timeLength]; lengths[0] = new ScalarField(Velocity.ScalarsAsSFU[0].TimeSlices[0], (v, J) => 0); _minLength = new float[timeLength]; _maxLength = new float[timeLength]; // Integrate the path line segments between each neighboring pair of time slices. for (int time = 1; time < timeLength; ++time) { _minLength[time] = float.MaxValue; _maxLength[time] = float.MinValue; // Integrate last points until next time slice. _pathlineSegments[time - 1] = intVF.Integrate(_intersectTimeSlices[time - 1], false, time)[0]; _pathlineSegments[time - 1].Color = Vector3.UnitZ * (float)time / timeLength; // if(time == timeLength - 1) _intersectTimeSlices[time] = _pathlineSegments[time - 1].GetValidEndPoints();//VectorField.Integrator.Status.BORDER); //else // _intersectTimeSlices[time] = _pathlineSegments[time - 1].GetEndPoints(VectorField.Integrator.Status.TIME_BORDER); _points[time] = new PointCloud(Plane, _intersectTimeSlices[time].ToBasicSet()); // Set all positions to 0, or invalid value. lengths[time] = new ScalarField(lengths[time - 1], (s, g) => s, false); int i = 0; for (int p = 0; p < _intersectTimeSlices[time].Points.Length; ++p) { EndPoint pP = _intersectTimeSlices[time].Points[p]; ++i; // Map floating position to int position. int iPos = _fieldPositionOfValidCell[p]; float timeStepped = (pP.Position.Z - (time - 1)); lengths[time][iPos] += timeStepped > 0 ? pP.LengthLine / timeStepped : 0; float tmp = lengths[time][iPos]; _minLength[time] = Math.Min(lengths[time][iPos], _minLength[time]); _maxLength[time] = Math.Max(lengths[time][iPos], _maxLength[time]); if (_minLength[time] < 0 || pP.Status != VectorField.Integrator.Status.TIME_BORDER) { i += 0; } //Console.WriteLine(lengths[time][iPos]); } Console.WriteLine("Integrated lines until time " + time); } lengths[0] = new VectorField(Velocity.GetTimeSlice(0), FieldAnalysis.VFLength, 1, false).Scalars[0] as ScalarField; _minLength[0] = 0; _maxLength[0] = RedSea.Singleton.NumTimeSlices; _pathLengths = new ScalarFieldUnsteady(lengths); mapLines = true; } if (_lastSetting == null || SliceTimeMainChanged || ShaderChanged) { ScalarField f = _pathLengths.GetTimeSlice(_currentSetting.SliceTimeMain); f.TimeOrigin = 0; VectorField vecField; switch (_currentSetting.Shader) { case FieldPlane.RenderEffect.LIC: VectorField slice = Velocity.GetTimeSlice(0); slice.TimeSlice = 0; vecField = new VectorField(new Field[] { slice.Scalars[0], slice.Scalars[1], f }); break; case FieldPlane.RenderEffect.LIC_LENGTH: vecField = Velocity.GetTimeSlice(_currentSetting.SliceTimeMain); vecField.TimeSlice = 0; break; default: case FieldPlane.RenderEffect.COLORMAP: case FieldPlane.RenderEffect.DEFAULT: vecField = new VectorField(new Field[] { f }); break; } _plane = new FieldPlane(Plane, vecField /*Velocity.GetSlice(_currentSetting.SliceTimeReference)*/, _currentSetting.Shader); } // The line settings have changed. Create new renderables from the lines. if (mapLines || LineSettingChanged) { _lines = new Renderable[_pathlineSegments.Length]; switch (_currentSetting.LineSetting) { // Map the vertices to colored points. case RedSea.DisplayLines.POINTS_2D_LENGTH: for (int i = 0; i < _pathlineSegments.Length; ++i) { PointSet <Point> linePoints = Velocity.ColorCodeArbitrary(_pathlineSegments[i], RedSea.DisplayLineFunctions[(int)_currentSetting.LineSetting]); _lines[i] = new PointCloud(Plane, linePoints); } break; // Render as line. default: case RedSea.DisplayLines.LINE: for (int i = 0; i < _pathlineSegments.Length; ++i) { _lines[i] = new LineBall(Plane, _pathlineSegments[i]); } break; } } // Set mapping values. //_plane.UpperBound = 0; //= (1 + _currentSetting.WindowWidth) * (_maxLength[_currentSetting.SliceTimeMain] - _minLength[_currentSetting.SliceTimeMain]) /2 + _minLength[_currentSetting.SliceTimeMain]; _plane.UpperBound = _currentSetting.WindowWidth + _currentSetting.WindowStart; ///= _currentSetting.SliceTimeMain; //_plane.LowerBound = 0; //= (1 - _currentSetting.WindowWidth) * (_maxLength[_currentSetting.SliceTimeMain] - _minLength[_currentSetting.SliceTimeMain]) /2 + _minLength[_currentSetting.SliceTimeMain]; _plane.LowerBound = _currentSetting.WindowStart; ///= _currentSetting.SliceTimeMain; _plane.UsedMap = _currentSetting.Colormap; _plane.SetRenderEffect(_currentSetting.Shader); List <Renderable> result = new List <Renderable>(50); result.Add(_plane); switch (_currentSetting.Tracking) { case RedSea.DisplayTracking.LINE: case RedSea.DisplayTracking.LINE_POINTS: Renderable[] lines = new Renderable[_currentSetting.SliceTimeMain]; Array.Copy(_lines, lines, _currentSetting.SliceTimeMain); result = result.Concat(lines).ToList(); break; case RedSea.DisplayTracking.POINTS: result.Add(_points[_currentSetting.SliceTimeMain]); break; case RedSea.DisplayTracking.LINE_SELECTION: VectorField.StreamLine <Vector3> line = intVF.IntegrateLineForRendering(new Vec3(_startPoint.X, _startPoint.Y, 0)); LineSet set = new LineSet(new Line[] { new Line() { Positions = line.Points.ToArray() } }); if (_currentSetting.Flat) { set.FlattenLines(_currentSetting.SliceTimeMain); } result.Add(new LineBall(Plane, set)); break; default: break; } return(result); }
protected void TubeToRenderables() { if (_tube.Count < 1) return; _tube = _tube.OrderBy(o => o[0].Z).ToList(); //_boundaryBallSpacetime = new LineBall(new Plane(_graphPlane, Vector3.UnitZ * 0.01f), _boundariesSpacetime, LineBall.RenderEffect.HEIGHT, ColorMapping.GetComplementary(Colormap), Flat); LineSet rings = new LineSet(_tube.ToArray()); rings.Thickness *= 0.5f; _boundaryBallSpacetime = new LineBall(_linePlane, rings, LineBall.RenderEffect.HEIGHT, ColorMapping.GetComplementary(Colormap), false); //if (_tube.Count > 1) // _specialObject = new Mesh(_linePlane, new TileSurface(rings), Mesh.RenderEffect.DEFAULT, Colormap); }
protected override void TraceCore(int member = 0, int startSubstep = 0) { int rad = NEIGHBOORHOOD_CP * (Core == CoreAlgorithm.ROUGH_STREAM_CONNECTION ? 4 : 1); string corename = RedSea.Singleton.CoreFileName + member + Core.ToString() + "cc.line"; if (System.IO.File.Exists(corename)) { GeometryWriter.ReadFromFile(corename, out _cores); LoadField(0, MemberMain, 1); } else { Vec3[] bases = new Vec3[] { new Vec3(463.1f, 53.6f, 0), new Vec3(366.4f, 34.4f, 0), new Vec3(230.1f, 218.6f, 0)}; if (Core == CoreAlgorithm.CLICK) { Line[] lines = new Line[bases.Length]; for(int b = 0; b < bases.Length; ++b) lines[b] = new Line() { Positions = new Vector3[] { (Vector3)bases[b], (Vector3)bases[b] + Vector3.UnitZ * (float)(RedSea.Singleton.NumSubstepsTotal / _everyNthTimestep) } }; _cores = new LineSet(lines); LoadField(0, MemberMain, 1); return; } int numSlices = RedSea.Singleton.NumSubstepsTotal / _everyNthTimestep; int stepSize = Core != CoreAlgorithm.ROUGH_STREAM_CONNECTION ? 1 : ROUGH_MULTIPLIER; // RedSea.Singleton.NumSubstepsTotal / _everyNthTimestep - 1; _cores = new LineSet(new Line[bases.Length]); for (int b = 0; b < _cores.Length; ++b) { _cores[b] = new Line((int)Math.Ceiling((float)(numSlices -1)/ stepSize)+1); //_cores[b][0] = (Vector3)bases[b]; } int idx = 0; // Connect to other slices. for(int slice = 0; slice < numSlices; slice += stepSize) { LoadField(Math.Min(slice, numSlices - 2), member, 2); VectorField field = _velocity; if (Core == CoreAlgorithm.PATHLINE) { var acc= new VectorFieldUnsteady(_velocity, FieldAnalysis.Acceleration, 2); field = acc.GetTimeSlice(slice); } else { field = _velocity.GetTimeSlice(slice); } for (int b = 0; b < _cores.Length; ++b) { Vector3 lastCP = idx > 0? _cores[b][idx-1] : (Vector3)bases[b]; Int2 x = new Int2((int)lastCP.X - rad, (int)Math.Ceiling(lastCP.X) + rad); Int2 y = new Int2((int)lastCP.Y - rad, (int)Math.Ceiling(lastCP.Y) + rad); CriticalPointSet2D points = FieldAnalysis.ComputeCriticalPointsRegularSubdivision2DRange(field, x, y); float minDist = float.MaxValue; CriticalPoint2D nearest = null; foreach(CriticalPoint2D point in points.Points) { float dist = (lastCP - point.Position).LengthSquared(); if(dist< minDist) { minDist = dist; nearest = point; } } _cores[b][idx] = nearest?.Position ?? lastCP; _cores[b].Positions[idx].Z = slice; } idx++; // Reverse-engineered: Always include the last possible slice. if (slice + stepSize >= numSlices && slice + 1 < numSlices) slice = numSlices - 1 - stepSize; } GeometryWriter.WriteToFile(corename, _cores); } }
protected void GenerateGeometryFlatXY(Plane plane, LineSet lines) { // Write poition and UV-map data. var stream = new DataStream(_numVertices * _vertexSizeBytes, true, true); Vector3 zAxis = plane.ZAxis; for (int index = 0; index < lines.Lines.Length; ++index) { Line line = lines.Lines[index]; if (line.Length < 2) continue; Debug.Assert(line.Length == lines.Lines[index].Length); stream.Write(new Vector4(plane.Origin + (plane.XAxis * line.Positions[0][0] + plane.YAxis * line.Positions[0][1] ), line.Positions[0][2])); for (int point = 1; point < line.Positions.Length - 1; ++point) { Vector4 pos = new Vector4(plane.Origin + (plane.XAxis * line.Positions[point][0] + plane.YAxis * line.Positions[point][1]), line.Positions[point][2]); stream.Write(pos); stream.Write(pos); } int end = line.Positions.Length - 1; stream.Write(new Vector4(plane.Origin + (plane.XAxis * line.Positions[end][0] + plane.YAxis * line.Positions[end][1]), line.Positions[end][2])); } stream.Position = 0; // Create and fill buffer. _vertices = new Buffer(_device, stream, new BufferDescription() { BindFlags = BindFlags.VertexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = _numVertices * _vertexSizeBytes, Usage = ResourceUsage.Default }); stream.Dispose(); }
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); } } }
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); }