NavVis
Point Streaming API Usage Guide
  • 01 Jul 2024
  • 14 Minutes to read
  • Dark
    Light
  • PDF

Point Streaming API Usage Guide

  • Dark
    Light
  • PDF

Article summary

Overview

This guide informs you on how to consume the NavVis IVION Point Streaming API from a third-party application. It covers the relevant webservice endpoints and the details about the binary Point cloud format used by NavVis IVION.

Note:

  • All information provided in this guide is only applicable to NavVis IVION version 10.7 or newer.

  • You can also use the C++ sample application provided alongside as a reference in addition to this document.

  • All placeholders in this document use curly brackets {}. For example, {instance_url}

Sample Request

Endpoint:

POST{instance_url}/api/site/{site_id}/pois
X-Authorization: Bearer {access_token}

Request Body:

[
  {
    "dataset_id": number
    "dataset_location": [number, number, number],
    "titles":
    {
      "en": string
    },
      ...
  }
]

Response Code & Status:

200 OK

Response Body:

[
  {
    "dataset_id": number,
    ...
  }
]

For detailed description of the entire NavVis IVION API, click here.

Logging In

The NavVis IVION web application provides a mechanism for the third-party applications to request access to the API and the data stored on a particular NavVis IVION Instance.

The consuming application should request a login mandate to begin the authorization process through the following endpoint:

Endpoint:

POST {instance_url}/api/auth/mandate/request

Response Code & Status:

200 OK

Response Body:

{
  "exchange_token": string,
  "authorization_token": string,
  "expiration": string
}

This POST request doesn’t require a body. The returned exchange and authorization tokens are 30 characters long ASCII alphanumeric strings. The expiration is a UNIX timestamp in seconds.

Once the login mandate is created, the consuming application opens a browser/webview window pointing to the URL below:

{instance_url}?mandate={authorization_token}&supplicant={application_name}

Note:

  • The authorization token to be supplied is the one previously returned by the ‘request’ endpoint.

  • The supplicant query parameter is optional. If provided, it should be an URL encoded version of the name of the consuming application.

NavVisIVION_API_AuthorizeRequest

Once the browser window is open the consuming application should start polling the following endpoint at a reasonable interval (every 3-5 seconds).

Endpoint:

GET {instance_url}/api/auth/mandate/validate?authorization_token=
{authorization_token}

Response Code & Status:

200 OK

Response Body:

{
  "authorized": boolean,
  "exchanged": boolean,
  "expired": boolean
}

The returned boolean values describe the state of the mandate associated with the supplied authorization token. If all the 3 attributes are false, the application should keep on polling the endpoint. As soon as the authorized attribute becomes true and the two other attributes are false, the application should proceed to the next step of the authorization process. If the expired attribute becomes true, the application should stop polling and request a new mandate. The exchanged attribute will never become true at this stage if the application implements the login flow properly.

Attribute

Description

Authorized

Indicates whether the mandate has been successfully authorized by the user (the user has clicked on ‘Allow’)

Exchanged

Shows if the mandate has already been exchanged for credentials

Expired

Shows if the mandate has expired

Once the mandate is authorized, the application can exchange it for access credentials by calling the following endpoint:

Endpoint:

POST {instance_url}/api/auth/mandate/exchange

Request Body:

{
  "exchage_token": string
}

Response Code & Status:

200 OK

Response Body:

{
  "access_token": string,
  "refresh_token": string,
  "principal" :
  {
    "username": string,
    "first_name": string | null,
    "last_name": string | null,
    ...
  },
  ...
}

Note:

  • This endpoint requires the exchange token of the log in mandate and not the authorization token.

  • The response to this call contains the access token needed for using the NavVis IVION API along with other information about the authorizing user. For detailed information about this response, see the SwaggerHub page.

  • The access token usually has short validity and must be refreshed regularly by using the refresh token which is also part of the response. See Refreshing the Access Token for more information on this topic.

Listing Sites

Retrieve the list of sites available to the authorizing user through the following endpoint:

Endpoint:

GET {instance_url}/api/sites
X-Authorization: Bearer {access_token}

Response Code & Status:

200 OK

Response Body:

[
  {
    "id": number,
    "name": string,
    "description": string | null,
    ...
  },
  ...
]

Listing Datasets

Retrieve the list of datasets for a given site by using the following endpoint:

Endpoint:

GET {instance_url}/api/site/{site_id}/datasets
X-Authorization: Bearer {access_token}

Response Code & Status:

200 OK

Response Body:

[
  {
    "id": number,
    "name": string,
    "title": string,
    "bundle_id": number | null,
    "reference_system_id": number,
    ...
  },
  ...
]

Loading the Cloud Metadata

Each NavVis IVION dataset contains a file named metadata.json in its cloud sub-directory. This file provides important information about the point cloud that must be read prior to parsing the Potree 2.0 hierarchy and the actual point cloud data.

Retrieve the contents of this file through the following endpoint:

Endpoint:

GET {instance_url}/data/{site_id}/datasets_web/{dataset_name}/cloud/metadata.json
X-Authorization: Bearer {access_token}

Response Code & Status:

200 OK

Response Body:

{
   "version": string,
   "name": string,
   "description": string,
   "points": number,
   "projection": string,
   "hierarchy": {
      "firstChunkSize": number,
      "stepSize": number,
      "depth": number
   },
   "offset": [number, number, number],
   "scale": [number, number, number],
   "spacing": number,
   "boundingBox": {
      "min": [number, number, number],
      "max": [number, number, number]
   },
   "encoding": string,
   "attributes": [
      {
         "name": string,
         "description": string,
         "size": number,
         "numElements": number,
         "elementSize": number,
         "type": string,
         "min": [number, …],
         "max": [number, …],
         "scale": [number, …],
         "offset": [number, …]
      }
   ]
}

The table below contains a short description of the most important attributes of the response received:

Attribute

Description

points

The total number of points in this point-cloud

hierarchy

firstChunkSize

The size (in bytes) of the first chunk (block) of the hierarchy file

stepSize

The maximum number of octree levels that can occupy a single chunk of the hierarchy file.

depth

The depth of the hierarchy octree. (The root is at level 0)

offset

An offset that must be applied to all points in the cloud to translate them to real dataset coordinates.

spacing

The minimum distance between two points in the root node. This distance halves in every subsequent tree level

scale

The scale multiplier that must be applied when converting coordinates from 32-bit unsigned integers to floating point numbers. This property applies only to the position attribute.

boundingBox

min

The ‘min’ edge of the point-cloud’s bounding box. Often is the same as offset.

max

The ‘max’ edge of the point-cloud’s bounding box.

encoding

The encoding (compression) of the point-cloud data. Can be BROTLI or UNCOMPRESSED.

The ‘attributes’ array is an ordered collection of attribute descriptors. The table below describes the fields of a single attribute descriptor.

Attribute

Description

name

The name of the attribute

size

The total decoded size of the attribute in bytes. Equals numElements multiplied by elementSize. For some special attributes that are Morton encoded this is NOT the real byte size of the attribute in the octree file.

numElements

The number of elements this attribute consists of.

elementSize

The byte size of each attribute element.

type

The data type of a single attribute element. (uint8, int32, etc.)

min

The minimum possible value for this attribute (in this point-cloud, not in general). The minimum is an array and is defined per attribute element.

max

The maximum possible value for this attribute (in this point-cloud, not in general). The maximum is an array and is defined per attribute element.

scale

Optional scale factor to be applied to the attribute per point.

offset

Optional offset value to be added to the attribute per point.

Parsing the Potree Hierarchy

The Potree 2.0 hierarchy is defined in a file called hierarchy.bin which contains a definition of an octree. The file consists of chunks (blocks), where every chunk represents a single branch of the octree. The root of the tree along with the first couple of levels are at the beginning of the file and occupy the first firstChunkSize number of bytes.

Use the following endpoint to retrieve this file:

Endpoint:

GET {instance_url}/data/{site_id}/datasets_web/{dataset_name}/cloud/hierarchy.bin
X-Authorization: Bearer {access_token}

Response Code & Status:

200 OK

Response Body:

[binary data]

Each node of the octree occupies 22 continuous bytes and consists of the following fields.

type

child_mask

point_count

offset

size

uint8

uint8

uint32

uint64

uint64

type – Defines the type of the node and can have 3 possible values 0 (normal), 1 (leaf) and 2 (proxy). Normal is a regular inner node of the tree which has child nodes. Leaf is a node without child nodes. Proxy is a special node which acts as a pointer to another block (chunk) of the tree.

child_mask – This is a bitmask describing the configuration of sub-nodes for this node. Each bit signifies the presence of a child node at the given position. The bit will be set to ‘1’ if the child is present and to ‘0’ otherwise. The volume in space (the bounding box) that each child node occupies within its parent is illustrated in the diagram below.

8BitMask

point_count - The number of points contained in this node. The actual point attributes are in a file called octree.bin which will be described later in this document.

offset – For normal and leaf nodes, this is the offset (in bytes) of the block in octree.bin where the point attributes of this node begin. For proxy nodes this is the offset (in bytes) of the chunk in hierarchy.bin where the sub-tree begins.

size – For normal and leaf nodes, this is the size (in bytes) of the block in octree.bin where the attributes of this node reside. For proxy nodes, this is the size (in bytes) of the chunk in hierarchy.bin where the sub-tree resides.

Note on proxy nodes: When parsing the octree hierarchy, the proxy nodes should be viewed only as a pointer to another “real” node. The proxy nodes themselves are not part of the hierarchy and do not contain points either.

Reading the Point cloud

The actual point-cloud data (point attributes) is contained in a file called octree.bin. This file was already mentioned in the ‘Parsing the Potree Hierarchy’ section because some of the offset and size values in hierarchy.bin are in reference to octree.bin.

Use the following endpoint to retrieve the octree.bin file:

Endpoint:

GET {instance_url}/data/{site_id}/datasets_web/{dataset_name}/cloud/octree.bin
X-Authorization: Bearer {access_token}

Response Code & Status:

200 OK

Response Body:

[binary data]

The layout of the attributes within the octree.bin file depends on the encoding of the file. BROTLI and UNCOMPRESED have different layouts. Only the BROTLI layout will be described in this document because this is the only Potree 2.0 format used by NavVis datasets.

The octree.bin file is divided in blocks that contain the point data for a single node of the potree. The location and size of these blocks is defined by the offset and size fields of the octree nodes in hierarchy.bin that were described in the previous section of this document. Each node-block is further divided into attribute blocks. The attribute-blocks are continuous arrays of a particular attribute defined for each point in the node.

It is important to note that each individual node block is compressed with the Brotli compression algorithm. The blocks need to be decompressed before the data can be used. The Google implementation of Brotli can be used for decompression GitHub - google/brotli: Brotli compression format or any implementation that comes with your operating system.

Once the block is decompressed the point attributes can be accessed. The byte size of each attribute and the order of the attribute blocks is defined in the metadata.json file, as described previously in this document. The total size of an attribute block in bytes is therefore attribute.size * points. This applies to all attributes except two special attributes where additional encoding is used. The position and rgb attributes are encoded with Morton encoding (Z-order encoding) and need to be decoded before use. The real byte size of the encoded position attribute is 16 bytes and the size of the rgb attribute is 8 bytes. For more information about the Morton encoding please have a look at the Wikipedia article Z-order curve - Wikipedia. Many different ready-to-use libraries exist on the internet that can encode and decode Morton.

Note on data types: The position attribute is persisted as a vector of integers in the attribute block, but it must be multiplied by the scale property from the metadata.json file. Therefore, the final type of the position attribute is floating point. This might apply to other attributes too.

Don’t forget to apply all scale and offset transformations to the raw attribute values before using them.

Applying Alignment

Alignment among multiple datasets becomes essential whenever they must be displayed at the same time. NavVis IVION provides a transformation matrix per dataset which, when applied to the points in dataset coordinates, transforms them to a common coordinate system (the site coordinate system).

Retrieve the transformation matrix by using the following endpoint:

Endpoint:

GET {instance_url}/data/{site_id}/affine_ref_sys/
{reference_system_id}?include_site_transform=true
X-Authorization: Bearer {access_token}

Response Code & Status:

200 OK

Response Body:

{ 
"site_transform":
  {
  "r11": number,
  "r12": number,
  "r13": number,
  "r21": number,
  "r22": number,
  "r23": number,
  "r31": number,
  "r32": number,
  "r33": number,
  "tx": number,
  "ty": number,
  "tz": number
  },
  "type": string,
  ...
}

The {reference_system_id} for each dataset is returned by the GET datasets endpoint which was described above.

The transformation matrix is provided in the field site_transform and is arranged as shown below.

r11

r12

r13

tx

r21

r22

r23

ty

r31

r32

r33

tz

0

0

0

1

Note: All dataset transformations are only to be applied after the point coordinates are converted from node-relative to dataset coordinates as described above.

Refreshing the Access Token

The access token returned by NavVis IVION is an expiring JSON web token (JWT) which must be refreshed (replaced) before its expiration timestamp to ensure uninterrupted user experience. Refreshing the access token involves using a refresh token which is returned along with the initial access token when the login mandate is exchanged for credentials.

The JWTs used by NavVis IVION are Base64 encoded JSON objects that are split into 3 dot separated segments as shown here.

[segment_1].[segment_2].[segment_3]

Segment 2 contains the token’s expiration timestamp. The Base46 decoded version of segment 2 contains an object of the type shown below.

{
 "type": string,
 "provider": string,
 "tokenType": string,
 "sub": string,
 "exp": number,
 "iat": number
}

The field of interest (exp) contains a UNIX timestamp with the token’s expiration.

Refresh the access token by using the following endpoint:

Endpoint:

POST {instance_url}/api/auth/refresh_access_token

Request Body:

{
  "refresh_token": string
}

Response Code & Status:

200 OK

Response Body:

{
  "access_token": string,
  "principal" : 
 {
    "username": string,
    "first_name": string | null,
    "last_name": string | null,
    ...
  },
  ...
}

The refresh token itself also has expiration and it may or may not be possible to get a new one depending on the instance configuration. If the refresh token cannot be updated, once it expires, the user should be prompted to log in again.

If the refresh token can be updated, renew it by using the endpoint below:

Endpoint:

POST {instance_url}/api/auth/update_refresh_token

Request Body:

{
  "refresh_token": string
}

Response Code & Status:

200 OK

Response Body:

{
  "refresh_token": string,
  ...
}

Note: The provided refresh token must be valid and not expired.

Visibility Descriptor

Overview

The Visibility Descriptor is an additional component of the NavVis IVION Point Streaming API, specifically designed to manage the visibility of individual points within a point cloud dataset.

Structure and Storage

Just like the main point cloud data stored in the cloud/ directory, the Visibility Descriptor utilizes a similar Potree structure. However, it is specifically stored within cloud_attributes/visibility/. This directory contains its own metadata.json, hierarchy.bin, and octree.bin files, which are structured similarly to those in the main dataset but are dedicated to visibility data.

Key Components

  • Visibility Attribute:
    Each point within the point cloud has a corresponding visibility attribute stored as a single byte. This byte indicates the visibility status of the point:

    • 0 (zero): The point is visible.

    • Non-zero value: The point is invisible.

  • Hierarchy and Octree:

    • The structures of the visibility tree and the normal point cloud tree are synchronized, allowing nodes and their points to be iterated over in the same order.

Node Type Encoding

For performance optimization, the upper 4 bits of the node type byte within the visibility hierarchy are used to encode the point visibility type:

  • PARTIALLY_VISIBLE (0): Some points within the node are visible, others are not. Access to cloud_attributes/visibility/octree.bin is required to determine the visibility of individual points.

  • FULLY_VISIBLE (1): All points within the node are visible. There is no need to access the visibility octree file for this node.

  • FULLY_INVISIBLE (2): No points within the node are visible. There is no need to access the visibility octree file for this node.

Data Access and Integration

Endpoints:

GET {instance_url}/data/{site_id}/datasets_web/{dataset_name}/cloud_attributes/visibility/metadata.json

X-Authorization: Bearer {access_token}

GET {instance_url}/data/{site_id}/datasets_web/{dataset_name}/cloud_attributes/visibility/hierarchy.bin

X-Authorization: Bearer {access_token}

GET {instance_url}/data/{site_id}/datasets_web/{dataset_name}/cloud_attributes/visibility/octree.bin

X-Authorization: Bearer {access_token}


Was this article helpful?

Changing your password will log you out immediately. Use the new password to log back in.
First name must have atleast 2 characters. Numbers and special characters are not allowed.
Last name must have atleast 1 characters. Numbers and special characters are not allowed.
Enter a valid email
Enter a valid password
Your profile has been successfully updated.