Introduction
While we're still supporting XML, JSON is going to become our primary
format soon. Our editor API also exposes the state of currently edited
floorplan, so this documentation will help those who need to use it for
various purposes at runtime.
A good way to explore the format
You can examine the state of currently edited floorplan
via the editor API property called state. The API is available as
window.api
. You can start a new project, draw something in the
editor and check the state in browser's developer console. Drawing a
single wall and checking api.state.walls[0]
is a good start. Also,
note the section about runtime format vs
persistent format.
The format
Using Typescript notation
In order to describe the format, we decided to use
Typescript notation. This will
allow to show what properties each object has and of what data
type. Furthermore, this will allow declaring nested objects and
frequently used sets of properties as separate interfaces with their
own names, making it easier to comprehend.
Runtime vs persistent
At runtime, a floorplan is represented by one big javascript
object. That's what you'll get from editor's API. When a floorplan is
saved or when it's exported as JSON, we use slightly different format
we call persistent. That's the format we describe in this
document. It doesn't contain some of runtime properties, and the one
called asset
is replaced by refid
. References to assets are
resolved when the plan is loaded, and the rest of runtime properties are
derived from those stored in the persistent format.
Project
When you start working on a plan in Flooplanner, you start with a
project. A project has one or more floors.
interface Project {
id: number;
name: string;
public: boolean;
settings?: ProjectSettings;
floors: Floor[];
}
Project settings
One important attribute of a project is settings
. It
contains a lot of configuration options specific for given project.
interface ProjectSettings {
wallHeight: number;
wallSectionHeight: number;
wallThickness: number;
wallOuterThickness: number;
useMetric: boolean;
showGrid: boolean;
showDims: boolean;
showShortDims: boolean;
showAreaDims: boolean;
generateOuterDimension: boolean;
showDropShadows: boolean;
showObjects: boolean;
showFixtures: boolean;
showItemOutline: boolean;
showObjectColour: boolean;
showStructuralColour: boolean;
showFloorsBelow: boolean;
showObjects3d: boolean;
showObjectMono: boolean;
showLights: boolean;
useSection3D: boolean;
showLabels: boolean;
areaLabelOutline: boolean;
areaLabelLetterSpacing: number;
dimLineLabelHorizontal: boolean;
exportLabels3D: boolean;
showShadows3D: boolean;
exportOrtho3D: boolean;
visuals: "ALL" | "BW" | "BWC";
showTexts: boolean;
arrowHeadType: "arrow-stop" | "stop" | "reverse-arrow-stop" | "arrow";
northArrowRotation: number;
northArrowKind: number;
blueprintMode: boolean;
dimLineFont: string;
hideItemsAboveHeight: number;
hideItemsAbove: boolean;
}
Floor
A floor is a container for designs, which are actual
Floorplans. It's also used as a container for cameras, which are
shared between desings on the same floor.
interface Floor {
id: number;
name: string;
level: number;
height: number; // default wall height
designs: Floorplan[];
cameras: Camera[];
drawing?: Drawing
}
Drawing
Another important attribute a floor may contain is called
drawing. It is an image a user can upload and then draw the plan on
top of it. Useful for tracing scans of paper floorplans.
interface Drawing {
x: number; // position of the drawing on the plan
y: number;
width: number; // size of the drawing in cm
height: number;
visible: boolean;
url: string;
rotation: number; // in degrees
alpha: number;
depth?: "LOW" | "HIGH" // drawn above or below the floorplan
}
Camera
Cameras are used as viewpoints to create 3D renders of floorplans.
interface Camera {
id: number;
name: string;
type_name: 'orbital' | 'walkthrough';
x: number; // position
y: number;
z: number;
ux: number; // direction of normals
uy: number;
uz: number;
dx: number; // direction of camera
dy: number;
dz: number;
fov: number; // field of view, in degrees
lightSettings: CameraLightSettings;
background_image: PresetSky | UserDefinedSky | {}
}
Camera light settings
Each camera has light environment settings, which describe the
position of the sun on the sky (if it's a day) as well as light
intensity.
interface CameraLightSettings {
altitude: number;
azimuth: number;
day: boolean;
intensity: number;
profile: boolean;
}
Camera background image
A camera may have a background image. Either a preset one or an image uploaded
by the user.
interface PresetSky {
sky_id: number;
url: string;
type_name: 'sphere'
}
interface UserDefinedSky {
url: string;
type_name: 'plane'
}
Floorplan
Floorplan is the core object in Floorplanner. It describes things like
walls, doors, windows and furniture items.
interface Floorplan {
id: number;
name: string;
walls: Wall[];
areas: Area[];
surfaces: Surface[];
dimensions: Dimension[];
items: Item[];
labels: Label[];
lines: Line[];
settings?: DesignSettings;
}
Before we go on describing all these types, let's introduce a few
basic ones used in multiple places in a floorplan.
We use centimeters for coordinates. The X axis is directed from left
to right and the Y axis - from the top to the bottom of the screen.
interface Point {
x: number;
y: number;
}
Not all the floorplan coordinates are 3D. We use the third dimension
when needed.
interface Point3D extends Point {
z: number;
}
For colors, we use a string starting with the # symbol and having
six hexadecimal digits.
type Color = string
All the lines in a Floorplan have two endpoints we refer to as a and
b. When the direction is important, we say that the line goes from
a to b.
interface GenericLine {
a: Point;
b: Point;
}
Wall
A wall is defined by the coordinates of the endpoints of its centerline. Curved walls also have the
control point. Wall balance defines how much of wall thickness goes to
the left and to the right of the centerline.
Terms left and right are also used when decorating a wall and, at
runtime, for holding data about wall's outline. Imagine standing at
point a and looking at point b. The left side then will be to the
left and the right side - to the right.
interface Wall extends GenericLine {
c?: Point | null; // control point for curved walls (quadratic bezier)
az: Endpoint3D;
bz: Endpoint3D;
thickness: number; // in cm
balance: number; // 0..1
openings: Opening[];
decor: WallDecor;
};
Note that each endpoint also has two z-coordinates: the lower and the higher.
interface Endpoint3D {
z: number; // elevation of the bottom of the wall's endpoint
h: number; // elevation of the top of the wall's endpoint
}
Openings
A wall also serves as a container for openings - doors and
windows. Type of the door or window is defined by the referenced
asset. The t
parameter describes the horizontal position of the opening relative to wall's endpoints. When it's 0, the middle of the opening is over the endpoint a, when 1 - over the endpoint b.
interface GenericOpening {
refid: string;
width: number;
z: number; // elevation
z_height: number; // height
t: number; // 0..1 - relative position of the opening on the wall
frameColor?: Color;
}
interface Door extends GenericOpening {
type: 'door';
mirrored: [0 | 1, 0 | 1]; // vertical and horizontal flipping
doorColor?: Color;
}
interface Window extends GenericOpening {
type: 'window'
}
Decor
Finally, each side of a wall may be independently decorated with
a color, a material or an image uploaded by the user.
interface WallDecor {
left: WallSideDecor;
right: WallSideDecor;
}
type WallSideDecor = null | WallSideWithColor | WallSideWithMaterial | WallSideWithTexture;
interface WallSideWithColor {
color: Color;
}
interface WallSideWithMaterial {
refid: string;
}
interface WallSideWithTexture {
texture: WallTexture;
}
interface WallTexture {
src: string; // url to the image
fit: 'free' | 'no-stretch' | 'fill' | 'contain' | 'tile-horizontally' | 'tile-vertically' | 'tile-both';
tlx: number; // top left corner coordinates on the wall side
tly: number;
brx: number; // bottom right corner coordinates on the wall side
bry: number;
}
Area
Areas in Floorplanner are generated automatically, whenever plan walls
make closed spaces. Quite often areas have a texture applied to them,
hence a set of texture-specific properties.
interface TextureProps {
rotation?: number; // rotation of the texture, in degrees, if a texture applied and rotation is not zero
tx?: number; // horizontal texture offset, in pixels, if a texture is applied and if the offset is not zero
ty?: number; // vertical texture offset, in pixels, if a texture is applied and if the offset is not zero
sx?: number; // horizontal texture scale, in %, if a texture is applied and scale is not 100%
sy?: number; // vertical texture scale, in %, if a texture is applied and scale is not 100%
}
Another set of area attributes is related to its purpose - an area may
have a name, either a standard one representing one of room types, or
a custom one. The same set of attributes is also used by surfaces.
interface AreaProps extends TextureProps {
refid?: string;
color: Color;
showSurfaceArea?: boolean;
showAreaLabel: boolean;
name?: string; // standard name, derived from the applied roomtype
customName?: string; // custom name, if supplied
role?: number; // roomtype identifier, if a roomtype is applied
name_x?: number; // area label position, horizontal offset from the area polygon centroid, in metres
name_y?: number; // area label position, vertical offset from the area polygon centroid, in metres
}
Finally, the shape of the area is represented by an array of 2D
points. Note that these points are located on edges of walls (not
on their center lines).
interface Area extends AreaProps {
poly: Point[];
ceiling?: Ceiling;
roomstyle_id?: string; // if a roomstyle was chosen for this area
};
Surface
Surfaces are quite similar to areas and share many attributes. They
are used for drawing special purpose stuctures such as roofs or
cutouts, as well area-like structures without walls. For instance,
a patch of grass in the garden. Unlike areas, surfaces are drawn
point-by-point by the user.
interface Surface extends AreaProps {
poly: SurfacePoint[];
isRoof?: boolean;
isCutout?: boolean;
transparency?: number;
};
Sufaces can also be elevated, therefore their points have the z
coordinate. Curves for surfaces are also modelled differently, areas
use approximation with straight segments for curved walls.
interface Point3D extends Point {
z: number;
}
interface BezierPoint extends Point {
cx: number;
cy: number;
cz?: number;
}
type SurfacePoint = Point3D | BezierPoint;
Dimension line
Dimension line is one of the simplest types in the Floorplan. It's
label shows the length of the corresponding line.
interface Dimension extends GenericLine {
type: 'custom_dimension';
}
Item
Furniture items, structural elements, icons and symbols - they all are
item objects in the floorplan. Exact type of the item is defined by
its asset, referenced by the refid
attribute.
interface Item extends Point3D {
refid: string;
width: number;
height: number;
z_height: number;
rotation: number;
mirrored?: [0 | 1, 0];
light?: Light;
materials?: SmartMaterials;
}
Light
Some of items represent light sources. In such case they also have the
light
attribute containing the following data structure.
interface Light {
on: boolean; // a light can be switched off
color: Color;
watt: number; // light intensity, integer in range 0..200
}
Smart items
Some of items are so-called smart items. These may have some of
their materials swapped, resulting in multiple variations with the
same geometry. Think of a table with a set of material options for its
top and legs.
interface SmartMaterials {
[materialName: string]: number;
}
The list of material names and available options is defined by the
asset for given item.
Label
Labels represent formatted pieces of text in the floorplan.
interface Label extends Point {
text: string;
fontFamily: string;
fontSize: number; // in px
letterSpacing: number; // in %
fontColor: Color;
backgroundColor: Color;
backgroundAlpha?: number; // in %
align: 'left' | 'center' | 'right';
rotation: number;
outline?: boolean;
bold?: boolean;
italic?: boolean;
}
Line
Lines are usually added to the floorplan for the notation purpose.
interface Line extends GenericLine {
type: 'solid_line' | 'dashed_line' | 'dotted_line' | 'dashdotted_line';
color: Color;
thickness: number; // in pixels
}
Design settings
Finally, there are several settings stored in each floorplan. This
means that they can vary from one plan to another, even on the same
floor.
interface DesignSettings {
engineAutoThickness: boolean; // no longer used, always false
engineAutoDims: boolean; // automatically generate dimension lines
areaLabelMultiplier: number; // text scale factor for area labels
scaleMultiplierDimensions: number; // text scale factor for dimension text
scaleMultiplierComments: number; // text scale factor for regular labels
showCeilings3D: boolean;
minWallLength?: number; // defaults to 4; walls shorter than this size are discarded
}