Commit 53f0a123 authored by Moritz's avatar Moritz

PointcloudToGridmapper: now works with the class PCachePoint, not with Cell...

PointcloudToGridmapper: now works with the class PCachePoint, not with Cell and vertice infos anymore, added constructor in case cells + vertices is passed; created class VTKDataReader to read data from VTK data sets, VTKtoVF: created script and scene to read VTK data, similar to CELtoVF
parent 8d45f017
This diff is collapsed.
fileFormatVersion: 2
guid: 6fff8da36b67f9b45b362f466b15a9d8
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
This diff is collapsed.
fileFormatVersion: 2
guid: e667097199195674f9e2867d98ca976f
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -16,32 +16,59 @@ namespace Teamproject {
/// </summary>
public float[,,] info { get; private set; }
Dictionary<int, Cell> _cells;
Dictionary<int, Vector3> _vertices;
//Dictionary<int, PCachePoint> _points;
float _inputGridStepSize = -1;
//pcache
private List<PCachePoint> points;
private List<PCachePoint> _points;
private Vector3 gridSize;
private Vector3 offsetCorrection; //if the grid doesn't start at 0, 0, 0 -> vector to move all points, so that grid is aligned
private float gridStepSize;
/// <summary>
///
/// Maps given points into a grid
/// Should have a complexity of (numberOfGridPoints) * (numberOfMappedPoints)
/// </summary>
/// <param name="cells"></param>
/// <param name="vertices"></param>
/// <param name="points"> List of PCachePoints that are mapped to the grid </param>
/// <param name="inputGridStepSize"> Distance of adjacent gridpoints, entered by the user, in Millimeter </param>
public PointcloudToGridMapper(Dictionary<int, PCachePoint> points, float inputGridStepSize) {
_points = new List<PCachePoint>(points.Values);
_inputGridStepSize = inputGridStepSize;
}
/// <summary>
/// Maps given points into a grid
/// Should have a complexity of (numberOfGridPoints) * (numberOfMappedPoints)
/// Converts the given cells and vertices to a List of PCachePoints
/// </summary>
/// <param name="cells"> List of Cells consisting to the vertices </param>
/// <param name="vertices"> List of vertices that belong to the Cells </param>
/// <param name="inputGridStepSize"> Distance of adjacent gridpoints, entered by the user, in Millimeter </param>
public PointcloudToGridMapper(Dictionary<int, Cell> cells, Dictionary<int, Vector3> vertices, float inputGridStepSize) {
_cells = cells;
_vertices = vertices;
_inputGridStepSize = inputGridStepSize;
//pcache point = middlepoint of cell
_points = new List<PCachePoint>();
foreach (KeyValuePair<int, Cell> kvp in cells) {
Cell cell = kvp.Value;
//calculate midpoint for each cell
Vector3 cellMid = Vector3.zero;
foreach (int vertexID in cell.VertexIDs)
cellMid += vertices[vertexID];
cellMid /= cell.VertexIDs.Count;
//add point to list
_points.Add(new PCachePoint(cell.CellType, cellMid, cell.Velocity));
}
}
public void StartConvert() {
Debug.Log("PointCloudToGridMapper: " + _points.Count + " point to map onto grid");
CreateGrid();
CalculatePointsFromCells();
IntegratePointsIntoGrid();
}
......@@ -55,7 +82,9 @@ namespace Teamproject {
float minZ = float.MaxValue;
//iterate through all vertices -> find min/max values
foreach (Vector3 vertex in _vertices.Values) {
foreach (PCachePoint p in _points) {
Vector3 vertex = p.Position;
if (vertex.x > maxX)
maxX = vertex.x;
......@@ -75,6 +104,8 @@ namespace Teamproject {
minZ = vertex.z;
}
//to align grid at point 0, 0, 0: calculate offset from origin
float xOffset = 0 - minX;
float yOffset = 0 - minY;
......@@ -84,32 +115,16 @@ namespace Teamproject {
//conversion to millimeter
gridStepSize = (_inputGridStepSize * Mathf.Pow(10, -3));
//create grid
int gridXSize = (int)Mathf.Ceil(maxX / gridStepSize);
int gridYSize = (int)Mathf.Ceil(maxY / gridStepSize);
int gridZSize = (int)Mathf.Ceil(maxZ / gridStepSize);
//create grid, include offset to get the bounding boxes size
int gridXSize = (int)Mathf.Ceil((maxX + xOffset) / gridStepSize);
int gridYSize = (int)Mathf.Ceil((maxY + yOffset) / gridStepSize);
int gridZSize = (int)Mathf.Ceil((maxZ + zOffset) / gridStepSize);
gridSize = new Vector3(gridXSize - 1, gridYSize - 1, gridZSize - 1); // -1 because following array is 0 based
directionGrid = new Vector3[gridXSize, gridYSize, gridZSize];
info = new float[gridXSize, gridYSize, gridZSize];
}
private void CalculatePointsFromCells() {
//pcache point = middlepoint of cell
points = new List<PCachePoint>();
foreach (KeyValuePair<int, Cell> kvp in _cells) {
Cell cell = kvp.Value;
//calculate midpoint for each cell
Vector3 cellMid = Vector3.zero;
foreach (int vertexID in cell.VertexIDs)
cellMid += _vertices[vertexID];
cellMid /= cell.VertexIDs.Count;
//add point to list
points.Add(new PCachePoint(cell.CellType, cellMid, cell.Velocity));
}
Debug.Log("Grid size: " + gridSize);
}
private void IntegratePointsIntoGrid() {
......@@ -137,9 +152,10 @@ namespace Teamproject {
* Points by reference abgespeichert oder? dann sollten die Listen ja eh nicht so groß sein
*/
//adjust free points by including offset
List<PCachePoint> adjPoints = new List<PCachePoint>();
foreach (PCachePoint pd in points)
foreach (PCachePoint pd in _points)
adjPoints.Add(new PCachePoint(pd.Type, pd.Position + offsetCorrection, pd.Direction));
......@@ -147,7 +163,10 @@ namespace Teamproject {
//Inverted Lists: calculate neighbourhoods (lists)
List<PCachePoint>[,,] nei = new List<PCachePoint>[(int)gridSize.x, (int)gridSize.y, (int)gridSize.z];
foreach (PCachePoint pcpoint in adjPoints) {
/*
* Find the grid points that surround the current point
* maxGridPoint: gridpoint (directly surrounding the current point) most distant from the grid origin
......@@ -172,7 +191,7 @@ namespace Teamproject {
float getCeilGridPoint(float value, int gridDimensionMax) {
value += neighborhoodRange;
value = Mathf.Floor(value / gridStepSize);
return value > gridDimensionMax ? gridDimensionMax : value;
return value > gridDimensionMax - 1 ? gridDimensionMax - 1 : value;
}
//get lower nearest gridpoint within neighborhood range (lower = nearest to the grid origin)
......@@ -194,8 +213,11 @@ namespace Teamproject {
//Debug.Log("size: " + gridSize + " und koordinaten x: " + x + ", y: " + y + ", z: " + z);
if ((x >= gridSize.x) || (y >= gridSize.y) || (z >= gridSize.z) || //index positive out of grids bounds
x < 0 || y < 0 || z < 0) //index negative out of grids bounds
x < 0 || y < 0 || z < 0) { //index negative out of grids bounds
Debug.LogWarning("WHAT WHAT SOLLTE ABGEFANGEN SEIN");
continue;
}
if (nei[x, y, z] == null)
nei[x, y, z] = new List<PCachePoint>();
......@@ -206,6 +228,8 @@ namespace Teamproject {
}
}
/*
* To calculate the direction vector on each gridpoint: take direction vectors of the neighbourhoods free points
* Different approaches to combine the Vectors:
......@@ -230,13 +254,13 @@ namespace Teamproject {
var dist = Vector3.Distance(pointPos, nei[x, y, z][i].Position);
if (dist < nearestDist) {
dist = nearestDist;
nearestDist = dist; //dist = nearestDist; //war wohl falsch
nearestIndex = i;
}
}
directionGrid[x, y, z] = nei[x, y, z][nearestIndex].Direction;
info[x, y, z] = nei[x, y, z][nearestIndex].Type;
info[x, y, z] = 0;//nei[x, y, z][nearestIndex].Type;
}
else {
directionGrid[x, y, z] = Vector3.zero;
......
fileFormatVersion: 2
guid: 44f03d364a054714290099080a513e1b
guid: 2faaf92828a0321409667fec874e10f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
......
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Teamproject {
public class VTKToVF : MonoBehaviour {
[Tooltip("Path to CEL Data files containing the extensions .cel, .daten and .vrt \n" +
"STAR-CCM+ export options should be: Export Data: all Regions, Velocity (only vector \"Lab Reference Frame\"," +
" not magnitude or i, j, k; Export Type: Mesh and Solution Data")]
public string PathToFolder = "";
[Tooltip("Distance between adjacent gridpoints on any axis, in Millimeter")]
public float GridStepSize = default;
public bool ConvertVTKToVectorfield = default;
Dictionary<int, PCachePoint> points;
private void Update() {
if (ConvertVTKToVectorfield) {
ConvertVTKToVectorfield = false;
StartCoroutine(StartConvert());
}
}
public IEnumerator StartConvert() {
var startingTime = DateTime.Now;
string filenames = FileNameFinder.GetName(PathToFolder, ".vtk");
Debug.Log("<color=teal> Starting reading data " + filenames + "</color>");
yield return new WaitForEndOfFrame();
VTKDataReader reader = new VTKDataReader(PathToFolder, filenames);
reader.ReadVTKData();
Debug.Log("<color=teal> Reading complete, starting mapping to grid </color>");
yield return new WaitForEndOfFrame();
points = reader.points;
var gridMapper = new PointcloudToGridMapper(points, GridStepSize);
gridMapper.StartConvert();
Debug.Log("<color=teal> Mapping complete, starting writing to vectorfield </color>");
yield return new WaitForEndOfFrame();
//test test
Debug.Log("ding start");
var testPointVis = GameObject.FindObjectOfType<Testing.PointCloudVisualizer>().GetComponent<Testing.PointCloudVisualizer>();
//testPointVis.Visualize(new List<PCachePoint>(points.Values));
var testVis = GameObject.FindObjectOfType<Testing.Array3DVisualizer>().GetComponent<Testing.Array3DVisualizer>();
testVis.Visualize(gridMapper.directionGrid);
Debug.Log("ding ende");
//test test ende
var writer = new VectorFieldWriter(PathToFolder, filenames);
//writer.WriteToVectorfield(gridMapper.directionGrid);
//writer.WriteToVectorfield(gridMapper.info);
Debug.Log("<color=teal> Writing to vectorfield complete </color>");
var calcTime = (DateTime.Now - startingTime);
Debug.Log("<color=teal> Everything done in " + (calcTime.Minutes * 60 + calcTime.Seconds) + " seconds. </color>");
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 6ea514f390717be4996e41605363758e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.IO;
using System.Globalization;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
namespace Teamproject {
public class VTKDataReader {
public Dictionary<int, PCachePoint> points { get; private set; }
private string _pathToFolder;
private string _filenames;
private StreamReader reader;
//if we see that a read line belongs to another data structure -> store it here
private string currentLine;
private string removedLines = "Removed Lines:";
public VTKDataReader(string pathToFolder, string filenames) {
_pathToFolder = pathToFolder;
_filenames = filenames;
}
public void ReadVTKData() {
points = new Dictionary<int, PCachePoint>();
reader = new StreamReader(_pathToFolder + @"\" + _filenames + ".vtk");
ReadPoints();
ReadCells();
ReadCellTypes();
//TODO: read scalar + vector information generic
ReadPressure();
ReadVelocity();
reader.Close();
}
private void ReadPoints() {
/*
* File starts with Header
* Point position information after line:
* "POINTS x type" with x = pointcount and type = datatype (should be float)
*/
bool dataStartDetected = false;
while (!dataStartDetected) {
currentLine = reader.ReadLine();
if (currentLine.StartsWith("POINTS"))
dataStartDetected = true;
else
removedLines += "\n" + currentLine;
}
//get number of points
string[] info = currentLine.Split(' ');
int pointCount = int.Parse(info[1], CultureInfo.InvariantCulture.NumberFormat);
currentLine = reader.ReadLine();
//read point data
int pointID = 0;
//store float values here, if enough floats (3) are present -> create a point from these floats
//i did this in case a point starts in one line and ends in another (although i am not sure anymore if this occurs)
List<float> storage = new List<float>();
int linecounter = 1;
while (pointID != pointCount) {
if (currentLine.EndsWith(" "))
currentLine = currentLine.Remove(currentLine.Length - 1); //else we get an empty array entry at the end in the next line
string[] parts = currentLine.Split(' ');
foreach (string part in parts) {
try {
//read next number
float f = float.Parse(part, CultureInfo.InvariantCulture);
storage.Add(f);
} catch (System.Exception) {
Debug.LogError("<color=red>Couldn't parse line " + linecounter + " while reading points</color>");
Debug.LogError("the line is: >" + currentLine + "<");
return;
}
//enough floats? -> create new point
if (storage.Count == 3)
StorageToPoint();
}
linecounter++;
currentLine = reader.ReadLine();
}
void StorageToPoint() {
points.Add(
pointID,
new PCachePoint(
0, //unknown
new Vector3(storage[0], storage[1], storage[2]),
Vector3.zero)); //is added later
storage.Clear();
pointID++;
}
Debug.Log("ReadPoints: " + points.Count + " from " + pointCount);
}
private void ReadCells() {
//cell information is unimportant, only stores cell type
//meaning of the cell type: https://vtk.org/doc/nightly/html/vtkCellType_8h_source.html
while (!currentLine.StartsWith("CELL_TYPES"))
currentLine = reader.ReadLine();
}
private void ReadCellTypes() {
while (!currentLine.StartsWith("POINT_DATA"))
currentLine = reader.ReadLine();
}
private void ReadPressure() {
currentLine = reader.ReadLine();
if (!currentLine.StartsWith("SCALARS"))
return;
//TODO: read scalar info
}
private void ReadVelocity() {
while (!currentLine.StartsWith("VECTORS"))
currentLine = reader.ReadLine();
//go into the first line with data
currentLine = reader.ReadLine();
//read point data
int pointID = 0;
//store float values here, if enough floats (3) are present -> create a point from these floats
//i did this in case a point starts in one line and ends in another (although i am not sure anymore if this occurs)
List<float> storage = new List<float>();
int pointCount = points.Count;
while (pointID != pointCount) {
if (currentLine.EndsWith(" "))
currentLine = currentLine.Remove(currentLine.Length - 1); //else we get an empty array entry at the end in the next line
string[] parts = currentLine.Split(' ');
foreach (string part in parts) {
try {
//read next number
float f = float.Parse(part, CultureInfo.InvariantCulture);
storage.Add(f);
}
catch (System.Exception) {
Debug.LogError("the line is: >" + currentLine + "<");
return;
}
//enough floats? -> create new point
if (storage.Count == 3)
StorageToPointDirection();
}
currentLine = reader.ReadLine();
}
void StorageToPointDirection() {
points[pointID].SetDirection(new Vector3(storage[0], storage[1], storage[2]));
storage.Clear();
pointID++;
}
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 23b0acafc0e118c47ab06eeca9266bdc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment