# RCAIDE/Library/Methods/Geometry/LOPA/LOPA_functions.py
#
#
# Created: Mar 2025, M. Clarke
# ----------------------------------------------------------------------------------------------------------------------
# IMPORT
# ----------------------------------------------------------------------------------------------------------------------
# RCAIDE imports
import RCAIDE
from RCAIDE.Framework.Core import Data
from .LOPA_functions import *
# python functions
import numpy as np
from copy import deepcopy
# ----------------------------------------------------------------------------------------------------------------------
# compute_layout_of_passenger_accommodations
# ----------------------------------------------------------------------------------------------------------------------
[docs]
def compute_layout_of_passenger_accommodations(fuselage):
'''
Creates the layout of passenger accommodations for a vehicle
'''
# lopa of entire vehicle
LOPA = np.empty(( 0, 14))
lopa_origin_x = []
lopa_origin_y = []
lopa_origin_z = []
if len(fuselage.cabins) > 0:
# instantiate dimension of LOPA container
# [ x, y, z , length, width, first-cl flag, business-cl flag, economy-cl flag, seat, emergency-row flag, galley/lav flag, type-A exit flag]
side_cabin_offset = 0
for cabin in fuselage.cabins:
# create empty data structures
cabin_LOPA = np.empty(( 0, 14))
cabin_number_of_seats = 0
cabin_class_origin = [0, 0, 0]
total_cabin_length = 0
# loop through cabin classes
for cabin_class in cabin.classes:
# compute LOPA
seat_data ,cabin_class_origin,cabin_number_of_seats,total_cabin_length = create_class_seating_map_layout(cabin, cabin_class,cabin_class_origin, side_cabin_offset,cabin_number_of_seats,total_cabin_length)
# determine offset if a side cabin (i.e. for a BWB) is defined
side_cabin_offset = cabin.width / 2
# append to cabin LOPA data structure
cabin_LOPA = np.vstack((cabin_LOPA,seat_data))
# apply cabin origin offset to seat coordinates (x, y, z)
if len(cabin_LOPA) > 0:
cabin_LOPA[:, 2] += cabin.origin[0][0]
cabin_LOPA[:, 3] += cabin.origin[0][1]
cabin_LOPA[:, 4] += cabin.origin[0][2]
# append to entire vehicle LOPA data structure
LOPA = np.vstack((LOPA, cabin_LOPA))
# store cabin LOPA onto cabin data structure
cabin.layout_of_passenger_accommodations = Data()
cabin.layout_of_passenger_accommodations.object_coordinates = cabin_LOPA
# store cabin properties
cabin.length = total_cabin_length
cabin.number_of_seats = cabin_number_of_seats
# determine offset of LOPA from reference point on aircraft (nose)
for cabin in fuselage.cabins:
for cabin_class in cabin.classes:
cabin_class.percentage = cabin_class.length/cabin.length
if LOPA.size > 0 :
fuselage.number_of_seats = np.sum(LOPA[:,10])
fuselage.layout_of_passenger_accommodations = Data()
fuselage.layout_of_passenger_accommodations.object_coordinates = LOPA
fuselage.layout_of_passenger_accommodations.origin = [[0, 0, 0]]
compute_lopa_properties(fuselage, LOPA)
return
[docs]
def compute_lopa_properties(fuselage, LOPA):
# Step 1: plot cabin bounds
# get points at x min
x_min_locs = np.where( LOPA[:,2] == min(LOPA[:,2]))[0]
x_min = LOPA[x_min_locs[0],2] - LOPA[x_min_locs[0],5]/2
x_min_y_max = max(LOPA[x_min_locs,3] + LOPA[x_min_locs,6]/2 )
x_min_y_min = min(LOPA[x_min_locs,3] - LOPA[x_min_locs,6]/2 )
x_border_pts = [x_min, x_min]
y_border_pts = [x_min_y_min, x_min_y_max]
# get points at y max
y_max_locs = np.where( LOPA[:,3] == max(LOPA[:,3]))[0]
y_max = LOPA[y_max_locs[0],3] + LOPA[y_max_locs[0],6]/2
y_max_x_max = max(LOPA[y_max_locs,2] + LOPA[y_max_locs[0],5]/2)
y_max_x_min = min(LOPA[y_max_locs,2] - LOPA[y_max_locs[0],5]/2)
x_border_pts.append(y_max_x_min)
x_border_pts.append(y_max_x_max)
y_border_pts.append(y_max)
y_border_pts.append(y_max)
# get points at x max
x_max_locs = np.where( LOPA[:,2] == max(LOPA[:,2]))[0]
x_max = LOPA[x_max_locs[0],2] + LOPA[x_max_locs[0],5]/2
x_max_y_max = max(LOPA[x_max_locs,3] + LOPA[x_max_locs,6]/2)
x_max_y_min = min(LOPA[x_max_locs,3] - LOPA[x_max_locs,6]/2)
x_border_pts.append(x_max)
x_border_pts.append(x_max)
y_border_pts.append(x_max_y_max)
y_border_pts.append(x_max_y_min)
# get points at y min
y_min_locs = np.where( LOPA[:,3] == min(LOPA[:,3]))[0]
y_min = LOPA[y_min_locs[0],3] - LOPA[y_min_locs[0],6]/2
y_min_x_max = max(LOPA[y_min_locs,2] + LOPA[y_min_locs[0],5]/2)
y_min_x_min = min(LOPA[y_min_locs,2] - LOPA[y_min_locs[0],5]/2)
x_border_pts.append(y_min_x_max)
x_border_pts.append(y_min_x_min)
y_border_pts.append(y_min)
y_border_pts.append(y_min)
# loop through points and determine if there are duplicates
y_border_pts = np.array(y_border_pts)
x_border_pts = np.array(x_border_pts)
# cut where y is negative
port_idxs = np.where(y_border_pts<0)[0]
starboard_x_points = np.delete(x_border_pts, port_idxs)
starboard_y_points = np.delete(y_border_pts, port_idxs)
fuselage.layout_of_passenger_accommodations.cabin_area_coordinates = np.vstack((starboard_x_points[None,:],starboard_y_points[None, :])).T
fuselage.layout_of_passenger_accommodations.cabin_length = max(starboard_x_points)
fuselage.layout_of_passenger_accommodations.cabin_width = 2*max(starboard_y_points)
return
[docs]
def create_class_seating_map_layout(cabin,cabin_class,cabin_class_origin, side_cabin_offset,cabin_number_of_seats,cabin_length):
s_y_coord, cabin_class_origin = get_seat_y_coords(cabin, cabin_class,cabin_class_origin)
s_x_coord,object_type, cabin_class_origin,cabin_length = get_seat_x_coords(cabin, cabin_class,cabin_class_origin,cabin_length)
# concatenate arrays
length = cabin_class.seat_length * np.ones_like(s_x_coord)
length[object_type[:,2] == 1] = cabin.galley_lavatory_length
length[object_type[:,3] == 1] = cabin.type_A_door_length
X_coords = np.atleast_2d((np.tile(s_x_coord[:,None], (1, len(s_y_coord)))).flatten()).T
Y_coords = np.atleast_2d((np.tile(s_y_coord[None,:], (len(s_x_coord), 1))).flatten()).T
Z_coords = np.atleast_2d((np.zeros_like(Y_coords)).flatten()).T
length = np.atleast_2d((np.tile(length[:,None], (1, len(s_y_coord)))).flatten()).T
width = cabin_class.seat_width * np.ones_like(Z_coords)
n_rows = cabin_class.number_of_rows * np.ones_like(Z_coords)
n_seats_y = cabin_class.number_of_seats_abrest * np.ones_like(Z_coords)
object_vec = np.repeat(object_type, len(s_y_coord), axis=0)
# cabin class flags
F_c = np.zeros_like(Z_coords)
B_c = np.zeros_like(Z_coords)
E_c = np.zeros_like(Z_coords)
if type(cabin_class) == RCAIDE.Library.Components.Fuselages.Cabins.Classes.First:
F_c = np.ones_like(Z_coords)
elif type(cabin_class) == RCAIDE.Library.Components.Fuselages.Cabins.Classes.Business:
B_c = np.ones_like(Z_coords)
elif type(cabin_class) == RCAIDE.Library.Components.Fuselages.Cabins.Classes.Economy:
E_c = np.ones_like(Z_coords)
# [n_rows , n_seats_y, x, y, z , length, width, first-cl flag, business-cl flag, economy-cl flag, [seat, emergency-row flag, galley/lav flag, type-A exit flag]]
seat_data = np.hstack((n_rows , n_seats_y, X_coords,Y_coords, Z_coords, length ,width,F_c,B_c,E_c,object_vec))
if type(cabin) == RCAIDE.Library.Components.Fuselages.Cabins.Side_Cabin:
seat_data[:, 3] += cabin.width / 2
seat_data = update_seat_map_layout_using_cabin_taper(seat_data,cabin)
seat_data[:, 3] += side_cabin_offset + cabin_class.y_offset_distance
# make copy about center
seat_data_ = deepcopy(seat_data)
seat_data_[:, 3] *= -1
seat_data = np.vstack((seat_data,seat_data_))
cabin_class.number_of_seats = int(np.sum(seat_data[:,10]))
cabin_number_of_seats += int(cabin_class.number_of_seats)
return seat_data ,cabin_class_origin,cabin_number_of_seats,cabin_length