Skip to content
Snippets Groups Projects
pointcloud_methods.py 6.52 KiB
Newer Older
import numpy as np
import pyvista as pv

from ntrfc.utils.geometry.alphashape import calc_concavehull
from ntrfc.utils.math.vectorcalc import  vecAngle, vecAbs, findNearest
from ntrfc.utils.pyvista_utils.line import polyline_from_points, refine_spline
from ntrfc.utils.geometry.profile_tele_extraction import extract_vk_hk
def mid_length(ind_1, ind_2, sorted_poly):
    calc length of a midline. currently only used in the iterative computation of LE and TE index of a profile. probably
    this method is not necessary, as it is only two lines
    :param ind_1: index LE
    :param ind_2: index TE
    :param sorted_poly: pv.PolyData sorted
    :return: length
    """
many's avatar
many committed
    ps_poly, ss_poly = extractSidePolys(ind_1, ind_2, sorted_poly)
    mids_poly = midline_from_sides(ps_poly, ss_poly)
    return mids_poly.length
Malte Nyhuis's avatar
Malte Nyhuis committed

def midline_from_sides(ps_poly, ss_poly):
    x_ps, y_ps = ps_poly.points[::, 0], ps_poly.points[::, 1]
    x_ss, y_ss = ss_poly.points[::, 0], ss_poly.points[::, 1]
    z = ps_poly.points[0][2]
many's avatar
many committed
    midsres = 100
        ax, ay = refine_spline(x_ps[::-1], y_ps[::-1], midsres)
    else:
        ax, ay = refine_spline(x_ps, y_ps, midsres)
        bx, by = refine_spline(x_ss[::-1], y_ss[::-1], midsres)
    else:
        bx, by = refine_spline(x_ss, y_ss, midsres)
    xmids, ymids = ((ax + bx) / 2, (ay + by) / 2)
    midsPoly = polyline_from_points(np.stack((xmids, ymids, z*np.ones(len(ymids)))).T)
many's avatar
many committed
def extractSidePolys(ind_1, ind_2, sortedPoly,verbose=False):
    # xs, ys = list(sortedPoly.points[::, 0]), list(sortedPoly.points[::, 1])
    indices = np.arange(0, sortedPoly.number_of_points)

    if ind_2 > ind_1:
        side_one_idx = indices[ind_1:ind_2+1]
        side_two_idx = np.concatenate((indices[:ind_1+1][::-1], indices[ind_2:][::-1]))
    elif ind_1 > ind_2:
        side_one_idx = indices[ind_2:ind_1+1]
        side_two_idx = np.concatenate((indices[:ind_2+1][::-1], indices[ind_1:][::-1]))

    side_one = extract_points_fromsortedpoly(side_one_idx, sortedPoly)
    side_two = extract_points_fromsortedpoly(side_two_idx, sortedPoly)
    side_one_spline = polyline_from_points(side_one.points)
    side_two_spline = polyline_from_points(side_two.points)
    if side_one_spline.length > side_two_spline.length:
        psPoly = side_two
        ssPoly = side_one
        psPoly = side_one
        ssPoly = side_two
many's avatar
many committed
    if verbose:
        p = pv.Plotter()
        p.add_mesh(ssPoly,color="g",label="ssPoly")
        p.add_mesh(psPoly,color="b",label="psPoly")
        p.add_mesh(sortedPoly.points[ind_1], color="w",label="ind_1")
        p.add_mesh(sortedPoly.points[ind_2], color="k",label="ind_2")
        p.add_legend()
        p.show()

    return ssPoly, psPoly
def extract_points_fromsortedpoly(sorted_indices, sorted_poly):
    side_two = pv.PolyData(sorted_poly.points[sorted_indices])  # polyblade.extract_cells(index_sort)
    for arr in sorted_poly.array_names:
        side_two[arr] = sorted_poly.point_data[arr][sorted_indices]
def extract_geo_paras(polyblade, alpha, verbose=False):
    """
    This function is extracting profile-data as stagger-angle, midline, psPoly, ssPoly and more from a set of points
    Be careful, you need a suitable alpha-parameter in order to get the right geometry
    The calculation of the leading-edge and trailing-edge index needs time and its not 100% reliable (yet)
    Keep in mind, to check the results!
    :param polyblade: pyvista polymesh of the blade
    :param alpha: nondimensional alpha-coefficient (calcConcaveHull)
    :param verbose: bool for plots
many's avatar
many committed
    :return: points, psPoly, ssPoly, ind_vk_, ind_vk, midsPoly, beta_leading, beta_trailing
    points = polyblade.points
    xs, ys = calc_concavehull(points[:, 0], points[:, 1], alpha)

    index_sort = [np.where(points[:, 0] == xs[i])[0][0] for i in range(len(xs)) if
many's avatar
many committed
                  len(np.where(points[:, 0] == xs[i])) == 1 and np.where(points[:, 0] == xs[i])[0][0] == np.where(
                      points[:, 1] == ys[i])[0][0]]

    sortedPoly = pv.PolyData(polyblade.points[index_sort])  # polyblade.extract_cells(index_sort)
    for arr in polyblade.array_names:
        if sortedPoly.number_of_points==len(polyblade[arr]):
            sortedPoly[arr]=polyblade.point_data[arr][index_sort]
    ind_hk, ind_vk = extract_vk_hk(sortedPoly)
    psPoly, ssPoly = extractSidePolys(ind_hk, ind_vk, sortedPoly)
    midsPoly = midline_from_sides(psPoly, ssPoly)
    # compute angles from 2d-midline
    xmids, ymids = midsPoly.points[::, 0], midsPoly.points[::, 1]
    vk_tangent = np.stack((xmids[0] - xmids[1], ymids[0] - ymids[1], 0)).T
    hk_tangent = np.stack((xmids[-2] - xmids[-1], ymids[-2] - ymids[-1], 0)).T
    chord = psPoly.points[0]-psPoly.points[-1]
    beta_leading = vecAngle(vk_tangent, -np.array([1, 0, 0])) / np.pi * 180
    beta_trailing = vecAngle(hk_tangent, -np.array([1, 0, 0])) / np.pi * 180
    camber_angle = vecAngle(chord, -np.array([1, 0, 0])) / np.pi * 180

    if verbose:
        p = pv.Plotter()
        p.add_mesh(points, color="orange", label="points")
        p.add_mesh(psPoly, color="green", label="psPoly")
        p.add_mesh(ssPoly, color="black", label="ssPoly")
        p.add_mesh(midsPoly, color="black", label="midsPoly")
        p.add_mesh(pv.Line((0, 0, 0), (midsPoly.length, 0, 0)))
        p.add_mesh(sortedPoly.points[ind_hk],color="red",point_size=5)
        p.add_mesh(sortedPoly.points[ind_vk],color="orange",point_size=5)
many's avatar
many committed
    return sortedPoly, psPoly, ssPoly, ind_vk, ind_hk, midsPoly, beta_leading, beta_trailing, camber_angle


def calcMidPassageStreamLine(x_mcl, y_mcl, beta1, beta2, x_inlet, x_outlet, t):
    """
    Returns two lists of Points representing a curve through the passage


    Input:
    x_mcl, y_mcl = Tuple
    beta1, beta2 = Angle in deg - Beta = Anströmwinkel
    x_inlet, x_outlet = scalar - representing position x-component of in/outlet
    t = scalar pitch
    """

    delta_x_vk = x_mcl[0] - x_inlet
    delta_y_vk = np.tan(np.deg2rad(beta1 - 90)) * delta_x_vk

    p_inlet_x = x_mcl[0] - delta_x_vk
    p_inlet_y = y_mcl[0] - delta_y_vk

    delta_x_hk = x_outlet - x_mcl[-1]
    delta_y_hk = delta_x_hk * np.tan(np.deg2rad(beta2 - 90))

    p_outlet_x = x_mcl[-1] + delta_x_hk
    p_outlet_y = y_mcl[-1] + delta_y_hk

    x_mpsl = [p_inlet_x] + list(x_mcl) + [p_outlet_x]
    y_mpsl = [p_inlet_y] + list(y_mcl) + [p_outlet_y]

    for i in range(len(x_mpsl)):
        y_mpsl[i] = y_mpsl[i] + 0.5 * t

    return refine_spline(x_mpsl, y_mpsl, 1000)