Пример #1
0
    def draw_blocks(self,
                    keys=None,
                    facecolor=None,
                    edgecolor=None,
                    edgewidth=None,
                    textcolor=None,
                    fontsize=None):
        """Draw the blocks of an assembly.

        Notes
        -----
        The blocks are drawn as the boundaing boxes of their vertices.

        """
        keys = keys or list(self.assembly.vertices())

        facecolordict = valuedict(keys, facecolor, self.block_plotter.defaults['face.facecolor'])
        edgecolordict = valuedict(keys, edgecolor, self.block_plotter.defaults['face.edgecolor'])
        edgewidthdict = valuedict(keys, edgewidth, self.block_plotter.defaults['face.edgewidth'])
        textcolordict = valuedict(keys, textcolor, self.block_plotter.defaults['face.textcolor'])
        fontsizedict  = valuedict(keys, fontsize,  self.block_plotter.defaults['face.fontsize'])

        polygons = []
        for key, attr in self.assembly.vertices(True):
            block = self.assembly.blocks[key]
            xyz = block.get_vertices_attributes('xyz')
            box = bounding_box_xy(xyz)
            polygons.append({
                'points': box,
                'edgecolor': edgecolordict[key],
                'edgewidth': edgewidthdict[key],
                'facecolor': facecolordict[key]
            })
        self.draw_polygons(polygons)
Пример #2
0
def offset_bbox_xy(pts, dist):
    bbox = pca_numpy(pts)
    frame1 = Frame(bbox[0], bbox[1][0], bbox[1][1])
    xform = Transformation.from_frame_to_frame(frame1, Frame.worldXY())
    pts = transform_points(pts, xform)
    bbox = bounding_box_xy(pts)
    bbox = offset_polygon(bbox, dist)
    return bbox, xform
Пример #3
0
def mesh_bounding_box_xy(mesh):
    """Compute the (axis aligned) bounding box of a projection of the mesh in the XY plane.

    Parameters
    ----------
    mesh : compas.datastructures.Mesh
        The mesh data structure.

    Returns
    -------
    list of point
        The 4 corners of the bounding polygon in the XY plane.

    Examples
    --------
    >>> mesh_bounding_box_xy(mesh)
    [[0.0, 0.0, 0.0], [10.0, 0.0, 0.0], [10.0, 10.0, 0.0], [0.0, 10.0, 0.0]]

    """
    xyz = mesh.get_vertices_attributes('xyz')
    return bounding_box_xy(xyz)
Пример #4
0
def mesh_bounding_box_xy(mesh):
    """Compute the (axis aligned) bounding box of a projection of the mesh in the XY plane.

    Parameters
    ----------
    mesh : compas.datastructures.Mesh
        The mesh data structure.

    Returns
    -------
    box_xy
        The bounding box.

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

        pass

    """
    xyz = mesh.get_vertices_attributes('xyz')
    return bounding_box_xy(xyz)
Пример #5
0
def mesh_bounding_box_xy(mesh):
    """Compute the (axis aligned) bounding box of a projection of the mesh in the XY plane.

    Parameters
    ----------
    mesh : :class:`compas.datastructures.Mesh`
        The mesh data structure.

    Returns
    -------
    list[list[float]]
        The 4 corners of the bounding polygon in the XY plane.

    Examples
    --------
    >>> from compas.datastructures import Mesh
    >>> mesh = Mesh.from_obj(compas.get('faces.obj'))
    >>> mesh_bounding_box_xy(mesh)
    [[0.0, 0.0, 0.0], [10.0, 0.0, 0.0], [10.0, 10.0, 0.0], [0.0, 10.0, 0.0]]

    """
    xyz = mesh.vertices_attributes('xyz')
    return bounding_box_xy(xyz)
    origin = result[0][0]
    xaxis = normalize_vector(result[1][0])
    yaxis = normalize_vector(result[1][1])
    zaxis = normalize_vector(result[1][2])
    frame = Frame(origin, xaxis, yaxis)

    if yaxis[2] > 0:
        offset = scale_vector(zaxis, -0.050)
    else:
        offset = scale_vector(zaxis, +0.050)

    points_xy = [
        frame.represent_point_in_local_coordinates(point) for point in points
    ]
    box_xy = bounding_box_xy(points_xy)
    box = [
        frame.represent_point_in_global_coordinates(corner_xy)[:]
        for corner_xy in box_xy
    ]
    box1 = offset_polygon(box, -0.025)
    box2 = [add_vectors(point, offset) for point in box1]

    POLYGONS.append({'points': box1 + box1[:1], 'color': (0, 0, 0)})

    POLYGONS.append({'points': box2 + box2[:1], 'color': (0, 0, 0)})

    POLYGONS.append({
        'points': [box1[0], box1[3], box2[3], box2[0], box1[0]],
        'color': (0, 0, 0)
    })
Пример #7
0
# ==============================================================================
# Transform the local coordinates to world coordinates to make it an axis-aligned
# problem.
# ==============================================================================

X = Transformation.from_frame_to_frame(frame1, Frame.worldXY())
points = transform_points(points, X)

# ==============================================================================
# Compute the axis aligned bounding box in world coordinates, ignoring the Z
# components of the points. Add some padding to the bounding box to avoid having
# vertices on the boundaries of the box. Convert the box back to the local
# coordinate system.
# ==============================================================================

bbox = bounding_box_xy(points)
bbox = offset_polygon(bbox, -PADDING)
bbox = transform_points(bbox, X.inverse())

# ==============================================================================
# Convert the box to a mesh for visualisation.
# ==============================================================================

bbox = Mesh.from_vertices_and_faces(bbox, [[0, 1, 2, 3]])

# ==============================================================================
# Use a frame artist to visualize the boundary frame.
# ==============================================================================

artist = FrameArtist(frame, layer="SOUTH::Frame", scale=0.3)
artist.clear_layer()
Пример #8
0
def test_bounding_box_xy(coords, expected):
    assert expected == bounding_box_xy(coords)
        # # ==============================================================================
        # # Transform the local coordinates to world coordinates to make it an axis-aligned
        # # problem.
        # # ==============================================================================

        X = Transformation.from_frame_to_frame(frame, Frame.worldXY())
        points = transform_points(points, X)

        # # ==============================================================================
        # # Compute the axis aligned bounding box in world coordinates, ignoring the Z
        # # components of the points. Add some padding to the bounding box to avoid having
        # # vertices on the boundaries of the box. Convert the box back to the local
        # # coordinate system.
        # # ==============================================================================

        front = bounding_box_xy(points)
        front = offset_polygon(front, -PADDING)
        front = transform_points(front, X.inverse())

        # # ==============================================================================
        # # Check if boundary normal and local normal have the same direction, if not reverse
        # # list of vertices. Create a 3D box by moving the vertices of the found 2D bounding
        # # box along the z-axis of the boundary coordinate system.
        # # ==============================================================================

        back = []
        angle = angles_vectors(frame.zaxis, frame_0.zaxis, deg=False)

        if angle[0] != 0:
            front.reverse()
Пример #10
0
def generate_raft(slicer,
                  raft_offset=10,
                  distance_between_paths=10,
                  direction="xy_diagonal",
                  raft_layers=1,
                  raft_layer_height=None):
    """Creates a raft.

    Parameters
    ----------
    slicer: :class:`compas_slicer.slicers.BaseSlicer`
        An instance of one of the compas_slicer.slicers.BaseSlicer classes.
    raft_offset: float
        Distance (in mm) that the raft should be offsetted from the first layer. Defaults to 10mm
    distance_between_paths: float
        Distance (in mm) between the printed lines of the raft. Defaults to 10mm
    direction: str
        x_axis: Create a raft aligned with the x_axis
        y_axis: Create a raft aligned with the y_axis
        xy_diagonal: Create a raft int the diagonal direction in the xy_plane
    raft_layers: int
        Number of raft layers to add. Defaults to 1
    raft_layer_height: float
        Layer height of the raft layers. Defaults to same value as used in the slicer.
    """

    # check if a raft_layer_height is specified, if not, use the slicer.layer_height value
    if not raft_layer_height:
        raft_layer_height = slicer.layer_height

    logger.info("Generating raft")

    # find if slicer has vertical or horizontal layers, and select which paths are to be offset.
    if isinstance(slicer.layers[0], compas_slicer.geometry.VerticalLayer):  # Vertical layers
        # then find all paths that lie on the print platform and make them brim.
        paths_to_offset, _ = slicer.find_vertical_layers_with_first_path_on_base()

    else:  # Horizontal layers
        # then replace the first layer with a raft layer.
        paths_to_offset = slicer.layers[0].paths

    # get flat lists of points in bottom layer
    all_pts = []
    for path in paths_to_offset:
        for pt in path.points:
            all_pts.append(pt)

    # get xy bounding box of bottom layer and create offset
    bb_xy = bounding_box_xy(all_pts)
    bb_xy_offset = offset_polygon(bb_xy, -raft_offset)
    # bring points in the xy_offset to the correct height
    for pt in bb_xy_offset:
        pt[2] = slicer.layers[0].paths[0].points[0][2]

    # calculate x range, y range, and number of steps
    x_range = abs(bb_xy_offset[0][0] - bb_xy_offset[1][0])
    y_range = abs(bb_xy_offset[0][1] - bb_xy_offset[3][1])

    # get maximum values of the bounding box
    bb_max_x_right = bb_xy_offset[1][0]
    bb_max_y_top = bb_xy_offset[3][1]

    # get point in bottom left corner as raft start point
    raft_start_pt = Point(bb_xy_offset[0][0], bb_xy_offset[0][1], bb_xy_offset[0][2])

    # create starting line for diagonal direction
    if direction == "xy_diagonal":
        c = math.sqrt(2*(distance_between_paths**2))

        pt1 = Point(raft_start_pt[0] + c, raft_start_pt[1], raft_start_pt[2])
        pt2 = Point(pt1[0] - y_range, pt1[1] + y_range, pt1[2])
        line = Line(pt1, pt2)

    # move all points in the slicer up so that raft layers can be inserted
    for i, layer in enumerate(slicer.layers):
        for j, path in enumerate(layer.paths):
            for k, pt in enumerate(path.points):
                slicer.layers[i].paths[j].points[k] = Point(pt[0], pt[1], pt[2] + (raft_layers)*raft_layer_height)

    for i in range(raft_layers):

        iter = 0
        raft_points = []

        # create raft points depending on the chosen direction
        while iter < 9999:  # to avoid infinite while loop in case something is not correct
            # ===============
            # VERTICAL RAFT
            # ===============
            if direction == "y_axis":
                raft_pt1 = Point(raft_start_pt[0] + iter*distance_between_paths, raft_start_pt[1], raft_start_pt[2] + i*raft_layer_height)
                raft_pt2 = Point(raft_start_pt[0] + iter*distance_between_paths, raft_start_pt[1] + y_range, raft_start_pt[2] + i*raft_layer_height)

                if raft_pt2[0] > bb_max_x_right or raft_pt1[0] > bb_max_x_right:
                    break

            # ===============
            # HORIZONTAL RAFT
            # ===============
            elif direction == "x_axis":
                raft_pt1 = Point(raft_start_pt[0], raft_start_pt[1] + iter*distance_between_paths, raft_start_pt[2] + i*raft_layer_height)
                raft_pt2 = Point(raft_start_pt[0] + x_range, raft_start_pt[1] + iter*distance_between_paths, raft_start_pt[2] + i*raft_layer_height)

                if raft_pt2[1] > bb_max_y_top or raft_pt1[1] > bb_max_y_top:
                    break

            # ===============
            # DIAGONAL RAFT
            # ===============
            elif direction == "xy_diagonal":
                # create offset of the initial diagonal line
                offset_l = offset_line(line, iter*distance_between_paths, Vector(0, 0, -1))

                # get intersections for the initial diagonal line with the left and bottom of the bb
                int_left = intersection_line_line(offset_l, [bb_xy_offset[0], bb_xy_offset[3]])
                int_bottom = intersection_line_line(offset_l, [bb_xy_offset[0], bb_xy_offset[1]])

                # get the points at the intersections
                raft_pt1 = Point(int_left[0][0], int_left[0][1], int_left[0][2] + i*raft_layer_height)
                raft_pt2 = Point(int_bottom[0][0], int_bottom[0][1], int_bottom[0][2] + i*raft_layer_height)

                # if the intersection goes beyond the height of the left side of the bounding box:
                if int_left[0][1] > bb_max_y_top:
                    # create intersection with the top side
                    int_top = intersection_line_line(offset_l, [bb_xy_offset[3], bb_xy_offset[2]])
                    raft_pt1 = Point(int_top[0][0], int_top[0][1], int_top[0][2] + i*raft_layer_height)

                    # if intersection goes beyond the length of the top side, break
                    if raft_pt1[0] > bb_max_x_right:
                        break

                # if the intersection goes beyond the length of the bottom side of the bounding box:
                if int_bottom[0][0] > bb_max_x_right:
                    # create intersection with the right side
                    int_right = intersection_line_line(offset_l, [bb_xy_offset[1], bb_xy_offset[2]])
                    raft_pt2 = Point(int_right[0][0], int_right[0][1], int_right[0][2] + i*raft_layer_height)

                    # if intersection goes beyond the height of the right side, break
                    if raft_pt2[1] > bb_xy_offset[2][1]:
                        break

            # append to list alternating
            if iter % 2 == 0:
                raft_points.extend((raft_pt1, raft_pt2))
            else:
                raft_points.extend((raft_pt2, raft_pt1))

            iter += 1

        # create raft layer
        raft_layer = Layer([Path(raft_points, is_closed=False)])
        raft_layer.is_raft = True
        # insert raft layer in the correct position into the slicer
        slicer.layers.insert(i, raft_layer)
Пример #11
0
def GetBoundingBox(pca_numpy, intersections, PADDING, start, end, frame):

    points = intersections[start:end]
    width = 0.1

    bbox = []

    if ((end - start == 2)):

        #print("2Points")

        vector = subtract_vectors(points[0], points[1])
        vector90 = cross_vectors(frame.zaxis, vector)

        X0 = Translation(
            scale_vector([vector90[0], vector90[1], vector90[2]], width))
        X1 = Translation(
            scale_vector([vector90[0], vector90[1], vector90[2]], -width))

        pointsMoved0 = [points[0], points[1]]
        pointsMoved0 = transform_points(pointsMoved0, X0)
        pointsMoved1 = [points[0], points[1]]
        pointsMoved1 = transform_points(pointsMoved1, X1)

        bbox = [
            pointsMoved0[0], pointsMoved0[1], pointsMoved1[1], pointsMoved1[0]
        ]

        poly = Polygon(bbox)
        #print(poly)
        offset = offset_polygon(poly.points, -PADDING)
        X = Translation((0, 0, 0))

        bbox_ = transform_points(offset, X)
        # bbox = bbox_
        #print(bbox)
        #print(bbox_)

        frame_1 = Frame(points[0], vector, vector90)
        vectorLen = length_vector(vector)
        vectorSmall = subtract_vectors(bbox[1], bbox[2])
        vectorLenSmall = length_vector(vectorSmall)

    else:

        #print("N+2Points")

        origin, axes, values = pca_numpy([list(point) for point in points])
        frame_1 = Frame(origin, axes[0], axes[1])

        X = Transformation.from_frame_to_frame(frame_1, Frame.worldXY())

        points2 = transform_points(points, X)
        bbox = bounding_box_xy(points2)
        bbox = offset_polygon(bbox, -PADDING)
        bbox = transform_points(bbox, X.inverse())

        vector = subtract_vectors(bbox[0], bbox[1])
        vectorLen = length_vector(vector)
        vectorSmall = subtract_vectors(bbox[1], bbox[2])
        vectorLenSmall = length_vector(vectorSmall)

    #Unify box
    pt0 = Point(bbox[0][0], bbox[0][1], bbox[0][2])
    pt1 = Point(bbox[1][0], bbox[1][1], bbox[1][2])
    pt2 = Point(bbox[2][0], bbox[2][1], bbox[2][2])
    pt3 = Point(bbox[3][0], bbox[3][1], bbox[3][2])

    pt03 = Point((bbox[0][0] + bbox[3][0]) * 0.5,
                 (bbox[0][1] + bbox[3][1]) * 0.5,
                 (bbox[0][2] + bbox[3][2]) * 0.5)
    pt12 = Point((bbox[1][0] + bbox[2][0]) * 0.5,
                 (bbox[1][1] + bbox[2][1]) * 0.5,
                 (bbox[1][2] + bbox[2][2]) * 0.5)

    vectorSmall = normalize_vector(vectorSmall)

    X0 = Translation(scale_vector(vectorSmall, width * 0.5))
    X1 = Translation(scale_vector(vectorSmall, -width * 0.5))

    pt01 = transform_points([pt03, pt12], X0)
    pt23 = transform_points([pt03, pt12], X1)
    bbox[0] = pt01[0]
    bbox[1] = pt01[1]
    bbox[2] = pt23[1]
    bbox[3] = pt23[0]

    bbox = Mesh.from_vertices_and_faces(bbox, [[0, 1, 2, 3]])

    return [frame_1, bbox, vectorLen, vectorLenSmall]