bluemira.geometry.coordinates ============================= .. py:module:: bluemira.geometry.coordinates .. autoapi-nested-parse:: Utility for sets of coordinates Attributes ---------- .. autoapisummary:: bluemira.geometry.coordinates.DIM Classes ------- .. autoapisummary:: bluemira.geometry.coordinates.RotationAxis bluemira.geometry.coordinates.Coordinates Functions --------- .. autoapisummary:: bluemira.geometry.coordinates.xyz_process bluemira.geometry.coordinates._validate_coordinates bluemira.geometry.coordinates.vector_lengthnorm bluemira.geometry.coordinates.interpolate_points bluemira.geometry.coordinates._interpolate_points bluemira.geometry.coordinates.interpolate_midpoints bluemira.geometry.coordinates.get_normal_vector bluemira.geometry.coordinates.get_perimeter bluemira.geometry.coordinates.get_perimeter_2d bluemira.geometry.coordinates.get_perimeter_3d bluemira.geometry.coordinates._get_perim_3d bluemira.geometry.coordinates.get_area bluemira.geometry.coordinates.get_area_2d bluemira.geometry.coordinates.get_area_3d bluemira.geometry.coordinates.check_ccw bluemira.geometry.coordinates.check_ccw_3d bluemira.geometry.coordinates.get_centroid bluemira.geometry.coordinates.get_centroid_2d bluemira.geometry.coordinates.get_centroid_3d bluemira.geometry.coordinates.get_angle_between_points bluemira.geometry.coordinates.get_angle_between_vectors bluemira.geometry.coordinates.rotation_matrix bluemira.geometry.coordinates.rotation_matrix_v1v2 bluemira.geometry.coordinates.project_point_axis bluemira.geometry.coordinates.principal_components bluemira.geometry.coordinates.check_linesegment bluemira.geometry.coordinates.in_polygon bluemira.geometry.coordinates.polygon_in_polygon bluemira.geometry.coordinates.on_polygon bluemira.geometry.coordinates.normal_vector bluemira.geometry.coordinates.vector_intersect bluemira.geometry.coordinates.get_bisection_line bluemira.geometry.coordinates._parse_to_xyz_array bluemira.geometry.coordinates._parse_array bluemira.geometry.coordinates._parse_dict bluemira.geometry.coordinates.vector_intersect_3d bluemira.geometry.coordinates.coords_plane_intersect bluemira.geometry.coordinates._coords_plane_intersect bluemira.geometry.coordinates.get_intersect bluemira.geometry.coordinates._intersect_count bluemira.geometry.coordinates.join_intersect bluemira.geometry.coordinates.convex_2d_hull_coordinates bluemira.geometry.coordinates.choose_direction Module Contents --------------- .. py:data:: DIM :value: 3 .. py:class:: RotationAxis(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: bluemira.geometry.coordinates.RotationAxis :parts: 1 :private-bases: Enumeration of rotation axes. .. py:attribute:: X .. py:attribute:: Y .. py:attribute:: Z .. py:method:: _missing_(value: str | RotationAxis) -> RotationAxis :classmethod: .. py:function:: xyz_process(func) Decorator for parsing x, y, z coordinates to numpy float arrays and dimension checking. :returns: Decorator for parsing x, y, z coordinates to numpy float arrays and dimension checking. .. py:function:: _validate_coordinates(x, y, z=None) .. py:function:: vector_lengthnorm(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray | None = None) -> numpy.ndarray Get a normalised 1-D parameterisation of a set of x-y(-z) coordinates. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates. If None, carries out the operation in 2-D :rtype: The normalised length vector .. rubric:: Notes The normalized length vector is: .. math:: \text{Normalized Length} = \frac{L}{L[-1]} where .. math:: L = \sum_{i=0}^{n-1} \sqrt{(\Delta x_i)^2 + (\Delta y_i)^2 + (\Delta z_i)^2} Where :math:`\Delta x_i`, :math:`\Delta y_i`, and :math:`\Delta z_i` are the finite differences along the x, y, and z dimensions, respectively for the i-th index. n is the length of the array of coordinates. .. py:function:: interpolate_points(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray, n_points: int) -> tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] Interpolate points. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates :param n_points: number of points :returns: * *x* -- The interpolated x coordinates * *y* -- The interpolated y coordinates * *z* -- The interpolated z coordinates .. py:function:: _interpolate_points(linterp, x, y, z) -> tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] .. py:function:: interpolate_midpoints(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray) -> tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] Interpolate the points adding the midpoint of each segment to the points. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates :returns: * *x* -- The interpolated x coordinates * *y* -- The interpolated y coordinates * *z* -- The interpolated z coordinates .. py:function:: get_normal_vector(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray) -> numpy.ndarray Calculate the normal vector from a series of planar points. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates :rtype: The normalised normal vector :raises CoordinatesError: Cannot find normal vector or arrays not of equal length >= 3 .. py:function:: get_perimeter(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray | None = None) -> float Calculate the perimeter of a set of coordinates. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates :rtype: The perimeter of the coordinates .. py:function:: get_perimeter_2d(x: numpy.ndarray, y: numpy.ndarray) -> float Calculate the perimeter of a 2-D set of coordinates. :param x: The x coordinates :param y: The y coordinates :rtype: The perimeter of the coordinates .. py:function:: get_perimeter_3d(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray) -> float Calculate the perimeter of a set of 3-D coordinates. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates :rtype: The perimeter of the coordinates .. py:function:: _get_perim_3d(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray) -> float Calculate the perimeter of a set of 3-D coordinates. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates :rtype: The perimeter of the coordinates .. py:function:: get_area(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray | None = None) -> float Calculate the area inside a closed polygon with x, y coordinate vectors. `Link Shoelace method `_ :param x: The first set of coordinates [m] :param y: The second set of coordinates [m] :param z: The third set of coordinates or None (for a 2-D polygon) :rtype: The area of the polygon [m^2] .. py:function:: get_area_2d(x: numpy.ndarray, y: numpy.ndarray) -> float Calculate the area inside a closed polygon with x, y coordinate vectors. `Link Shoelace method `_ :param x: The first set of coordinates [m] :param y: The second set of coordinates [m] :rtype: The area of the polygon [m^2] .. py:function:: get_area_3d(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray) -> float Calculate the area inside a closed polygon. `Link Shoelace method `_ :param x: The first set of coordinates [m] :param y: The second set of coordinates [m] :param z: The third set of coordinates [m] :rtype: The area of the polygon [m^2] .. py:function:: check_ccw(x: numpy.ndarray, z: numpy.ndarray) -> bool Check that a set of x, z coordinates are counter-clockwise. :param x: The x coordinates of the polygon :param z: The z coordinates of the polygon :rtype: True if polygon counterclockwise .. py:function:: check_ccw_3d(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray, normal: numpy.ndarray) -> bool Check if a set of coordinates is counter-clockwise w.r.t a normal vector. :param x: The first set of coordinates [m] :param y: The second set of coordinates [m] :param z: The third set of coordinates [m] :param normal: The normal vector about which to check for CCW :rtype: Whether or not the set is CCW about the normal vector .. py:function:: get_centroid(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray | None = None) -> numpy.ndarray Calculate the centroid of a non-self-intersecting 2-D counter-clockwise polygon. :param x: x coordinates of the coordinates to calculate on :param y: y coordinates of the coordinates to calculate on :param z: z coordinates of the coordinates to calculate on :rtype: The x, y, [z] coordinates of the centroid [m] .. py:function:: get_centroid_2d(x: numpy.ndarray, z: numpy.ndarray) -> list[float] Calculate the centroid of a non-self-intersecting 2-D counter-clockwise polygon. :param x: x coordinates of the coordinates to calculate on :param z: z coordinates of the coordinates to calculate on :rtype: The x, z coordinates of the centroid [m] .. py:function:: get_centroid_3d(x: numpy.ndarray, y: numpy.ndarray, z: numpy.ndarray) -> list[float] Calculate the centroid of a non-self-intersecting counterclockwise polygon in 3-D. :param x: The x coordinates :param y: The y coordinates :param z: The z coordinates :rtype: The x, y, z coordinates of the centroid [m] .. py:function:: get_angle_between_points(p0: numpy.ndarray, p1: numpy.ndarray, p2: numpy.ndarray) -> float Angle between points. P1 is vertex of angle. ONly tested in 2d :returns: The angle between points. .. py:function:: get_angle_between_vectors(v1: numpy.ndarray, v2: numpy.ndarray, *, signed: bool = False) -> float Angle between vectors. Will return the signed angle if specified. :param v1: The first vector :param v2: The second vector :param signed: Whether or not to calculate the signed angle :rtype: The angle between the vectors [radians] .. py:function:: rotation_matrix(theta: float, axis: str | RotationAxis | numpy.ndarray = RotationAxis.Z) -> numpy.ndarray Old-fashioned rotation matrix: :math:`\mathbf{R_{u}}(\theta)` :math:`\mathbf{x^{'}}=\mathbf{R_{u}}(\theta)\mathbf{x}` :math:`\mathbf{R_{u}}(\theta)=cos(\theta)\mathbf{I}+sin(\theta)[\mathbf{u}]_{\times}(1-cos(\theta))(\mathbf{u}\otimes\mathbf{u})` :param theta: The rotation angle [radians] (counter-clockwise about axis!) :param axis: The rotation axis (specified by axis label or vector) :rtype: The (active) rotation matrix about the axis for an angle theta .. py:function:: rotation_matrix_v1v2(v1: numpy.ndarray, v2: numpy.ndarray) -> numpy.ndarray Get a rotation matrix based off two vectors. :returns: A roational matrix based off two vectors. .. py:function:: project_point_axis(point: numpy.typing.ArrayLike, axis: numpy.typing.ArrayLike) -> numpy.ndarray Project a 3-D point onto a 3-D axis. :math:`\mathbf{p_{proj}} = \dfrac{\mathbf{p}\cdot\mathbf{a}}{\mathbf{a}\cdot\mathbf{a}}\mathbf{a}` :param point: The point to project onto the axis :param axis: The axis onto which to project the point :rtype: The coordinates of the projected point .. py:function:: principal_components(xyz_array: numpy.ndarray) -> tuple[numpy.ndarray, numpy.ndarray] Principal component analysis. :returns: Eigenvalues and eigenvectors or an xyz array. .. py:function:: check_linesegment(point_a: numpy.ndarray, point_b: numpy.ndarray, point_c: numpy.ndarray) -> bool Check that point C is on the line between points A and B. :param point_a: The first line segment 2-D point :param point_b: The second line segment 2-D point :param point_c: The 2-D point which to check is on A--B :returns: **True** :rtype: if C on A--B, else False .. py:function:: in_polygon(x: float, z: float, poly: numpy.ndarray, include_edges: bool = False) -> bool Determine if a point (x, z) is inside a 2-D polygon. :param x: Point x coordinate :param z: Point z coordinate :param poly: The 2-D array of polygon point coordinates :param include_edges: Whether or not to return True if a point is on the perimeter of the polygon :rtype: Whether or not the point is in the polygon .. py:function:: polygon_in_polygon(poly1: numpy.ndarray, poly2: numpy.ndarray, include_edges: bool = False) -> numpy.ndarray Determine what points of a 2-D polygon are inside another 2-D polygon. :param poly1: The array of 2-D polygon1 point coordinates :param poly2: The array of 2-D polygon2 point coordinates :param include_edges: Whether or not to return True if a point is on the perimeter of the polygon :rtype: The array of boolean values per index of polygon1 .. py:function:: on_polygon(x: float, z: float, poly: numpy.typing.NDArray[numpy.float64]) -> bool Determine if a point (x, z) is on the perimeter of a closed 2-D polygon. :param x: Point x coordinate :param z: Point z coordinate :param poly: The array of 2-D polygon point coordinates :rtype: Whether or not the point is on the perimeter of the polygon .. py:function:: normal_vector(side_vectors: numpy.ndarray) -> numpy.ndarray Find the anti-clockwise normal vector to the given side vectors. :param side_vectors: The side vectors of a polygon (shape: (2, N)). :returns: * *The array of 2-D normal vectors of each side of a polygon* * **(shape** (*(2, N)).*) .. rubric:: Notes The normal vector `a` is calculated using the formula: .. math:: \mathbf{a} = -\frac{-[\mathbf{v}[1],~ \mathbf{v}[0]]}{\sqrt{\mathbf{v}[0]^2~ + \mathbf{v}[1]^2}} where :math:`\mathbf{v}` are the side vectors. .. py:function:: vector_intersect(p1: numpy.ndarray, p2: numpy.ndarray, p3: numpy.ndarray, p4: numpy.ndarray) -> numpy.ndarray Get the intersection point between two 2-D vectors. :param p1: The first point on the first vector (shape: (2,)). :param p2: The second point on the first vector (shape: (2,)). :param p3: The first point on the second vector (shape: (2,)). :param p4: The second point on the second vector (shape: (2,)). :returns: **The point of the intersection between the two vectors (shape** :rtype: (2,)). .. rubric:: Notes If the vectors are parallel: - The vectors do not intersect. - The function returns p2 Otherwise: - Calculates the intersection point using vector algebra: .. math:: \text{point} = \frac{ \lVert \mathbf{p2} - \mathbf{p1} \rVert~ \cdot (\mathbf{p1} - \mathbf{p3}) }{ \lVert \mathbf{p2} - \mathbf{p1} \rVert~ \cdot (\mathbf{p4} - \mathbf{p3}) } (\mathbf{p4} - \mathbf{p3}) + \mathbf{p3} .. py:function:: get_bisection_line(p1: numpy.typing.NDArray[float], p2: numpy.typing.NDArray[float], p3: numpy.typing.NDArray[float], p4: numpy.typing.NDArray[float]) -> tuple[numpy.typing.NDArray[float], numpy.typing.NDArray[float]] Find the bisection line between two lines. :param p1: The first point on the first vector (shape: (2,)). :param p2: The second point on the first vector (shape: (2,)). :param p3: The first point on the second vector (shape: (2,)). :param p4: The second point on the second vector (shape: (2,)). :returns: * *origin* -- A point on that bisection line. (shape: (2,)) * *direction* -- A normal vector that the bisection line points in (shape: (2,)) .. rubric:: Notes The intersection point is calculated using vector algebra, and the direction is the normalized sum of the normalized vectors of da and db. .. py:function:: _parse_to_xyz_array(xyz_array: numpy.typing.ArrayLike | dict[str, numpy.typing.ArrayLike]) -> numpy.typing.NDArray Make a 3, N xyz array out of just about anything. :returns: A 3, N xyz array. :raises CoordinatesError: Cannot instantiate coordinates .. py:function:: _parse_array(xyz_array: numpy.typing.ArrayLike) .. py:function:: _parse_dict(xyz_dict) .. py:class:: Coordinates(xyz_array: numpy.typing.ArrayLike | dict[str, numpy.typing.ArrayLike]) Coordinates object for storing ordered sets of coordinates. An array shape of (3, N) is enforced. Counter-clockwise direction can be set relative to a normal vector. .. rubric:: Notes This is a utility class for dealing with sets of coordinates in a number of different contexts. It should not be used for the creation of CAD geometries. If a 3 x 3 array is provided it is assumed that the first axis is xyz and the second is the coordinate, this will output a warning to notify users. .. py:attribute:: __slots__ :value: ('_array', '_is_planar', '_normal_vector') .. py:attribute:: _array .. py:attribute:: _is_planar :value: None .. py:attribute:: _normal_vector :value: None .. py:method:: from_json(filename: str) -> Coordinates :classmethod: Load a Coordinates object from a JSON file. :param filename: Full path file name of the data :returns: Coordinate object. :raises CoordinatesError: Cannot read json file .. py:method:: _set_plane_props() Set the planar properties of the Coordinates. .. py:method:: _update_plane_props() .. py:property:: is_planar :type: bool Whether or not the Coordinates are planar. .. py:property:: normal_vector :type: numpy.ndarray The normal vector of the best-fit plane of the Coordinates. .. py:method:: check_ccw(axis: numpy.ndarray | None = None) -> bool Whether or not the Coordinates are ordered in the counter-clockwise direction about a specified axis. If None is specified, the Coordinates normal vector will be used. :returns: The check for whether the Coordinates are ordered in counter-clockwise or not. :raises CoordinatesError: axis must be of size 3 .. py:method:: set_ccw(axis: numpy.ndarray | None = None) Set the Coordinates to be counter-clockwise about a specified axis. If None is specified, the Coordinates normal vector will be used. .. py:method:: distance_to(point: numpy.ndarray) -> numpy.ndarray Calculates the distances from each point in the Coordinates to the point. :param point: The point (3-D) to which to calculate the distances :rtype: The vector of distances of the Coordinates to the point .. rubric:: Notes Euclidean distance: .. math:: d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2 + (z_2 - z_1)^2} where indices refer to the Coordinate and the given point. .. py:method:: argmin(point: numpy.ndarray) -> int :param point: The 3-D point to which to calculate the distances :rtype: The index of the closest point .. py:method:: interpolate(ndiscr: int | None = None, dl: float | None = None, *, preserve_points: bool = False) Interpolate coordinates :param ndiscr: number of points to discretise to :param dl: target discretisation length. :param preserve_points: will preserve the original coordinates in addition to the discretisation :returns: Array of points :raises ValueError: if neither dl or ndiscr are specified If ndiscr < 2 If dl <= 0.0 .. rubric:: Notes When preserving original points the dl will be <= the discretisation .. py:property:: x :type: numpy.ndarray The x coordinate vector .. py:property:: y :type: numpy.ndarray The y coordinate vector .. py:property:: z :type: numpy.ndarray The z coordinate vector .. py:property:: xy :type: numpy.ndarray The x-y coordinate array .. py:property:: xz :type: numpy.ndarray The x-z coordinate array .. py:property:: yz :type: numpy.ndarray The y-z coordinate array .. py:property:: xyz :type: numpy.ndarray The x-y-z coordinate array .. py:property:: points :type: list[numpy.ndarray] A list of the individual points of the Coordinates. .. py:method:: as_dict() -> dict[str, numpy.ndarray] Cast the Coordinates as a dictionary. :returns: **d** -- Dictionary with {'x': [], 'y': [], 'z':[]} :rtype: dict .. py:method:: to_json(filename: str, **kwargs: dict[str, Any]) -> str Save the Coordinates as a JSON file. :returns: The Coordinates as a JSON file. .. py:property:: closed :type: bool Whether or not this is a closed set of Coordinates. .. py:property:: length :type: float Perimeter length of the coordinates. .. py:property:: center_of_mass :type: tuple[float, float, float] Geometrical centroid of the Coordinates. .. py:property:: T :type: numpy.ndarray Transpose of the Coordinates .. py:property:: shape :type: tuple[int, int] Shape of the Coordinates .. py:method:: reverse() Reverse the direction of the Coordinates. .. py:method:: open() Open the Coordinates (if they are closed) .. py:method:: insert(point: numpy.ndarray, index: int = 0) Insert a point to the Coordinates. :param point: The 3-D point to insert into the Coordinates :param index: The position of the point in the Coordinates (order index) .. py:method:: close() Close the Coordinates (if they are open) .. py:method:: rotate(base: tuple[float, float, float] = (0, 0, 0), direction: tuple[float, float, float] = (0, 0, 1), degree: float = 0.0) Rotate the Coordinates. :param base: Origin location of the rotation :param direction: The direction vector :param degree: rotation angle [degrees] :raises CoordinatesError: Base and direction must be of size 3 .. py:method:: translate(vector: tuple[float, float, float] = (0, 0, 0)) Translate this shape with the vector. This function modifies the self object. :raises CoordinatesError: vector must be of size 3 .. py:method:: simplify(max_angle: float, dx_min: float, dx_max: float = np.inf) -> tuple[Coordinates, numpy.typing.NDArray[numpy.int64]] Generate a set of pivot points along the given boundary. Given a set of boundary points, some maximum angle, and minimum and maximum segment length, this function derives a set of pivot points along the boundary, that define a 'string'. You might picture a 'string' as a thread wrapped around some nails (pivot points) on a board. :param max_angle: Maximum turning angle [degree] :type max_angle: float :param dx_min: Minimum segment length :type dx_min: float :param dx_max: Maximum segment length :type dx_max: float :returns: * *new_points* -- The pivot points' coordinates. * *index* -- The indices of the pivot points into the input points. :raises ValueError: dx_min > dx_maz .. py:method:: __eq__(other: Coordinates) -> bool Check the Coordinates for equality with other Coordinates. :param other: The other Coordinates to compare against :returns: The check of the Coordinates for equality with other Coordinates. .. rubric:: Notes Coordinates with identical coordinates but different orderings will not be counted as identical. .. py:method:: __hash__() Hash of Coordinates :returns: The hash of Coordinates. .. py:method:: __len__() -> int The number of points in the Coordinates. :returns: The number of points in the Coordinates. .. py:method:: __repr__() -> str Representation of the Coordinates. :returns: Representation of the Coordinates. .. py:method:: __getitem__(*args, **kwargs) Array-like indexing and slicing. :returns: Indexed or sliced array. .. py:method:: __iter__() Array-like unpacking. :returns: Unpacked array. .. py:method:: copy() Copy of itself :returns: * *An instance of Coordinates, with exactly the same class and coordinates,* * *but sharing a different underlying copy of the data array.* .. py:function:: vector_intersect_3d(p_1: numpy.ndarray, p_2: numpy.ndarray, p_3: numpy.ndarray, p_4: numpy.ndarray) -> numpy.ndarray Get the intersection point between two 3-D vectors. :param p_1: The first point on the first vector :param p_2: The second point on the first vector :param p_3: The first point on the second vector :param p_4: The second point on the second vector :rtype: The point of the intersection between the two vectors :raises CoordinatesError: If there is no intersection between the points .. rubric:: Notes Credit: Paul Bourke at https://paulbourke.net/geometry/pointlineplane/#:~:text=The%20shortest%20line%20between%20two%20lines%20in%203D .. py:function:: coords_plane_intersect(coords: Coordinates, plane: bluemira.geometry.plane.BluemiraPlane) -> numpy.ndarray | None Calculate the intersection of Coordinates with a plane. :param coords: The coordinates to calculate the intersection on :param plane: The plane to calculate the intersection with :returns: * *The xyz coordinates (3, n_intersections) of the intersections with the Coordinates.* * *Returns None if there are no intersections detected* .. py:function:: _coords_plane_intersect(array: numpy.ndarray, p1: numpy.ndarray, vec2: numpy.ndarray) -> list[float] .. py:function:: get_intersect(xy1: numpy.ndarray, xy2: numpy.ndarray) -> numpy.ndarray[numpy.ndarray[numpy.float64], numpy.ndarray[numpy.float64]] Calculates the intersection points between two sets of 2-D coordinates. Will return a unique list of x, z intersections (no duplicates in x-z space). :param xy1: The 2-D coordinates between which intersection points should be calculated. Shape = (2, N) :param xy2: The 2-D coordinates between which intersection points should be calculated. Shape = (2, N) :returns: The x, z coordinates of the intersection points. shape = (2, N) .. rubric:: Notes D. Schwarz, .. py:function:: _intersect_count(xz_inter: numpy.ndarray, xz_2: numpy.ndarray) -> numpy.ndarray Get the indices of the intersects that are :param xz_inter: x and z coordinates of the points created by the get_intersect function, shape = (N, 2) :param xz_2: x and z coordinates of one of the vertices of the polygon inputted into the get_intersect function. shape = (N, 2) :returns: a list of indices j, where the xz_inter[i] is expected to lie on the [j]-th edge, i.e. between xz_2[j] and xz_2[j+1] :rtype: insertion_locations .. py:function:: join_intersect(tgt_poly: Coordinates, ref_poly: Coordinates, *, get_arg: bool = False) -> tuple[Coordinates, list[int] | None] | Coordinates Add the intersection points between tgt_poly and ref_poly to tgt_poly. :param tgt_poly: The target polygon's vertices expressed as Coordinates. The intersection points should be inserted into this polygon. :param ref_poly: The reference polygon's vertices expressed as Coordinates. :param get_arg: Whether or not to return the indices in the MODIFIED tgt_poly which are newly inerted (intersection) points. :returns: * *dest_poly* -- Destination polygon, which is the union of the (target polygon) and (intersection points). * *set of insertion_locations* -- Only returned if get_arg is True: The indices in tgt_poly in which the intersections were added. .. py:function:: convex_2d_hull_coordinates(coordinates: Coordinates) -> Coordinates Given a list of coordinates, simplify it so that only the points that makes up the convex hull of this coordinates set remains. Parameter --------- coordinates: Either a set of planar coordinates (in which case, a 2d convex hull is made), or a set of 3D, non-planar coordinates (in which case, a 3D convex hull is made.) :returns: ONLY the list of vertices that forms the convex hull. Those that doesn't form the convex hull are removed. :raises CoordinatesError: Cannot process coplanar coordinates whose common plane is not perpendicular to one of the 3 cardinal axes. .. py:function:: choose_direction(vector: numpy.typing.NDArray[float], lower_pt: numpy.typing.NDArray[float], higher_pt: numpy.typing.NDArray[float]) Flip the vector to the correct side (multiply by +1 or -1) so that when lower_pt is projected onto the vector, it has a smaller value than when higher_pt is projected onto the vector. :returns: The flipped vector.