projection_pointXYZ.py 3.65 KiB
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import copy

import numpy as np
import pandas as pd
from time import time

from Model.Geometry import PointXYZ
from Model.Geometry.ProfileXYZ import ProfileXYZ
from Model.Geometry.vector_1d import Vector1d


def update_station(list_header, list_point_xyz):
    profile = ProfileXYZ(list_header, list_point_xyz)
    if profile.nb_points >= 3:
        return get_station(profile)
    else:
        pass


def get_station(profile: ProfileXYZ) -> np.ndarray:
    """Projection of the points of the profile on a plane.

    Args:
        profile: The profile

    Returns:
        Projection of the points of the profile on a plane.
    """
    if profile.nb_points >= 3:
        first_named_point = None
        index_first_named_point = None
        last_named_point = None

        for index, point in enumerate(profile.points):
            if point.point_is_named():
                index_first_named_point = index
                first_named_point = point
                break

        for point in profile.points[::-1]:
            if point.point_is_named():
                last_named_point = point
                break

        station = []  # abscisse en travers
        constant = 0.0  # constante pour décaler l'origine de l'ascisse en travers caluculée.

        if (first_named_point is not None) and (last_named_point is not None):
            if first_named_point != last_named_point and first_named_point.x != last_named_point.x:
                vector = Vector1d(first_named_point, last_named_point)
                normalized_direction_vec = vector.normalized_direction_vector()
            else:
                vector = Vector1d(_first_point_not_nan(profile), _last_point_not_nan(profile))
                normalized_direction_vec = vector.normalized_direction_vector()

            for point in profile.points:
                xi = point.x - first_named_point.x
                yi = point.y - first_named_point.y
                station_i = normalized_direction_vec[0] * xi + normalized_direction_vec[1] * yi
                station.append(station_i)

            station = np.array(station)

            constant = station[index_first_named_point]  # pour placer l'origine au premier point nomme.
        elif first_named_point is None:
            vector = Vector1d(_first_point_not_nan(profile), _last_point_not_nan(profile))
            normalized_direction_vec = vector.normalized_direction_vector()

            for point in profile.points:
                xi = point.x - _first_point_not_nan(profile).x
                yi = point.y - _first_point_not_nan(profile).y
                station_i = normalized_direction_vec[0] * xi + normalized_direction_vec[1] * yi
                station.append(station_i)

            station = np.array(station)
            index_profile_z_min = np.where(np.array(profile.z) == profile.z_min)[0][0]
            constant = station[index_profile_z_min]  # pour placer l'origine au fond ie à la cote minimale
            # z_min du profil.
        station = station - constant

        return station
    else:
        return np.array(np.nan)

def _point_is_nan(point: PointXYZ):
    return pd.isna(point.x) or pd.isna(point.y) or pd.isna(point.z)

def _first_point_not_nan(profile: ProfileXYZ):
    first_point_not_nan = profile.points[0]

    for point in profile.points:
        if not _point_is_nan(point):
            first_point_not_nan = point
            break

    return first_point_not_nan

def _last_point_not_nan(profile: ProfileXYZ):
    last_point = profile.points[-1]

    for point in profile.points[::-1]:
        if not _point_is_nan(point):
            last_point = point
            break

    return last_point