### ===================================================================================================================
### viia_find_min_max_z
### ===================================================================================================================
# Copyright ©VIIA 2024
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
import math
from typing import List
# References for functions and classes in the rhdhv_fem package
from rhdhv_fem.fem_math import fem_unit_vector, fem_greater, fem_smaller
### ===================================================================================================================
### 2. Function to find the minimum and maxium z coordinates of the intersections
### ===================================================================================================================
[docs]def viia_find_min_max_z(plane_points: List[List[float]], point: List[float]):
"""
This function returns the intersections of a vertical line through a vertical plane. The plane (wall) may be angled
in x- and y- direction. The shape of the plane is free to chose, as long as it is vertical.
Input:
- plane_points (list with lists of 3 floats): The sorted points of a given plane. Coordinates in x-, y- and z-
directionm e.g. [[0,1,2],[2,3,4],[3,6,4], etc.
- point (list with 3 floats): The coordinates (x,y,z) of the requested point where vertical section is made.
The z-coordinate is not used. For example: [0.1, 0.3, 2.3]
Output:
The z-coordinates of intersections are returned as list. Should always be an even number.
For example:
>>> viia_find_min_max_z([[0.0, 0.0, -0.175], [0.0, 0.0, 2.325], [0.0, 5.0, 4.325], [0.0, 5.0, 1.825]], [0, 5])
Returns the list: [[4.325], [1.8250000000000002]]
"""
# The first found vector in x- and y- directions from the first point of the plane, determines the direction of the
# line in x- and y- projection of the plane. If the second point is vertically above the first point, the next point
# will be evaluated, etc.
for i in range(1, len(plane_points)):
deltaX0 = plane_points[i][0] - plane_points[i - 1][0]
deltaY0 = plane_points[i][1] - plane_points[i - 1][1]
r = math.sqrt(deltaX0*deltaX0 + deltaY0*deltaY0)
if r != 0:
break
# Following the contour of the plane, the delta-functions are saved in a list
Zfunctions = []
for i in range(0, len(plane_points)):
if i == len(plane_points)-1:
deltaX = plane_points[0][0] - plane_points[i][0]
deltaY = plane_points[0][1] - plane_points[i][1]
deltaZ = plane_points[0][2] - plane_points[i][2]
else:
deltaX = plane_points[i + 1][0] - plane_points[i][0]
deltaY = plane_points[i + 1][1] - plane_points[i][1]
deltaZ = plane_points[i + 1][2] - plane_points[i][2]
if deltaX0 == 0:
Zfunctions.append([deltaY/deltaY0 * r, deltaZ])
else:
Zfunctions.append([deltaX/deltaX0 * r, deltaZ])
### ADDED BY ROB, CHECK WORKING ###
# Check if Zfunctions contains consecutive functions with the same direction
# Add these up, otherwise one intersection can be found twice, when it is exactly at the point where two functions
# coincide
# Initiate counter to count number of merged functions
mergecounter = 0
for i in range(len(Zfunctions)):
if i-mergecounter == len(Zfunctions) - 1:
# Compute unit vectors of consecutive functions
uv1 = fem_unit_vector(Zfunctions[i-mergecounter])
uv2 = fem_unit_vector(Zfunctions[0])
# If equal, functions can be merged
if uv1 == uv2:
# Add both functions up in Zfunction
Zfunction = []
Zfunction.append(Zfunctions[i-mergecounter][0] + Zfunctions[0][0])
Zfunction.append(Zfunctions[i-mergecounter][1] + Zfunctions[0][1])
# Replace first function
Zfunctions[i-mergecounter] = Zfunction
# Delete second function
del Zfunctions[0]
# Update counter
mergecounter += 1
else:
uv1 = fem_unit_vector(Zfunctions[i-mergecounter])
uv2 = fem_unit_vector(Zfunctions[i-mergecounter+1])
if uv1 == uv2:
Zfunction = []
Zfunction.append(Zfunctions[i-mergecounter][0] + Zfunctions[i-mergecounter+1][0])
Zfunction.append(Zfunctions[i-mergecounter][1] + Zfunctions[i-mergecounter+1][1])
Zfunctions[i-mergecounter] = Zfunction
del Zfunctions[i-mergecounter+1]
mergecounter += 1
### ADDED BY ROB, CHECK WORKING ###
# Determine the requested coordinate on the line of the projection of the wall in x- and y-direction.
# This direction is called r in this function.
deltaX = point[0] - plane_points[0][0]
deltaY = point[1] - plane_points[0][1]
if deltaX0 == 0:
rc = deltaY/deltaY0 * r
else:
rc = deltaX/deltaX0 * r
# Following the contour of the plane, it is checked if the r-coordinate is defined in the delta-functions.
Intersections = []
r = 0
z = plane_points[0][2]
for i in range(len(Zfunctions)):
if fem_smaller(r, rc) and fem_smaller(rc, r + Zfunctions[i][0]):
if Zfunctions[i][0] != 0:
zc = z + Zfunctions[i][1]*(rc - r)/Zfunctions[i][0]
Intersections.append(zc)
if fem_greater(r, rc) and fem_greater(rc, r + Zfunctions[i][0]):
if Zfunctions[i][0] != 0:
zc = z + Zfunctions[i][1]*(r - rc)/-Zfunctions[i][0]
Intersections.append(zc)
r = r + Zfunctions[i][0]
z = z + Zfunctions[i][1]
# The intersections are returned as list (should be even number)
return Intersections
### ===================================================================================================================
### 3. End of script
### ===================================================================================================================