Ejemplo n.º 1
0
def barycentric_coordinates(point, triangle):
    """Compute the barycentric coordinates of a point wrt to a triangle.

    Parameters
    ----------
    point: list
        Point location.
    triangle: (point, point, point)
        A triangle defined by 3 points.

    Returns
    -------
    list
        The barycentric coordinates of the point.

    """
    a, b, c = triangle
    v0 = subtract_vectors(b, a)
    v1 = subtract_vectors(c, a)
    v2 = subtract_vectors(point, a)
    d00 = dot_vectors(v0, v0)
    d01 = dot_vectors(v0, v1)
    d11 = dot_vectors(v1, v1)
    d20 = dot_vectors(v2, v0)
    d21 = dot_vectors(v2, v1)
    D = d00 * d11 - d01 * d01
    v = (d11 * d20 - d01 * d21) / D
    w = (d00 * d21 - d01 * d20) / D
    u = 1.0 - v - w
    return u, v, w
Ejemplo n.º 2
0
def barycentric_coordinates(point, triangle):
    """Compute the barycentric coordinates of a point wrt to a triangle.

    Parameters
    ----------
    point: [float, float, float] | :class:`compas.geometry.Point`
        Point location.
    triangle: [point, point, point]
        A triangle defined by 3 points.

    Returns
    -------
    [float, float, float]
        The barycentric coordinates of the point.

    """
    a, b, c = triangle
    v0 = subtract_vectors(b, a)
    v1 = subtract_vectors(c, a)
    v2 = subtract_vectors(point, a)
    d00 = dot_vectors(v0, v0)
    d01 = dot_vectors(v0, v1)
    d11 = dot_vectors(v1, v1)
    d20 = dot_vectors(v2, v0)
    d21 = dot_vectors(v2, v1)
    D = d00 * d11 - d01 * d01
    v = (d11 * d20 - d01 * d21) / D
    w = (d00 * d21 - d01 * d20) / D
    u = 1.0 - v - w
    return [u, v, w]
Ejemplo n.º 3
0
def matrix_from_parallel_projection(point, normal, direction):
    """Returns an parallel projection matrix to project onto a plane defined by
    point, normal and direction.

    Parameters
    ----------
    point : list of float
        Base point of the plane.
    normal : list of float
        Normal vector of the plane.
    direction : list of float
        Direction of the projection.

    Examples
    --------
    >>> point = [0, 0, 0]
    >>> normal = [0, 0, 1]
    >>> direction = [1, 1, 1]
    >>> P = matrix_from_parallel_projection(point, normal, direction)

    """
    T = identity_matrix(4)
    normal = normalize_vector(normal)

    scale = dot_vectors(direction, normal)
    for j in range(3):
        for i in range(3):
            T[i][j] -= direction[i] * normal[j] / scale

    T[0][3], T[1][3], T[2][3] = scale_vector(
        direction,
        dot_vectors(point, normal) / scale)
    return T
Ejemplo n.º 4
0
def matrix_from_parallel_projection(plane, direction):
    """Returns an parallel projection matrix to project onto a plane.

    Parameters
    ----------
    plane : compas.geometry.Plane or (point, normal)
        The plane to project onto.
    direction : list of float
        Direction of the projection.

    Examples
    --------
    >>> point = [0, 0, 0]
    >>> normal = [0, 0, 1]
    >>> plane = (point, normal)
    >>> direction = [1, 1, 1]
    >>> P = matrix_from_parallel_projection(plane, direction)

    """
    point, normal = plane
    T = identity_matrix(4)
    normal = normalize_vector(normal)

    scale = dot_vectors(direction, normal)
    for j in range(3):
        for i in range(3):
            T[i][j] -= direction[i] * normal[j] / scale

    T[0][3], T[1][3], T[2][3] = scale_vector(
        direction,
        dot_vectors(point, normal) / scale)
    return T
Ejemplo n.º 5
0
def matrix_from_shear(angle, direction, point, normal):
    """Constructs a shear matrix by an angle along the direction vector on the
    shear plane (defined by point and normal).

    Parameters
    ----------
    angle : float
        The angle in radians.
    direction : list of float
        The direction vector as list of 3 numbers.
        It must be orthogonal to the normal vector.
    point : list of float
        The point of the shear plane as list of 3 numbers.
    normal : list of float
        The normal of the shear plane as list of 3 numbers.

    Raises
    ------
    ValueError
        If direction and normal are not orthogonal.

    Notes
    -----
    A point P is transformed by the shear matrix into P" such that
    the vector P-P" is parallel to the direction vector and its extent is
    given by the angle of P-P'-P", where P' is the orthogonal projection
    of P onto the shear plane (defined by point and normal).

    Examples
    --------
    >>> angle = 0.1
    >>> direction = [0.1, 0.2, 0.3]
    >>> point = [4, 3, 1]
    >>> normal = cross_vectors(direction, [1, 0.3, -0.1])
    >>> S = matrix_from_shear(angle, direction, point, normal)

    """
    fabs = math.fabs

    normal = normalize_vector(normal)
    direction = normalize_vector(direction)

    if fabs(dot_vectors(normal, direction)) > _EPS:
        raise ValueError('Direction and normal vectors are not orthogonal')

    angle = math.tan(angle)
    M = identity_matrix(4)

    for j in range(3):
        for i in range(3):
            M[i][j] += angle * direction[i] * normal[j]

    M[0][3], M[1][3], M[2][3] = scale_vector(
        direction, -angle * dot_vectors(point, normal))

    return M
Ejemplo n.º 6
0
def matrix_from_orthogonal_projection(point, normal):
    """Returns an orthogonal projection matrix to project onto a plane defined
    by point and normal.

    Parameters
    ----------
    point : list of float
        Base point of the plane.
    normal : list of float
        Normal vector of the plane.

    Examples
    --------
    >>> point = [0, 0, 0]
    >>> normal = [0, 0, 1]
    >>> P = matrix_from_orthogonal_projection(point, normal)

    """
    T = identity_matrix(4)
    normal = normalize_vector(normal)

    for j in range(3):
        for i in range(3):
            T[i][j] -= normal[i] * normal[j]  # outer_product

    T[0][3], T[1][3], T[2][3] = scale_vector(normal,
                                             dot_vectors(point, normal))
    return T
Ejemplo n.º 7
0
def check_cell_convexity(cell):
    """cell: mesh / mesh3gs
    check the convexity of the cell
    check that all the other vertices lie on the same side of that face.
    by calculating the face normal vector and computing the dot-product for each vector from one vertex on the face to all the others
    The signs must be the same.

    """
    vkeys = cell.vertices()
    for fkey in cell.faces():
        f_normal = cell.face_normal(fkey)
        f_vkeys = cell.face_vertices(fkey)
        f_v_xyz = cell.vertex_coordinates(f_vkeys[0]) # one vertex on the face
        other_vkeys = [vkey for vkey in vkeys if vkey not in f_vkeys]
        for i, v in enumerate(other_vkeys):
            v_xyz = cell.vertex_coordinates(f_vkeys[v])
            vec = cg.Vector.from_start_end(f_v_xyz, v_xyz)
            dot = dot_vectors(f_normal, vec)
            if i == 0:
                dot_0 = dot
            else:
                if dot_0 * dot < 0:
                    return "This is not a convex cell."
    print("This is a convex cell.")
    return True
Ejemplo n.º 8
0
def trimesh_edge_cotangent(mesh, u, v):
    """Compute the cotangent of the angle opposite a halfedge of the triangle mesh.

    Parameters
    ----------
    mesh : :class:`compas.datastructures.Mesh`
        Instance of mesh.
    u : int
        The identifier of the first vertex of the halfedge.
    v : int
        The identifier of the second vertex of the halfedge.

    Returns
    -------
    float
        The edge cotangent.

    """
    fkey = mesh.halfedge[u][v]
    cotangent = 0.0
    if fkey is not None:
        w = mesh.face_vertex_ancestor(fkey, u)
        wu = mesh.edge_vector(w, u)
        wv = mesh.edge_vector(w, v)
        length = length_vector(cross_vectors(wu, wv))
        if length:
            cotangent = dot_vectors(wu, wv) / length
    return cotangent
Ejemplo n.º 9
0
def get_force_mags(volmesh, network):
    """Returns a dictionary of (u,v)-magnitude pairs.
    Negative magnitude means compression, while positive magnitude means tension.
    """
    uv_hf_dict = pair_uv_to_hf(network, volmesh)

    mags = {}

    for u, v in network.edges():
        hfkey = uv_hf_dict[(u, v)]
        edge_vector = network.edge_vector(u, v)
        face_normal = volmesh.halfface_oriented_normal(hfkey)
        face_area = volmesh.halfface_oriented_area(hfkey)
        dot = dot_vectors(face_normal, edge_vector)

        if dot < 0:
            factor = -1

        if dot > 0:
            factor = 1

        force = face_area * factor

        mags[(u, v)] = force

    return mags
Ejemplo n.º 10
0
    def from_plane(cls, plane):
        """Construct a reflection transformation that mirrors wrt the given plane.

        Parameters
        ----------
        plane : [point, vector] | :class:`compas.geometry.Plane`
            The reflection plane.

        Returns
        -------
        :class:`compas.geometry.Reflection`
            The reflection transformation.

        """
        point, normal = plane
        normal = normalize_vector((list(normal)))
        matrix = identity_matrix(4)
        for i in range(3):
            for j in range(3):
                matrix[i][j] -= 2.0 * normal[i] * normal[j]
        for i in range(3):
            matrix[i][3] = 2 * dot_vectors(point, normal) * normal[i]
        R = cls()
        R.matrix = matrix
        return R
Ejemplo n.º 11
0
def matrix_from_orthogonal_projection(plane):
    """Returns an orthogonal projection matrix to project onto a plane.

    Parameters
    ----------
    plane : [point, normal] | :class:`compas.geometry.Plane`
        The plane to project onto.

    Returns
    -------
    list[list[float]]
        The 4x4 transformation matrix representing an orthogonal projection.

    Examples
    --------
    >>> point = [0, 0, 0]
    >>> normal = [0, 0, 1]
    >>> plane = (point, normal)
    >>> P = matrix_from_orthogonal_projection(plane)

    """
    point, normal = plane
    T = identity_matrix(4)
    normal = normalize_vector(normal)

    for j in range(3):
        for i in range(3):
            T[i][j] -= normal[i] * normal[j]  # outer_product

    T[0][3], T[1][3], T[2][3] = scale_vector(normal,
                                             dot_vectors(point, normal))
    return T
Ejemplo n.º 12
0
def closest_point_on_line(a, b, c):
    """Closest point on line.
    Same as projection.

    Parameters
    ----------
    a: list
        First line point coordinates.
    b: list
        Second line point coordinates.
    c: list
        Point coordinates.

    Returns
    -------
    tuple
        The projected point coordinates and the distance from the input point.
    """

    ab = subtract_vectors(b, a)
    ac = subtract_vectors(c, a)

    if length_vector(ab) == 0:
        return a, distance_point_point(c, a)

    p = add_vectors(
        a, scale_vector(ab,
                        dot_vectors(ab, ac) / length_vector(ab)**2))
    distance = distance_point_point(c, p)
    return p, distance
Ejemplo n.º 13
0
def intersection_plane_plane(plane1, plane2, tol=1e-6):
    """Computes the intersection of two planes

    Parameters
    ----------
    plane1 : tuple
        The base point and normal (normalized) defining the 1st plane.
    plane2 : tuple
        The base point and normal (normalized) defining the 2nd plane.
    tol : float, optional
        A tolerance for membership verification.
        Default is ``1e-6``.

    Returns
    -------
    line : tuple
        Two points defining the intersection line. None if planes are parallel.

    """
    o1, n1 = plane1
    o2, n2 = plane2

    if fabs(dot_vectors(n1, n2)) >= 1 - tol:
        return None

    # direction of intersection line
    d = cross_vectors(n1, n2)
    # vector in plane 1 perpendicular to the direction of the intersection line
    v1 = cross_vectors(d, n1)
    # point on plane 1
    p1 = add_vectors(o1, v1)

    x1 = intersection_line_plane((o1, p1), plane2, tol=tol)
    x2 = add_vectors(x1, d)
    return x1, x2
Ejemplo n.º 14
0
def trimesh_edge_cotangent(mesh, u, v):
    """Compute the cotangent of the angle opposite a halfedge of the triangle mesh.

    Parameters
    ----------
    mesh : compas.datastructures.Mesh
        The triangle mesh data structure.
    u : int
        The identifier of the first vertex of the halfedge.
    v : int
        The identifier of the second vertex of the halfedge.

    Returns
    -------
    float
        The edge cotangent.

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

        pass

    """
    fkey = mesh.halfedge[u][v]
    cotangent = 0.0
    if fkey is not None:
        w = mesh.face_vertex_ancestor(fkey, u)
        wu = mesh.edge_vector(w, u)
        wv = mesh.edge_vector(w, v)
        l = length_vector(cross_vectors(wu, wv))
        if l:
            cotangent = dot_vectors(wu, wv) / l
    return cotangent
def match_paths_orientations(pts, reference_points, is_closed):
    """
    Check if new curve has same direction as prev curve, otherwise reverse.

    Parameters
    ----------
    pts: list, :class: 'compas.geometry.Point'. The list of points whose direction we are fixing.
    reference_points: list, :class: 'compas.geometry.Point'. [p1, p2] Two reference points.
    is_closed : bool, Determines if the path is closed or open
    """
    if len(pts) > 2 and len(reference_points) > 2:
        v1 = normalize_vector(subtract_vectors(pts[0], pts[2]))
        v2 = normalize_vector(
            subtract_vectors(reference_points[0], reference_points[2]))
    else:
        v1 = normalize_vector(subtract_vectors(pts[0], pts[1]))
        v2 = normalize_vector(
            subtract_vectors(reference_points[0], reference_points[1]))

    if dot_vectors(v1, v2) < 0:
        if is_closed:
            items = deque(reversed(pts))
            items.rotate(1)  # bring last point again in the front
            pts = list(items)
        else:
            pts.reverse()
    return pts
Ejemplo n.º 16
0
def closest_point_on_segment(a, b, c):
    """Closest point on segment.
    Different from projection because an extremity is yielded if the projection is on the line but outside the segment.

    Parameters
    ----------
    a: list
        First line point coordinates.
    b: list
        Second line point coordinates.
    c: list
        Point coordinates.

    Returns
    -------
    tuple
        The projected point coordinates and the distance from the input point.
    """

    p, distance = closest_point_on_line(a, b, c)

    ab = subtract_vectors(b, a)
    ap = subtract_vectors(p, a)

    if dot_vectors(ab, ap) < 0:
        return a, distance_point_point(c, a)
    elif length_vector(ab) < length_vector(ap):
        return b, distance_point_point(c, b)
    else:
        return p, distance
Ejemplo n.º 17
0
def mirror_vector_vector(v1, v2):
    """Mirrors vector about vector.

    Parameters
    ----------
    v1 : [float, float, float] | :class:`compas.geometry.Vector`
        The vector.
    v2 : [float, float, float] | :class:`compas.geometry.Vector`
        The normalized vector as mirror axis

    Returns
    -------
    [float, float, float]
        The mirrored vector.

    Notes
    -----
    For more info, see [1]_.

    References
    ----------
    .. [1] Math Stack Exchange. *How to get a reflection vector?*
           Available at: https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector.

    """
    return subtract_vectors(v1, scale_vector(v2, 2 * dot_vectors(v1, v2)))
Ejemplo n.º 18
0
def face_skewnesses(mesh):
    """Skewnesses of the mesh faces as dict face: face skewness.

	https://en.wikipedia.org/wiki/Types_of_mesh

	Parameters
	----------
	mesh : Mesh
		A mesh.

	Returns
	-------
	face_aspect_ratio_dict: dict
		Dictionary of aspect ratios per face {face: face aspect ratio}.

	Raises
	------
	-

	"""

    face_skewness_dict = {}
    for fkey in mesh.faces():
        equi_angle = 180 * (1 - 2 / float(len(mesh.face_vertices(fkey))))
        angles = []
        face_vertices = mesh.face_vertices(fkey)
        for i in range(len(face_vertices)):
            u = mesh.vertex_coordinates(face_vertices[i - 2])
            v = mesh.vertex_coordinates(face_vertices[i - 1])
            w = mesh.vertex_coordinates(face_vertices[i])
            uv = subtract_vectors(v, u)
            vw = subtract_vectors(w, v)
            dot = dot_vectors(uv, vw) / (length_vector(uv) * length_vector(vw))
            cross = dot_vectors(mesh.face_normal(fkey), cross_vectors(uv, vw))
            sign = 1
            if sign < 0:
                sign = -1
            angle = sign * degrees(acos(dot))
            angles.append(angle)
        max_angle = maximum(angles)
        min_angle = minimum(angles)

        face_skewness_dict[fkey] = max(
            (max_angle - equi_angle) / (180 - equi_angle),
            (equi_angle - min_angle) / equi_angle)

    return face_skewness_dict
Ejemplo n.º 19
0
 def get_frame(self):
     """ Returns a Frame with x-axis pointing up, y-axis pointing towards the mesh normal. """
     if abs(dot_vectors(self.up_vector, self.mesh_normal)
            ) < 1.0:  # if the normalized vectors are not co-linear
         c = cross_vectors(self.up_vector, self.mesh_normal)
         return Frame(self.pt, c, self.mesh_normal)
     else:  # in horizontal surfaces the vectors happen to be co-linear
         return Frame(self.pt, Vector(1, 0, 0), Vector(0, 1, 0))
Ejemplo n.º 20
0
def trimesh_edge_cotangent(mesh, u, v):
    fkey = mesh.halfedge[u][v]
    cotangent = 0.0
    if fkey is not None:
        w = mesh.face[fkey][v]  # self.vertex_descendent(v, fkey)
        wu = mesh.edge_vector(w, u)
        wv = mesh.edge_vector(w, v)
        cotangent = dot_vectors(wu, wv) / length_vector(cross_vectors(wu, wv))
    return cotangent
Ejemplo n.º 21
0
 def is_negative(self, key):
     o = self.plane.point
     n = self.plane.normal
     if key in self.intersections:
         return False
     a = self.mesh.vertex_attributes(key, 'xyz')
     oa = subtract_vectors(a, o)
     similarity = dot_vectors(n, oa)
     return similarity < 0.0
Ejemplo n.º 22
0
def intersection_segment_plane(segment, plane, tol=1e-6):
    """Computes the intersection point of a line segment and a plane

    Parameters
    ----------
    segment : [point, point] | :class:`compas.geometry.Line`
        Two points defining the line segment.
    plane : [point, vector] | :class:`compas.geometry.Plane`
        The base point and normal defining the plane.
    tol : float, optional
        A tolerance for membership verification.

    Returns
    -------
    [float, float, float] | None
        The intersection point between the line and the plane,
        or None if the line and the plane are parallel.

    """
    a, b = segment
    o, n = plane

    ab = subtract_vectors(b, a)
    cosa = dot_vectors(n, ab)

    if fabs(cosa) <= tol:
        # if the dot product (cosine of the angle between segment and plane)
        # is close to zero the line and the normal are almost perpendicular
        # hence there is no intersection
        return None

    # based on the ratio = -dot_vectors(n, ab) / dot_vectors(n, oa)
    # there are three scenarios
    # 1) 0.0 < ratio < 1.0: the intersection is between a and b
    # 2) ratio < 0.0: the intersection is on the other side of a
    # 3) ratio > 1.0: the intersection is on the other side of b
    oa = subtract_vectors(a, o)
    ratio = -dot_vectors(n, oa) / cosa

    if 0.0 <= ratio and ratio <= 1.0:
        ab = scale_vector(ab, ratio)
        return add_vectors(a, ab)

    return None
Ejemplo n.º 23
0
def matrix_from_perspective_projection(plane, center_of_projection):
    """Returns a perspective projection matrix to project onto a plane along lines that emanate from a single point, called the center of projection.

    Parameters
    ----------
    plane : [point, normal] | :class:`compas.geometry.Plane`
        The plane to project onto.
    center_of_projection : [float, float, float] | :class:`compas.geometry.Point`
        The camera view point.

    Returns
    -------
    list[list[float]]
        A 4-by-4 transformation matrix.

    Examples
    --------
    >>> point = [0, 0, 0]
    >>> normal = [0, 0, 1]
    >>> plane = (point, normal)
    >>> center_of_projection = [1, 1, 0]
    >>> P = matrix_from_perspective_projection(plane, center_of_projection)

    """
    point, normal = plane
    T = identity_matrix(4)
    normal = normalize_vector(normal)

    T[0][0] = T[1][1] = T[2][2] = dot_vectors(
        subtract_vectors(center_of_projection, point), normal)

    for j in range(3):
        for i in range(3):
            T[i][j] -= center_of_projection[i] * normal[j]

    T[0][3], T[1][3], T[2][3] = scale_vector(center_of_projection,
                                             dot_vectors(point, normal))

    for i in range(3):
        T[3][i] -= normal[i]

    T[3][3] = dot_vectors(center_of_projection, normal)

    return T
Ejemplo n.º 24
0
 def is_positive(self, key):
     o = self.plane.point
     n = self.plane.normal
     if key not in self.intersections:
         a = self.mesh.vertex_attributes(key, 'xyz')
         oa = subtract_vectors(a, o)
         similarity = dot_vectors(n, oa)
         if similarity > 0.0:
             return True
     return False
Ejemplo n.º 25
0
def _add_point(points, hull, p):
    seen_faces = [face for face in hull if _seen(points, face, p)]
    if len(seen_faces) == len(hull):
        # if can see all faces, unsee ones looking "down"
        normal = _normal_face(points, seen_faces[0])
        seen_faces = [face for face in seen_faces if dot_vectors(_normal_face(points, face), normal) > 0]
    for face in seen_faces:
        hull.remove(face)
    for edge in _bdry(seen_faces):
        hull.append([edge[0], edge[1], p])
Ejemplo n.º 26
0
    def dot(self, other):
        """The dot product of this ``Vector`` and another ``Vector``.

        Parameters:
            other (tuple, list, Vector): The vector to dot.

        Returns:
            float: The dot product.
        """
        return dot_vectors(self, other)
Ejemplo n.º 27
0
def _check_deviation(volmesh, network):
    deviation = 0
    for u, v in network.edges():
        u_hf, v_hf = volmesh.cell_pair_halffaces(u, v)
        normal = volmesh.halfface_oriented_normal(u_hf)
        edge   = network.edge_vector(u, v, unitized=True)
        dot    = dot_vectors(normal, edge)
        perp_check = 1 - abs(dot)
        if perp_check > deviation:
            deviation = perp_check
    return deviation
Ejemplo n.º 28
0
    def filter_aligned_vectors(self, vec, vecs_a, vecs_b):
        vec_tuples = zip(vecs_a, vecs_b)
        aligned_vecs = []

        for vec_t in vec_tuples:
            if cg.dot_vectors(vec, vec_t[0]) < 0:
                aligned_vecs.append(vec_t[1])

            else:
                aligned_vecs.append(vec_t[0])
        return aligned_vecs
def check_for_parallel_vectors(start_beam, beams_to_check):
    #this function is only used once

    a = start_beam.frame.xaxis
    for beam in beams_to_check:
        tol = 1.0e-5
        b = beam.frame.xaxis
        if abs(abs(dot_vectors(a, b)) - 1.0) > tol:
            return False

    return True
Ejemplo n.º 30
0
    def __init__(self, point, normal):
        super(Reflection, self).__init__()

        normal = normalize_vector((list(normal)))

        for i in range(3):
            for j in range(3):
                self.matrix[i][j] -= 2.0 * normal[i] * normal[j]

        for i in range(3):
            self.matrix[i][3] = 2 * dot_vectors(point, normal) *\
                normal[i]