123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- """Reader for NIST SAVG files.
- This reader reads in a .savg file and produces a vtkPartionedDatasSetCollection
- with one vtkPartitionedDataSet for each type of primitive: points, lines,
- and polygons.
- """
- from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase
- from .. import print_error
- def get_coords_from_line(line):
- """ Given a line, split it, and parse out the coordinates.
- Return:
- A tuple containing coords (position, color, normal)
- """
- values = line.split()
- pt = None
- pt_n = None
- pt_col = None
- # The first three are always the point coords
- if len(values) >= 3:
- pt = [float(values[0]), float(values[1]), float(values[2])]
- # Then if there are only 6 total, the next three are normal coords
- if len(values) == 6:
- pt_n = [float(values[3]), float(values[4]), float(values[5])]
- else:
- if len(values) >= 7: # Otherwise the next 4 are colors
- pt_col = [float(values[3]), float(values[4]), float(values[5]), float(values[6])]
- if len(values) >= 10: # And if there are more, those are the normals
- pt_n = [float(values[7]), float(values[8]), float(values[9])]
- return pt, pt_col, pt_n
- def not_supported(line):
- return (
- line.startswith('tri') or
- line.startswith('pixel') or
- line.startswith('text') or
- line.startswith('program') or
- line.startswith('attribute') or
- line.startswith('nooptimizations')
- )
- class SAVGReader(VTKPythonAlgorithmBase):
- def __init__(self):
- VTKPythonAlgorithmBase.__init__(self, nInputPorts=0, nOutputPorts=1, outputType="vtkPartitionedDataSetCollection")
- self._filename = None
- self._ndata = None
- self._timesteps = None
- def SetFileName(self, name):
- """Specify filename for the file to read."""
- if name.lower().endswith("savg"):
- if self._filename != name:
- self._filename = name
- self.Modified()
- def RequestData(self, request, inInfoVec, outInfoVec):
- from vtkmodules.vtkCommonCore import vtkFloatArray, vtkPoints
- from vtkmodules.vtkCommonDataModel import (
- vtkCellArray,
- vtkCompositeDataSet,
- vtkPartitionedDataSet,
- vtkPartitionedDataSetCollection,
- vtkPolyData
- )
- output = vtkPartitionedDataSetCollection.GetData(outInfoVec);
- partitioned_datasets = []
- partitioned_dataset_names = []
- # Parse line file
- if not self._filename:
- print_error("SAVGReader requires a FileName")
- return 0
- # Stores lines of text from the file associated with each group of
- # geometries encountered.
- geometries = {
- "lines": [],
- "points": [],
- "poly": []
- }
- # Read the file and build up data structure to hold the primitives
- with open(self._filename, "r") as file:
- current = None
- for line in file:
- parts = line.split("#")
- line = parts[0].strip().lower()
- if len(line) < 1:
- continue
- if not_supported(line):
- continue
- if line.startswith("lin"):
- geometries["lines"].append({
- "rgba": None,
- "values": []
- })
- current = geometries["lines"][-1]
- line_parts = line.split(" ")
- if len(line_parts) == 5:
- current["rgba"] = [float(n) for n in line_parts[1:]]
- elif line.startswith("point"):
- geometries["points"].append({
- "rgba": None,
- "values": [],
- })
- current = geometries["points"][-1]
- line_parts = line.split(" ")
- if len(line_parts) == 5:
- current["rgba"] = [float(n) for n in line_parts[1:]]
- elif line.startswith("poly"):
- geometries["poly"].append({
- "rgba": None,
- "npts": None,
- "values": [],
- })
- current = geometries["poly"][-1]
- line_parts = line.split(" ")
- if len(line_parts) == 2:
- current["npts"] = int(line_parts[1])
- elif len(line_parts) == 6:
- current["rgba"] = [float(n) for n in line_parts[1:5]]
- current["npts"] = int(line_parts[5])
- elif line.startswith("end"):
- current = None
- else:
- if current is not None:
- if "npts" in current and current["npts"] is not None:
- # polygon, known num pts per poly
- if len(current["values"]) == current["npts"]:
- # Reached the number of points for the current one,
- # start a new one.
- geometries["poly"].append({
- "npts": current["npts"],
- "rgba": current["rgba"],
- "values": []
- })
- current = geometries["poly"][-1]
- pt, pt_col, pt_n = get_coords_from_line(line)
- if pt:
- current["values"].append({
- "pos": pt,
- })
- color = pt_col or current["rgba"]
- if color:
- current["values"][-1]["col"] = color
- if pt_n:
- current["values"][-1]["norm"] = pt_n
- # Build lines polydata if there were any lines
- if geometries["lines"]:
- line_points = vtkPoints()
- line_cells = vtkCellArray()
- line_point_colors = vtkFloatArray()
- line_point_colors.SetNumberOfComponents(4)
- line_point_colors.SetName("rgba_colors")
- line_point_normals = vtkFloatArray()
- line_point_normals.SetNumberOfComponents(3)
- line_point_normals.SetName("vertex_normals")
- pt_count = 0
- for batch in geometries["lines"]:
- num_in_batch = len(batch["values"])
- first_in_batch = True
- for coord in batch["values"]:
- if "pos" in coord:
- line_points.InsertNextPoint(coord["pos"])
- if "norm" in coord:
- line_point_normals.InsertNextTuple(coord["norm"])
- if "col" in coord:
- line_point_colors.InsertNextTuple(coord["col"])
- if first_in_batch:
- line_cells.InsertNextCell(num_in_batch)
- first_in_batch = False
- line_cells.InsertCellPoint(pt_count)
- pt_count += 1
- output_lines = vtkPolyData()
- output_lines.SetPoints(line_points)
- output_lines.SetLines(line_cells)
- if line_point_colors.GetNumberOfTuples() > 0:
- output_lines.GetPointData().AddArray(line_point_colors)
- if line_point_normals.GetNumberOfTuples() > 0:
- output_lines.GetPointData().AddArray(line_point_normals)
- ds = vtkPartitionedDataSet()
- ds.SetNumberOfPartitions(1)
- ds.SetPartition(0, output_lines)
- partitioned_datasets.append(ds)
- partitioned_dataset_names.append("Lines")
- # Build the points polydata if we found points
- if geometries["points"]:
- p_points = vtkPoints()
- p_cells = vtkCellArray()
- p_point_colors = vtkFloatArray()
- p_point_colors.SetNumberOfComponents(4)
- p_point_colors.SetName("rgba_colors")
- p_point_normals = vtkFloatArray()
- p_point_normals.SetNumberOfComponents(3)
- p_point_normals.SetName("vertex_normals")
- p_count = 0
- for batch in geometries["points"]:
- num_in_batch = len(batch["values"])
- first_in_batch = True
- for coord in batch["values"]:
- if "pos" in coord:
- p_points.InsertNextPoint(coord["pos"])
- if "norm" in coord:
- p_point_normals.InsertNextTuple(coord["norm"])
- if "col" in coord:
- p_point_colors.InsertNextTuple(coord["col"])
- if first_in_batch:
- p_cells.InsertNextCell(num_in_batch)
- first_in_batch = False
- p_cells.InsertCellPoint(p_count)
- p_count += 1
- output_points = vtkPolyData()
- output_points.SetPoints(p_points)
- output_points.SetVerts(p_cells)
- if p_point_colors.GetNumberOfTuples() > 0:
- output_points.GetPointData().AddArray(p_point_colors)
- if p_point_normals.GetNumberOfTuples() > 0:
- output_points.GetPointData().AddArray(p_point_normals)
- ds = vtkPartitionedDataSet()
- ds.SetNumberOfPartitions(1)
- ds.SetPartition(0, output_points)
- partitioned_datasets.append(ds)
- partitioned_dataset_names.append("Points")
- # Build the polygons if there were any
- if geometries["poly"]:
- poly_points = vtkPoints()
- poly_cells = vtkCellArray()
- poly_point_colors = vtkFloatArray()
- poly_point_colors.SetNumberOfComponents(4)
- poly_point_colors.SetName("rgba_colors")
- poly_point_normals = vtkFloatArray()
- poly_point_normals.SetNumberOfComponents(3)
- poly_point_normals.SetName("vertex_normals")
- pt_count = 0
- for batch in geometries["poly"]:
- num_in_batch = len(batch["values"])
- if num_in_batch < 1:
- continue
- first_in_batch = True
- for coord in batch["values"]:
- if "pos" in coord:
- poly_points.InsertNextPoint(coord["pos"])
- if "norm" in coord:
- poly_point_normals.InsertNextTuple(coord["norm"])
- if "col" in coord:
- poly_point_colors.InsertNextTuple(coord["col"])
- if first_in_batch:
- np_in_cell = num_in_batch
- poly_cells.InsertNextCell(np_in_cell)
- first_in_batch = False
- poly_cells.InsertCellPoint(pt_count)
- pt_count += 1
- output_polys = vtkPolyData()
- output_polys.SetPoints(poly_points)
- output_polys.SetPolys(poly_cells)
- if poly_point_colors.GetNumberOfTuples() > 0:
- output_polys.GetPointData().AddArray(poly_point_colors)
- if poly_point_normals.GetNumberOfTuples() > 0:
- output_polys.GetPointData().AddArray(poly_point_normals)
- ds = vtkPartitionedDataSet()
- ds.SetNumberOfPartitions(1)
- ds.SetPartition(0, output_polys)
- partitioned_datasets.append(ds)
- partitioned_dataset_names.append("Polygons")
- # Add any partioned datasets we created
- output.SetNumberOfPartitionedDataSets(len(partitioned_datasets))
- for idx, pds in enumerate(partitioned_datasets):
- output.SetPartitionedDataSet(idx, pds)
- output.GetMetaData(idx).Set(vtkCompositeDataSet.NAME(), partitioned_dataset_names[idx])
- return 1
|