KADCAD (kadcad.cz) is a browser-based 3D planner for plots and gardens. It shows a real Czech/Slovak cadastral parcel with its terrain, or a free rectangular plot of your own, and lets you place a house, pool, walls, stairs, paving, garden elements and plants, then export drawings (DXF, IFC, PDF, ...).
This page tells an AI agent (Claude, ChatGPT, a voice bot, ...) how to drive the planner on behalf of a user. The application exposes a JavaScript API on the page: window.k3d.
https://kadcad.cz (or the address the user gave you) in a browser you can control (Claude in Chrome, ChatGPT agent/Operator, Playwright, ...). The user may be logged in; guests can build and view everything, exports require login.typeof window.k3d === 'object' (a second or two after load).await k3d.plot(). Every function returns plain JSON (or a Promise of it). Errors are thrown as Error with a readable message; read it and fix the call.await k3d.screenshot() (PNG data URL) and look at it, or k3d.plot() to read facts. Tell the user what you did in their language (usually Czech or Ukrainian).If you cannot run JavaScript on the page, tell the user the page must be opened in an agent-capable browser.
[y, x]. y grows to the WEST, x grows to the SOUTH. (Looking at the plan with north up: east is at small y, north is at small x.)k3d.plot().bbox gives {yMin,yMax,xMin,xMax} of the plot boundary; place objects inside it. k3d.heightAt(y, x) returns the terrain height at a point.west, southwest, south, southeast, east, northeast, north, northwest.
await k3d.createFreePlot({ width: 20, length: 30 }); // flat rectangle
const b = k3d.plot().bbox; // where is the plot?
const house = await k3d.addHouse({ width: 10, depth: 8, roof: 'gable',
eaveHeight: 3, ridgeHeight: 6.2, frontSetback: 5, sideSetback: 3, frontDir: 'north', sideDir: 'west' });
await k3d.addPool({ y: b.yMin + 5, x: b.xMax - 7, len: 8, wid: 4, depth: 1.5 });
await k3d.addPaving({ preset: 'zamk6', ring: [[b.yMin+3,b.xMin+14],[b.yMin+10,b.xMin+14],[b.yMin+10,b.xMin+19],[b.yMin+3,b.xMin+19]] });
await k3d.view({ mode: '3d', azimuth: 40, elevation: 35 });
const png = await k3d.screenshot(); // data:image/png;base64,...
k3d.plot() – current plot: {loaded, id, name, free, areaM2, boundary, bbox, terrain, buildings[], objects{}, project, axes}. free is {w,d,slope,angle,z} for a free plot, otherwise null. buildings[] has {id,name,originLocal,baseZ,warning} (a non-null warning means e.g. the house crosses the boundary).k3d.heightAt(y, x) – terrain height in m a.s.l.k3d.catalog({ plants: 'dub' }) – allowed values: roofs, directions, wall materials, paving presets, garden element types, pool options; plants searches the plant database by Latin or Czech name.k3d.list(kind) – objects of a kind: pool | paving | element | wall | stairs | pond | plant | hedge, with their uid (plants and hedges are identified by sd instead).k3d.getScene() – the whole scene state as JSON (advanced; same data that is saved in the project).k3d.help() – this document as Markdown text.await k3d.createFreePlot({ width, length, slopePercent = 0, direction = 'west', baseZ = 300 }) – flat or evenly sloped rectangle, no cadastre. width = east-west size (3-300 m), length = north-south size (3-300 m). slopePercent 0-60: the terrain falls toward direction (word or degrees 0-359; 0 = west, 90 = south, 180 = east, 270 = north). baseZ = height at the plot centre. Calling it again while a free plot is open resizes the same project (houses and objects stay).await k3d.loadParcel(ku, parcelNumber) – real cadastral parcel, e.g. ('Černošice', '3830/53'). Needs internet access to the national cadastre; can take 10-60 s.await k3d.addHouse({ width, depth, roof, eaveHeight, ridgeHeight, pitchDeg, eaveOverhang, frontSetback, sideSetback, frontDir, sideDir, rotationDeg, baseZ, name, buildingId }) – rectangular house. roof: flat | hip | gable. For flat, eaveHeight is the top height above the floor; for hip/gable, eaveHeight and ridgeHeight are heights of the eaves and the ridge above the floor. Placement by distances: the house sits frontSetback m from the frontDir boundary and sideSetback m from the sideDir boundary. Or give exact placement: at: { y, x } (reference corner in local coordinates). baseZ omitted = automatic (highest terrain point under the house). Pass buildingId to modify an existing house. Returns {id, baseZ, originLocal, warning}.await k3d.removeBuilding(id) – deletes a house, returns the remaining list.uid, or sd for plants and hedges)k3d.addPool({ y, x, ang, len, wid, depth, kind, rad, cop, water, ... }) – pool with its centre point at [y,x], rotated ang degrees. len 1-40, wid 1-25, depth 0.3-4. kind: std | bio. cop = coping material, water = water colour (see catalog().pool).k3d.addPaving({ preset, ring }) – paved area (terrace, path, driveway) with polygon ring [[y,x],...] (at least 3 points). preset from catalog().paving (e.g. zamk6 interlocking paving, beton, kamen, drevo, mlat, sterk).k3d.addWall({ pts, h, t, mat, closed, mode, cap }) – wall / fence along the polyline pts [[y,x],...]; h height, t thickness (m), mat from catalog().wallMaterials; closed: true closes the loop; mode: 'follow' follows terrain, 'level' stays horizontal.k3d.addStairs({ y1, x1, y2, x2, w, h, rise }) – stairs from point 1 to point 2, width w.k3d.addElement({ type, y, x, ang, w, d, h, col }) – garden element, type from catalog().elements (garden shed, raised bed, sandbox, boulder, swing frame, kitchen, lamp, block).k3d.addPond({ ring, depth, bank, water }) – pond with polygon ring.k3d.addPlant({ species, y, x, height, width }) – a tree/shrub; species is the Latin name from catalog({plants:'...'}).k3d.addHedge({ species, pts, height, width, closed }) – hedge along a polyline.k3d.remove(kind, id) – delete one object by uid (or sd). k3d.clear(kind) – delete all of a kind.k3d.view({ mode: '3d'|'2d', azimuth, elevation, distance }) – camera. azimuth degrees, elevation 0-90 degrees above the horizon, distance metres.await k3d.screenshot({ delayMs: 400 }) – PNG data URL of the 3D view.k3d.exportUrl('dxf') – URL of the terrain export of the current plot; formats xyz, txt, dxf, xml (LandXML). Download it with the user's logged-in browser session; exports need an account. Plan exports of the designed objects (DXF/IFC/PDF) are available in the app's Export menu.await k3d.setScene(state) – replace the whole scene state with a JSON obtained from getScene() (undo helper / advanced).plot().buildings[].warning is set, fix it (smaller house or setbacks) before continuing.plot().bbox; keep a distance of at least 1.5 m between a pool and a wall, and 3 m between the house and the boundary unless the user asks otherwise.clear anything the user did not ask about. Use list(kind) to show what exists.