Пример #1
0
def distance_point_line(point, line):
    """Compute the distance between a point and a line.

    This implementation computes the *right angle distance* from a point P to a
    line defined by points A and B as twice the area of the triangle ABP divided
    by the length of AB.

    Parameters
    ----------
    point : list, tuple
        Point location.
    line : list, tuple
        Line defined by two points.

    Returns
    -------
    d : float
        The distance between the point and the line.

    Examples
    --------
    >>>

    References
    ----------
    https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line

    """
    a, b = line
    ab = subtract_vectors(b, a)
    pa = subtract_vectors(a, point)
    pb = subtract_vectors(b, point)
    l = length_vector(cross_vectors(pa, pb))
    l_ab = length_vector(ab)
    return l / l_ab
Пример #2
0
def angle_vectors(u, v, deg=False):
    """Compute the smallest angle between two vectors.

    Parameters
    ----------
    u : sequence of float
        XYZ components of the first vector.
    v : sequence of float
        XYZ components of the second vector.
    deg : boolean
        returns angle in degrees if True

    Returns
    -------
    float
        The smallest angle in radians (in degrees if deg == True).
        The angle is always positive.

    Examples
    --------
    >>> angle_vectors([0.0, 1.0, 0.0], [1.0, 0.0, 0.0])

    """
    a = dot_vectors(u, v) / (length_vector(u) * length_vector(v))
    a = max(min(a, 1), -1)

    if deg:
        return degrees(acos(a))
    return acos(a)
Пример #3
0
def area_polygon(polygon):
    """Compute the area of a polygon.

    Parameters
    ----------
    polygon : sequence
        The XYZ coordinates of the vertices/corners of the polygon.
        The vertices are assumed to be in order.
        The polygon is assumed to be closed:
        the first and last vertex in the sequence should not be the same.

    Returns
    -------
    float
        The area of the polygon.

    """
    o = centroid_points(polygon)
    u = subtract_vectors(polygon[-1], o)
    v = subtract_vectors(polygon[0], o)
    a = 0.5 * length_vector(cross_vectors(u, v))
    for i in range(0, len(polygon) - 1):
        u = v
        v = subtract_vectors(polygon[i + 1], o)
        a += 0.5 * length_vector(cross_vectors(u, v))
    return a
Пример #4
0
def lines_tangent_to_cylinder(base_point, line_vect, ref_point, dist):
    """Calculating of plane tangents to one cylinder
        See SP dissertation 3.1.3.b (p. 74)

    .. image:: ../images/plane_tangent_to_one_cylinder.png
        :scale: 80 %
        :align: center

    Parameters
    ----------
    base_point : [type]
        [description]
    line_vect : [type]
        vector [other end of the axis, base_point], **the direction here is very important!**
    ref_point : point
        new point Q
    dist : float
        radius of the cylinder

    Returns
    -------
    list
        [origin point M, vector MB, -1 * vector MB], the latter two entries represent
        the tangent points' local coordinate in the plane [point M, e_x, e_y]
    """
    l_vect = normalize_vector(line_vect)
    line_QMprime = subtract_vectors(ref_point, base_point)
    # ppol = point M, project out longitutude axis component of base_point
    ppol = add_vectors(base_point,
                       scale_vector(l_vect, dot_vectors(line_QMprime, l_vect)))
    # ppolr_vect = line QB
    line_QM = subtract_vectors(ref_point, ppol)

    e_x = normalize_vector(line_QM)
    e_y = cross_vectors(e_x, l_vect)
    if length_vector(line_QM) == 0: return None
    x = dist / length_vector(line_QM)
    # x coordinate in the local axis
    d_e1 = scale_vector(e_x, dist * x)
    # d(radius of bar section) has to be larger than l(distance from point to bar axis), otherwise the sqrt turns negative
    # if d < l: change ref_point
    if x * x < 1.0:
        # y coordinate in the local axis
        d_e2 = scale_vector(e_y, dist * math.sqrt(1.0 - x * x))
    else:
        return None

    # upper tangent point
    d_e_add = add_vectors(d_e1, d_e2)
    # lower tangent point
    d_e_sub = subtract_vectors(d_e1, d_e2)
    return [ppol, d_e_add, d_e_sub]
Пример #5
0
def centroid_polygon_edges(polygon):
    """Compute the centroid of the edges of a polygon.

    Parameters
    ----------
    polygon : list of point
        A sequence of polygon point coordinates.

    Returns
    -------
    list
        The XYZ coordinates of the centroid.

    Notes
    -----
    The centroid of the edges is the centroid of the midpoints of the edges, with
    each midpoint weighted by the length of the corresponding edge proportional
    to the total length of the boundary.

    """
    L = 0
    cx = 0
    cy = 0
    cz = 0
    p = len(polygon)
    for i in range(-1, p - 1):
        p1 = polygon[i]
        p2 = polygon[i + 1]
        d = length_vector(subtract_vectors(p2, p1))
        cx += 0.5 * d * (p1[0] + p2[0])
        cy += 0.5 * d * (p1[1] + p2[1])
        cz += 0.5 * d * (p1[2] + p2[2])
        L += d
    return [cx / L, cy / L, cz / L]
Пример #6
0
def distance_point_point(a, b):
    """Compute the distance bewteen a and b.

    Parameters
    ----------
    a : sequence of float
        XYZ coordinates of point a.
    b : sequence of float
        XYZ coordinates of point b.

    Returns
    -------
    d : float
        Distance bewteen a and b.

    Examples
    --------
    >>> distance_point_point([0.0, 0.0, 0.0], [2.0, 0.0, 0.0])
    2.0

    See Also
    --------
    distance_point_point_xy

    """
    ab = subtract_vectors(b, a)
    return length_vector(ab)
Пример #7
0
def normal_triangle(triangle, unitized=True):
    """Compute the normal vector of a triangle.

    Parameters
    ----------
    triangle : list of list
        A list of triangle point coordinates.

    Returns
    -------
    list
        The normal vector.

    Raises
    ------
    ValueError
        If the triangle does not have three vertices.

    """
    assert len(triangle) == 3, "Three points are required."
    a, b, c = triangle
    ab = subtract_vectors(b, a)
    ac = subtract_vectors(c, a)
    n = cross_vectors(ab, ac)
    if not unitized:
        return n
    lvec = length_vector(n)
    return n[0] / lvec, n[1] / lvec, n[2] / lvec
Пример #8
0
def normal_polygon(points, unitized=True):
    """Compute the normal of a polygon defined by a sequence of points.

    Parameters:
        points (sequence): A sequence of points.

    Returns:
        list: The normal vector.

    Raises:
        ValueError: If less than three points are provided.

    Notes:
        The points in the list should be unique. For example, the first and last
        point in the list should not be the same.

    """
    p = len(points)
    assert p > 2, "At least three points required"
    nx = 0
    ny = 0
    nz = 0
    o = centroid_points(points)
    a = subtract_vectors(points[-1], o)
    for i in range(p):
        b = subtract_vectors(points[i], o)
        n = cross_vectors(a, b)
        a = b
        nx += n[0]
        ny += n[1]
        nz += n[2]
    if not unitized:
        return nx, ny, nz
    l = length_vector([nx, ny, nz])
    return nx / l, ny / l, nz / l
Пример #9
0
def _normal_polygon(points, normalised=True):
    """Compute the normal of a polygon defined by a sequence of points.

    Note:
        The points in the list should be unique. For example, the first and last
        point in the list should not be the same.

    Parameters:
        points (sequence): A sequence of points.

    Returns:
        list: The normal vector.

    Raises:
        ValueError: If less than three points are provided.
    """
    p = len(points)
    assert p > 2, "At least three points required"
    nx = 0
    ny = 0
    nz = 0
    for i in range(-1, p - 1):
        p1 = points[i - 1]
        p2 = points[i]
        p3 = points[i + 1]
        v1 = subtract_vectors(p1, p2)
        v2 = subtract_vectors(p3, p2)
        n = cross_vectors(v1, v2)
        nx += n[0]
        ny += n[1]
        nz += n[2]
    if not normalised:
        return nx, ny, nz
    l = length_vector([nx, ny, nz])
    return nx / l, ny / l, nz / l
Пример #10
0
def normal_triangle(triangle, unitized=True):
    """Compute the normal vector of a triangle.
    """
    assert len(triangle) == 3, "Three points are required."
    a, b, c = triangle
    ab = subtract_vectors(b, a)
    ac = subtract_vectors(c, a)
    n  = cross_vectors(ab, ac)
    if not unitized:
        return n
    lvec = length_vector(n)
    return n[0] / lvec, n[1] / lvec, n[2] / lvec
Пример #11
0
def normal_polygon(polygon, unitized=True):
    """Compute the normal of a polygon defined by a sequence of points.

    Parameters
    ----------
    polygon : list of list
        A list of polygon point coordinates.

    Returns
    -------
    list
        The normal vector.

    Raises
    ------
    ValueError
        If less than three points are provided.

    Notes
    -----
    The points in the list should be unique. For example, the first and last
    point in the list should not be the same.

    """
    p = len(polygon)

    assert p > 2, "At least three points required"

    nx = 0
    ny = 0
    nz = 0

    o = centroid_points(polygon)
    a = polygon[-1]
    oa = subtract_vectors(a, o)

    for i in range(p):
        b = polygon[i]
        ob = subtract_vectors(b, o)
        n = cross_vectors(oa, ob)
        oa = ob

        nx += n[0]
        ny += n[1]
        nz += n[2]

    if not unitized:
        return nx, ny, nz

    l = length_vector([nx, ny, nz])

    return nx / l, ny / l, nz / l
Пример #12
0
def angle_smallest_vectors(u, v):
    """Compute the smallest angle (radians) between two vectors.

    Parameters
    ----------
    u : sequence of float
        XYZ components of the first vector.
    v : sequence of float)
        XYZ components of the second vector.

    Returns
    -------
    float
        The smallest angle in radians.
        The angle is always positive.

    Examples
    --------
    >>> angle_smallest_vectors([0.0, 1.0, 0.0], [1.0, 0.0, 0.0])

    """
    a = dot_vectors(u, v) / (length_vector(u) * length_vector(v))
    a = max(min(a, 1), -1)
    return acos(a)
Пример #13
0
def area_triangle(triangle):
    """Compute the area of a triangle defined by three points.

    Parameters
    ----------
    triangle : list of list
        XYZ coordinates of the corners of the triangle.

    Returns
    -------
    float
        The area of the triangle.

    """
    return 0.5 * length_vector(normal_triangle(triangle, False))
Пример #14
0
def distance_line_line(l1, l2, tol=0.0):
    """Compute the shortest distance between two lines.

    Parameters
    ----------
    l1 : tuple
        Two points defining a line.
    l2 : tuple
        Two points defining a line.

    Returns
    -------
    d : float
        The distance between the two lines.

    Notes
    -----
    The distance is the absolute value of the dot product of a unit vector that
    is perpendicular to the two lines, and the vector between two points on the lines ([1]_, [2]_).

    If each of the lines is defined by two points (:math:`l_1 = (\mathbf{x_1}, \mathbf{x_2})`,
    :math:`l_2 = (\mathbf{x_3}, \mathbf{x_4})`), then the unit vector that is
    perpendicular to both lines is...

    References
    ----------
    .. [1] Weisstein, E.W. *Line-line Distance*.
           Available at: http://mathworld.wolfram.com/Line-LineDistance.html.
    .. [2] Wikipedia. *Skew lines Distance*.
           Available at: https://en.wikipedia.org/wiki/Skew_lines#Distance.

    Examples
    --------
    >>>

    """
    a, b = l1
    c, d = l2
    ab = subtract_vectors(b, a)
    cd = subtract_vectors(d, c)
    ac = subtract_vectors(c, a)
    n = cross_vectors(ab, cd)
    l = length_vector(n)
    if l <= tol:
        return distance_point_point(closest_point_on_line(l1[0], l2), l1[0])
    n = scale_vector(n, 1.0 / l)
    return fabs(dot_vectors(n, ac))
Пример #15
0
def circle_from_points(a, b, c):
    """Construct a circle from three points.

    Parameters
    ----------
    a : sequence of float
        XYZ coordinates.
    b : sequence of float
        XYZ coordinates.
    c : sequence of float
        XYZ coordinates.

    Returns
    -------
    circle : tuple
        Center, radius, normal  of the circle.

    References
    ----------
    https://en.wikipedia.org/wiki/Circumscribed_circle

    Examples
    --------
    >>>

    """
    ab = subtract_vectors(b, a)
    cb = subtract_vectors(b, c)
    ba = subtract_vectors(a, b)
    ca = subtract_vectors(a, c)
    ac = subtract_vectors(c, a)
    bc = subtract_vectors(c, b)
    normal = normalize_vector(cross_vectors(ab, ac))
    d = 2 * length_vector_sqrd(cross_vectors(ba, cb))
    A = length_vector_sqrd(cb) * dot_vectors(ba, ca) / d
    B = length_vector_sqrd(ca) * dot_vectors(ab, cb) / d
    C = length_vector_sqrd(ba) * dot_vectors(ac, bc) / d
    Aa = scale_vector(a, A)
    Bb = scale_vector(b, B)
    Cc = scale_vector(c, C)
    center = sum_vectors([Aa, Bb, Cc])
    radius = length_vector(subtract_vectors(a, center))
    return center, radius, normal
Пример #16
0
def angle_vectors_signed(u, v, normal, deg=False, threshold=1e-3):
    """Computes the signed angle between two vectors.

    It calculates the angle such that rotating vector u about the normal by
    angle would result in a vector that looks into the same direction as v.

    Parameters
    ----------
    u : sequence of float
        XYZ components of the first vector.
    v : sequence of float
        XYZ components of the second vector.
    normal : sequence of float
        XYZ components of the plane's normal spanned by u and v.
    deg : boolean
        returns angle in degrees if True
    threshold : The threshold (radians) used to consider if the angle is zero.
        Defaults to 1e-3.

    Returns
    -------
    float
        The signed angle in radians (in degrees if deg == True).

    Examples
    --------
    >>> normal = [0.0, 0.0, 1.0]
    >>> angle_vectors_signed([0.0, 1.0, 0.0], [1.0, 0.0, 0.0], normal)
    """
    angle = angle_vectors(u, v)
    normal_uv = cross_vectors(u, v)

    if length_vector(normal_uv) > threshold:
        # check if normal_uv has the same direction as normal
        angle_btw_normals = angle_vectors(normal, normal_uv)
        if angle_btw_normals > threshold:
            angle *= -1

    if deg:
        return degrees(angle)
    else:
        return angle
Пример #17
0
    def from_axis_angle_vector(cls, axis_angle_vector, point=[0, 0, 0]):
        """Calculates a ``Rotation`` from an axis-angle vector.

        Args:
            axis_angle_vector (:obj:`list` of :obj:`float`): Three numbers
                that represent the axis of rotation and angle of rotation
                through the vector's magnitude.
            point (:obj:`list` of :obj:`float`, optional): A point to
                perform a rotation around an origin other than [0, 0, 0].

        Example:
            >>> aav1 = [-0.043, -0.254, 0.617]
            >>> R = Rotation.from_axis_angle_vector(aav1)
            >>> aav2 = R.axis_angle_vector
            >>> allclose(aav1, aav2)
            True
        """

        axis_angle_vector = list(axis_angle_vector)
        angle = length_vector(axis_angle_vector)
        return cls.from_axis_and_angle(axis_angle_vector, angle, point)
Пример #18
0
def center_of_mass_polygon(polygon):
    """Compute the center of mass of a polygon defined as a sequence of points.

    The center of mass of a polygon is the centroid of the midpoints of the edges,
    each weighted by the length of the corresponding edge.

    Parameters
    ----------
    polygon : sequence
        A sequence of XYZ coordinates representing the locations of the corners of a polygon.

    Returns
    -------
    tuple of floats
        The XYZ coordinates of the center of mass.

    Examples
    --------
    >>> pts = [(0.,0.,0.),(1.,0.,0.),(0.,10.,0.)]
    >>> print("Center of mass: {0}".format(center_of_mass(pts)))
    >>> print("Centroid: {0}".format(centroid(pts)))

    """
    L = 0
    cx = 0
    cy = 0
    cz = 0
    p = len(polygon)
    for i in range(-1, p - 1):
        p1 = polygon[i]
        p2 = polygon[i + 1]
        d = length_vector(subtract_vectors(p2, p1))
        cx += 0.5 * d * (p1[0] + p2[0])
        cy += 0.5 * d * (p1[1] + p2[1])
        cz += 0.5 * d * (p1[2] + p2[2])
        L += d
    cx = cx / L
    cy = cy / L
    cz = cz / L
    return cx, cy, cz
Пример #19
0
def matrix_from_axis_angle_vector(axis_angle_vector, point=[0, 0, 0]):
    """Calculates a rotation matrix from an axis-angle vector.

    Parameters
    ----------
    axis_angle_vector : list of float
        Three numbers that represent the axis of rotation and angle of rotation
        through the vector's magnitude.
    point : list of float, optional
        A point to perform a rotation around an origin other than [0, 0, 0].

    Examples
    --------
    >>> aav1 = [-0.043, -0.254, 0.617]
    >>> R = matrix_from_axis_angle_vector(aav1)
    >>> aav2 = axis_angle_vector_from_matrix(R)
    >>> allclose(aav1, aav2)
    True

    """
    axis = list(axis_angle_vector)
    angle = length_vector(axis_angle_vector)
    return matrix_from_axis_and_angle(axis, angle, point)
Пример #20
0
def matrix_from_axis_and_angle(axis, angle, point=None, rtype='list'):
    """Calculates a rotation matrix from an rotation axis, an angle and an optional
    point of rotation.

    Parameters
    ----------
    axis : list of float
        Three numbers that represent the axis of rotation.
    angle : float
        The rotation angle in radians.
    point : list of float, optional
        A point to perform a rotation around an origin other than [0, 0, 0].

    Returns
    -------
    list of list of float
        The matrix.

    Notes
    -----
    The rotation is based on the right hand rule, i.e. anti-clockwise if the
    axis of rotation points towards the observer.

    Examples
    --------
    >>> axis1 = normalize_vector([-0.043, -0.254, 0.617])
    >>> angle1 = 0.1
    >>> R = matrix_from_axis_and_angle(axis1, angle1)
    >>> axis2, angle2 = axis_and_angle_from_matrix(R)
    >>> allclose(axis1, axis2)
    True
    >>> allclose([angle1], [angle2])
    True

    """
    if not point:
        point = [0.0, 0.0, 0.0]

    axis = list(axis)
    if length_vector(axis):
        axis = normalize_vector(axis)

    sina = math.sin(angle)
    cosa = math.cos(angle)

    R = [[cosa, 0.0, 0.0], [0.0, cosa, 0.0], [0.0, 0.0, cosa]]

    outer_product = [[axis[i] * axis[j] *
                      (1.0 - cosa) for i in range(3)] for j in range(3)]
    R = [[R[i][j] + outer_product[i][j]
          for i in range(3)] for j in range(3)]

    axis = scale_vector(axis, sina)
    m = [[0.0, -axis[2], axis[1]],
         [axis[2], 0.0, -axis[0]],
         [-axis[1], axis[0], 0.0]]

    M = [[1. if x == y else 0. for x in range(4)] for y in range(4)]
    for i in range(3):
        for j in range(3):
            R[i][j] += m[i][j]
            M[i][j] = R[i][j]

    # rotation about axis, angle AND point includes also translation
    t = subtract_vectors(point, multiply_matrix_vector(R, point))
    M[0][3] = t[0]
    M[1][3] = t[1]
    M[2][3] = t[2]

    if rtype == 'list':
        return M
    if rtype == 'array':
        from numpy import asarray
        return asarray(M)

    raise NotImplementedError
Пример #21
0
def centroid_polygon(polygon):
    r"""Compute the centroid of the surface of a polygon.

    Parameters
    ----------
    polygon : list of point
        A sequence of polygon point coordinates.

    Returns
    -------
    list
        The XYZ coordinates of the centroid.

    Examples
    --------
    .. code-block:: python

        from compas.geometry import centroid_polygon

        polygon = [
            [0.0, 0.0, 0.0],
            [1.0, 0.0, 0.0],
            [1.0, 1.0, 0.0],
            [0.0, 1.0, 0.0]
        ]

        c = centroid_polygon(polygon)

        print(c)  # [0.5, 0.5, 0.0]

    .. code-block:: python

        from compas.geometry import centroid_polygon
        from compas.geometry import centroid_points

        polygon = [
            [0.0, 0.0, 0.0],
            [1.0, 0.0, 0.0],
            [1.0, 1.0, 0.0],
            [0.5, 1.0, 0.0],
            [0.0, 1.0, 0.0]
        ]

        c = centroid_polygon(polygon)
        print(c)  # [0.5, 0.5, 0.0]

        c = centroid_points(polygon)
        print(c)  # [0.5, 0.6, 0.0]

    Notes
    -----
    The centroid is the centre of gravity of the polygon surface if mass would be
    uniformly distributed over it.

    It is calculated by triangulating the polygon surface with respect to the centroid
    of the polygon vertices, and then computing the centroid of the centroids of
    the individual triangles, weighted by the corresponding triangle area in
    proportion to the total surface area.

    .. math::

        c_x = \frac{1}{A} \sum_{i=1}^{N} A_i \cdot c_{x,i}
        c_y = \frac{1}{A} \sum_{i=1}^{N} A_i \cdot c_{y,i}
        c_z = \frac{1}{A} \sum_{i=1}^{N} A_i \cdot c_{z,i}

    Warning
    -------
    The polygon need not be convex.

    The polygon need not be flat. However, it is unclear what the meaning of the
    centroid is in that case.

    The polygon may be self-intersecting. However, it is unclear what the meaning
    of the centroid is in that case.

    """
    p = len(polygon)

    assert p > 2, "At least three points required"

    if p == 3:
        return centroid_points(polygon)

    cx, cy, cz = 0.0, 0.0, 0.0
    A2 = 0

    o = centroid_points(polygon)
    a = polygon[-1]
    b = polygon[0]
    oa = subtract_vectors(a, o)
    ob = subtract_vectors(b, o)
    n0 = cross_vectors(oa, ob)

    x, y, z = centroid_points([o, a, b])
    a2 = length_vector(n0)

    A2 += a2
    cx += a2 * x
    cy += a2 * y
    cz += a2 * z

    for i in range(1, len(polygon)):
        a = b
        b = polygon[i]

        oa = ob
        ob = subtract_vectors(b, o)

        n = cross_vectors(oa, ob)
        x, y, z = centroid_points([o, a, b])

        if dot_vectors(n, n0) > 0:
            a2 = length_vector(n)
        else:
            a2 = -length_vector(n)

        A2 += a2
        cx += a2 * x
        cy += a2 * y
        cz += a2 * z

    return [cx / A2, cy / A2, cz / A2]
Пример #22
0
            n = cross_vectors(ab, ac)
            V += dot_vectors(a, n)
    return V / 6.


# ==============================================================================
# Main
# ==============================================================================

if __name__ == "__main__":

    from compas.geometry import Polyhedron

    cube = Polyhedron.generate(6)

    L = length_vector(subtract_vectors(cube.vertices[0], cube.vertices[1]))

    V1 = L * L * L
    V2 = volume_polyhedron(cube)

    print(V1 - V2 <= 1e-6)

    # plotter = Plotter(figsize=(10, 7))

    # polygon = [
    #     [0, 0, 0],
    #     [1.0, 0, 0],
    #     [1.0, 1.0, 0],
    #     [0.5, 0.0, 0],
    #     [0, 1.0, 0]
    # ]
Пример #23
0
def area_triangle(triangle):
    """Compute the area of a triangle defined by three points.
    """
    return 0.5 * length_vector(normal_triangle(triangle, False))
Пример #24
0
def area_polygon(polygon):
    """Compute the area of a polygon.

    Parameters
    ----------
    polygon : sequence
        The XYZ coordinates of the vertices/corners of the polygon.
        The vertices are assumed to be in order.
        The polygon is assumed to be closed:
        the first and last vertex in the sequence should not be the same.

    Returns
    -------
    float
        The area of the polygon.

    Examples
    --------
    .. plot::
        :include-source:

        from compas.geometry import area_polygon
        from compas_plotters import Plotter

        plotter = Plotter()

        polygon = [
            [0.0, 0.0, 0.0],
            [1.0, 0.0, 0.0],
            [1.0, 1.0, 0.0],
            [0.0, 1.0, 0.0]
        ]

        area_polygon(polygon)

        # 1.0

        plotter.draw_polygons([{'points': polygon}])
        plotter.show()

    .. plot::
        :include-source:

        from compas.geometry import area_polygon
        from compas_plotters import Plotter

        plotter = Plotter()

        polygon = [
            [0.0, 0.0, 0.0],
            [1.0, 0.0, 0.0],
            [1.0, 1.0, 0.0],
            [0.5, 0.0, 0.0],
            [0.0, 1.0, 0.0]
        ]

        area_polygon(polygon)

        # 0.5

        plotter.draw_polygons([{'points': polygon}])
        plotter.show()

    """
    o = centroid_points(polygon)
    a = polygon[-1]
    b = polygon[0]
    oa = subtract_vectors(a, o)
    ob = subtract_vectors(b, o)

    n0 = cross_vectors(oa, ob)

    area = 0.5 * length_vector(n0)

    for i in range(0, len(polygon) - 1):
        oa = ob
        b = polygon[i + 1]
        ob = subtract_vectors(b, o)
        n = cross_vectors(oa, ob)

        if dot_vectors(n, n0) > 0:
            area += 0.5 * length_vector(n)
        else:
            area -= 0.5 * length_vector(n)

    return area
Пример #25
0
 def length_vectors(vectors):
     return [length_vector(vector) for vector in vectors]
Пример #26
0
 def length(self):
     """float: The length of this ``Vector``."""
     return length_vector(self)
Пример #27
0
def calculate_gripping_plane(b_struct,
                             v,
                             pt_mean,
                             nb_rot=8,
                             nb_trans=8,
                             planes_rot=True,
                             planes_trans=True):
    """calculate gripping planes for a given bar structure and the vertex key (representing a bar)

    Parameters
    ----------
    b_struct : [type]
        [description]
    v : [type]
        [description]
    pt_mean : [type]
        [description]
    nb_rot : int, optional
        number of rotational division, by default 8
    nb_trans : int, optional
        number of translational division, by default 8
    planes_rot : bool, optional
        [description], by default True
    planes_trans : bool, optional
        [description], by default True
    """

    end_pts_0 = b_struct.vertex[v]["axis_endpoints"]
    # local coordinate system
    vec_x, vec_y, vec_z = calculate_coord_sys(end_pts_0, pt_mean)
    # mid point of the bar axis
    pt_o = centroid_points(end_pts_0)

    b_struct.vertex[v].update({"gripping_plane": (pt_o, vec_x, vec_y, vec_z)})
    gripping_plane = b_struct.vertex[v]["gripping_plane"]

    frames_all = []

    if planes_trans == True:
        # extend both end points for 30 mm
        vec_bar = scale_vector(
            normalize_vector(subtract_vectors(end_pts_0[1], end_pts_0[0])), 30)
        pt1 = add_vectors(end_pts_0[0], vec_bar)
        vec_bar = scale_vector(vec_bar, -1)
        pt2 = add_vectors(end_pts_0[1], vec_bar)
        vec_n = subtract_vectors(pt2, pt1)
        len_vec = length_vector(vec_n)
        len_new = len_vec / (nb_trans - 1)

        for i in range(nb_trans):
            origin = add_vectors(
                pt1, scale_vector(normalize_vector(vec_n), len_new * i))
            frame_n = [origin, gripping_plane[1], gripping_plane[2]]
            if not planes_rot:
                frames_all.append(frame_n)
                # if planes_flip == True:
                #     frame_n = [frame_n[0], scale_vector(frame_n[1], -1), scale_vector(frame_n[2], -1)]
                #     frames_all.append(frame_n)
            else:
                ang = math.radians(360 / nb_rot)
                for n in range(nb_rot):
                    gripping_plane = frame_n
                    vecs_n = rotate_points(
                        [gripping_plane[1], gripping_plane[2]],
                        angle=n * ang,
                        axis=subtract_vectors(end_pts_0[1], end_pts_0[0]),
                        origin=(0, 0, 0))
                    frame_n = [gripping_plane[0], vecs_n[0], vecs_n[1]]
                    frames_all.append(frame_n)
                    # if planes_flip == True:
                    #     frame_n = [frame_n[0], scale_vector(frame_n[1], -1), scale_vector(frame_n[2], -1)]
                    #     frames_all.append(frame_n)
    elif planes_rot == True:
        ang = math.radians(360 / nb_rot)
        for n in range(nb_rot):
            vecs_n = rotate_points([gripping_plane[1], gripping_plane[2]],
                                   angle=n * ang,
                                   axis=subtract_vectors(
                                       end_pts_0[1], end_pts_0[0]),
                                   origin=(0, 0, 0))
            frame_n = [gripping_plane[0], vecs_n[0], vecs_n[1]]
            frames_all.append(frame_n)

            # if planes_flip == True:
            #     frame_n = [frame_n[0], scale_vector(frame_n[1], -1), scale_vector(frame_n[2], -1)]
            #     frames_all.append(frame_n)

    for i, f in enumerate(frames_all):
        z_vec = cross_vectors(f[1], f[2])
        frames_all[i].append(z_vec)

    b_struct.vertex[v].update({"gripping_planes_all": frames_all})