Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/novorender/docs into main
Browse files Browse the repository at this point in the history
  • Loading branch information
torelode committed Aug 31, 2023
2 parents dad96c9 + d2b202a commit 72c268d
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 0 deletions.
1 change: 1 addition & 0 deletions v2/demo-snippets/guides/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./clipping";
export * from "./dynamic";
export * from "./object_selection";
export * from "./searching";
export * from "./measure";
9 changes: 9 additions & 0 deletions v2/demo-snippets/guides/measure/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { demo } from "../../demo";
import { MeasureDemoHost } from "../../hosts/measure";

/** Here goes code demo code that you can see in the playground */
import parametricMeasure from "./parametric_measure.ts?raw";

export const measure = {
...demo("measure", "parametric_measure", "Parametric Measure", parametricMeasure, MeasureDemoHost, {}, "Measure API can be used to fetch parametric data based on real world position, and calculate measurements between 2 objects."),
};
44 changes: 44 additions & 0 deletions v2/demo-snippets/guides/measure/parametric_measure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { View } from "@novorender/api";
// import { type MeasureEntity } from "@novorender/api/types/measure";

// we export this function to our react component which will then execute it once the demo started running.
export function showTip() {
return openAlert(
"Click to select parametric object, parametric data will be shown in an alert dialog. Select another object and the measurement data between the objects will be shown in the alert dialog. Clicking further objects will alternate between first and second selected and show measure values within an alert dialog."
);
}

export async function main(view: View, canvas: HTMLCanvasElement) {
const measureView = await view.measure;

// Parametric entities used to measure between
// @todo - implement interface `MeasureEntity`
let measureEntity1: any | undefined = undefined;
let measureEntity2: any | undefined = undefined;

// number to alternate between selected entities.
let selectEntity: 1 | 2 = 1;

canvas.onclick = async (e: MouseEvent) => {
const result = await view.pick(e.offsetX, e.offsetY);
if (result) {
const { objectId, position } = result;

if (selectEntity === 1) {
// Find measure entity at pick location
measureEntity1 = (await measureView.core.pickMeasureEntity(objectId, position)).entity;
selectEntity = 2;
} else {
// Find measure entity at pick location
measureEntity2 = (await measureView.core.pickMeasureEntity(objectId, position)).entity;
selectEntity = 1;
}
// As long as one object is selected log out the values
// Note that if measureEntity2 is undefined then the result will be the parametric values of measureEntity1
if (measureEntity1) {
const _log = await measureView.core.measure(measureEntity1, measureEntity2);
openInfoPane(_log);
}
}
};
}
65 changes: 65 additions & 0 deletions v2/demo-snippets/hosts/measure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { createAPI, type SceneData } from "@novorender/data-js-api";
import { View } from "@novorender/api";
import { IDemoContext, IDemoHost, IModule } from "../demo";

type Args = [View: View, canvas: HTMLCanvasElement];
type Ret = void;
type Module = IModule<Ret, Args>;

export class MeasureDemoHost implements IDemoHost<Module> {
private readonly view: View;
private sceneData!: SceneData;

constructor(readonly context: IDemoContext) {
const {
canvasElements: { primaryCanvas: canvas },
deviceProfile,
imports,
} = this.context;
this.view = new View(canvas, deviceProfile, imports);
}

async run(): Promise<void> {
const { view } = this;
await this.loadScene();
await view.run();
view.dispose();
}

async loadScene() {
const { view } = this;

// Initialize the data API with the Novorender data server service
const dataApi = createAPI({
serviceUrl: "https://data.novorender.com/api",
});

try {
// Load scene metadata
// Condos scene ID, but can be changed to any public scene ID
const sceneData = await dataApi.loadScene("95a89d20dd084d9486e383e131242c4c");

console.log("sceneData ", sceneData);

this.sceneData = sceneData as SceneData;

// Destructure relevant properties into variables
const { url, db } = sceneData as SceneData;
// load the scene using URL gotten from `sceneData`
const config = await view.loadSceneFromURL(new URL(url));
const { center, radius } = config.boundingSphere;
view.activeController.autoFit(center, radius);
} catch (error) {
console.log("Error while loading scene from URL ", error);
}
}

updateModule(module: Module) {
// TODO: verify module shape first
module.main(this.view, this.context.canvasElements.primaryCanvas);
}

exit(): void {
this.view?.exit();
}
}
71 changes: 71 additions & 0 deletions v2/docs/guides/parametric_measure.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: "Parametric measure"
description: "Fetch parametric data based on real world position, and calculate measurements between 2 objects using Web API's Measure module."
keywords: ["novorender api docs", "web api", "measure module", "parametric measure"]
---

import { snippets } from "@site/demo-snippets/index";

TODO - add correct links to mentioned functions

Web API's Measure module can be used to fetch parametric data based on real world position, and calculate measurements between 2 objects

### Measure entity

A measure entity refers to a part of a parametric object, for example the inner or outer cylinder of a pipe.
A measure entity can also be a single point, this is usually used if no parametric object exists at a clicked location.

The normal way of getting measure entities is to used the <code>[pickMeasureEntity()](/docs/web_api/Classes/class.View#pickmeasureentity)</code> function on the <code>[measure view](/docs/web_api/Classes/class.View#measure)</code> object. This will use world coordinates and <code>[objectId](/docs/web_api/Interfaces/interface.PickSample#objectid)</code> to find the closest edge surface or point. It will return the picked point if no parametric data is found near the input point. <code>[objectId](/docs/web_api/Interfaces/interface.PickSample#objectid)</code> and <code>[position](/docs/web_api/Interfaces/interface.PickSample#position)</code> can be used from the <code>[pick](/docs/web_api/Classes/class.View#pick)</code> function on <code>[view](/docs/web_api/Classes/class.View)</code>

```typescript
const view = new View(canvas, deviceProfile, imports);
const result = await view.pick(x, y);

if (result) {
const entity = await measureView.core.pickMeasureEntity(objectId, position);
}
```

### Parametric values on entity

To get the parametric values such as the the radius, and centerline of a cylinder the <code>[measure()](#)</code>
function can be used. This function be be used to get values from a single object by leaving the second argument as undefined.

```typescript
const measureView = await view.measure;
const measureValues = await measureView.core.measure(entity);

if (measureValues.kind === "cylinder") {
console.log(`Radius of cylinder is: ${measureValues.radius}`);
}
```

### Measure against another entity

A measure between two entities is done by using the <code>[core.measure()](#)</code> function on scene with 2 arguments.
What property the resulting object has will depend on the input arguments. There is also an option parameter
to support additional options such as where a cylinder should measure from

```typescript
const view = new View(canvas, deviceProfile, imports);
const result1 = await view.pick(x1, y1);
const result2 = await view.pick(x2, y2);

if (result1 && result2) {
const entity1 = await measureView.core.pickMeasureEntity(result1.objectId, result1.position);
const entity2 = await measureView.core.pickMeasureEntity(result2.objectId, result2.position);

const measureValues = await measureView.core.measure(entity1, entity1);

if (measureValues && measureValues.distance) {
console.log(`Distance between objects is: ${measureValues.distance}`);
}
}
```

### Demo

Click to select parametric object, parametric data will be shown in an alert dialog. Select another object and the measurement data between the objects will be shown in the alert dialog.
Clicking further objects will alternate between first and second selected and show measure values within an alert dialog.

<PlaygroundComponent {...snippets.measure.parametric_measure}></PlaygroundComponent>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified v2/static/assets/demo-screenshots/parametric_measure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 72c268d

Please sign in to comment.