def comm_tower(height=25.0, radius=0.5): base_height = 1.2 pole_radius = 0.10 top_height = 0.1 antenna_height = 2.0 obj_base = ddd.regularpolygon(3, radius, "Comm Tower Base").extrude(base_height) obj_base = ddd.uv.map_cubic(obj_base) obj_base = obj_base.material(ddd.mats.metal_paint_red) obj_pole = ddd.regularpolygon(4, pole_radius, "Comm Tower Pole").extrude(height - base_height - top_height) obj_pole = ddd.uv.map_cubic(obj_pole) obj_pole = obj_pole.material(ddd.mats.metal_paint_red) obj_pole = ddd.align.matrix_polar(obj_pole.translate([radius - pole_radius * 2, 0, base_height]), 3) obj_top = ddd.regularpolygon(3, radius, "Comm Tower Top").extrude(top_height) obj_top = obj_top.material(ddd.mats.metal_paint_red) obj_top = ddd.uv.map_cubic(obj_top) obj_top = obj_top.translate([0, 0, height - top_height]) obj_antenna = ddd.regularpolygon(3, 0.05, "Comm Antenna Vert").extrude(antenna_height).translate([0, 0, height]) obj_antenna = ddd.uv.map_cubic(obj_antenna) obj_antenna = obj_antenna.material(ddd.mats.steel) # TODO: Combination of suitable meshes shall be done automatically combined = ddd.group([obj_base, obj_pole, obj_top]).combine() obj = ddd.group([combined, obj_antenna]) obj.name = "Communications Tower" return obj
def trafficlights_head(height=0.8, depth=0.3): head = ddd.rect([-0.15, 0, 0.15, height], name="TrafficLight Box").material(ddd.mats.metal_paint_green).extrude(depth) disc_green = ddd.disc(ddd.point([0, 0.2]), r=0.09, name="TrafficLight Disc Green").material(ddd.mats.light_green).extrude(0.05) disc_orange = ddd.disc(ddd.point([0, 0.4]), r=0.09, name="TrafficLight Disc Green").material(ddd.mats.light_orange).extrude(0.05) disc_red = ddd.disc(ddd.point([0, 0.6]), r=0.09, name="TrafficLight Disc Green").material(ddd.mats.light_red).extrude(0.05) discs = ddd.group([disc_green, disc_orange, disc_red], name="TrafficLight Discs").translate([0, 0, depth]) # Put discs over head head = ddd.group([head, discs], name="TrafficLight Head").translate([0, -height / 2.0, 0]) # Center vertically head = head.rotate([math.pi / 2.0, 0, 0]) head = ddd.uv.map_cubic(head) return head
def gltf_ddd(): sphere1 = ddd.sphere(r=1.0, name="Sphere1").translate([0, 0, -2]) sphere2 = ddd.sphere(r=2.0, name="Sphere2").translate([5, 5, 5]) sphere1.append(sphere2) sphere1.extra['testSphere1'] = 'MyTest' sphere2.extra.update(test_metadata) sphere2.extra['test_obj'] = test_metadata root = ddd.group([sphere1], name="Spheres Root") scene1 = ddd.group([root], name="Scene") scene1.extra['test'] = test_metadata scene1.dump() scene1.save("gltf-hierarchy-ddd.glb") scene1.show()
def lighthouse(height=10, r=1.5): mat = random.choice([ddd.mats.metal_paint_green, ddd.mats.metal_paint_red]) disc = ddd.point([0, 0]).buffer(r, resolution=3, cap_style=ddd.CAP_ROUND) obj = disc.extrude_step(disc, height * 0.3) obj = obj.extrude_step(disc.scale(0.7), height * 0.5) obj = obj.extrude_step(disc.scale(1.0), height * 0.18) obj = obj.extrude_step(disc.scale(1.2), height * 0.02) obj = obj.material(mat) obj = ddd.uv.map_cylindrical(obj) obj.name = "Lighthouse" lamp = lamp_ball(r=0.2).material(mat) lamp = ddd.uv.map_spherical(lamp) top = post(top=lamp, mat_post=ddd.mats.steel).translate([0, 0, height]) rail = disc.scale(1.2).extrude_step(disc.scale(1.2), 1.0, base=False, cap=False) #.twosided() rail = rail.translate([0, 0, height]).material(ddd.mats.railing) rail = ddd.uv.map_cylindrical(rail) obj = ddd.group([obj, top, rail], name="Lighthouse Small") return obj
def childrens_playground_arc(length=3.25, width=1.0, sides=7, height=None): arc_thick = 0.08 bar_thick = 0.05 if height is None: height = length / 2 * 0.9 circleline = ddd.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).intersection(ddd.rect([-length, 0, length, height * 2])) arc = arc.extrude(arc_thick, center=True).material(ddd.mats.metal_paint_red) 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="Childrens Playground Arc Bar").buffer(bar_thick / 2).extrude(width - arc_thick, center=True).rotate(ddd.ROT_FLOOR_TO_FRONT) bar = ddd.uv.map_cubic(bar) mats = [ddd.mats.metal_paint_white, ddd.mats.metal_paint_red] for idx, p in enumerate(arcline.geom.coords[1:-1]): pbar = bar.copy().translate([p[0], 0, p[1]]) pbar = pbar.material(mats[idx % 2]) item.append(pbar) item = ddd.meshops.batch_by_material(item).clean(remove_degenerate=False) return item
def osm_model_rest(pipeline, root, osm, logger): # Final grouping scene = [ root.find("/Areas"), #root.find("/Water"), root.find("/Ways"), root.find("/Structures3"), root.find("/Buildings"), root.find("/Items3"), root.find("/Other3"), root.find("/Roadlines3"), ] scene = ddd.group(scene, name="Scene") # Add metadata to tile root object # (some of these are used by ddd-viewer format) metadataobj = ddd.instance(None, name="Metadata") metadataobj.set('tile:bounds_wgs84', pipeline.data['tile:bounds_wgs84']) metadataobj.set('tile:bounds_m', pipeline.data['tile:bounds_m']) metadataobj.set('tile:create_time', str(datetime.datetime.now())) scene.append(metadataobj) logger.info("Scene properties: %s", (scene.extra)) pipeline.root = scene
def bench(length=1.40, height=1.00, width=0.8, seat_height=0.45, legs=2, hangout=0.20): seat_thick = 0.05 leg_thick = 0.05 leg_padding = 0.3 leg_width = width - leg_padding leg_height = seat_height - seat_thick seat = ddd.rect([-length/ 2.0, -width / 2.0, length / 2.0, width / 2.0], name="Bench Seat") seat = seat.extrude(-seat_thick).translate([0, 0, seat_height]) legs_objs = [] leg_spacing = (length - leg_padding * 2) / (legs - 1) for leg_idx in range(legs): leg = ddd.rect([-leg_thick / 2, -leg_width / 2.0, leg_thick / 2, leg_width / 2], name="Bench Leg").extrude(leg_height) leg = leg.translate([-(length / 2) + leg_padding + leg_spacing * leg_idx, 0, 0]) legs_objs.append(leg) bench = ddd.group([seat] + legs_objs, name="Bench") bench = bench.material(ddd.mats.stone) bench = ddd.uv.map_cubic(bench) bench.name = "Bench" bench.mat = None # to avoid batching issues bench = ddd.meshops.batch_by_material(bench).clean(remove_degenerate=False) return bench
def osm_structured_tunnel(osm, root, pipeline): """ Create tunnel walls for tunnels. TODO: More tunnel types """ #layer_m1 = root.select(path="/Ways/", selector='["ddd:layer" = "-1"];["ddd:layer" = "-1a"]') #layer_1 = root.select(path="/Ways/", selector='["ddd:layer" = "0a"];["ddd:layer" = "1"]') #groups = [layer_m1, layer_1] layer_m1 = root.select(path="/Ways/", selector='["ddd:layer" = "-1"]') layer_m1a = root.select(path="/Ways/", selector='["ddd:layer" = "-1a"]') ways = layer_m1.children + layer_m1a.children union = layer_m1.union() union_with_transitions = ddd.group(ways, empty="2").union() union_sidewalks = union_with_transitions.buffer(0.6, cap_style=2, join_style=2) sidewalks_2d = union_sidewalks.subtract(union_with_transitions) # we include transitions sidewalks_2d.name="Tunnel Sidewalks" sidewalks_2d.set("ddd:layer", "-1") sidewalks_2d = sidewalks_2d.material(ddd.mats.pavement) root.find("/Areas").append(sidewalks_2d) walls_2d = sidewalks_2d.buffer(0.5, cap_style=2, join_style=2).subtract(union_sidewalks) walls_2d.name = "Walls" walls_2d.set("ddd:layer", "-1") root.find("/Structures2").append(walls_2d) floors_2d = union_sidewalks.copy() ceilings_2d = union.buffer(0.6, cap_style=2, join_style=2).subtract(layer_m1a) ceilings_2d.name = "Ceilings" ceilings_2d.set("ddd:layer", "-1") root.find("/Structures2").append(ceilings_2d)
def column(r=0.1, height=2.0, top=None): col = ddd.point([0, 0]).buffer(r, resolution =1).extrude(height) col = ddd.uv.map_cubic(col) if top: top = top.translate([0, 0, height]) col = ddd.group([col, top]) return col
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
def text(text): chars = [] for idx, c in enumerate(text): spacing = 1 if c != " ": char_2d = char(c) char_2d = char_2d.translate([idx * spacing, 0, 0]) chars.append(char_2d) return ddd.group(chars)
def powertower(height=14.0): obj_pole = ddd.rect([-0.5, -0.5, 0.5, 0.5]).extrude(height) obj_horz1 = ddd.rect([-2.5, -0.3, 2.5, 0.3]).extrude(0.6).translate([0, 0, height - 2]) obj_horz2 = ddd.rect([-3, -0.3, 3, 0.3]).extrude(0.6).translate([0, 0, height - 4]) obj = ddd.group([obj_pole, obj_horz1, obj_horz2]) obj = obj.material(ddd.mats.steel) obj = ddd.uv.map_cubic(obj) obj = obj.combine() return obj
def busstop_small(height=2.50, panel_height=1.4, panel_width=0.45, text=None): text = "🚍 %s" % text obj_post = post(height=height).material(ddd.mats.metal_paint_green) obj_panel = panel(height=panel_width, width=panel_height, depth=0.05, text=text, text_back=text, center=True) obj_panel = obj_panel.rotate([0, math.pi / 2, 0]).translate([panel_width / 2 + 0.075, 0, height - 0.20 - panel_height / 2]) for o in obj_panel.select('[ddd:text]', path="*").children: o.set('ddd:text:font', 'opensansemoji') obj = ddd.group([obj_post, obj_panel]) return obj
def generate_ways_3d_subways(self): """ Generates boxing for sub ways. """ logger.info("Generating subways.") logger.warn("IMPLEMENT 2D/3D separation for this, as it needs to be cropped, and it's being already cropped earlier") # Take roads ways = [w for w in self.osm.ways_2d["-1a"].children] + [w for w in self.osm.ways_2d["-1"].children] union = self.osm.ways_2d["-1"].union() union_with_transitions = ddd.group(ways, empty="2").union() union_sidewalks = union_with_transitions.buffer(0.6, cap_style=2, join_style=2) sidewalks_2d = union_sidewalks.subtract(union_with_transitions) # we include transitions walls_2d = sidewalks_2d.buffer(0.5, cap_style=2, join_style=2).subtract(union_sidewalks) floors_2d = union_sidewalks.copy() ceilings_2d = union.buffer(0.6, cap_style=2, join_style=2).subtract(self.osm.ways_2d["-1a"]) # FIXME: Move cropping to generic site, use interintermediatemediate osm.something for storage crop = ddd.shape(self.osm.area_crop) sidewalks_2d = sidewalks_2d.intersection(crop) walls_2d = walls_2d.intersection(crop) floors_2d = floors_2d.intersection(crop) ceilings_2d = ceilings_2d.intersection(crop) sidewalks_3d = sidewalks_2d.extrude(0.3).translate([0, 0, -5]).material(ddd.mats.sidewalk) walls_3d = walls_2d.extrude(5).translate([0, 0, -5]).material(ddd.mats.cement) #floors_3d = floors_2d.extrude(-0.3).translate([0, 0, -5]).material(ddd.mats.sidewalk) floors_3d = floors_2d.triangulate().translate([0, 0, -5]).material(ddd.mats.sidewalk) ceilings_3d = ceilings_2d.extrude(0.5).translate([0, 0, -1.0]).material(ddd.mats.cement) sidewalks_3d = terrain.terrain_geotiff_elevation_apply(sidewalks_3d, self.osm.ddd_proj) sidewalks_3d = ddd.uv.map_cubic(sidewalks_3d) walls_3d = terrain.terrain_geotiff_elevation_apply(walls_3d, self.osm.ddd_proj) walls_3d = ddd.uv.map_cubic(walls_3d) floors_3d = terrain.terrain_geotiff_elevation_apply(floors_3d, self.osm.ddd_proj) ceilings_3d = terrain.terrain_geotiff_elevation_apply(ceilings_3d, self.osm.ddd_proj) ceilings_3d = ddd.uv.map_cubic(ceilings_3d) subway = ddd.group([sidewalks_3d, walls_3d, floors_3d, ceilings_3d], empty=3).translate([0, 0, -0.2]) self.osm.other_3d.children.append(subway)
def rooms_test_show(root, pipeline): root.dump() items = ddd.group([root.find("/Rooms"), root.find("/Items")]) nitems = ddd.group3() items = items.flatten() for item in items.children: item = item.extrude(20.0 + item.get('ddd:z_index', 0)) item = item.translate([0, 0, -item.get('ddd:z_index', 0)]) nitems.append(item)
def pedestal(obj=None, d=1.0): """ A pedestal with an optional object on top. Sits centered on its base. """ pedestal = ddd.cube(d=d / 2.0).material(ddd.mats.bronze) pedestal = ddd.uv.map_cubic(pedestal) obj = obj.translate([0, 0, d]) item = ddd.group([pedestal, obj], name="Pedestal: %s" % obj.name) return item
def sign_pharmacy_side(size=1.0, depth=0.3, arm_length=1.0): ''' A pharmacy sign, attached sideways to a post arm. The post attaches centered (on the vertical plane). ''' arm_thick = depth / 2 sign = sign_pharmacy(size, depth) arm = ddd.rect([-arm_thick / 2, -arm_thick / 2, arm_thick / 2, arm_thick / 2]).extrude(arm_length) arm = arm.rotate([math.pi / 2.0, 0, 0]) arm = arm.material(ddd.material(color='#888888')) arm = ddd.uv.map_cubic(arm) sign = sign.rotate([0, 0, -math.pi / 2.0]).translate([depth / 2, 0, 0]) sign = sign.translate([0, -(arm_length + size * 0.66), 0]) return ddd.group([sign, arm], name="Pharmacy Side Sign with Arm")
def lamppost_high_mast(height=20.5, arm_count=3, span=math.pi * 2): """ """ bulb = lamp_ball(r=0.45).material(ddd.mats.lightbulb) arm = post_arm_angled(lamp=bulb) arms = ddd.align.matrix_polar(arm, arm_count, span=span) item = roundedpost(height=height, r=0.25, mat_post=ddd.mats.steel) item = ddd.group([item, arms.translate((0, 0, height))]) item = ddd.meshops.batch_by_material(item) item = item.clean(remove_degenerate=False) return item
def lamp_case(height=0.5, r=0.30): lamp_shape = ddd.point(name="Lamp Case").buffer(r - 0.10, resolution=1) lamp = lamp_shape.extrude_step(lamp_shape.buffer(0.10, cap_style=ddd.CAP_SQUARE, join_style=ddd.JOIN_BEVEL), height * 0.8) lamp = lamp.extrude_step(lamp_shape.buffer(-0.10), height * 0.2) lamp = lamp.merge_vertices().smooth() lamp = lamp.material(ddd.mats.lightbulb) lamp = ddd.collision.aabox_from_aabb(lamp) lamp = ddd.uv.map_spherical(lamp, split=True) # TODO: Possibly add this with styling too, although lights are first class citizens (used for render) light = PointLight([0, 0, height * 0.8], name="Lamp Light", color="#e4e520", radius=18, intensity=1.25, enabled=False) lamp_case = ddd.group([lamp, light], name="Lamp Case and Light") return lamp_case
def childrens_playground_sandbox(r=1.5, sides=5, height=0.4, thick=0.1): """ """ area = ddd.regularpolygon(sides, r, name="Playground Sand") item = area.material(ddd.mats.wood) item = item.outline().buffer(thick / 2).extrude(height) item = ddd.uv.map_cubic(item) item.name = "Playground sandbox border" area = area.triangulate().material(ddd.mats.sand).translate([0, 0, height / 3]) area = ddd.uv.map_cubic(area) item = ddd.group([area, item], name="Playground Sandbox") return item
def osm_positioning_init(pipeline, osm, root, logger): """Repositions features in different ways.""" pipeline.data['positioning_ways_2d_0'] = root.select( path="/Ways/*", selector='["osm:layer" = "0"]', recurse=False) pipeline.data['positioning_ways_2d_0_major'] = root.select( path="/Ways/*", selector='["osm:layer" = "0"]', recurse=False).flatten().filter(lambda i: i.extra.get( 'osm:highway', None) not in ('path', 'track', 'footway', None)) #pipeline.data['positioning_ways_2d_0_traffic_sign'] = root.select(path="/Ways/*", selector='["osm:layer" = "0"]', recurse=False).flatten().filter(lambda i: i.extra.get('osm:highway', None) not in ('path', 'track', 'footway', None)) pipeline.data['positioning_buildings_2d'] = root.select( path="/Buildings/*", recurse=False) pipeline.data['positioning_ways_2d_0_and_buildings'] = ddd.group([ pipeline.data['positioning_ways_2d_0'], pipeline.data['positioning_buildings_2d'] ]).individualize().clean(eps=0.01) pipeline.data['positioning_areas_ways_2d_outline'] = ddd.group([ root.select(path="/Ways/*", selector='["osm:layer" = "0"]', recurse=False).outline(), root.select(path="/Areas/*", selector='["osm:layer" = "0"]', recurse=False).outline() ])
def generate_item_3d_pond(self, item_2d): # Todo: Use fountain shape if available, instead of centroid exterior = item_2d.subtract( item_2d.buffer(-0.4)).extrude(0.4).material(ddd.mats.dirt) exterior = ddd.uv.map_cylindrical(exterior) water = item_2d.buffer(-0.2).triangulate().material(ddd.mats.water) #coords = item_2d.geom.centroid.coords[0] #insidefountain = urban.fountain(r=item_2d.geom).translate([coords[0], coords[1], 0.0]) item_3d = ddd.group([exterior, water]) # .translate([0, 0, 0.3]) item_3d.name = 'Pond: %s' % item_2d.name return item_3d
def generate_item_3d_fountain(self, item_2d): # Todo: Use fountain shape if available, instead of centroid exterior = item_2d.subtract(item_2d.buffer(-0.3)).extrude(1.0).material(ddd.mats.stone) exterior = ddd.uv.map_cubic(exterior) water = item_2d.buffer(-0.20).triangulate().material(ddd.mats.water).translate([0, 0, 0.4]) water = ddd.uv.map_cubic(water) # map_2d_linear #coords = item_2d.geom.centroid.coords[0] #insidefountain = urban.fountain(r=item_2d.geom).translate([coords[0], coords[1], 0.0]) item_3d = ddd.group([exterior, water]) item_3d.name = 'Fountain: %s' % item_2d.name return item_3d
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()
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
def bell(r=1.00, height=2.6, thick=0.10): """ The bell is hung on 0, 0, 0. """ base = ddd.disc(r=r, resolution=4, name="Bell").subtract(ddd.disc(r=r - thick, resolution=4)) extrude_steps = ((4.45, 0), (4.5, 0.25), (4.3, 1), (3.7, 2), (3.0, 3), (2.5, 4), (2.3, 5), (2.4, 6), (2.6, 7)) bell = extrude_step_multi(base, extrude_steps, base=True, cap=False, scale_y=height / 10) bell = bell.twosided() cap = extrude_dome(ddd.disc(r=r * (2.6 / 4.45), resolution=4), height=1.5 / 10) cap = cap.translate([0, 0, 7 / 10 * height]) bell = ddd.group([bell, cap]).combine() bell = bell.material(ddd.mats.bronze) bell = ddd.uv.map_cylindrical(bell) bell = bell.translate([0, 0, -height]) return bell
def fountain(r=1.5): # Base base = ddd.disc(r=r, resolution=2).extrude(0.30).material(ddd.mats.stone) base = ddd.uv.map_cylindrical(base) # Fountain fountain = ddd.sphere(r=r, subdivisions=1).subtract(ddd.cube(d=r * 1.2)).subtract(ddd.sphere(r=r - 0.2, subdivisions=1)) fountain = fountain.translate([0, 0, 1.2]) # TODO: align fountain = fountain.material(ddd.mats.stone) fountain = ddd.uv.map_spherical(fountain) #.subtract(base) # Water water = ddd.disc(r=r-0.2, resolution=2).triangulate().translate([0, 0, 1.1]).material(ddd.mats.water) water.extra['ddd:collider'] = False water.extra['ddd:occluder'] = False water.extra['ddd:shadows'] = False item = ddd.group([base, fountain, water]) return item
def patio_umbrella(side=2.5, height=2.5): base_height = 0.04 base_side = 0.4 base_weight = ddd.rect([base_side, base_side], name="Base weight").recenter() base_weight = base_weight.extrude(base_height).material(ddd.mats.metal_paint_white) base_weight = ddd.uv.map_cubic(base_weight) pole_r = 0.04 pole = ddd.point(name="Pole").buffer(pole_r).extrude(height - base_height).translate([0, 0, base_height]) pole = pole.material(ddd.mats.metal_paint_white) pole = ddd.uv.map_cylindrical(pole) umbrella_height = height - 1.8 umbrella = ddd.rect([side, side], name="Umbrella").recenter().material(ddd.mats.rope) umbrella = umbrella.extrude_step(ddd.point(), umbrella_height, base=False, cap=False) umbrella = umbrella.twosided().translate([0, 0, height - umbrella_height - 0.02]) umbrella = ddd.uv.map_cubic(umbrella) #EXTRUSION_METHOD_WRAP item = ddd.group([base_weight, pole, umbrella]) return item
def recursivetree(height=2.25, r=0.30, fork_height_ratio=1.0, fork_angle=30.0, fork_r_scale=0.8, fork_spawn=3, fork_iters=2, fork_level=0, leaves_callback=None, trunk_callback=None): # Create trunk part #section = ddd.point([0, 0, 0]).buffer(r, cap_style=ddd.CAP_ROUND, resolution=1).extrude(height * fork_height_ratio) branches = [] if fork_iters > 0: section = trunk_callback(height * fork_height_ratio) azimuth = 0 num_items = fork_spawn + random.choice([-1, 0, +1]) if fork_level > 1: stop_prob = 0.1 if random.uniform(0.0, 1.0) < stop_prob: num_items = 0 # Only 1 leave in last iter if fork_iters == 1: num_items = 1 offset = random.uniform(0, 360) for i in range(num_items): azimuth = offset + (360.0 / fork_spawn) * i + (360.0 / fork_spawn) * random.uniform(-0.15, 0.15) if fork_iters > 1: ssection = recursivetree(height=height * (1 - fork_height_ratio) * random.uniform(0.8, 1.2), r=r * fork_r_scale, fork_height_ratio=fork_height_ratio * random.uniform(0.8, 1.2), fork_r_scale=fork_r_scale, fork_iters=fork_iters - 1, fork_level=fork_level + 1, leaves_callback=leaves_callback, trunk_callback=trunk_callback) elif leaves_callback: ssection = leaves_callback(height * (1 - fork_height_ratio)) ssection = ssection.rotate([(fork_angle * random.uniform(0.65, 1.35)) / 180.0 * math.pi, 0.0, 0.0]) ssection = ssection.rotate([0.0, 0.0, azimuth / 180.0 * math.pi]) ssection = ssection.translate([0, 0, height * fork_height_ratio]) ssection.name = "Branch (level %d)" % fork_level branches.append(ssection) #else: # Optionally increase fork_spawn each iteration (golden ratio) # Optionally randomize number of branches (fork_spawn) each iteration branches = [section] + branches return ddd.group(branches)
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