Esempio n. 1
0
    def load_svg(path):
        """
        """

        paths, attributes = svg2paths(path)

        result = ddd.group2()

        for k, v in enumerate(attributes):
            #print(v)  # v['d']  # print d-string of k-th path in SVG

            # Ex svgpath = 'M10 10 C 20 20, 40 20, 50 10Z'
            mpl_path = parse_path(v['d'])
            '''
            import matplotlib.pyplot as plt
            fig = plt.figure(figsize=(200, 200))
            ax = fig.add_subplot(111)
            ax.axis([0, 0, 200, 200])
            collection = matplotlib.collections.PathCollection([mpl_path])
            collection.set_transform(ax.transData)
            #patch = matplotlib.patches.PathPatch(mpl_path, facecolor="red", lw=2)
            ax.add_artist(collection)
            #ax.add_patch(patch)
            ax.set_xlim([0, 200])
            ax.set_ylim([200, 0])
            plt.show()
            '''

            coords = mpl_path.to_polygons(closed_only=True)

            item = ddd.polygon(coords[0]).clean()  #.convex_hull()

            for c in coords[1:]:
                ng = ddd.polygon(c).clean()  #.convex_hull()
                #ng.show()
                #print (ng.geom.is_valid)
                #if not ng.geom.is_valid: continue
                if item.contains(ng):
                    item = item.subtract(ng)
                else:
                    item = item.union(ng)

            #result = ddd.group([ddd.polygon(c) for c in coords], empty=2)
            result.append(item)

        #result = result.scale([1.0 / (48 * 64), -1.0 / (48 * 64)])
        #result = result.simplify(0.005)  #
        #result.show()

        result = result.union().scale([1, -1]).clean(0)
        xmin, ymin, xmax, ymax = result.bounds()
        result = result.translate([0, -(ymin + ymax)])
        #result = ddd.align.anchor(result, ddd.ANCHOR_CENTER)

        return result
Esempio n. 2
0
def reed(height=None, leaves=None):

    if leaves is None:
        leaves = random.randint(4, 7)
    if height is None:
        height = random.uniform(1.3, 1.9)

    reed = ddd.group3(name="Reed")
    for i in range(leaves):
        lh = height + random.uniform(-0.4, 0.4)
        lb = 0.02 * lh
        item = ddd.polygon([[-lb, 0.0], [lb, 0.0], [0, lh]],
                           name="Reed leaf").triangulate(
                               twosided=True).material(ddd.mats.treetop)
        item = item.rotate(ddd.ROT_FLOOR_TO_FRONT)
        item = ddd.group([item, item.rotate(ddd.ROT_TOP_CW)], name="Reed leaf")
        item = ddd.uv.map_cubic(item, scale=(0.2, 2.0))
        item = item.rotate([0, 0, random.uniform(0, math.pi)])
        item = item.rotate([random.uniform(0.1, 0.3), 0, 0])
        torsion_advance = math.pi / 4
        item = item.rotate([0, 0, torsion_advance])
        rt = 0.15
        item = item.translate(
            [random.uniform(-rt, rt),
             random.uniform(-rt, rt), 0])
        reed.append(item)

    reed = ddd.align.polar(reed, 0.1, rotate=True)

    reed = reed.combine()
    return reed
Esempio n. 3
0
    def generate_areas_2d_ways_interiors(self, union):
        """
        Generates interways areas.
        """

        result = ddd.group2()
        if not union.geom: return result

        for c in ([union.geom]
                  if union.geom.type == "Polygon" else union.geom):
            if c.type == "LineString":
                logger.warning(
                    "Interways areas union resulted in LineString geometry. Skipping."
                )
                continue
            if len(c.interiors) == 0:
                continue

            logger.info("Generating %d interiors.", len(c.interiors))
            for interior in c.interiors:
                area = ddd.polygon(interior.coords, name="Interways area")
                if area:
                    area = area.subtract(union)
                    area = area.clean(eps=0.01)
                    #area = area.clean()
                    if area.geom:
                        area.set('ddd:area:interways', True)
                        result.append(area)
                else:
                    logger.warn("Invalid interways area.")

        return result
Esempio n. 4
0
def cart_wheel_axis(height_to_axis=0.1,
                    wheel_radius=0.075,
                    width=0.06,
                    thick_interior=0.032):
    """
    """
    #wheel_radius = height_to_axis * 0.75
    #height_to_axis = wheel_radius * 1.25 # 0.10

    item = ddd.point().line_to([0, -height_to_axis]).line_to(
        [width, -height_to_axis - wheel_radius * 0.5]).line_to([width, 0])
    item = ddd.polygon(item.geom.coords)

    item = item.translate([-width * 0.5, 0]).triangulate().twosided()
    item = item.rotate(ddd.ROT_FLOOR_TO_FRONT).rotate(ddd.ROT_TOP_CW)

    side1 = item.copy().translate([-thick_interior, 0, 0])
    side2 = item.copy().translate([thick_interior, 0, 0])

    item = side1.append(side2)
    item = item.combine()
    item = item.material(ddd.mats.steel)
    item = ddd.uv.map_cubic(item)

    item.set('ddd:connector:axis', [0, 0, -height_to_axis])

    return item
Esempio n. 5
0
def childrens_playground_slide(length=4.5, height=None, width=0.60):

    slide_thick = 0.03
    side_thick = 0.06
    if height is None:
        height = length * 0.45

    side_mat = random.choice([ddd.mats.metal_paint_red, ddd.mats.metal_paint_green, ddd.mats.metal_paint_yellow])

    slideline = ddd.point([0, 0], name="Slide").line_to([0.5, 0]).line_to([3, 1.5]).line_to([3.5, 1.5])
    # TODO: slideline.interpolate_cubic(), or slideline.smooth() or similar
    slideprofile = slideline.buffer(slide_thick / 2, cap_style=ddd.CAP_FLAT)
    slide = slideprofile.scale([1 / 4.5 * length, 1 / 2.0 * height])
    slide = slide.extrude(width - side_thick, center=True).rotate(ddd.ROT_FLOOR_TO_FRONT)
    slide = slide.material(ddd.mats.steel)
    slide = ddd.uv.map_cubic(slide)

    slidesideprofile = slideline.line_to([3.5, 1.7]).line_to([3, 1.7]).line_to([0.5, 0.2]).line_to([0, 0.2])
    slidesideprofile = ddd.polygon(list(slidesideprofile.geom.coords), name="Slide profile")
    stairssideprofile = ddd.polygon([[3.5, 1.5], [3.5, 2], [4, 2], [4, 1.5], [4.5, 0], [4.0, 0], [3.5, 1.5]])
    stairssideprofile = stairssideprofile.union(ddd.point([3.75, 2]).buffer(0.25, cap_style=ddd.CAP_ROUND))
    stairssideprofile = stairssideprofile.subtract(ddd.point([3.75, 2]).buffer(0.15, cap_style=ddd.CAP_ROUND, resolution=2))  # Hole
    stairssideprofile = stairssideprofile.translate([-0.25, 0])
    slidesideprofile = slidesideprofile.union(stairssideprofile)

    slidesideprofile = slidesideprofile.scale([1 / 4.5 * length, 1 / 2.0 * height])
    slidesideprofile = slidesideprofile.extrude(side_thick, center=True).rotate(ddd.ROT_FLOOR_TO_FRONT)
    slidesideprofile = slidesideprofile.material(side_mat)
    slidesideprofile = ddd.uv.map_cubic(slidesideprofile)

    slidesideprofile1 = slidesideprofile.translate([0, width / 2, 0])
    slidesideprofile2 = slidesideprofile.translate([0, -width / 2, 0])

    item = ddd.group([slide, slidesideprofile1, slidesideprofile2])

    numsteps = int((height - 1) / 0.3) + 1
    for i in range(numsteps):
        step = ddd.box([-0.1, -((width - side_thick) / 2), 0, 0.1, ((width - side_thick) / 2), 0.05], name="Slide Step")
        step = step.translate([4 - (i + 1) * (0.5 / (numsteps + 1)), 0, (i + 1) * 0.3]).material(ddd.mats.steel)
        step = ddd.uv.map_cubic(step)
        item.append(step)

    item = item.translate([-4.5/2, 0, 0]).rotate(ddd.ROT_TOP_CCW)

    item = ddd.meshops.batch_by_material(item).clean(remove_degenerate=False)

    return item
Esempio n. 6
0
def features_points_voronoi(pipeline, root, logger):

    points = root.find("/Features2/Points")
    vor = Voronoi(points.extra['points_coords'])

    #lines = [ddd.line(vor.vertices[line]) for line in vor.ridge_vertices if -1 not in line]
    #lines = ddd.group2(lines)

    #[[], [-1, 0], [-1, 1], [1, -1, 0], [3, -1, 2], [-1, 3], [-1, 2], [0, 1, 3, 2], [2, -1, 0], [3, -1, 1]]
    #print(vor.regions)
    regions = [ddd.polygon( [vor.vertices[i] for i in r ] ) for r in vor.regions if -1 not in r]

    regions = ddd.group2(regions, name="Regions")

    root.find("/Features2").append(regions)
Esempio n. 7
0
    def process_node(prefix, node):
        node_path = prefix + "/" + node.name

        if (node.type == "Polygon2D"):
            #print(node['polygon'])
            #print(node['polygon'].__class__.__name__)
            coords = godot_vector2array(node['polygon'].args)
            position = godot_vector2(node['position'].args) if (
                'position' in node.properties) else [0, 0]
            #scale = godot_vector2(node['scale'].args) if ('scale' in node.properties) else [1, 1]
            rotation = node['rotation'] if ('rotation'
                                            in node.properties) else 0.0
            visible = node['visible'] if ('visible'
                                          in node.properties) else True

            feat = ddd.polygon(coords, name=node.name)
            feat = feat.rotate(rotation)
            feat = feat.translate(position)  # Transform should be maintained
            #feat = feat.scale([0.6, 0.6])  #T TODO: support scale somehow (ideally through godot hierarchy, but at least in metadata)

            feat.extra['godot:node:path'] = node_path
            feat.extra['godot:visible'] = visible
            #print(node_path)

            process_node_meta(feat, node)
            features.append(feat)

        elif (node.type == "Line2D"):
            coords = godot_vector2array(node['points'].args)
            position = godot_vector2(node['position'].args) if (
                'position' in node.properties) else [0, 0]
            visible = node['visible'] if ('visible'
                                          in node.properties) else True

            feat = ddd.line(coords, name=node.name)
            feat = feat.translate(position)

            feat.extra['godot:node:path'] = node_path
            feat.extra['godot:visible'] = visible

            process_node_meta(feat, node)
            features.append(feat)

        for c in node.get_children():
            process_node(prefix + "/" + node.name, c)
Esempio n. 8
0
    def georaster_coverage(self):

        covermap = ddd.group2(name="DDD GeoRaster Coverage")

        tiles_config = settings.DDD_GEO_DEM_TILES
        transformers = {}
        for tc in tiles_config:

            logger.info("Inspecting DEM file: %s", tc['path'])

            crs = tc['crs'].lower()
            transformer = transformers.get(crs, None)
            if not transformer:
                transformer = pyproj.Transformer.from_proj(crs, 'epsg:4326', always_xy=True)
                transformers[crs] = transformer

            projected_point_x0y0 = transformer.transform(tc['bounds'][0], tc['bounds'][1])
            projected_point_x0y1 = transformer.transform(tc['bounds'][0], tc['bounds'][3])
            projected_point_x1y0 = transformer.transform(tc['bounds'][2], tc['bounds'][1])
            projected_point_x1y1 = transformer.transform(tc['bounds'][2], tc['bounds'][3])

            # Generate polygon in wgs84
            tile = ddd.polygon([projected_point_x0y0, projected_point_x1y0, projected_point_x1y1, projected_point_x0y1])
            tile.name = "Tile: %s" % tc['path']

            tile.extra.update(tc)

            file_size = None
            try:
                file_size = os.path.getsize(tc['path'])
            except FileNotFoundError as e:
                pass

            tile.extra['file_size'] = file_size
            tile.extra['file_available'] = file_size is not None

            covermap.append(tile)

            #print(tc)

        #map.show()
        filename = "/tmp/ddd-georaster-coverage.geojson"
        logger.info("Saving map to: %s", filename)
        covermap.save(filename)
Esempio n. 9
0
def tennis_net(width, net_height_center=0.914, net_height_post=1.07):
    """
    Tennis net, on XY along the Y axis (since playground fields are seen x: length, y: width).
    """
    post1 = urban.post(net_height_post + 0.15).translate(
        [0, -width * 0.5, 0]).material(ddd.mats.steel)
    post2 = urban.post(net_height_post + 0.15).translate(
        [0, +width * 0.5, 0]).material(ddd.mats.steel)

    net = ddd.polygon(
        [[-width * 0.5, 0], [width * 0.5, 0], [width * 0.5, net_height_post],
         [0, net_height_center], [-width * 0.5, net_height_post]],
        name="Tennis net")
    net = net.triangulate(twosided=True).material(ddd.mats.fence)
    net = net.rotate(ddd.ROT_FLOOR_TO_FRONT).rotate(ddd.ROT_TOP_CCW)
    net = ddd.uv.map_cubic(net)

    item = ddd.group3([post1, post2, net])
    return item
Esempio n. 10
0
def post_arm_angled(height=6.0, length=5.0, lamp=None):
    """
    A lamppost arm, with a central anchor point lying _below_ the XY plane.
    Lamp is copied to the lamp anchor position.
    TODO: Support anchor points instead (should support assigment/cloning).
    """

    r = 0.5  # Distance to inner point
    width = 0.3
    height_raise = 1.0

    shape = ddd.polygon([(0, 0), (0, height - height_raise), (length, height), (r, height - height_raise - r)], name="Lamppost Arm Angled")
    arm = shape.extrude(width).rotate(ddd.ROT_FLOOR_TO_FRONT)
    arm = arm.material(ddd.mats.steel)
    arm = ddd.uv.map_cubic(arm)
    arm = arm.translate([0, width / 2, height_raise - height])

    if lamp:
        arm.append(lamp.copy().translate([length - 0.3, 0, height_raise - 0.3]))

    return arm
Esempio n. 11
0
def pipeline_test_vertex_order_align_snap(pipeline, root):
    """
    Tests geometric operations.
    """

    # Test polygon subtract, and 2D convex hull
    coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
    obj = ddd.polygon(coords).subtract(ddd.rect([1, 1, 2, 2]))
    ref = obj.convex_hull().material(ddd.MAT_HIGHLIGHT)

    # Test vertex reordering
    obj = ddd.geomops.vertex_order_align_snap(obj, ref)

    result = ddd.group([
        obj,
        ref,
        ddd.point(obj.geom.exterior.coords[0]).buffer(0.1),
        ddd.point(ref.geom.exterior.coords[0]).buffer(0.2).material(
            ddd.MAT_HIGHLIGHT),
    ])

    result.show()

    root.append(result)
Esempio n. 12
0
    def char(self, ch):
        def tuple_to_imag(t):
            return t[0] + t[1] * 1j

        #face = Face('/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf')
        face = Face(ddd.DATA_DIR + '/fonts/OpenSansEmoji.ttf')
        face.set_char_size(self.char_size)
        face.load_char(ch)

        #kerning = face.get_kerning(ch, 'x')  # or from previous, actually?
        #print(kerning)

        outline = face.glyph.outline
        y = [t[1] for t in outline.points]
        # flip the points
        outline_points = [(p[0], max(y) - p[1]) for p in outline.points]

        start, end = 0, 0
        paths = []

        for i in range(len(outline.contours)):
            end = outline.contours[i]
            points = outline_points[start:end + 1]
            points.append(points[0])
            tags = outline.tags[start:end + 1]
            tags.append(tags[0])

            segments = [
                [
                    points[0],
                ],
            ]
            for j in range(1, len(points)):
                segments[-1].append(points[j])
                if tags[j] and j < (len(points) - 1):
                    segments.append([
                        points[j],
                    ])

            for segment in segments:
                if len(segment) == 2:
                    paths.append(
                        Line(start=tuple_to_imag(segment[0]),
                             end=tuple_to_imag(segment[1])))
                elif len(segment) == 3:
                    paths.append(
                        QuadraticBezier(start=tuple_to_imag(segment[0]),
                                        control=tuple_to_imag(segment[1]),
                                        end=tuple_to_imag(segment[2])))
                elif len(segment) == 4:
                    paths.append(
                        CubicBezier(start=tuple_to_imag(segment[0]),
                                    control1=tuple_to_imag(segment[1]),
                                    control2=tuple_to_imag(segment[2]),
                                    end=tuple_to_imag(segment[3])))
                    #C = ((segment[1][0] + segment[2][0]) / 2.0,
                    #     (segment[1][1] + segment[2][1]) / 2.0)
                    #paths.append(QuadraticBezier(start=tuple_to_imag(segment[0]),
                    #                             control=tuple_to_imag(segment[1]),
                    #                             end=tuple_to_imag(C)))
                    #paths.append(QuadraticBezier(start=tuple_to_imag(C),
                    #                             control=tuple_to_imag(segment[2]),
                    #                             end=tuple_to_imag(segment[3])))

            start = end + 1

        path = Path(*paths)
        #wsvg(path, filename="/tmp/test.svg")
        path_d = path.d()

        # https://gis.stackexchange.com/questions/301605/how-to-create-shape-in-shapely-from-an-svg-path-element
        # This page also has info about SVG reading!

        #svgpath = 'M10 10 C 20 20, 40 20, 50 10Z'
        mpl_path = parse_path(path_d)

        coords = mpl_path.to_polygons(closed_only=True)

        item = None
        for c in coords:  # coords[1:]:
            if len(c) < 3: continue
            ng = ddd.polygon(c)  #.clean(eps=char_size / 100)  #.convex_hull()
            #ng.show()
            if item is None:
                item = ng
            elif item.contains(ng):
                item = item.subtract(ng)
            else:
                item = item.union(ng)
            item = item.clean(
                eps=self.char_size /
                200)  # Note that this is effectively limiting resolution

        #result = ddd.group([ddd.polygon(c) for c in coords], empty=2)
        result = item
        result = result.scale([1.0 / self.char_size, -1.0 / self.char_size])
        result = result.simplify(
            0.005)  # Note that this is effectively limiting resolution

        return (result, face)
Esempio n. 13
0
area = ddd.polygon([[0, 0], [10, 0], [10, 5], [0, 5]])
lines = sports.football_field_lines_area(area).translate([0, 0, 0.05])
area = area.triangulate().material(ddd.mats.pitch)
item = ddd.group2([area, lines])
items.append(item)
item.show()
'''

functions = (sports.handball_field_lines, sports.basketball_field_lines,
             sports.tennis_field_lines, sports.football_field_lines)

count = 3
for m in functions:
    items = ddd.group3()
    for i in range(count):
        area = ddd.polygon([[0, 0], [10, 0], [10, 5], [0, 5]]).scale(1 + i * 3).rotate(i * 2 * math.pi / count)
        lines = sports.field_lines_area(area, m).translate([0, 0, 0.05])
        area = area.triangulate().material(ddd.mats.pitch)
        item = ddd.group2([area, lines])
        items.append(item)
    items.show()

    area = ddd.regularpolygon(7, r=random.uniform(12, 20)).scale([random.uniform(0.5, 1.5), random.uniform(0.5, 1.5)]).rotate(random.uniform(0, math.pi * 2))
    lines = sports.field_lines_area(area, m).translate([0, 0, 0.05])
    area = area.triangulate().material(ddd.mats.pitch)
    item = ddd.group2([area, lines])
    item.show()



Esempio n. 14
0
def pipeline_start(pipeline, root):
    """
    Tests subdivision on several geometries (check wireframe).
    """

    items = ddd.group3()

    # Subdivision to grid
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.rect([-3, -1, -1, 1])
    figh = fig1.subtract(fig2)
    fig = figh.extrude_step(figh,
                            1.0,
                            base=False,
                            method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.extrude_step(figh.buffer(-0.25),
                           1.0,
                           method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.material(ddd.mats.logo)
    fig = ddd.uv.map_cubic(fig)
    fig = ddd.meshops.subdivide_to_grid(fig, 0.5)
    fig.show()
    items.append(fig)

    # Test slicing with plane
    figa = ddd.meshops.slice_plane(fig, [-1, -1, -1], [0.3, 0.3, 0.3])
    #figa = ddd.uv.map_cubic(figa)  # This should not be needed, slice_plane should do this
    figb = ddd.meshops.slice_plane(fig, [1, 1, 1],
                                   [0.3, 0.3, 0.3]).material(ddd.MAT_HIGHLIGHT)
    ddd.group([figa, figb]).show()

    # Subdivide to grid
    coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
    ref = ddd.polygon(coords).subtract(ddd.rect([1, 1, 2, 2]))
    obj = ref.triangulate()
    obj = ddd.meshops.subdivide_to_grid(obj, 2.0)
    #obj= obj.subdivide_to_size(2.0)
    #ddd.group3([obj, ref.triangulate().material(ddd.MAT_HIGHLIGHT).translate([0, 0, -1])]).show()
    items.append(obj.scale([0.1, 0.1, 1]).translate([0, 0, 1]))

    # Subdivide to grid (cube)
    obj = ddd.cube(d=2)
    obj = obj.material(ddd.mats.dirt)
    obj = ddd.uv.map_cubic(obj)
    obj = ddd.meshops.subdivide_to_grid(obj, 0.5)
    #obj.show()
    items.append(obj)

    # Subdivide
    fig1 = ddd.rect().extrude(1)
    fig1 = fig1.subdivide_to_size(0.5)
    items.append(fig1)
    #fig1.show()

    fig1 = ddd.rect([1, 3]).extrude(1)
    fig1 = fig1.subdivide_to_size(0.5)
    items.append(fig1)

    # Pointy end
    fig = ddd.point().buffer(0.5, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(ddd.point(), 2)
    fig = fig.subdivide_to_size(0.5)
    items.append(fig)

    # Remove bottom test
    fig = ddd.cube(d=2)
    fig = fig.subdivide_to_size(1.0)
    fig = ddd.meshops.remove_faces_pointing(fig, ddd.VECTOR_DOWN)
    items.append(fig)

    # All items
    items = ddd.align.grid(items, space=10.0)
    items.append(ddd.helper.all())
    items.show()

    root.append(items)
Esempio n. 15
0
                          penetrate=0.5).material(ddd.mats.highlight)
fig = ddd.group([point, obj, result])
fig.buffer(0.1).triangulate().show()

# Snap point inside with penetration
point = ddd.point([4.5, 0])
obj = ddd.point([5, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
result = ddd.snap.project(point, obj,
                          penetrate=0.5).material(ddd.mats.highlight)
fig = ddd.group([point, obj, result])
fig.buffer(0.1).triangulate().show()

# Irregular object
fig = ddd.group2()
coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
obj = ddd.polygon(coords)
fig.append(obj)
for i in range(10):
    point = ddd.point([random.uniform(-10, 10), random.uniform(-10, 10)])
    result = ddd.snap.project(point, obj,
                              penetrate=0).material(ddd.mats.highlight)
    fig.append(point)
    fig.append(result)
fig.buffer(0.1).triangulate().show()

# Irregular object
fig = ddd.group2()
coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
obj = ddd.polygon(coords)
fig.append(obj)
for i in range(10):
Esempio n. 16
0
def pipeline_start(pipeline, root):
    """
    Generate different geometric objects.
    """

    items = ddd.group3()

    # Remember to use JOIN_ROUND so resolution is applied when buffering points
    fig = ddd.point([0, 0]).buffer(1.0, resolution=2, join_style=ddd.JOIN_ROUND, cap_style=ddd.CAP_ROUND).triangulate()
    items.append(fig)
    fig = ddd.point([0, 0]).buffer(1.0, resolution=3, join_style=ddd.JOIN_ROUND, cap_style=ddd.CAP_ROUND).triangulate()
    items.append(fig)
    fig = ddd.point([0, 0]).buffer(1.0, resolution=4, join_style=ddd.JOIN_ROUND, cap_style=ddd.CAP_ROUND).triangulate()
    items.append(fig)

    # Extrusion with optional caps
    fig = ddd.disc().extrude(5)
    items.append(fig)
    fig = ddd.disc().extrude(5, base=False)
    items.append(fig)
    fig = ddd.disc().extrude(5, cap=False)
    items.append(fig)
    fig = ddd.disc().extrude(5, cap=False, base=False)
    items.append(fig)


    # Extrude line (to faces, not volume)
    fig1 = ddd.line([[-2, 0], [0, 0], [2, 2]])
    fig = fig1.extrude(2.0).twosided()
    items.append(fig)

    # Extrusion to line (explicit)
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.line([[-4, 0], [4, 0]])
    fig = fig1.extrude_step(fig2, 1.0)
    items.append(fig)

    # Extrusion to line (explicit)
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.line([[-3, 0], [3, 0]])
    fig = fig1.extrude_step(fig2, 1.0)
    items.append(fig)

    # Extrusion to line (explicit, method subtract)
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.line([[-3, 0], [3, 0]])
    fig = fig1.extrude_step(fig2, 1.0, method=ddd.EXTRUSION_METHOD_SUBTRACT)  # TODO: this currently fails but should be fixed
    items.append(fig)

    # Extrusion to line with vertical (explicit) for skillion roofs
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.line([[-4, 2], [4, 2]])
    fig = fig1.extrude_step(fig2, 1.0)  # TODO: this currently fails but should be fixed
    items.append(fig)

    # Extrusion to line (axis middle)
    fig1 = ddd.rect([-4, -2, 4, 2]) #.rotate(math.pi * 1.5)
    axis_major, axis_minor, axis_angle = ddd.geomops.oriented_axis(fig1)
    fig = fig1.extrude_step(axis_minor, 1.0)
    items.append(fig)

    # Extrusion to line (axis middle)
    fig1 = ddd.rect([-4, -2, 4, 2]) #.rotate(math.pi * 1.5)
    axis_major, axis_minor, axis_angle = ddd.geomops.oriented_axis(fig1)
    fig = fig1.extrude_step(axis_major, 1.0)
    items.append(fig)

    # Extrusion to line (buffered geometry) - currently fails (shapely does not return the reduced polygon linestring)
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig = fig1.extrude_step(fig1.buffer(-2.5), 1.0)
    items.append(fig)

    # Extrusion to line (buffered geometry) and back (fails, extrusion from point to shape)
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig = fig1.extrude_step(fig1.buffer(-2.5), 1.0)
    fig = fig.extrude_step(fig1, 1.0)
    items.append(fig)

    # Triangulation with hole
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.rect([-3, -1, -1, 1])
    fig = fig1.subtract(fig2).triangulate()
    items.append(fig)

    # Extrusion with hole
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.rect([-3, -1, -1, 1])
    fig = fig1.subtract(fig2).extrude(1.0)
    items.append(fig)

    # Extrusion with steps with hole
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.rect([-3, -1, -1, 1])
    figh = fig1.subtract(fig2)
    fig = figh.extrude_step(figh, 1.0, base=False)
    fig = fig.extrude_step(figh.buffer(-0.25), 1.0)
    items.append(fig)

    # Extrusion with steps with hole 2
    fig1 = ddd.rect([-4, -2, 4, 2])
    fig2 = ddd.rect([-3, -1, -1, 1])
    figh = fig1.subtract(fig2)
    fig = figh.extrude_step(figh, 1.0, base=False, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.extrude_step(figh.buffer(-0.25), 1.0, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)


    # Simple extrusion
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND).extrude(5.0)
    items.append(fig)

    # Simple extrusion
    fig = ddd.regularpolygon(5).extrude(5.0)
    items.append(fig)


    # Simple extrusion no caps
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(fig, 5.0, base=False, cap=False)
    items.append(fig)

    # Extrusion between shapes
    fig1 = ddd.point([0, 0]).buffer(1.0)
    fig2 = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig3 = ddd.point([0, 0]).buffer(1.0)
    fig = fig1.extrude_step(fig2, 3.0).extrude_step(fig3, 2.0)
    items.append(fig)

    # Extrusion
    fig = ddd.point([0, 0]).buffer(1.0)
    for i in range(10):
        fign = ddd.point([0, 0]).buffer(1.0).rotate(math.pi / 12 * i)
        fig = fig.extrude_step(fign, 0.5)
    items.append(fig)

    # Pointy end
    fig = ddd.point().buffer(2.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(ddd.point(), 5.0)
    items.append(fig)

    # Convex shapes (this fails)
    coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
    #coords.reverse()
    fig = ddd.polygon(coords).scale(0.25)
    fig = fig.extrude_step(fig.buffer(-0.5), 1)
    items.append(fig)

    # Convex shapes - subtract method (works)
    coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
    #coords.reverse()
    fig = ddd.polygon(coords).scale(0.25)
    fig = fig.extrude_step(fig.buffer(-0.5), 1, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)

    # Extrude-subtract to bigger
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(fig.buffer(1.0), 5.0, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)

    # Extrude-subtract downwards
    shape = ddd.disc().scale([3, 2])
    fig = shape.extrude_step(shape.buffer(-0.5), -1.0, base=False, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.extrude_step(shape.buffer(-1.0), -0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)

    # Extrude-subtract vertical case
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(fig, 5.0, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)

    # Convex shapes with holes - subtract method
    fig = ddd.group3()
    text = Text3D.quick_text("86A").scale(2.0)
    for f in text.children:
        #f.replace(f.subtract(f.buffer(-0.2)))
        fe = f.extrude_step(f.buffer(-0.05), 0.2, method=ddd.EXTRUSION_METHOD_SUBTRACT)
        fig.append(fe)
    items.append(fig)

    # Extrude to point
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(fig.centroid(), 2.0)
    items.append(fig)
    """
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(fig.centroid(), 2.0, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)
    """

    # Extrude to empty
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(fig.buffer(-2.0), 2.0)
    items.append(fig)
    fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
    fig = fig.extrude_step(fig.buffer(-2.0), 2.0, base=False, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)


    # Extrude with division
    fig1 = ddd.disc().translate([1.5, 0]).union(ddd.disc())
    fig = fig1.extrude_step(fig1.buffer(-0.2), 0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.extrude_step(fig1.buffer(-0.5), 0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)


    # Extrude multiple with empty geometry
    fig1 = ddd.point([0, 0]).buffer(2.0, cap_style=ddd.CAP_ROUND)
    fig = fig1.extrude_step(fig1.buffer(-0.5), 0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.extrude_step(fig1.buffer(-1.5), 0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.extrude_step(fig1.buffer(-2.5), 0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    fig = fig.extrude_step(fig1.buffer(-2.5), 0.5, method=ddd.EXTRUSION_METHOD_SUBTRACT)
    items.append(fig)

    # Triangulate/Extrude with colinear segments
    fig1 = ddd.polygon([[0, 0], [1, 0], [2, 0], [2, 1], [1, 1], [0, 1]])
    #fig = fig1.triangulate()
    fig = fig1.extrude(1.0)
    items.append(fig)


    # All items
    items = ddd.align.grid(items, space=10.0)
    #items.append(ddd.helper.all())
    items.show()

    root.append(items)
Esempio n. 17
0
def crane_vertical():
    """
    Large vertical crane (such as those seen in cargo ports).
    Inspired by: https://commons.wikimedia.org/wiki/File:Port_crane_of_Mammoet,_Schiedam-8054.jpg
    """

    base_width = 7
    base_length = 6

    # Piers
    pier_height = 2.0
    pier_width = 1.5
    pier_length = base_length + 2
    pier = ddd.rect(
        [-pier_width / 2, -pier_length / 2, pier_width / 2, pier_length / 2],
        name="Crane Pier")
    pier = pier.extrude(pier_height).material(ddd.mats.metal_paint_red)
    pier = ddd.uv.map_cubic(pier)

    pier_l = pier.translate([-base_width * (2 / 6), 0, 0])
    pier_r = pier.translate([base_width * (2 / 6), 0, 0])
    piers = ddd.group3([pier_l, pier_r], name="Crane Piers")

    # Base
    base_height = 1.5
    base = ddd.rect([0, 0, base_width, base_length],
                    name="Crane Base").recenter()
    base = base.extrude(base_height).translate([0, 0, pier_height])
    base = base.material(ddd.mats.cement)
    base = ddd.uv.map_cubic(base)

    # Base Tower
    column_height = 8
    column_radius_base = base_width * 0.85 * 0.5
    column_radius = column_radius_base * 0.5
    column_shape_base = ddd.regularpolygon(4, column_radius_base)
    column_shape_middle = ddd.regularpolygon(12, column_radius)
    column = column_shape_base.extrude_step(column_shape_middle, 1, base=False)
    column = column.extrude_step(column_shape_middle,
                                 column_height - 1,
                                 cap=False)
    column = column.translate([0, 0, pier_height + base_height
                               ]).material(ddd.mats.metal_paint_red)
    column = ddd.uv.map_cubic(column)
    column.name = "Crane column"

    # Platform and railing
    platform_radius = column_radius + 0.85
    platform_base_height = pier_height + base_height + column_height - 2.0
    platform_shape = ddd.point(name="Crane platform").buffer(
        platform_radius, cap_style=ddd.CAP_ROUND)
    platform = platform_shape.triangulate(twosided=True)
    platform = platform.material(ddd.mats.metallic_grid)
    platform_fence = platform_shape.outline().extrude(1.2).material(
        ddd.mats.fence)
    platform = ddd.group([platform, platform_fence], name="Crane platform")
    platform = ddd.uv.map_cylindrical(platform)
    platform = platform.translate([0, 0, platform_base_height])

    # WeightBlock
    block_width = base_width * 0.6
    block_length = base_length * 1.25
    block_base_height = pier_height + base_height + column_height
    block_height = 2.2
    block = ddd.rect([-block_width / 2, 0, block_width / 2, block_length],
                     name="Crane Weight")
    block = block.extrude(block_height).translate([0, -2.5, block_base_height
                                                   ]).material(ddd.mats.cement)
    block = ddd.uv.map_cubic(block)

    # Cabin
    cabin_width = block_width * 0.6
    cabin_length = 3
    cabin_height = block_height
    cabin_shape = ddd.rect(
        [-block_width * 0.5, 0, block_width * 0.5, cabin_length])
    cabin_shape_top = ddd.rect(
        [-block_width * 0.5, 1, block_width * 0.5, cabin_length])
    cabin = cabin_shape.extrude_step(cabin_shape, 1)
    cabin = cabin.extrude_step(cabin_shape_top, cabin_height - 1)
    cabin = cabin.extrude_step(cabin_shape_top.buffer(-0.4), 0.3)
    cabin = cabin.material(ddd.mats.metal_paint_yellow)
    cabin = cabin.translate([0, -2.5 - cabin_length, block_base_height])
    cabin = ddd.uv.map_cubic(cabin)

    mainsupport_width = 2
    mainsupport_skew = 2
    mainsupport_height = 10
    mainsupport_base_height = block_base_height + block_height
    mainsupport = ddd.rect([0, 0, mainsupport_width, mainsupport_width],
                           name="Main Support").recenter()
    mainsupport = mainsupport.extrude_step(mainsupport.translate(
        [0, -mainsupport_skew]),
                                           mainsupport_height,
                                           base=False)
    mainsupport = mainsupport.material(ddd.mats.metal_paint_red)
    mainsupport = mainsupport.translate([0, 0, mainsupport_base_height])
    mainsupport = ddd.uv.map_cubic(mainsupport)

    secsupport_width = 1.5
    secsupport_skew = 11
    secsupport_height = 18
    secsupport_base_height = block_base_height + block_height
    secsupport = ddd.rect([0, 0, secsupport_width, secsupport_width],
                          name="Sec Support").recenter()
    secsupport = secsupport.extrude_step(secsupport.scale(
        [0.8, 0.7]).translate([0, -secsupport_skew]),
                                         secsupport_height,
                                         base=False)
    secsupport = secsupport.material(ddd.mats.metal_paint_red)
    secsupport = secsupport.translate([0, -1.5, secsupport_base_height])
    secsupport = ddd.uv.map_cubic(secsupport)

    maincable1 = cable(
        [-block_width * 0.4, block_length - 3, mainsupport_base_height], [
            -mainsupport_width * 0.2, -mainsupport_skew,
            mainsupport_base_height + mainsupport_height - 0.2
        ])
    maincable1 = maincable1.material(ddd.mats.cable_metal)
    maincable2 = cable(
        [block_width * 0.4, block_length - 3, mainsupport_base_height], [
            mainsupport_width * 0.2, -mainsupport_skew,
            mainsupport_base_height + mainsupport_height - 0.2
        ])
    maincable2 = maincable2.material(ddd.mats.cable_metal)

    seccable1 = cable(
        [0, -mainsupport_skew, mainsupport_base_height + mainsupport_height], [
            0, -1.5 - secsupport_skew,
            mainsupport_base_height + secsupport_height - 0.2
        ])
    seccable1 = seccable1.material(ddd.mats.cable_metal)

    # Drag cable
    dragcable_length = 20
    dragcable_point = [
        0, -1.5 - secsupport_skew,
        mainsupport_base_height + secsupport_height - 0.2
    ]
    dragcable_endpoint = [
        0, -1.5 - secsupport_skew,
        mainsupport_base_height + secsupport_height - 0.2 - dragcable_length
    ]
    dragcable = cable(dragcable_endpoint, dragcable_point)
    dragcable = dragcable.material(ddd.mats.cable_metal)

    # Pulley block
    pulley_block_width = 0.5
    pulley_block_thick = 0.3
    pulley_block_height = 0.8
    pulley_block_profile = ddd.polygon(
        [[-pulley_block_width * 0.25, 0], [pulley_block_width * 0.25, 0],
         [pulley_block_width / 2, pulley_block_height],
         [-pulley_block_width / 2, pulley_block_height]],
        name="Pulley block")
    pulley_block_profile = pulley_block_profile.buffer(
        0.2, resolution=3, join_style=ddd.JOIN_ROUND)

    pulley_block = pulley_block_profile.extrude(pulley_block_thick).translate(
        [0, 0, -pulley_block_thick / 2])
    pulley_block = pulley_block.rotate(ddd.ROT_FLOOR_TO_FRONT).rotate(
        ddd.ROT_TOP_CW)
    pulley_block = pulley_block.material(ddd.mats.metal_paint_yellow)
    pulley_block = ddd.uv.map_cubic(pulley_block)
    pulley_block = pulley_block.translate(dragcable_endpoint)

    # Hook
    hook_radius = 0.6
    hook_radius_inner = 0.35
    hook = ddd.sphere(r=hook_radius, name="Hook")
    hook = hook.scale([0.2, 1.0, 1.0])

    hole = ddd.point().buffer(hook_radius_inner,
                              resolution=3,
                              cap_style=ddd.CAP_ROUND).extrude(4.0).translate(
                                  [0, 0, -2])
    hole = hole.rotate(ddd.ROT_FLOOR_TO_FRONT).rotate(ddd.ROT_TOP_CW)
    hook = hook.subtract(hole)
    hook = hook.material(ddd.mats.steel)
    #hook = ddd.uv.map_cubic(hook)
    hook = hook.translate(dragcable_endpoint)

    item = ddd.group3([
        piers, base, column, platform, block, cabin, mainsupport, maincable1,
        maincable2, secsupport, seccable1, dragcable, pulley_block, hook
    ],
                      name="Crane Vertical")
    return item
Esempio n. 18
0
# Extrusion
fig = ddd.point([0, 0]).buffer(1.0)
for i in range(10):
    fign = ddd.point([0, 0]).buffer(1.0).rotate(math.pi / 12 * i)
    fig = fig.extrude_step(fign, 0.5)
items.append(fig)

# Pointy end
fig = ddd.point().buffer(2.0, cap_style=ddd.CAP_ROUND)
fig = fig.extrude_step(ddd.point(), 5.0)
items.append(fig)

# Convex shapes (this fails)
coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
#coords.reverse()
fig = ddd.polygon(coords).scale(0.25)
fig = fig.extrude_step(fig.buffer(-0.5), 1)
items.append(fig)

# Convex shapes - subtract method (works)
coords = [[10, 10], [5, 9], [3, 12], [1, 5], [-8, 0], [10, 0]]
#coords.reverse()
fig = ddd.polygon(coords).scale(0.25)
fig = fig.extrude_step(fig.buffer(-0.5),
                       1,
                       method=ddd.EXTRUSION_METHOD_SUBTRACT)
items.append(fig)

# Extrude-subtract to bigger
fig = ddd.point([0, 0]).buffer(1.0, cap_style=ddd.CAP_ROUND)
fig = fig.extrude_step(fig.buffer(1.0),
Esempio n. 19
0
def char(ch):
    def tuple_to_imag(t):
        return t[0] + t[1] * 1j

    from freetype import Face
    #face = Face('/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf')
    face = Face(ddd.DATA_DIR + '/fonts/OpenSansEmoji.ttf')
    face.set_char_size(48 * 64)
    face.load_char(ch)

    #kerning = face.get_kerning(ch, 'x')  # or from previous, actually?
    #print(kerning)

    outline = face.glyph.outline
    y = [t[1] for t in outline.points]
    # flip the points
    outline_points = [(p[0], max(y) - p[1]) for p in outline.points]

    start, end = 0, 0
    paths = []

    for i in range(len(outline.contours)):
        end = outline.contours[i]
        points = outline_points[start:end + 1]
        points.append(points[0])
        tags = outline.tags[start:end + 1]
        tags.append(tags[0])

        segments = [
            [
                points[0],
            ],
        ]
        for j in range(1, len(points)):
            segments[-1].append(points[j])
            if tags[j] and j < (len(points) - 1):
                segments.append([
                    points[j],
                ])

        for segment in segments:
            if len(segment) == 2:
                paths.append(
                    Line(start=tuple_to_imag(segment[0]),
                         end=tuple_to_imag(segment[1])))
            elif len(segment) == 3:
                paths.append(
                    QuadraticBezier(start=tuple_to_imag(segment[0]),
                                    control=tuple_to_imag(segment[1]),
                                    end=tuple_to_imag(segment[2])))
            elif len(segment) == 4:
                C = ((segment[1][0] + segment[2][0]) / 2.0,
                     (segment[1][1] + segment[2][1]) / 2.0)

                paths.append(
                    QuadraticBezier(start=tuple_to_imag(segment[0]),
                                    control=tuple_to_imag(segment[1]),
                                    end=tuple_to_imag(C)))
                paths.append(
                    QuadraticBezier(start=tuple_to_imag(C),
                                    control=tuple_to_imag(segment[2]),
                                    end=tuple_to_imag(segment[3])))

        start = end + 1

    path = Path(*paths)
    #wsvg(path, filename="/tmp/test.svg")
    path_d = path.d()

    # https://gis.stackexchange.com/questions/301605/how-to-create-shape-in-shapely-from-an-svg-path-element
    # This page also has info about SVG reading!

    from svgpath2mpl import parse_path
    #svgpath = 'M10 10 C 20 20, 40 20, 50 10Z'
    mpl_path = parse_path(path_d)
    coords = mpl_path.to_polygons()

    # Add or subtract
    char_2d = ddd.polygon(coords[0])
    for c in coords[1:]:
        ng = ddd.polygon(c)
        #print (ng.geom.is_valid)
        if not ng.geom.is_valid: continue
        if char_2d.contains(ng):
            char_2d = char_2d.subtract(ng)
        else:
            char_2d = char_2d.union(ng)

    #result = ddd.group([ddd.polygon(c) for c in coords], empty=2)
    result = char_2d
    result = result.scale([1.0 / (48 * 64), -1.0 / (48 * 64)])

    result = result.simplify(0.005)  #

    return result