Zusätzliche Features, Einstellungen oder Probleme, die nicht von bestimmten Microsoft Teams-Kategorien abgedeckt werden
Create Microsoft Places indoor maps from a Figma SVG floor plan
Create Microsoft Places indoor maps from a Figma SVG floor plan
This article describes a reproducible, low-cost method for producing correlated IMDF map packages for Microsoft Places without a specialized CAD/IMDF partner. Instead of tracing CAD data, you draw the floor plan in Figma, name each shape after its Microsoft Places PlaceId, export as SVG, and convert it to a fully correlated IMDF ZIP with a small script.
The approach was developed and validated on a real two-floor building (ground floor + upper floor, 66 Places objects: 1 building, 2 floors, 11 sections, 19 rooms/spaces, 33 desks).
[!NOTE] Microsoft recommends working with an IMDF integration partner for complex venues. This method is intended for organizations that want an in-house, repeatable, multi-tenant-friendly workflow for simple office buildings.
Prerequisites
- PowerShell 7.4+ launched as Administrator.
- The MicrosoftPlaces PowerShell module (tested with v2.1.3).
- Places Directory already configured: the building, floors, sections, rooms, spaces, and desks must exist as bookable resources before you import a map.
- Figma (or any tool that exports SVG with element IDs).
- A drawing tool result: one SVG per floor.
- An AI assistant (e.g., Microsoft Copilot) to generate/convert the geometry and correlation files.
Tools used
| Tool | Purpose |
|---|---|
| Figma | Draw the true building outline, sections, rooms, and desks as vector shapes. |
| MicrosoftPlaces module | Import-MapCorrelations, New-Map, Remove-Map, Get-PlaceV3, Get-PlacesSettings, Set-PlacesSettings. |
Python 3 (lxml, shapely) |
Parse the SVG, apply transforms, georeference, and emit IMDF GeoJSON + ZIP. |
| AI assistant (Copilot) | Generate the converter, build the pre-filled mapfeatures.csv, and troubleshoot errors. |
Concept: why SVG beats PDF/CAD tracing
The core insight from this project: the exact geometry and the "who sits where" knowledge lives with you, not in any file. A PDF blueprint contains anonymous furniture symbols; the Places directory contains team- and person-named resources. Nothing links them automatically.
Drawing in Figma puts that knowledge directly into named vector shapes:
- Layer name = Places
PlaceId→ correlation becomes deterministic. - Vector polygon = real room/desk shape → the map matches the building.
This eliminates the guesswork that makes rectangle-grid or auto-trace approaches look wrong.
IMDF file requirements (Microsoft Places)
An IMDF package is a ZIP with GeoJSON files zipped directly (no subfolders):
| File | Required | Contents |
|---|---|---|
building.geojson |
✅ | Building anchor (lon/lat). |
footprint.geojson |
✅ | Building outline polygon. |
level.geojson |
✅ | Each floor + its ordinal. |
unit.geojson |
✅ | Rooms/spaces. |
section.geojson |
⬜ | Zones/team areas (needed for sections view). |
fixture.geojson |
⬜ | Desks (needed for desk icons + avatars). |
[!IMPORTANT] To show desks and sections in Places, you must include
section.geojsonandfixture.geojson.
Step 1 – Draw the floor plan in Figma
- Create one frame per floor.
- Draw:
- the building outline (one closed shape per floor),
- sections (team zones),
- rooms/spaces (offices, meeting rooms, etc.),
- desks (one shape per desk).
- Name every layer with the exact Places
PlaceIdof the corresponding object. - For desk pools where you only know the group, you may name the group with the section
PlaceIdand the individual desks generically (e.g.,Desk,Desk_2) — see Handling desk pools.
Export from Figma
- Select the frame → Export → SVG.
- Open the format options (…) and enable Include "id" attribute.
[!WARNING] If Include "id" attribute is not enabled, Figma strips all layer names and the SVG contains only colored shapes with no IDs. This was the single most common failure in development — the geometry looked correct but nothing could be correlated.
Resulting SVG structure (example)
<svg width="2351" height="3489" viewBox="0 0 2351 3489" ...>
<g id="fc4d191d-78c3-4c38-a496-27fea5d1f67c"> <!-- Floor = level -->
<path id="fc4d191d-..._2" d="M2077.5 1944.5..." fill="#D70000"/> <!-- footprint outline -->
<rect id="5ce00a3c-5c3a-447b-94f9-3e3f7633dda9" .../> <!-- Section: Projekte -->
<g id="6d36184c-2c98-4ee3-bd30-ea1e898a5142"> ... </g> <!-- Section drawn as group -->
<rect id="7abfe522-a9e5-4adf-8bc5-8d438965fe36" .../> <!-- Room: Büro Arnold -->
<path id="a40c5bb5-0f81-4fd6-b4b1-50480e3613fc" d="..." fill="#30EB5F"/> <!-- Desk: Tim -->
</g>
</svg>
Step 2 – Convert SVG to a correlated IMDF ZIP
Use a converter script that:
- Parses SVG
rect,polygon,path,circle,ellipse, and applies nestedtransform(translate/scale/rotate/matrix). - Maps each shape's
idto a Places object via the exported directory hierarchy CSV (PlaceId, DisplayName, Type, ParentId). - Auto-detects the feature type from the Places
Type(Floor→level,Section→section,Room/Space→unit,Desk→fixture). - Georeferences all pixels to real coordinates using a building anchor (lon/lat), a meters-per-unit scale, and optional rotation.
- Writes
building/footprint/level/unit/section/fixture.geojson, zips them flat, and emits a pre-filledmapfeatures.csv(becauseFeatureId == PlaceId).
Export the directory hierarchy first
# Find the building PlaceId
Get-PlaceV3 -Type Building | ? {$_.DisplayName -eq 'OCOM AG'} | ft DisplayName,PlaceId
# Export the full hierarchy for that building
Get-PlaceV3 -AncestorId <BuildingPlaceId> |
Export-Csv "C:\Temp\OCOM_Hierarchy.csv" -NoTypeInformation -Encoding UTF8
Georeference parameters
| Parameter | Example | Notes |
|---|---|---|
| Anchor latitude | 46.3072914 |
Real building coordinate. |
| Anchor longitude | 7.9670292 |
Real building coordinate. |
| Longest side (m) | 30.0 |
Scales the drawing to real-world size. |
| Rotation (° CW) | 0 |
Adjust so "image up" = North. |
Step 3 – Correlate and upload to Places
Import-MapCorrelations runs twice: once to extract features, once to embed the correlation.
# 0. Connect
Connect-MicrosoftPlaces
# 1. FIRST RUN — extract feature IDs into mapfeatures.csv (next to the ZIP)
Import-MapCorrelations -MapFilePath "C:\Users\<you>\Downloads\OCOM_AG_Places_Map.zip"
# 2. Fill PlaceId / Name / Type columns in mapfeatures.csv
# (the converter can produce this pre-filled — FeatureId == PlaceId)
# 3. SECOND RUN — embed correlations -> writes imdf_correlated.zip
Import-MapCorrelations `
-MapFilePath "C:\Users\<you>\Downloads\OCOM_AG_Places_Map.zip" `
-CorrelationsFilePath "C:\Users\<you>\Downloads\mapfeatures.csv"
# 4. Remove any existing map for the building (replace scenario)
Remove-Map -BuildingId 3ab4336a-bcc1-432d-852b-ac898b4a42b4
# 5. Upload the correlated package
New-Map -BuildingId 3ab4336a-bcc1-432d-852b-ac898b4a42b4 `
-FilePath "C:\Users\<you>\Downloads\imdf_correlated.zip"
[!IMPORTANT]
Import-MapCorrelationswrites toimdf_correlated.zipby default (in the source folder), not<name>_correlated.zip. PointNew-Mapat the exact file name the tool reports (SUCCESS: correlated IMDF zip package created).
[!NOTE] New or updated maps can take up to 1 hour to appear in Microsoft Places. There is no
Get-Mapcmdlet in module v2.1.3 to query map status — verify visually in the Places app.
The mapfeatures.csv schema
The extracted file has these columns; you fill the first three:
PlaceId,Name,Type,FeatureType,FeatureId,FeatureName,FeatureCategory
Because the converter sets FeatureId == PlaceId, filling is deterministic:
| Column | Source |
|---|---|
PlaceId |
= FeatureId |
Name |
Directory DisplayName (looked up by PlaceId) |
Type |
Directory Type (Building/Floor/Section/Room/Space/Desk) |
FeatureType,FeatureId,FeatureName,FeatureCategory |
Pre-populated by the extract run |
Handling desk pools and duplicates
- Duplicate names (e.g., three desks named "Philipp") cannot be matched by name. Correlate by FeatureId instead, or name the Figma layer directly with the
PlaceId. - Desk pools drawn as a group (e.g., group
id= section PlaceId with generic child desks) can be split by reading order. If the SVG contains one extra duplicate shape and one missing desk, a 1:1 reassignment resolves it (this happened once: a duplicated "Maurice" triangle was reassigned to the missing "Noemie").
Error sources and fixes
| Symptom / message | Root cause | Fix |
|---|---|---|
SVG has shapes but no ids |
"Include id attribute" not enabled in Figma export | Re-export with the option enabled. |
New-Map → "Place levels in the building should be created before ingesting map." |
Correlation not embedded (map IDs never linked to directory floors) | Run the second Import-MapCorrelations with -CorrelationsFilePath, then upload the correlated ZIP. |
Import not supported for file fixtures.geojson |
Wrong file name/format | Use exactly fixture.geojson (singular), zipped flat. |
No levels were found correlated to directory floors |
mapfeatures.csv PlaceId/Type not filled for levels |
Fill level rows; ensure FeatureId matches a real Floor PlaceId. |
New-Map: Could not find file '..._correlated.zip' |
Wrong output filename | Use the actual output imdf_correlated.zip. |
| Ambiguous name match (3× "Philipp") | Correlating by name | Correlate by FeatureId / name the layer with PlaceId. |
| Map not visible after upload | Propagation delay | Wait up to 1 hour; verify in Places app. |
| Rotated/flipped map | Wrong rotation/anchor | Adjust rotation so image-up = North; re-georeference. |
| Generic "Office" location still shown | Known Places limitation | See Related: default office location. |
Validation checklist (before upload)
- [ ] All GeoJSON polygons are closed rings (first point == last point).
- [ ] All feature
ids are unique. - [ ] Every
unit/section/fixturelevel_idresolves to an existinglevelid. - [ ] Object count matches the directory (here: 66).
- [ ] ZIP contains the six files at the root (no subfolder).
AI prompts used (Copilot)
These prompts drove the automation with an AI assistant:
- Research & scaffolding
"Research the Microsoft Places Map feature and write a script to pull all the data needed to create an IMDF file that maps objects to this map."
- Blueprint reference
"Reference the real blueprint of the building — don't just draw rectangles."
- Layout knowledge injection (the missing link)
"From the top it's Admin/Marketing/Beratung, then Empfang to the right; below Admin are the 4 offices, to their right a hallway, then Service … Cafeteria between Projekte and Gemeinde-Software."
- Switch to SVG
"Can you work with SVG? I think it's easier if I draw it in Figma."
- Final delivery
"All objects are named after Places IDs except desk pools where the groups are named. Give me a finished correlated file plus the command to replace the current map."
[!TIP] The decisive improvement came from prompt #3 and #4: giving the assistant the team layout (local knowledge) and switching input from PDF to named SVG turned "correct shape, guessed positions" into "correct shape, correct positions."
Reusability (multi-tenant)
The workflow is tenant-agnostic. To reuse for another customer, swap only:
- The per-floor SVG files (layers named with that tenant's PlaceIds).
- The hierarchy CSV (
Get-PlaceV3 -AncestorId). - The anchor coordinates and BuildingId.
Parameterize the converter (-BuildingId, -AnchorLat/-AnchorLon, -Hierarchy, -Svg) to ship it as a solution package.
Summary
- Draw each floor in Figma; name layers with Places
PlaceIds; export SVG with IDs. - Convert SVG → IMDF ZIP + pre-filled
mapfeatures.csv(FeatureId == PlaceId). -
Import-MapCorrelations(extract → embed) →Remove-Map→New-Map. - Validate geometry, wait up to 1 hour, verify in Places.
This produces an indoor map that matches the real building outline, with rooms and desks exactly where you placed them, fully correlated to bookable Places resources.
Microsoft Teams | Microsoft Teams für Unternehmen | Andere
Gesperrte Frage. Sie können darüber abstimmen, ob sie hilfreich ist, aber Sie können keine Kommentare oder Antworten hinzufügen oder der Frage folgen.