// isokit/ground: site plate, paved and green areas, roads, parking, walls, // fences and lamps. Ground surfaces go to the unsorted "ground" layer in // document order (later objects lie on top). fn ground_materials() { ["g-grass", "g-grass2", "g-green", "g-garden", "g-asph", "g-conc", "g-pad", "g-path", "g-sand", "g-court", "dirt"] } fn meta_site() { #{ label: "Site ground", category: "Ground", icon: "▭", help: "The ground plate: a surface with earth sides. Frames the view.", props: [ #{ key: "w", type: "float", def: 60.0, min: 4.0, max: 1000.0, step: 1.0, label: "Width (m)" }, #{ key: "d", type: "float", def: 40.0, min: 4.0, max: 1000.0, step: 1.0, label: "Depth (m)" }, #{ key: "mat", type: "material", def: "g-grass", choices: ground_materials(), label: "Surface" }, #{ key: "base", type: "float", def: 1.6, min: 0.2, max: 10.0, step: 0.1, label: "Earth depth (m)" }, ] } } fn prefab_site(o) { let p = o.p; let w = p.w / 2.0; let d = p.d / 2.0; layer("ground"); sprite().box(-w, -d, w, d, -p.base, 0.0, "dirt", #{ top: p.mat }); bounds(-w, -d, w, d, -p.base); } fn meta_area() { #{ label: "Area", category: "Ground", icon: "▱", help: "A paved or planted area lying on the ground.", props: [ #{ key: "w", type: "float", def: 10.0, min: 0.5, max: 1000.0, step: 0.5, label: "Width (m)" }, #{ key: "d", type: "float", def: 6.0, min: 0.5, max: 1000.0, step: 0.5, label: "Depth (m)" }, #{ key: "mat", type: "material", def: "g-conc", choices: ground_materials(), label: "Surface" }, ] } } fn prefab_area(o) { let p = o.p; layer("ground"); let s = sprite(); if o.pts != () && o.pts.len() >= 3 { s.flat(o.pts, 0.006, p.mat + " t"); } else { s.flat(rect(-p.w / 2.0, -p.d / 2.0, p.w / 2.0, p.d / 2.0), 0.006, p.mat + " t"); } } fn meta_road() { #{ label: "Road", category: "Ground", icon: "═", help: "A straight road along its length, with a dashed centre line.", props: [ #{ key: "w", type: "float", def: 40.0, min: 2.0, max: 2000.0, step: 1.0, label: "Length (m)" }, #{ key: "d", type: "float", def: 6.0, min: 2.0, max: 40.0, step: 0.5, label: "Width (m)" }, #{ key: "dashed", type: "bool", def: true, label: "Centre line" }, #{ key: "kerb", type: "bool", def: true, label: "Kerb lines" }, ] } } fn prefab_road(o) { let p = o.p; let w = p.w / 2.0; let d = p.d / 2.0; layer("ground"); let s = sprite(); s.flat(rect(-w, -d, w, d), 0.007, "g-asph t"); if p.dashed { s.lines([[-w, 0.0, w, 0.0]], 0.012, "dash"); } if p.kerb { s.lines([[-w, -d, w, -d], [-w, d, w, d]], 0.012, "kerb"); } } fn meta_parking() { #{ label: "Parking bays", category: "Ground", icon: "P", props: [ #{ key: "n", type: "int", def: 6, min: 1, max: 60, step: 1, label: "Bays" }, #{ key: "bay_w", type: "float", def: 2.5, min: 2.0, max: 4.0, step: 0.1, label: "Bay width (m)" }, #{ key: "bay_d", type: "float", def: 5.0, min: 4.0, max: 7.0, step: 0.1, label: "Bay depth (m)" }, ] } } fn prefab_parking(o) { let p = o.p; let w = p.n * p.bay_w / 2.0; let d = p.bay_d / 2.0; layer("ground"); let s = sprite(); s.flat(rect(-w, -d, w, d), 0.008, "g-pad t"); let segs = []; for i in 0..(p.n + 1) { let x = -w + i * p.bay_w; segs.push([x, -d, x, d]); } s.lines(segs, 0.014, "bayline"); } fn meta_wall() { #{ label: "Wall", category: "Site", icon: "▬", props: [ #{ key: "w", type: "float", def: 20.0, min: 0.5, max: 500.0, step: 0.5, label: "Length (m)" }, #{ key: "h", type: "float", def: 2.2, min: 0.3, max: 8.0, step: 0.1, label: "Height (m)" }, #{ key: "t", type: "float", def: 0.24, min: 0.1, max: 1.0, step: 0.02, label: "Thickness (m)" }, ] } } fn prefab_wall(o) { // long walls in pieces of at most 30 m, each its own sprite for the depth sort let p = o.p; let n = (p.w / 30.0).ceiling().to_int(); let L = p.w / n; for i in 0..n { let x0 = -p.w / 2.0 + i * L; sprite().box(x0, -p.t / 2.0, x0 + L, p.t / 2.0, 0.0, p.h, "wallp", #{ top: "wallt" }); } } fn meta_fence() { #{ label: "Fence", category: "Site", icon: "┼", props: [ #{ key: "w", type: "float", def: 20.0, min: 1.0, max: 500.0, step: 0.5, label: "Length (m)" }, #{ key: "h", type: "float", def: 1.8, min: 0.5, max: 4.0, step: 0.1, label: "Height (m)" }, ] } } fn prefab_fence(o) { let p = o.p; let n = (p.w / 30.0).ceiling().to_int(); let L = p.w / n; for i in 0..n { let x0 = -p.w / 2.0 + i * L; let s = sprite(); s.box(x0, -0.03, x0 + L, 0.03, 0.0, p.h, "fence"); let k = (L / 2.5).floor().to_int(); for j in 0..(k + 1) { let x = x0 + j * L / fmax(k, 1); s.box(x - 0.04, -0.04, x + 0.04, 0.04, 0.0, p.h + 0.05, "steel"); } } } fn meta_lamp() { #{ label: "Street lamp", category: "Site", icon: "†", help: "Keep lamps on verges and kerbs, not on drive areas.", props: [ #{ key: "h", type: "float", def: 5.0, min: 2.0, max: 12.0, step: 0.5, label: "Height (m)" } ] } } fn prefab_lamp(o) { let s = sprite(); s.box(-0.07, -0.07, 0.07, 0.07, 0.0, o.p.h, "lampost", #{ no_top: true }); s.circle(0.0, 0.0, o.p.h + 0.1, 1.2, "lamp"); } fn meta_marker() { #{ label: "Marker", category: "Site", icon: "⚑", help: "A pin with a label: set the label in Tag and the tooltip in Info.", props: [ #{ key: "h", type: "float", def: 1.5, min: 0.3, max: 20.0, step: 0.1, label: "Height (m)" } ] } } fn prefab_marker(o) { let s = sprite(); s.box(-0.05, -0.05, 0.05, 0.05, 0.0, o.p.h, "steel", #{ no_top: true }); s.circle(0.0, 0.0, o.p.h, 2.0, "led ledo"); }