Esempio n. 1
0
def project_point_line_xy(point, line):
    """Project a point onto a line in the XY plane.

    Parameters
    ----------
    point : [float, float, float] | :class:`compas.geometry.Point`
        XY(Z) coordinates of the point.
    line : [point, point] | :class:`compas.geometry.Line`
        Two points defining the projection line.

    Returns
    -------
    [float, float, float]
        XYZ coordinates of the projected point, with Z=0.

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

    References
    ----------
    .. [1] Wiki Books. *Linear Algebra/Orthogonal Projection Onto a Line*.
           Available at: https://en.wikibooks.org/wiki/Linear_Algebra/Orthogonal_Projection_Onto_a_Line.

    """
    a, b = line
    ab = subtract_vectors_xy(b, a)
    ap = subtract_vectors_xy(point, a)
    c = vector_component_xy(ap, ab)
    return add_vectors_xy(a, c)
Esempio n. 2
0
def mirror_point_point_xy(point, mirror):
    """Mirror a point about a point.

    Parameters
    ----------
    point : [float, float, float] | :class:`compas.geometry.Point`
        XY(Z) coordinates of the point to mirror.
    mirror : [float, float, float] | :class:`compas.geometry.Point`
        XY(Z) coordinates of the mirror point.

    Returns
    -------
    [float, float, float]
        The mirrored point, with Z=0.

    """
    return add_vectors_xy(mirror, subtract_vectors_xy(mirror, point))
Esempio n. 3
0
def mirror_point_point_xy(point, mirror):
    """Mirror a point about a point.

    Parameters
    ----------
    point : list of float
        XY(Z) coordinates of the point to mirror.
    mirror : list of float
        XY(Z) coordinates of the mirror point.

    Returns
    -------
    list of float
        The mirrored point, with Z=0.

    """
    return add_vectors_xy(mirror, subtract_vectors_xy(mirror, point))
Esempio n. 4
0
def mirror_point_line_xy(point, line):
    """Mirror a point about a line.

    Parameters
    ----------
    point : [float, float, float] | :class:`compas.geometry.Point`
        XY(Z) coordinates of the point to mirror.
    line : [point, point] | :class:`compas.geometry.Line`
        Two points defining the line.
        XY(Z) coordinates of the two points defining the mirror line.

    Returns
    -------
    [float, float, float]
        The mirrored point, with Z=0.

    """
    closest = closest_point_on_line_xy(point, line)
    return add_vectors_xy(closest, subtract_vectors_xy(closest, point))
Esempio n. 5
0
def mirror_point_line_xy(point, line):
    """Mirror a point about a line.

    Parameters
    ----------
    point : list of float
        XY(Z) coordinates of the point to mirror.
    line : tuple
        Two points defining the line.
        XY(Z) coordinates of the two points defining the mirror line.

    Returns
    -------
    list of float
        The mirrored point, with Z=0.

    """
    closest = closest_point_on_line_xy(point, line)
    return add_vectors_xy(closest, subtract_vectors_xy(closest, point))
Esempio n. 6
0
def intersection_circle_circle_xy(circle1, circle2):
    """Calculates the intersection points of two circles in 2d lying in the XY plane.

    Parameters
    ----------
    circle1 : tuple
        center, radius of the first circle in the xy plane.
    circle2 : tuple
        center, radius of the second circle in the xy plane.

    Returns
    -------
    points : list of tuples
        the intersection points if there are any
    None
        if there are no intersection points

    """
    p1, r1 = circle1[0], circle1[1]
    p2, r2 = circle2[0], circle2[1]

    d = length_vector_xy(subtract_vectors_xy(p2, p1))

    if d > r1 + r2:
        return None

    if d < fabs(r1 - r2):
        return None

    if (d == 0) and (r1 == r2):
        return None

    a = (r1 * r1 - r2 * r2 + d * d) / (2 * d)
    h = (r1 * r1 - a * a)**0.5
    cx2 = p1[0] + a * (p2[0] - p1[0]) / d
    cy2 = p1[1] + a * (p2[1] - p1[1]) / d
    i1 = ((cx2 + h * (p2[1] - p1[1]) / d), (cy2 - h * (p2[0] - p1[0]) / d), 0)
    i2 = ((cx2 - h * (p2[1] - p1[1]) / d), (cy2 + h * (p2[0] - p1[0]) / d), 0)

    return i1, i2
Esempio n. 7
0
def intersection_circle_circle_xy(circle1, circle2):
    """Calculates the intersection points of two circles in 2d lying in the XY plane.

    Parameters
    ----------
    circle1 : [plane, float] | :class:`compas.geometry.Circle`
        Circle defined by a point, with at least XY coordinates, and a radius.
    circle2 : [plane, float] | :class:`compas.geometry.Circle`
        Circle defined by a point, with at least XY coordinates, and a radius.

    Returns
    -------
    tuple[[float, float, float], [float, float, float]] | None
        The intersection points if there are any.
        If the circles are tangent to each other, the two intersection points are identical.
        None otherwise.

    """
    p1, r1 = circle1[0], circle1[1]
    p2, r2 = circle2[0], circle2[1]

    d = length_vector_xy(subtract_vectors_xy(p2, p1))

    if d > r1 + r2:
        return None

    if d < fabs(r1 - r2):
        return None

    if (d == 0) and (r1 == r2):
        return None

    a = (r1 * r1 - r2 * r2 + d * d) / (2 * d)
    h = (r1 * r1 - a * a)**0.5
    cx2 = p1[0] + a * (p2[0] - p1[0]) / d
    cy2 = p1[1] + a * (p2[1] - p1[1]) / d
    i1 = ((cx2 + h * (p2[1] - p1[1]) / d), (cy2 - h * (p2[0] - p1[0]) / d), 0)
    i2 = ((cx2 - h * (p2[1] - p1[1]) / d), (cy2 + h * (p2[0] - p1[0]) / d), 0)

    return i1, i2
Esempio n. 8
0
def network_embed_in_plane(network, fixed=None, straightline=True):
    """Embed the network in the plane.

    Parameters
    ----------
    network : Network
        A network object.
    fixed : list (None)
        Two fixed points.
    straightline : bool (True)
        Embed using straight lines.

    Returns
    -------
    bool
        True if the embedding was successful.
        False otherwise.

    Raises
    ------
    ImportError
        If NetworkX is not installed.

    Examples
    --------
    >>>
    """
    try:
        import networkx as nx
    except ImportError:
        print(
            "NetworkX is not installed. Get NetworkX at https://networkx.github.io/."
        )
        raise

    x = network.nodes_attribute('x')
    y = network.nodes_attribute('y')
    xmin, xmax = min(x), max(x)
    ymin, ymax = min(y), max(y)
    xspan = xmax - xmin
    yspan = ymax - ymin

    edges = [(u, v) for u, v in network.edges()
             if not network.is_leaf(u) and not network.is_leaf(v)]

    is_embedded = False

    count = 100
    while count:
        graph = nx.Graph(edges)
        pos = nx.spring_layout(graph, iterations=100, scale=max(xspan, yspan))
        if not _are_edges_crossed(edges, pos):
            is_embedded = True
            break
        count -= 1

    if not is_embedded:
        return False

    if fixed:
        a, b = fixed
        p0 = network.node_attributes(a, 'xy')
        p1 = network.node_attributes(b, 'xy')
        p2 = pos[b]
        vec0 = subtract_vectors_xy(p1, p0)
        vec1 = subtract_vectors_xy(pos[b], pos[a])
        # rotate
        angle = angle_vectors_xy(vec0, vec1)
        if is_ccw_xy(p0, p1, p2):
            angle = 2 * pi - angle
        cosa = cos(angle)
        sina = sin(angle)
        for key in pos:
            x, y = pos[key]
            pos[key][0] = cosa * x - sina * y
            pos[key][1] = sina * x + cosa * y
        # scale
        l0 = (vec0[0]**2 + vec0[1]**2)**0.5
        l1 = (vec1[0]**2 + vec1[1]**2)**0.5
        scale = l0 / l1
        for key in pos:
            pos[key][0] *= scale
            pos[key][1] *= scale
        # translate
        t = subtract_vectors_xy(p0, pos[a])
        for key in pos:
            pos[key][0] += t[0]
            pos[key][1] += t[1]

    # update network node coordinates
    for key in network.nodes():
        if key in pos:
            network.node_attributes(key, 'xy', pos[key])

    return True
Esempio n. 9
0
    def add_feet(self, segments, feet=2):
        """"""
        def rotate(point, angle):
            x = cos(angle) * point[0] - sin(angle) * point[1]
            y = sin(angle) * point[0] + cos(angle) * point[1]
            return x, y, 0

        def cross_z(ab, ac):
            return ab[0] * ac[1] - ab[1] * ac[0]

        scale = self.attributes['feet.scale']
        alpha = self.attributes['feet.alpha'] * pi / 180
        tol = self.attributes['feet.tol']

        key_foot = {}
        key_xyz = {
            key: self.vertex_coordinates(key, 'xyz')
            for key in self.vertices()
        }

        for i, vertices in enumerate(segments):
            key = vertices[0]
            after = vertices[1]
            before = segments[i - 1][-2]

            b = key_xyz[before]
            o = key_xyz[key]
            a = key_xyz[after]

            ob = normalize_vector_xy(subtract_vectors_xy(b, o))
            oa = normalize_vector_xy(subtract_vectors_xy(a, o))

            z = cross_z(ob, oa)

            if z > +tol:
                r = normalize_vector_xy(add_vectors_xy(oa, ob))
                r = [-scale * axis for axis in r]

            elif z < -tol:
                r = normalize_vector_xy(add_vectors_xy(oa, ob))
                r = [+scale * axis for axis in r]

            else:
                ba = normalize_vector_xy(subtract_vectors_xy(a, b))
                r = cross_vectors([0, 0, 1], ba)
                r = [+scale * axis for axis in r]

            if feet == 1:
                x, y, z = add_vectors_xy(o, r)
                m = self.add_vertex(x=x,
                                    y=y,
                                    z=o[2],
                                    is_fixed=True,
                                    is_external=True)
                key_foot[key] = m

            elif feet == 2:
                lx, ly, lz = add_vectors_xy(o, rotate(r, +alpha))
                rx, ry, rz = add_vectors_xy(o, rotate(r, -alpha))
                l = self.add_vertex(x=lx,
                                    y=ly,
                                    z=o[2],
                                    is_fixed=True,
                                    is_external=True)
                r = self.add_vertex(x=rx,
                                    y=ry,
                                    z=o[2],
                                    is_fixed=True,
                                    is_external=True)
                key_foot[key] = l, r

            else:
                pass

        for vertices in segments:
            l = vertices[0]
            r = vertices[-1]

            if feet == 1:
                lm = key_foot[l]
                rm = key_foot[r]
                self.add_face([lm] + vertices + [rm], is_loaded=False)
                self.set_edge_attribute((l, lm), 'is_external', True)
                self.set_edge_attribute((rm, lm), 'is_edge', False)

            elif feet == 2:
                lb = key_foot[l][0]
                la = key_foot[l][1]
                rb = key_foot[r][0]
                self.add_face([lb, l, la], is_loaded=False)
                self.add_face([la] + vertices + [rb], is_loaded=False)
                self.set_edge_attribute((l, lb), 'is_external', True)
                self.set_edge_attribute((l, la), 'is_external', True)
                self.set_edge_attribute((lb, la), 'is_edge', False)
                self.set_edge_attribute((la, rb), 'is_edge', False)

            else:
                pass