コード例 #1
0
ファイル: sports.py プロジェクト: c3ypt1c/ddd
def field_lines_area(area, lines_method, padding=0.5, **kwargs):
    """
    Playground fields are seen x: length, y: width
    """

    rectangle = ddd.geomops.inscribed_rectangle(area, padding=padding)
    if not rectangle.geom or not rectangle.geom.exterior: return

    coords = rectangle.geom.exterior.coords
    width_seg = ddd.line([coords[0], coords[1]])
    length_seg = ddd.line([coords[1], coords[2]])
    width_l = width_seg.geom.length
    length_l = length_seg.geom.length

    if width_l > length_l:
        (width_l, length_l) = (length_l, width_l)
        (width_seg, length_seg) = (length_seg, width_seg)

    # Generate lines, rotate and translate to area
    lines = lines_method(length_l, width_l, **kwargs)
    angle = math.atan2(
        length_seg.geom.coords[1][1] - length_seg.geom.coords[0][1],
        length_seg.geom.coords[1][0] - length_seg.geom.coords[0][0])
    lines = lines.rotate([0, 0, angle]).translate([
        rectangle.geom.centroid.coords[0][0],
        rectangle.geom.centroid.coords[0][1], 0
    ])

    return lines
コード例 #2
0
    def generate_item_3d_historic_archaeological_site(self, item_2d):
        # TODO: Move the actual site generation, given an area, to sketchy

        coords = item_2d.centroid().geom.coords[0]
        if item_2d.geom.type in ("Point", "LineString"):
            points = item_2d.buffer(5.0).random_points(12)
        else:
            points = item_2d.random_points(12)

        line1 = ddd.line(points[0:2])
        line2 = ddd.line(points[2:5])
        line3 = ddd.line(points[5:])
        geomobj = ddd.group2([line1, line2, line3]).buffer(0.5).union()
        #geomobj = filters.noise_random(geomobj, scale=0.075).clean().remove_z()
        #geomobj.show()

        item_3d = geomobj.extrude(0.8)
        #item_3d.copy_from(item_2d)
        item_3d = filters.noise_random(item_3d, scale=0.3)
        item_3d = item_3d.material(ddd.mats.tiles_stones_veg_sparse)
        item_3d = ddd.uv.map_cubic(item_3d)

        # Dont translate ir rotate, item is already in world space (built from item_2d).
        #item_3d = item_3d.rotate([0, 0, item_2d.get('ddd:angle', 0) - math.pi / 2])
        #item_3d = item_3d.translate([coords[0], coords[1], 0.0])  # mat_bronze
        item_3d.name = 'Archaeological Site: %s' % item_2d.name
        return item_3d
コード例 #3
0
def pipeline_logo(pipeline, root):
    """
    """

    logo = ddd.group3()

    thick = 0.125
    margin = 0.4

    line_out = ddd.line([
        (1.0, 0.0, 0.4),
        (1.0, 0.0, 0.0),
        (0.0, 0.0, 0.0),
        (0.0, 1.0, 0.0),
        (0.0, 1.0, 1.0),
        (1.0, 1.0, 1.0),
        (1.0, 0.0, 1.0),
        (1.0, 0.0, 0.6),
    ])

    base = ddd.rect([thick, thick], name="Logo exterior").recenter()

    item = base.extrude_along(line_out)
    item = item.material(ddd.mats.steel)
    #item = item.rotate([0, 0, 0.2])
    item = ddd.uv.map_cubic(
        item
    )  # FIXME: One of the corner vertices are not being split (but they are if slightly rotated)
    logo.append(item)

    line_in = ddd.line([
        (1.0 - margin, 1.0 - margin - 0.1, 1),
        (1.0 - margin, 1.0 - margin, 1),
        (0.0, 1.0 - margin, 1),
        (0.0, 0.0, 1),
        (1.0 - margin, 0.0, 1),
        (1.0 - margin, 0.0, margin),
        (0.0, 0.0, margin),
        (0.0, 1.0 - margin, margin),
        (0.0, 1.0 - margin, 1.0 - margin),
        (0.0, 1.0 - margin - 0.1, 1.0 - margin),
    ])

    item = base.extrude_along(line_in)
    item = item.material(ddd.mats.green)
    item = ddd.uv.map_cubic(item)
    logo.append(item)

    #logo = logo.scale([2, 2, 2])

    logo.show()

    root.append(logo)

    root.append(ddd.helper.all(center=[10, 10, 1]))
コード例 #4
0
def religion_cross(width=1, height=1.5):
    """
    Religion cross.
    """
    l1 = ddd.line([[-width / 2, height - width], [width / 2, height - width]]).buffer(width / 8.0, cap_style=2)
    l2 = ddd.line([[0, 0], [0, height]]).buffer(width / 8.0, cap_style=2)
    sign = l1.union(l2)
    sign = sign.extrude(width / 4.0)
    sign = sign.translate([0, 0, -width / 8.0]).rotate([-math.pi / 2.0, 0, 0])
    sign = sign.translate([0, 0, height])
    sign = ddd.uv.map_cubic(sign)
    sign.name = "Cross"
    return sign
コード例 #5
0
def sign_pharmacy(size=1.0, depth=0.3):
    '''
    A pharmacy sign (cross). Sits centered on its back (vertical plane).
    '''
    l1 = ddd.line([[-size / 2, 0], [size / 2, 0]]).buffer(size / 3.0, cap_style=3)
    l2 = ddd.line([[0, -size / 2], [0, size / 2]]).buffer(size / 3.0, cap_style=3)
    sign = l1.union(l2)
    sign = sign.extrude(depth)
    sign = sign.rotate([math.pi / 2.0, 0, 0])
    sign = sign.material(ddd.material(color='#00ff00'))
    sign = ddd.uv.map_cubic(sign)
    sign.name = "Pharmacy Sign"
    return sign
コード例 #6
0
ファイル: sports.py プロジェクト: jjmontesl/ddd
def field_lines_area(area,
                     lines_method,
                     padding=0.5,
                     search_erode=0.5,
                     **kwargs):
    """
    Playground fields are seen x: length, y: width
    """

    rectangle = ddd.geomops.inscribed_rectangle(area,
                                                padding=padding,
                                                search_erode=search_erode)
    if not rectangle.geom or not rectangle.geom.exterior: return

    coords = rectangle.geom.exterior.coords
    width_seg = ddd.line([coords[0], coords[1]])
    length_seg = ddd.line([coords[1], coords[2]])
    width_l = width_seg.geom.length
    length_l = length_seg.geom.length

    if width_l > length_l:
        (width_l, length_l) = (length_l, width_l)
        (width_seg, length_seg) = (length_seg, width_seg)

    # Generate lines, rotate and translate to area
    lines = lines_method(length_l, width_l, **kwargs)
    angle = math.atan2(
        length_seg.geom.coords[1][1] - length_seg.geom.coords[0][1],
        length_seg.geom.coords[1][0] - length_seg.geom.coords[0][0])
    lines = lines.rotate([0, 0, angle]).translate([
        rectangle.geom.centroid.coords[0][0],
        rectangle.geom.centroid.coords[0][1], 0
    ])

    field_lines_only = lines.select_remove(
        func=lambda o: o.mat == ddd.mats.painted_line)
    field_lines_only = field_lines_only.combine()
    field_lines_only = ddd.uv.map_cubic(field_lines_only)
    field_lines_only.name = "Combined field lines: %s" % lines.name

    field = lines.append(field_lines_only)

    return field
コード例 #7
0
 def to_geom(self, resolution):
     """
     Currently, resolution is interpolated on the x axis. Returns a linestring.
     """
     length = Vector2.distance(self.start, self.end)
     numpoints = length / resolution
     coords = []
     for x in numpy.linspace(self.start[0], self.end[0], numpoints, endpoint=True):
         coords.append((x, self.curve.evaluate_y(x)))
     obj = ddd.line(coords)
     obj.copy_from(self)
     return obj
コード例 #8
0
ファイル: geomops.py プロジェクト: jjmontesl/ddd
def pipeline_test_line_substring(pipeline, root, logger):
    """
    Tests geometric operations.
    """

    items = ddd.group3()

    # Test substrings
    obj = ddd.line([(0, 0), (4, 0)])
    obj2 = obj.line_substring(1.0, -1.0)

    result = ddd.group([
        obj.buffer(0.1, cap_style=ddd.CAP_FLAT),
        obj2.buffer(0.1, cap_style=ddd.CAP_FLAT).material(ddd.MAT_HIGHLIGHT)
    ])
    result.show()
コード例 #9
0
def catenary_cable(a, b, thick=0.10, length_ratio=1.1):
    """
    TODO: move catenary calculations to "path" module and also check Trimesh paths to support that.

    The library requires the anchor to be below the fairlead.
    """

    a = np.array(a)
    b = np.array(b)
    dist = np.linalg.norm(a - b)

    if (a[2] > b[2]):
        a, b = b, a

    length = dist * length_ratio
    w = 0  # submerged weight
    EA = 560e3  # axial stiffness
    floor = False   # if True, contact is possible at the level of the ancho

    l1 = MooringLine(L=length, w=w, EA=EA, anchor=a, fairlead=b, floor=floor)
    l1.computeSolution()
    #l1.plot2D()
    #l1.plot3D()

    # get xyz coordinates along line (between 0. and total line length)
    #T = l1.getTension(s)
    #xyz = l1.s2xyz(s)
    #dxyz = l1.ds2xyz(s)

    # Build cable
    points_d = np.linspace(0, length, int(length / 3) + 3, endpoint=True)
    points_cable = []
    for d in points_d:
        p = l1.s2xyz(d)
        points_cable.append(p)

    base = ddd.point(name="Catenary").buffer(thick / 2, resolution=3)
    path = ddd.line(points_cable)
    item = base.extrude_along(path)
    #item = item.rotate(ddd.ROT_FLOOR_TO_FRONT).rotate(ddd.ROT_TOP_CW)
    item = item.material(ddd.mats.steel)

    item = item.merge_vertices()
    item = item.smooth(angle=math.pi * 2/3)
    item = ddd.uv.map_cubic(item, split=False)  # FIXME: Incorrect, should map along catenary, during construction

    return item
コード例 #10
0
ファイル: s20_godot_features.py プロジェクト: jjmontesl/ddd
    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)
コード例 #11
0
ファイル: landscape.py プロジェクト: jjmontesl/ddd
def ladder_pool(height=1.75, width=0.6):
    """
    """
    arc_thick = 0.08
    bar_thick = 0.05
    arc_radius = 0.35
    steps_interval = 0.30

    height_above_ground = arc_radius

    circleline = ddd.point([-arc_radius, 0], "Ladder").arc_to([arc_radius, 0], [0, 0], False, resolution=4)
    circleline = circleline.line_rel([0, -(height - height_above_ground)])
    circleline = circleline.arc_to([0, -(height - height_above_ground + arc_radius)], [0, -(height - height_above_ground)], False)
    #circleline = circleline.simplify(0.01)
    #regularpolygon(sides * 2, name="Childrens Playground Arc Side Arc").rotate(-math.pi / 2).outline().scale([length / 2, height])
    #arcline = circleline.intersection(ddd.rect([-length, 0.1, length, height * 2]))
    arc = circleline.buffer(arc_thick / 2, cap_style=ddd.CAP_FLAT)  #.intersection(ddd.rect([-length, 0, length, height * 2]))
    arc = arc.extrude(arc_thick, center=True).material(ddd.mats.steel)
    arc = arc.rotate(ddd.ROT_FLOOR_TO_FRONT)
    arc = ddd.uv.map_cubic(arc)

    arc1 = arc.copy().translate([0, -width / 2, 0])
    arc2 = arc.copy().translate([0, +width / 2, 0])
    item = ddd.group([arc1, arc2])

    bar = ddd.point(name="Ladder step").buffer(bar_thick / 2).extrude(width - arc_thick, center=True).rotate(ddd.ROT_FLOOR_TO_FRONT)
    bar = bar.material(ddd.mats.steel)
    bar = ddd.uv.map_cubic(bar)

    stepsline = ddd.line([[arc_radius, 0], [arc_radius, -(height - height_above_ground)]])
    numsteps = int(stepsline.length() / steps_interval) + 1
    step_interval_adjusted = stepsline.length() / numsteps
    for idx in range(numsteps):
        (p, segment_idx, segment_coords_a, segment_coords_b) = stepsline.interpolate_segment(idx * step_interval_adjusted)
        pbar = bar.copy().translate([p[0], 0, p[1]])
        item.append(pbar)

    item = item.combine()
    item = item.rotate(ddd.ROT_TOP_CW)

    return item
コード例 #12
0
def solids_borders(root, pipeline, obj):

    if 'godot:material' in obj.extra:
        del(obj.extra['godot:material'])

    floors = ddd.group2(name="Floors")
    ceilings = ddd.group2(name="Ceilings")
    walls = ddd.group2(name="Walls")

    angles_ceiling = [-math.pi / 4, math.pi / 4]
    angles_floor1 = [math.pi / 4 * 3, math.pi / 4 * 4]
    angles_floor2 = [-math.pi / 4 * 4, -math.pi / 4 * 3]

    polygon = obj.geom.exterior
    if polygon.is_ccw: polygon.coords = reversed(list(polygon.coords))
    segments = zip(polygon.coords, polygon.coords[1:] + polygon.coords[:1])
    for a, b in segments:
        angle = math.atan2(b[1] - a[1], b[0] - a[0])
        if (angle >= angles_floor1[0] and angle <= angles_floor1[1]):
            borderline = ddd.line([a, b])
            borderline.extra.update(obj.extra)
            floors.append(borderline)
        if (angle >= angles_floor2[0] and angle <= angles_floor2[1]):
            borderline = ddd.line([a, b])
            borderline.extra.update(obj.extra)
            floors.append(borderline)
        if (angle >= angles_ceiling[0] and angle <= angles_ceiling[1]):
            borderline = ddd.line([a, b])
            borderline.extra.update(obj.extra)
            ceilings.append(borderline)

    '''
    ddd.mats.grass = ddd.material(name="Grass", color='#2dd355',
                                  texture_path="res://assets/scene/props/grass-texture-tiled.png",
                                  #alpha_cutoff=0.05,
                                  #extra={'ddd:collider': False, 'ddd:shadows': False, 'uv:scale': 0.05}
                                  )
    '''

    floors2 = ddd.group2(name="Floors Background")

    floor_lines = floors
    floors = ddd.line([[0, 0], [1, 1]], name="Floors")
    floors.extra.update(obj.extra)
    floors.geom = linemerge([g.geom for g in floor_lines.children])
    # Iterate merged lines
    floors = floors.individualize(always=True).clean()
    for line in floors.children:
        floor = line.buffer(8.0, resolution=1, cap_style=ddd.CAP_FLAT)  # cap_style=ddd.CAP_FLAT)
        floor = floor.material(ddd.mats.grass_fore)
        floor.name = "Floor Fore: %s" % line.name
        floor.extra['floor_line'] = line.copy()
        #floor.extra['godot:material'] = "grass_fore"
        floor.extra['ddd:z_index'] = 46
        # floor = floor.subtract(obj)
        floor = uvmapping.map_2d_path(floor, line, line_x_offset=64.0, line_x_width=63.0)
        if 'uv' in floor.extra:
            floor.extra['uv'] = [(v[0], v[1] * 4.0) for v in floor.extra['uv']]  # temp: transposed and scaled
        floor.extra['ddd:collider'] = False
        floor.extra['ddd:occluder'] = False
        floor.extra['solid'] = False
        floor.extra['godot:light_mask'] = 0
        # floor = filters.noise_random(floor, scale=3.0)
        # ddd.trace(locals())
        # print(floor.get('uv', None))

        floor2 = line.buffer(18.0, resolution=3, cap_style=ddd.CAP_FLAT)
        floor2 = floor2.material(ddd.mats.grass)
        floor2.name = "Floor: %s" % line.name
        floor2.extra['floor_line'] = line.copy()
        #floor.extra['godot:material'] = "grass"
        floor2.extra['ddd:z_index'] = -1
        floor2 = uvmapping.map_2d_path(floor2, line, line_x_offset=64.0, line_x_width=63.0)
        if 'uv' in floor2.extra:
            floor2.extra['uv'] = [(v[0], 16.0 + v[1] * 3.5)for v in floor2.extra['uv']]  # temp: transposed and scaled
        # floor2 = filters.noise_random(floor2, scale=3.0)
        floor2.extra['ddd:collider'] = False
        floor2.extra['ddd:occluder'] = False
        floor2.extra['solid'] = False
        floor2.extra['godot:light_mask'] = 1

        min_length = 50
        if line.length() > min_length and not obj.get('border:floor', None) == 'false':
            floors2.append(floor2)
            line.replace(floor)
        else:
            line.geom = None

    # for f2 in floors2:  floors.append(f2)
    floors.append(floors2)

    # floors.extra['ddd:z_index'] = 40
    # newobj = ddd.group2([obj, floors], name="Solid")
    # obj.replace(newobj)
    root.find("/Rooms").append(floors)
    obj.extra['floors'] = floors

    ceiling_lines = ceilings
    lines = linemerge([g.geom for g in ceiling_lines.children])
    ceilings = DDDObject2(name="Ceilings", geom=lines)
    ceilings.extra.update(obj.extra)
    ceilings.extra['ddd:z_index'] = 40
    ceilings = ceilings.individualize(always=True).clean()
    for pc in ceilings.children:
        c = pc.copy()
        c.extra['ceiling_line'] = c.copy()
        c = c.buffer(15.0)
        c = filters.noise_random(c, scale=10.0)
        pc.replace(c)
    ceilings = ceilings.material(ddd.mats.bricks)
    # ceilings.mat.color_rgba[3] = 128
    ceilings = ceilings.clean()

    ceilings.set('ddd:collider', False, children=True)
    ceilings.set('ddd:occluder', False, children=True)
    ceilings.set('solid', False, children=True)
    ceilings.set('godot:light_mask', 1, children=True)

    # newobj = ddd.group2([obj, floors], name="Solid")
    # obj.replace(newobj)
    root.find("/Rooms").append(ceilings)
    obj.extra['ceilings'] = ceilings
コード例 #13
0
from ddd.text import fonts

items = ddd.group3()

# 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)
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)
コード例 #14
0
ファイル: sports.py プロジェクト: jjmontesl/ddd
def basketball_field_lines(length=28, width=15, line_width=0.075):
    """
    Note that an additional 2m around the field shall be granted.

    Playground fields are seen x: length, y: width
    """

    item = ddd.group3(name="Basketball lines")

    length = min(length, 28)
    width = min(width, 15)
    (length, width) = enforce_aspect_ratio(length, width, 28 / 15)

    rectangle = ddd.rect([-length / 2, -width / 2, length / 2, width / 2])
    coords = rectangle.geom.exterior.coords
    width_seg = ddd.line([coords[0], coords[1]])
    length_seg = ddd.line([coords[1], coords[2]])
    width2_seg = ddd.line([coords[2], coords[3]])
    length2_seg = ddd.line([coords[3], coords[0]])
    width_l = width_seg.geom.length
    length_l = length_seg.geom.length

    exterior = rectangle.outline().buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    exterior.name = "Bounds line"
    exterior.extra['ddd:collider'] = False
    exterior.extra['ddd:shadows'] = False

    midline_2d = ddd.line(
        [length_seg.geom.centroid, length2_seg.geom.centroid], name="Mid line")
    midline = midline_2d.buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    midline.extra['ddd:collider'] = False
    midline.extra['ddd:shadows'] = False

    midcircle_radius_ratio = (3.60 / 2) / 15
    midcircle = ddd.disc(center=midline_2d.geom.centroid.coords,
                         r=width_l * midcircle_radius_ratio).outline()
    midcircle = midcircle.buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    midcircle.extra['ddd:collider'] = False
    midcircle.extra['ddd:shadows'] = False

    item.append(exterior)
    item.append(midline)
    item.append(midcircle)

    centralline_2d = ddd.line(
        [width_seg.geom.centroid, width2_seg.geom.centroid],
        name="Central line")

    # Sides
    for side in (-1, 1):
        if width > 12.0:
            smallarea = ddd.line([[0, -3], [5.80, -(3 - 1.80)]
                                  ]).arc_to([5.80, 3 - 1.80],
                                            center=[5.80, 0],
                                            ccw=True).line_to([0, 3])
            #smallarea = smallarea.scale([smallarea_length_ratio * length, smallarea_width_ratio * width * 0.5])
            if side == 1: smallarea = smallarea.rotate(math.pi)
            smallarea = smallarea.translate([side * length_l / 2, 0])
            smallarea = smallarea.buffer(
                line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                    ddd.mats.painted_line)
            smallarea.extra['ddd:collider'] = False
            smallarea.extra['ddd:shadows'] = False
            item.append(smallarea)

            smallline = ddd.line([[5.80, -(3 - 1.80)], [5.80, 3 - 1.80]])
            if side == 1: smallline = smallline.rotate(math.pi)
            smallline = smallline.translate([side * length_l / 2, 0])
            smallline = smallline.buffer(
                line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                    ddd.mats.painted_line)
            smallline.extra['ddd:collider'] = False
            smallline.extra['ddd:shadows'] = False
            item.append(smallline)

        if width > 14.0:
            largearea = ddd.line([[0, -6.75],
                                  [1.575,
                                   -6.75]]).arc_to([1.575, 6.75],
                                                   center=[1.575, 0],
                                                   ccw=True).line_to([0, 6.75])
            if side == 1: largearea = largearea.rotate(math.pi)
            largearea = largearea.translate([side * length_l / 2, 0])
            largearea = largearea.buffer(
                line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                    ddd.mats.painted_line)
            largearea.extra['ddd:collider'] = False
            largearea.extra['ddd:shadows'] = False
            item.append(largearea)

        goal = basketball_hoop().rotate(ddd.ROT_TOP_CCW)
        if side == 1: goal = goal.rotate(ddd.ROT_TOP_HALFTURN)
        goal = goal.translate([side * (length_l / 2 - 1.22 - 0.15), 0, 0])
        item.append(goal)

    item = ddd.uv.map_cubic(item)

    #hoop = basketball_hoop(width=width + 0.5, net_height_center=net_height_center, net_height_post=net_height_post)
    #item.append(hoop)

    return item
コード例 #15
0
ファイル: sports.py プロジェクト: jjmontesl/ddd
def tennis_field_lines(length=23.77,
                       width=10.97,
                       square_length_ratio=6.40 / 23.77,
                       net_height_center=0.914,
                       net_height_post=1.07,
                       line_width=0.10):
    """
    Playground fields are seen x: length, y: width

    doubles_width_official = 10.97
    singles_width_official = 8.23
    extra_width = 3.65 (/2?)
    extra_length = 6.50 (/2?)
    """

    length = min(length, 23.77)
    width = min(width, 10.97)
    (length, width) = enforce_aspect_ratio(length, width, 23.77 / 10.97)

    item = ddd.group3(name="Tennis lines")

    rectangle = ddd.rect([-length / 2, -width / 2, length / 2, width / 2])
    coords = rectangle.geom.exterior.coords
    width_seg = ddd.line([coords[0], coords[1]])
    length_seg = ddd.line([coords[1], coords[2]])
    width2_seg = ddd.line([coords[2], coords[3]])
    length2_seg = ddd.line([coords[3], coords[0]])
    width_l = width_seg.geom.length
    length_l = length_seg.geom.length

    exterior = rectangle.outline().buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    exterior.name = "Bounds line"
    exterior.extra['ddd:collider'] = False
    exterior.extra['ddd:shadows'] = False

    item.append(exterior)

    centralline_2d = ddd.line(
        [width_seg.geom.centroid, width2_seg.geom.centroid],
        name="Central line")
    goal_width = 4.88

    # Sideline
    sideline_pos_ratio = 8.23 / 10.97
    for side in (-1, 1):
        sideline = centralline_2d.translate(
            [0, side * width * sideline_pos_ratio * 0.5])
        sideline = sideline.buffer(
            line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                ddd.mats.painted_line)
        sideline.extra['ddd:collider'] = False
        sideline.extra['ddd:shadows'] = False
        item.append(sideline)

    for side in (-1, 1):
        midline = ddd.line([[
            side * length * square_length_ratio,
            -width * sideline_pos_ratio * 0.5
        ],
                            [
                                side * length * square_length_ratio,
                                width * sideline_pos_ratio * 0.5
                            ]])
        midline = midline.buffer(
            line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                ddd.mats.painted_line)
        midline.extra['ddd:collider'] = False
        midline.extra['ddd:shadows'] = False
        item.append(midline)

    item = ddd.uv.map_cubic(item)

    net = tennis_net(width=width + 0.5,
                     net_height_center=net_height_center,
                     net_height_post=net_height_post)
    item.append(net)

    return item
コード例 #16
0
ファイル: sports.py プロジェクト: jjmontesl/ddd
def handball_field_lines(length=40.0, width=20.0, line_width=0.10):
    """
    """

    item = ddd.group3(name="Handball field")

    length = min(length, 40)
    width = min(width, 20)
    (length, width) = enforce_aspect_ratio(length, width, 40 / 20)

    rectangle = ddd.rect([-length / 2, -width / 2, length / 2, width / 2])

    coords = rectangle.geom.exterior.coords
    width_seg = ddd.line([coords[0], coords[1]])
    length_seg = ddd.line([coords[1], coords[2]])
    width2_seg = ddd.line([coords[2], coords[3]])
    length2_seg = ddd.line([coords[3], coords[0]])
    width_l = width_seg.geom.length
    length_l = length_seg.geom.length

    exterior = rectangle.outline().buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    exterior.name = "Bounds line"
    exterior.extra['ddd:collider'] = False
    exterior.extra['ddd:shadows'] = False

    midline_2d = ddd.line(
        [length_seg.geom.centroid, length2_seg.geom.centroid], name="Mid line")
    midline = midline_2d.buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    midline.extra['ddd:collider'] = False
    midline.extra['ddd:shadows'] = False

    #midcircle_radius_ratio = 9.15 / 67.5
    #midcircle = ddd.disc(center=midline_2d.geom.centroid.coords, r=width_l * midcircle_radius_ratio).outline()
    #midcircle = midcircle.buffer(line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    #midcircle.extra['ddd:collider'] = False
    #midcircle.extra['ddd:shadows'] = False

    item.append(exterior)
    item.append(midline)
    #item.append(midcircle)

    centralline_2d = ddd.line(
        [width_seg.geom.centroid, width2_seg.geom.centroid],
        name="Central line")
    goal_width = 3

    smallarea_width_ratio = (goal_width + 5.5 * 2) / 67.5
    smallarea_length_ratio = 5.5 / 67.5
    largearea_width_ratio = 40.3 / 67.5
    largearea_length_ratio = 16.5 / 105.5

    for side in (-1, 1):
        if width > (1.5 + 6) * 2:
            smallarea = ddd.point([0, -1.5 - 6]).arc_to([6, -1.5], [0, -1.5],
                                                        True)
            smallarea = smallarea.line_to([6, 1.5]).arc_to([0, 1.5 + 6],
                                                           [0, 1.5], True)
            if side == 1: smallarea = smallarea.rotate(math.pi)
            smallarea = smallarea.translate([side * length_l / 2, 0])
            smallarea = smallarea.buffer(
                line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                    ddd.mats.painted_line)
            smallarea.extra['ddd:collider'] = False
            smallarea.extra['ddd:shadows'] = False
            item.append(smallarea)

        if width > (8 * 2):
            largearea = ddd.point([0, -1.5 - 9]).arc_to([9, -1.5], [0, -1.5],
                                                        True)
            largearea = largearea.line_to([9, 1.5]).arc_to([0, 1.5 + 9],
                                                           [0, 1.5], True)
            if side == 1: largearea = largearea.rotate(math.pi)
            largearea = largearea.translate([side * length_l / 2, 0])
            largearea = largearea.buffer(line_width, cap_style=ddd.CAP_SQUARE)
            largearea = largearea.intersection(rectangle)
            largearea = largearea.triangulate().material(
                ddd.mats.painted_line
            )  # TODO: use sketchy line material with discontinuous line
            largearea.extra['ddd:collider'] = False
            largearea.extra['ddd:shadows'] = False
            item.append(largearea)

        # TODO: shall depend on the soccer type, assign earlier maybe
        if width > 10:
            goal = football_goal(width=3.0, height=2)
        else:
            goal = football_goal_small()

        goal = goal.rotate(ddd.ROT_TOP_CCW)
        if side == 1: goal = goal.rotate(ddd.ROT_TOP_HALFTURN)
        goal = goal.translate([side * length_l / 2, 0, 0])
        item.append(goal)

    item = ddd.uv.map_cubic(item)

    return item
コード例 #17
0
def solids_borders(root, pipeline, obj):
    floors = ddd.group2(name="Floors")
    ceilings = ddd.group2(name="Ceilings")
    walls = ddd.group2(name="Walls")

    angles_ceiling = [-math.pi / 4, math.pi / 4]
    angles_floor1 = [math.pi / 4 * 3, math.pi / 4 * 4]
    angles_floor2 = [-math.pi / 4 * 4, -math.pi / 4 * 3]

    polygon = obj.geom.exterior
    if polygon.is_ccw: polygon.coords = reversed(list(polygon.coords))
    segments = zip(polygon.coords, polygon.coords[1:] + polygon.coords[:1])
    for a, b in segments:
        angle = math.atan2(b[1] - a[1], b[0] - a[0])
        if (angle > angles_floor1[0] and angle < angles_floor1[1]):
            floors.append(ddd.line([a, b]))
        if (angle > angles_floor2[0] and angle < angles_floor2[1]):
            floors.append(ddd.line([a, b]))
        if (angle > angles_ceiling[0] and angle < angles_ceiling[1]):
            ceilings.append(ddd.line([a, b]))

    ddd.mats.grass = ddd.material(
        name="Grass",
        color='#2dd355',
        texture_path="res://assets/scene/props/grass-texture-tiled.png",
        #alpha_cutoff=0.05,
        #extra={'ddd:collider': False, 'ddd:shadows': False, 'uv:scale': 0.05}
    )

    floor_lines = floors
    floors = ddd.line([[0, 0], [1, 1]], name="Floors")
    floors.geom = linemerge([g.geom for g in floor_lines.children])
    # Iterate merged lines
    floors = floors.individualize(always=True)
    for line in floors.children:
        floor = line.buffer(10.0)
        floor = floor.material(ddd.mats.grass)
        floor.extra['floor_line'] = line
        floor.extra['ddd:z_index'] = 40
        floor = uvmapping.map_2d_path(floor,
                                      line,
                                      line_x_offset=64.0,
                                      line_x_width=64.0)
        #ddd.trace(locals())
        print(floor.get('uv', None))
        line.replace(floor)

    #floors.extra['ddd:z_index'] = 40
    #newobj = ddd.group2([obj, floors], name="Solid")
    #obj.replace(newobj)
    root.find("/Rooms").append(floors)
    obj.extra['floors'] = floors

    ceiling_lines = ceilings
    lines = linemerge([g.geom for g in ceiling_lines.children])
    ceilings = DDDObject2(name="Ceilings", geom=lines)
    ceilings.extra['ddd:z_index'] = 40
    ceilings = ceilings.individualize(always=True).clean()
    for pc in ceilings.children:
        c = pc.copy()
        c.extra['ceiling_line'] = c.copy()
        c = c.buffer(15.0)
        c = filters.noise_random(c, scale=10.0)
        pc.replace(c)
    ceilings = ceilings.material(ddd.mats.bricks)
    ceilings.mat.color_rgba[3] = 128
    ceilings = ceilings.clean()
    #newobj = ddd.group2([obj, floors], name="Solid")
    #obj.replace(newobj)
    root.find("/Rooms").append(ceilings)
    obj.extra['ceilings'] = ceilings
コード例 #18
0
ファイル: sports.py プロジェクト: jjmontesl/ddd
def football_field_lines(length=105.0, width=67.5, line_width=0.10):
    """
    Playground fields are seen x: length, y: width
    """

    item = ddd.group3(name="Football lines")

    rectangle = ddd.rect([-length / 2, -width / 2, length / 2, width / 2])

    coords = rectangle.geom.exterior.coords
    width_seg = ddd.line([coords[0], coords[1]])
    length_seg = ddd.line([coords[1], coords[2]])
    width2_seg = ddd.line([coords[2], coords[3]])
    length2_seg = ddd.line([coords[3], coords[0]])
    width_l = width_seg.geom.length
    length_l = length_seg.geom.length

    exterior = rectangle.outline().buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    exterior.name = "Bounds line"
    exterior.extra['ddd:collider'] = False
    exterior.extra['ddd:shadows'] = False

    midline_2d = ddd.line(
        [length_seg.geom.centroid, length2_seg.geom.centroid], name="Mid line")
    midline = midline_2d.buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    midline.extra['ddd:collider'] = False
    midline.extra['ddd:shadows'] = False

    midcircle_radius_ratio = 9.15 / 67.5
    midcircle = ddd.disc(center=midline_2d.geom.centroid.coords,
                         r=width_l * midcircle_radius_ratio).outline()
    midcircle = midcircle.buffer(
        line_width,
        cap_style=ddd.CAP_SQUARE).triangulate().material(ddd.mats.painted_line)
    midcircle.extra['ddd:collider'] = False
    midcircle.extra['ddd:shadows'] = False

    item.append(exterior)
    item.append(midline)
    item.append(midcircle)

    centralline_2d = ddd.line(
        [width_seg.geom.centroid, width2_seg.geom.centroid],
        name="Central line")
    goal_width = 7.2

    smallarea_width_ratio = (goal_width + 5.5 * 2) / 67.5
    smallarea_length_ratio = 5.5 / 67.5
    largearea_width_ratio = 40.3 / 67.5
    largearea_length_ratio = 16.5 / 105.5

    for side in (-1, 1):
        smallarea = ddd.line([[0, -1], [1, -1], [1, 1], [0, 1]])
        smallarea = smallarea.scale([
            smallarea_length_ratio * length,
            smallarea_width_ratio * width * 0.5
        ])
        if side == 1: smallarea = smallarea.rotate(math.pi)
        smallarea = smallarea.translate([side * length_l / 2, 0])
        smallarea = smallarea.buffer(
            line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                ddd.mats.painted_line)
        smallarea.extra['ddd:collider'] = False
        smallarea.extra['ddd:shadows'] = False
        item.append(smallarea)

        largearea = ddd.line([[0, -1], [1, -1], [1, 1], [0, 1]])
        largearea = largearea.scale([
            largearea_length_ratio * length,
            largearea_width_ratio * width * 0.5
        ])
        if side == 1: largearea = largearea.rotate(math.pi)
        largearea = largearea.translate([side * length_l / 2, 0])
        largearea = largearea.buffer(
            line_width, cap_style=ddd.CAP_SQUARE).triangulate().material(
                ddd.mats.painted_line)
        largearea.extra['ddd:collider'] = False
        largearea.extra['ddd:shadows'] = False
        item.append(largearea)

        # TODO: shall depend on the soccer type, assign earlier maybe
        if width > 30: goal = football_goal11()
        elif width > 15: goal = football_goal9()
        elif width > 9: goal = football_goal7()
        else: goal = football_goal_small()

        goal = goal.rotate(ddd.ROT_TOP_CCW)
        if side == 1: goal = goal.rotate(ddd.ROT_TOP_HALFTURN)
        goal = goal.translate([side * length_l / 2, 0, 0])
        item.append(goal)

    item = ddd.uv.map_cubic(item)

    return item
コード例 #19
0
    def generate_building_3d_generic(self, building_2d):
        """
        Buildings 2D may contain references to building parts.

        TODO: Do a lot more in tags in 2D and here, and generalize tasks to pipelines and tags.
        Support buildings recursively earlier.
        """

        floors = building_2d.extra.get('osm:building:levels', None)
        floors_min = building_2d.extra.get('osm:building:min_level', 0)
        if not floors:
            floors = random.randint(2, 8)

        floors = int(float(floors))
        floors_min = int(float(floors_min))
        base_floors = floors
        base_floors_min = floors_min

        random.seed(hash(building_2d.name))
        building_material = random.choice([ddd.mats.building_1, ddd.mats.building_2, ddd.mats.building_3])

        if building_2d.extra.get('osm:building:material', None):
            material_name = building_2d.extra.get('osm:building:material')
            if hasattr(ddd.mats, material_name):
                building_material = getattr(ddd.mats, material_name)

        entire_building_2d = ddd.group2()
        entire_building_3d = building_2d.copy3(name="Building: %s" % (building_2d.name))

        roof_type = weighted_choice({'none': 2,
                                     'flat': 1,
                                     'pyramidal': 0.5,
                                     'attic': 0.5,
                                     'terrace': 1})
        roof_buffered = weighted_choice({True: 1, False: 5})
        roof_buffer = random.uniform(0.5, 1.2)
        roof_wall_material = weighted_choice({"stone": 3, "bricks": 1})

        for part in (building_2d.extra.get('ddd:building:parts', []) + [building_2d]):

            # Process subbuildings recursively (non standard, but improves support and compatibility with other renderers)
            if part != building_2d and part.extra.get('osm:building', None) is not None:
                subbuilding = self.generate_building_3d_generic(part)
                entire_building_2d.append(part)
                entire_building_3d.append(subbuilding)
                continue

            building_3d = None
            try:

                floors = int(float(part.extra.get('osm:building:levels', base_floors)))
                if floors == 0:
                    logger.warn("Building part with 0 floors (setting to 1): %s", floors)
                    floors = 1
                floors_min = int(float(part.extra.get('osm:building:min_level', base_floors_min)))

                # Remove the rest of the building
                if part == building_2d:
                    part = part.subtract(entire_building_2d)
                if part.geom.is_empty:
                    continue

                material = building_material
                if part.extra.get('osm:building:material', None):
                    material_name = part.extra.get('osm:building:material')
                    if hasattr(ddd.mats, material_name):
                        material = getattr(ddd.mats, material_name)
                if part.extra.get('osm:building:facade:material', None):
                    material_name = part.extra.get('osm:building:facade:material')
                    if hasattr(ddd.mats, material_name):
                        material = getattr(ddd.mats, material_name)

                # Roof: default
                pbuffered = roof_buffered
                roof_shape = roof_type
                if floors < 2:
                    roof_shape = 'none'
                if floors < base_floors:
                    pbuffered = False
                    if (random.uniform(0, 1) < 0.5): roof_shape = random.choice(['terrace', 'none'])
                    if (floors <= 2):
                        if (random.uniform(0, 1) < 0.8): roof_shape = random.choice(['terrace', 'terrace', 'terrace', 'none'])
                if 'osm:building:part' in part.extra:
                    roof_shape = 'none'
                    pbuffered = 0

                # Roof: info
                roof_shape = part.extra.get('osm:roof:shape', roof_shape)
                roof_height = float(part.extra.get('osm:roof:height', 0))

                roof_material = ddd.mats.roof_tiles
                if part.extra.get('osm:roof:material', None):
                    material_name = part.extra.get('osm:roof:material')
                    if hasattr(ddd.mats, material_name):
                        roof_material = getattr(ddd.mats, material_name)

                floors_height = floors * 3.00
                floors_min_height = floors_min * 3.00
                min_height = float(part.extra.get('osm:min_height', floors_min_height))
                #max_height = parse_meters(part.extra.get('osm:height', floors_height + min_height)) - roof_height
                max_height = parse_meters(part.extra.get('osm:height', floors_height)) - roof_height
                dif_height = max_height - min_height

                # Generate building procedurally (use library)
                try:
                    building_3d = part.extrude(dif_height)
                except ValueError as e:
                    logger.error("Could not generate building (%s): %s", part, e)
                    continue
                except DDDException as e:
                    logger.error("Could not generate building (%s): %s", part, e)
                    continue

                if min_height == 0:
                    building_3d = ddd.meshops.remove_faces_pointing(building_3d, ddd.VECTOR_DOWN)

                if min_height: building_3d = building_3d.translate([0, 0, min_height])
                building_3d = building_3d.material(material)

                # Building solid post processing
                if part.extra.get('osm:tower:type', None) == 'bell_tower':  # and dif_height > 6:
                    # Cut
                    center_pos = part.centroid().geom.coords[0]
                    (axis_major, axis_minor, axis_rot) = ddd.geomops.oriented_axis(part)
                    cut1 = ddd.rect([-axis_major.length(), -axis_minor.length() * 0.20, +axis_major.length(), +axis_minor.length() * 0.20])
                    cut2 = ddd.rect([-axis_major.length() * 0.20, -axis_minor.length(), +axis_major.length() * 0.20, +axis_minor.length()])
                    cuts = ddd.group2([cut1, cut2]).union().rotate(axis_rot).extrude(-6.0).translate([center_pos[0], center_pos[1], max_height - 2])
                    #ddd.group3([building_3d, cuts]).show()
                    building_3d = building_3d.subtract(cuts)
                    #building_3d.show()

                    # TODO: Create 1D items
                    (axis_major, axis_minor, axis_rot) = ddd.geomops.oriented_axis(part.buffer(-0.80))
                    for coords in (axis_major.geom.coords[0], axis_major.geom.coords[1], axis_minor.geom.coords[0], axis_minor.geom.coords[1]):
                        bell = urban.bell().translate([coords[0], coords[1], max_height - 3.0])
                        entire_building_3d.append(bell)



                # Base
                if 'osm:building:part' not in part.extra:
                    if random.uniform(0, 1) < 0.2:
                        base = part.buffer(0.3, cap_style=2, join_style=2).extrude(1.00)
                        base = base.material(random.choice([ddd.mats.building_1, ddd.mats.building_2, ddd.mats.building_3, ddd.mats.stone, ddd.mats.cement]))
                        building_3d.children.append(base)

                # Roof
                try:
                    roof = None

                    if roof_shape == 'flat':
                        # Flat
                        default_height = 0.75
                        roof_height = roof_height if roof_height else default_height
                        roof = part.buffer(roof_buffer if pbuffered else 0, cap_style=2, join_style=2).extrude(roof_height).translate([0, 0, max_height]).material(roof_material)

                    elif roof_shape == 'terrace':
                        # Flat
                        usefence = random.uniform(0, 1) < 0.8
                        if usefence:
                            terrace = part.subtract(part.buffer(-0.4)).extrude(0.6).translate([0, 0, max_height]).material(getattr(ddd.mats, roof_wall_material))
                            fence = part.buffer(-0.2).outline().extrude(0.7).twosided().translate([0, 0, max_height + 0.6]).material(ddd.mats.railing)
                            roof = ddd.group3([terrace, fence], name="Roof")
                        else:
                            terrace = part.subtract(part.buffer(-0.4)).extrude(random.uniform(0.40, 1.20)).translate([0, 0, max_height]).material(ddd.mats.stone)
                            roof = ddd.group3([terrace], name="Roof")

                    elif roof_shape == 'pyramidal':
                        # Pointy
                        default_height = floors * 0.2 + random.uniform(2.0, 5.0)
                        roof_height = roof_height if roof_height else default_height
                        roof = part.buffer(roof_buffer if pbuffered else 0, cap_style=2, join_style=2).extrude_step(part.centroid(), roof_height)
                        roof = roof.translate([0, 0, max_height]).material(roof_material)

                    elif roof_shape == 'attic':
                        # Attic
                        height = random.uniform(3.0, 4.0)
                        roof = part.buffer(roof_buffer if pbuffered else 0, cap_style=2, join_style=2).extrude_step(part.buffer(-2), height, method=ddd.EXTRUSION_METHOD_SUBTRACT).translate([0, 0, max_height]).material(roof_material)

                    elif roof_shape == 'gabled':
                        # Attic
                        base = part.buffer(roof_buffer if pbuffered else 0)
                        orientation = "major"
                        if part.extra.get("osm:roof:orientation", "along") == "across": orientation = "minor"
                        (axis_major, axis_minor, axis_rot) = ddd.geomops.oriented_axis(base)
                        axis_line = axis_major if orientation == "major" else axis_minor
                        default_height = random.uniform(3.0, 4.0)
                        roof_height = roof_height if roof_height else default_height
                        roof = base.extrude_step(axis_line, roof_height).translate([0, 0, max_height]).material(roof_material)

                        '''
                        #elif roof_shape == 'round':
                        # Attic
                        base = part.buffer(roof_buffer if pbuffered else 0)
                        orientation = "major"
                        if part.extra.get("osm:roof:orientation", "along") == "across": orientation = "minor"
                        (axis_major, axis_minor, axis_rot) = ddd.geomops.oriented_axis(base)
                        axis_line = axis_major if orientation == "major" else axis_minor

                        major_seg_plus = ((axis_major.coords[0][0] + (axis_minor.coords[0][0] - axis_minor.coords[1][0]) * 0.5, axis_major.coords[0][1] + (axis_minor.coords[0][1] - axis_minor.coords[1][1]) * 0.5),
                                          (axis_major.coords[1][0] + (axis_minor.coords[0][0] - axis_minor.coords[1][0]) * 0.5, axis_major.coords[1][1] + (axis_minor.coords[0][1] - axis_minor.coords[1][1]) * 0.5))
                        minor_seg_plus = ((axis_minor.coords[0][0] + (axis_major.coords[0][0] - axis_major.coords[1][0]) * 0.5, axis_minor.coords[0][1] + (axis_major.coords[0][1] - axis_major.coords[1][1]) * 0.5),
                                          (axis_minor.coords[1][0] + (axis_major.coords[0][0] - axis_major.coords[1][0]) * 0.5, axis_minor.coords[1][1] + (axis_major.coords[0][1] - axis_major.coords[1][1]) * 0.5))



                        default_height = random.uniform(3.0, 4.0)
                        roof_height = roof_height if roof_height else default_height
                        roof = base.extrude_step(axis_line, roof_height).translate([0, 0, max_height]).material(roof_material)
                        '''

                    elif roof_shape == 'skillion':
                        # Attic
                        base = part.buffer(roof_buffer if pbuffered else 0)
                        orientation = "major"
                        if part.extra.get("osm:roof:orientation", "along") == "across": orientation = "minor"
                        (axis_major, axis_minor, axis_rot) = ddd.geomops.oriented_axis(base)

                        axis_major = axis_major.geom
                        axis_minor = axis_minor.geom

                        major_seg_plus = ((axis_major.coords[0][0] + (axis_minor.coords[0][0] - axis_minor.coords[1][0]) * 0.5, axis_major.coords[0][1] + (axis_minor.coords[0][1] - axis_minor.coords[1][1]) * 0.5),
                                          (axis_major.coords[1][0] + (axis_minor.coords[0][0] - axis_minor.coords[1][0]) * 0.5, axis_major.coords[1][1] + (axis_minor.coords[0][1] - axis_minor.coords[1][1]) * 0.5))
                        minor_seg_plus = ((axis_minor.coords[0][0] + (axis_major.coords[0][0] - axis_major.coords[1][0]) * 0.5, axis_minor.coords[0][1] + (axis_major.coords[0][1] - axis_major.coords[1][1]) * 0.5),
                                          (axis_minor.coords[1][0] + (axis_major.coords[0][0] - axis_major.coords[1][0]) * 0.5, axis_minor.coords[1][1] + (axis_major.coords[0][1] - axis_major.coords[1][1]) * 0.5))

                        skillion_line = major_seg_plus if orientation == "major" else minor_seg_plus
                        default_height = random.uniform(1.0, 2.0)
                        roof_height = roof_height if roof_height else default_height
                        roof = base.extrude_step(ddd.line(skillion_line), roof_height).translate([0, 0, max_height]).material(roof_material)

                    elif roof_shape == 'hipped':
                        # Attic
                        base = part.buffer(roof_buffer if pbuffered else 0)
                        orientation = "major"
                        if part.extra.get("osm:roof:orientation", "along") == "across": orientation = "minor"
                        (axis_major, axis_minor, axis_rot) = ddd.geomops.oriented_axis(base)
                        axis_line = axis_major if orientation == "major" else axis_minor
                        #other_axis_line = axis_minor if orientation == "major" else axis_major

                        axis_line = axis_line.intersection(axis_line.centroid().buffer(axis_minor.geom.length / 2, cap_style=ddd.CAP_ROUND, resolution=8))

                        default_height = random.uniform(1.0, 2.0)
                        roof_height = roof_height if roof_height else default_height
                        roof = base.extrude_step(axis_line, roof_height).translate([0, 0, max_height]).material(roof_material)

                    elif roof_shape == 'dome':
                        default_height = random.uniform(2.0, 4.0)
                        roof_height = roof_height if roof_height else default_height

                        roofbase = part.buffer(roof_buffer if pbuffered else 0, cap_style=2, join_style=2)
                        roof = roofbase.copy()

                        steps = 6
                        stepheight = 1.0 / steps
                        for i in range(steps):
                            stepy = (i + 1) * stepheight
                            stepx = math.sqrt(1 - (stepy ** 2))
                            stepbuffer = -(1 - stepx)
                            roof = roof.extrude_step(roofbase.buffer(stepbuffer * roof_height), stepheight * roof_height)
                        roof = roof.translate([0, 0, max_height]).material(roof_material)

                    elif roof_shape == 'none':
                        pass

                    else:
                        logger.warning("Unknown roof shape: %s", roof_shape)

                    if roof: building_3d.children.append(roof)

                except Exception as e:
                    logger.warning("Cannot generate roof: %s (geom: %s)" % (e, part.geom))

                # UV Mapping
                building_3d = ddd.uv.map_cubic(building_3d)

                entire_building_2d.append(part)
                entire_building_3d.append(building_3d)

            except ValueError as e:
                logger.error("Cannot generate building part %s: %s (geom: %s)" % (part, e, part.geom))
                raise
                #return None
            except IndexError as e:
                logger.error("Cannot generate building part %s: %s (geom: %s)" % (part, e, part.geom))
                raise
                #return None
            except Exception as e:
                logger.error("Cannot generate building part %s: %s (geom: %s)" % (part, e, part.geom))
                raise

        entire_building_3d.extra['building_2d'] = building_2d
        entire_building_3d.extra['ddd:building:feature'] = building_2d

        return entire_building_3d
コード例 #20
0
ファイル: operations.py プロジェクト: jjmontesl/ddd
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)
コード例 #21
0
ファイル: buildings_3d.py プロジェクト: jjmontesl/ddd
    def snap_to_building(self, item_3d, building_3d):

        # Find building segment to snap
        item_1d = item_3d.extra.get('ddd:item', None)

        building_2d = building_3d.get('ddd:building:parent', building_3d.get('ddd:building:building_2d', None))
        if building_2d: building_2d = building_2d.get('osm:original', building_2d)
        #building_2d = item_3d.get('ddd:building').get('ddd:building:building_2d', None)

        logger.debug("Snapping %s to %s, using 2D %s", item_3d, building_3d, building_2d)

        if building_2d is None:
            logger.error("Could not find linked building 2D geometry to snap item %s to building %s.", item_3d, building_3d)
            return None

        if building_2d.is_empty():
            logger.warn("Cannot snap item to empty geometry: %s", building_3d)
            return None

        '''
        if building_2d.geom is None:
            logger.warn("Cannot snap item to building with no geometry (fixme: building was not considered empty though): %s", building_2d)
            return None

        if building_2d.geom.type == "MultiPolygon":
            logger.warn("Cannot snap to MultiPolygon building (ignoring item_3d)  TODO: usecommon snap functions which should support MultiPolygon")
            return None
        '''

        #lines = building_2d.individualize()  # geom.exterior

        # Project only to facade lines
        building_2d_margin = building_2d.union().buffer(-1)
        lines = []
        for b in [building_3d] + building_3d.children:
            for s in b.get('ddd:building:segments', []):
                l = ddd.line([s.p1, s.p2], )
                #l.set('ddd:building:segment') = s
                if s.facade_type != 'contact' and not building_2d_margin.contains(l):
                    lines.append(l)

        if len(lines) == 0:
            logger.error("No segments geometry to snap item %s to building %s.", item_3d, building_3d)
            building_3d.dump()
            return None

        lines = ddd.group2(lines)

        closest_point, segment_idx, segment_coords_a, segment_coords_b, closest_object, closest_object_d = lines.closest_segment(item_1d.centroid())

        dir_ver = (segment_coords_b[0] - segment_coords_a[0], segment_coords_b[1] - segment_coords_a[1])
        dir_ver_length = math.sqrt(dir_ver[0] ** 2 + dir_ver[1] ** 2)
        dir_ver = (dir_ver[0] / dir_ver_length, dir_ver[1] / dir_ver_length)
        angle = math.atan2(dir_ver[1], dir_ver[0]) + math.pi

        # Reverse angle if point is inside
        #if building_2d.contains(item_1d.centroid()):
        #if not building_2d.geom.exterior.is_ccw:
        #logger.debug("Amenity: %s Closest point: %s Closest Segment: %s Angle: %s" % (amenity.geom.centroid, closest_point, closest_segment, angle))


        target_point = closest_point

        # Fit width in segment
        # TODO: Move to "snap/align" and make reusable
        bounds = item_3d.bounds()
        width = abs(bounds[0][0] - bounds[1][0])
        segment_d = math.sqrt((closest_point[0] - segment_coords_a[0]) ** 2 + (closest_point[1] - segment_coords_a[1]) ** 2)
        #item_3d.set('debug:segment_d_before', segment_d, children=True)
        min_d = width / 2
        max_d = dir_ver_length - min_d
        if max_d < min_d:
            # If segment is smaller than width, align to center
            min_d = dir_ver_length / 2
            max_d = dir_ver_length / 2
        if segment_d < min_d or segment_d > max_d:
            segment_d = max(min_d, min(max_d, segment_d))
            target_point = (segment_coords_a[0] + dir_ver[0] * segment_d, segment_coords_a[1] + dir_ver[1] * segment_d)
        #item_3d.set('debug:segment_d_after', segment_d, children=True)
        #item_3d.set('debug:width', width, children=True)
        #item_3d.set('debug:min_d', min_d, children=True)
        #item_3d.set('debug:max_d', max_d, children=True)
        #item_3d.set('debug:dir_ver_length', dir_ver_length, children=True)

        # Align rotation
        item_3d = item_3d.rotate([0, 0, angle])  # + math.pi / 2.0
        item_3d = item_3d.translate([target_point[0], target_point[1], 0])

        # Raise to floor level, since currently items are not considered by floor
        point_elevation = terrain.terrain_geotiff_elevation_value(item_1d.centroid().geom.coords[0], self.osm.ddd_proj)
        extra_elevation = point_elevation - building_3d.get('ddd:building:elevation:min')
        item_3d = item_3d.translate([0, 0, extra_elevation])

        return item_3d
コード例 #22
0
    def process_building_segment_analyze(self, part, segment, buildings_ref,
                                         ways_ref):
        """
        Analyze a segment of a building, resolving:

        - Forward object/way/area (ways only?): distance + link + type  # not so significative if a single ray is cast from center, line cast? (?)
        - Segment type: interior, detail, facade.... # interiors may be missed if using single ray cast from segment center
        - Type of convex hull segment: facade_main, facade_secondary, interior
        """

        # Check if segment touches another segment in this or other building
        '''
        contacts = part.get('ddd:building:contacts')
        seg_vert_idx_a = segment.seg_idx
        seg_vert_idx_b = (segment.seg_idx + 1) % (len(part.vertex_list()) - 1)
        contact_a = contacts.get(seg_vert_idx_a, None)
        contact_b = contacts.get(seg_vert_idx_b, None)
        if contact_a and contact_b and contact_a.other == contact_b.other:
            coa = contact_a.other_idx
            cob = contact_b.other_idx
            # Check that segment is contiguous on the "other" geometry (note it can also cycle around vertex list)
            if abs(coa - cob) == 1 or (abs(coa - cob) == len(contact_a.other.vertex_list()) - 2):
                segment.contact = contact_a.other
        '''

        othersegments = self._segment_cache[segment.vertex_key()]
        othersegments = [s for s in othersegments if s.building != part]
        if othersegments:
            segment.contact = othersegments[0]
        if len(othersegments) > 1:
            logger.warn(
                "Building segment with several contacts to other buildings, using only first contact."
            )

        # Get the closest (forward) way to the segment,
        seg_center = (np.array(segment.p2) + np.array(segment.p1)) / 2
        point = ddd.point(seg_center)

        if not ways_ref.is_empty():
            try:
                coords_p, segment_idx, segment_coords_a, segment_coords_b, closest_obj, closest_d = ways_ref.closest_segment(
                    point)
                segment.closest_way = closest_obj

                # Check if there is another building between building segment and way
                ray = ddd.line([seg_center,
                                coords_p]).line_substring(1.0, -1.0)
                segment.building_front = buildings_ref.intersects(ray)

            except DDDException as e:
                logger.warn("Cannot find closest to building segment %s: %s",
                            segment, e)
                pass

        # Facade classification
        # TODO: Do this in styling, study cases
        if segment.contact:
            segment.facade_type = 'contact'
        elif segment.building_front:
            # TODO: Check distance too
            segment.facade_type = 'lateral'  # / vieable/non-viewable
        else:
            # TODO: Check way weights for main/secondary facades
            segment.facade_type = 'main'  # secondary / lateral / back