| import json, os |
| from devcore.parser import parse_description |
|
|
| TEMPLATE_PATH = os.path.join(os.path.dirname(__file__), "templates", "viewer.html") |
|
|
|
|
| def description_to_blueprint(text): |
| data = parse_description(text) |
| return _build_threejs_html(data) |
|
|
|
|
| def _build_threejs_html(data): |
| scene = data["structure"] |
| rooms = data["rooms"] |
| w = scene["width"] |
| d = scene["depth"] |
| s = scene["stories"] |
| roof_style = scene.get("roof_style", "gable") |
|
|
| wall_height = 8 if s <= 1 else 9 |
| floor_height = 0.5 |
|
|
| room_meshes = [] |
| wall_meshes = [] |
| label_data = [] |
| measurements = [] |
|
|
| for room in rooms: |
| rx, rz = room["x"], room["z"] |
| rw, rd = room["w"], room["d"] |
| floor_n = room.get("floor", 0) |
| cy = floor_n * (wall_height + floor_height) + floor_height / 2 |
| exterior = room.get("exterior", False) |
| color = room["color"] |
|
|
| room_meshes.append({ |
| "x": rx, "z": rz, "w": rw, "d": rd, |
| "y": cy, "h": floor_height, |
| "color": color, "name": room["name"], "exterior": exterior, |
| }) |
|
|
| lx = rx + rw / 2 |
| lz = rz + rd / 2 |
| label_data.append({"x": lx, "z": lz, "y": cy + 0.3, "text": room["name"]}) |
|
|
| measurements.append({ |
| "x": rx + rw / 2, "z": rz - 1, "y": 0.1, |
| "text": f"{rw:.0f}'", |
| "dim": "width", |
| }) |
| measurements.append({ |
| "x": rx - 1, "z": rz + rd / 2, "y": 0.1, |
| "text": f"{rd:.0f}'", |
| "dim": "depth", |
| }) |
|
|
| if not exterior: |
| for side in ["north", "south", "east", "west"]: |
| wall_meshes.append({ |
| "side": side, "x": rx, "z": rz, |
| "w": rw, "d": rd, "h": wall_height, |
| "room_name": room["name"], |
| }) |
|
|
| roof_h = 4 if roof_style == "flat" else 6 |
| roof_elev = s * (wall_height + floor_height) |
| roof_info = { |
| "w": w * 1.15, "d": d * 1.15, "y": roof_elev, |
| "h": roof_h, "style": roof_style, "color": "#5a4a3a", |
| "pitch": 0.5 if roof_style == "steep-gable" else (0.3 if roof_style == "low-gable" else 0.4), |
| } |
|
|
| blueprint = { |
| "scene": { |
| "width": w, "depth": d, "stories": s, |
| "wall_height": wall_height, "floor_height": floor_height, |
| "roof_style": roof_style, "style": scene.get("style", "modern"), |
| }, |
| "floors": room_meshes, |
| "walls": wall_meshes, |
| "roof": roof_info, |
| "labels": label_data, |
| "measurements": measurements, |
| "summary": data["summary"], |
| "features": data["features"], |
| } |
|
|
| return _render_html(blueprint) |
|
|
|
|
| def _render_html(blueprint): |
| bp_json = json.dumps(blueprint) |
| with open(TEMPLATE_PATH, "r") as f: |
| template = f.read() |
| return template.replace("/* BLUEPRINT_DATA */", f"const BLUEPRINT = {bp_json};") |
|
|
|
|
| def blueprint_to_json(text): |
| data = parse_description(text) |
| return json.dumps(data, indent=2) |
|
|