Hi @mjovic ,
You are right that this API under Forma.experimental.geometry is now deprecated, but there is another way to get the geometry that you are looking for.
You need to fetch the element and load the volume25DCollection representation of the element.
async function loadVolume25Collection(
representation?: Representation<JsonRepresentations["volume25DCollection"]>,
): Promise<JsonRepresentations["volume25DCollection"] | undefined> {
if (!representation) return undefined;
switch (representation.type) {
case "linked": {
const data = await Forma.elements.blobs.get({ blobId: representation.blobId });
return JSON.parse(
new TextDecoder().decode(data.data),
) as JsonRepresentations["volume25DCollection"];
}
case "embedded-json":
return representation.data;
default:
return;
}
}
With the deprecated API, the geometry was returned with the position relative to the root. For the new API, the raw representation is loaded, so if your use case care about the position of the geometry relative to the proposal, you will need to apply the transformations from the element tree. Here is a code example:
const { element, elements } = await Forma.elements.get({ urn })
const volume25DCollectionRep = element.representations?.volume25DCollection;
const volume25DCollection = await loadVolume25Collection(volume25DCollectionRep)!;
if (!volume25DCollection) continue;
const { transform } = await Forma.elements.getWorldTransform({ path });
const selectionPredicate = createSelectionPredicate(volume25DCollectionRep?.selection);
const filteredVolume25DCollection = volume25DCollection.features.filter((f) =>
selectionPredicate(f.id),
);
const transformedVolume25DCollection = {
type: "FeatureCollection" as const,
features: filteredVolume25DCollection.map((feature: Volume25D) => {
return {
...feature,
properties: {
...feature.properties,
// Scale height by 3rd diagonal element in transform matrix
height: feature.properties.height * transform[10],
// Translate and scale elevation -- default untransformed elevation is zero
elevation: (feature.properties.elevation ?? 0 * transform[10]) + transform[14],
},
geometry: {
...feature.geometry,
coordinates: feature.geometry.coordinates.map((coordinates) =>
transformCoordinates(transform, coordinates),
),
},
};
}),
};
Using the helper functions:
export function transformCoordinates(mat1: number[], coordinates: number[][]) {
const res = Array<[number, number]>(coordinates.length);
let i, j, k;
for (k = 0; k < coordinates.length; k++) {
const resItem: [number, number] = [0, 0];
const point = [...(coordinates[k] as [number, number]), 0, 1];
for (i = 0; i < 4; i++) {
for (j = 0; j < 2; j++) {
resItem[j] += mat1[i * 4 + j]! * point[i]!;
}
}
res[k] = resItem;
}
return res;
}
function createSelectionPredicate(selection?: RepresentationSelection) {
switch (selection?.type) {
case undefined:
return () => true;
case "equals":
return (value: string) => value === selection.value;
case "startsWith":
return (value: string) => value.startsWith(selection.value);
default:
throw new Error(`Invalid selection: ${JSON.stringify(selection ?? {})}`);
}
}
I hope this solves your use case, if not, let me know!
Best regards,
Vilde from the Forma team