Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
cutter.py 3.50 KiB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright 2020 University of Liège
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


# @brief VTK cut plane post-processing
# @authors Adrien Crovato, Kim Liegeois

try:
    import vtk
except:
    raise Exception('VTK not found. Aborting!\n')

class Cutter:
    def __init__(self, _grid):
        self.grid = _grid

    def cut(self, tag, cutO, cutN, tag_name="tag"):
        """Cut the physical group ided "tag" with a plane defined by point "cutO" and normal "cutN"
        """
        # create a threshold containing the physical group (tag) to cut
        thresh = vtk.vtkThreshold()
        thresh.SetLowerThreshold(tag)
        thresh.SetUpperThreshold(tag)
        thresh.SetInputConnection(self.grid)
        thresh.SetInputArrayToProcess(0, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_CELLS, tag_name) # "tag" is the default name set in tboxVtk::VtkExport::save
        thresh.Update()
        # create cutting plane
        plane = vtk.vtkPlane()
        plane.SetOrigin(cutO[0], cutO[1], cutO[2])
        plane.SetNormal(cutN[0], cutN[1], cutN[2])
        # cut the threshold and get data
        cutter = vtk.vtkCutter()
        cutter.SetCutFunction(plane)
        cutter.SetInputConnection(thresh.GetOutputPort())
        cutter.Update()
        return cutter.GetOutput()

    def extract(self, cutData, tagDim, vname, atPoint = True):
        """Extract points "pts", connectivity list "elems" and data "vals" named "vname" from cutting plane data "cutData".
        The physical group dimension is given by "tagDim" and "atPoint" is True if vname is defined at points.
        """
        import numpy as np
        # transfer point coordinates
        _pts = cutData.GetPoints()
        pts = np.zeros((_pts.GetNumberOfPoints(), 3))
        for i in range(0, pts.shape[0]):
            for j in range(0, 3):
                pts[i][j] = _pts.GetPoint(i)[j]
        # transfer connectivity
        if tagDim == 3:
            _elems = cutData.GetPolys().GetData()
            nV = 3 # assumes that all Poly(gon)s are triangles
        elif tagDim == 2:
            _elems = cutData.GetLines().GetData()
            nV = 2
        else:
            raise Exception('tagDim can only be 2 or 3 but ' + tagDim + ' was given!\n')
        elems = np.zeros((_elems.GetNumberOfTuples() // (nV+1), nV), dtype=int)
        for i in range(0, elems.shape[0]):
                for j in range(0, nV):
                    elems[i][j] = _elems.GetTuple((nV+1)*i+j+1)[0]
        # transfer variables
        vals = {}
        for name in vname:
            if atPoint: # data at points
                _vals =  cutData.GetPointData().GetArray(name)
            else: # data at elements
                _vals =  cutData.GetCellData().GetArray(name)
            vals[name] = np.zeros((_vals.GetNumberOfTuples(), _vals.GetNumberOfComponents()))
            for i in range(0, vals[name].shape[0]):
                for j in range(0, vals[name].shape[1]):
                    vals[name][i][j] = _vals.GetTuple(i)[j]
        return pts, elems, vals