项目作者: cosmoscout

项目描述 :
VTK.js persistence visualization
高级语言: TypeScript
项目地址: git://github.com/cosmoscout/PersistenceRenderer.git
创建时间: 2020-02-10T13:15:25Z
项目社区:https://github.com/cosmoscout/PersistenceRenderer

开源协议:MIT License

下载


Persistence Renderer

Visualize and interact with VTK.js persistence data.

Requirements

Persistence Renderer Class

constructor(container: HTMLElement | string, id: string, settings: ISettings = {})

container: The element where the canvas and all control element will be placed into.
This can be an actual HTMLElement or a query string passed to document.querySelector.

id: A unique id that will be used to identify the canvas and control elements.
Canvas id will be build as: persistence_canvas_${id}.

settings: Customized settings. Refer to the settings documentation below.

async load(fileName: string): Promise<void>

Loads a given filename using the default HttpDataSetReader.
fileName: string: The file name / url to load.

A dataloaded-event will be dispatched on the containing element.
This method returns a promise.

update(): void

Draws all loaded points and updates enabled control element.

filteredPoints(): PersistencePointTuple[]

Returns the points filtered by persistence and selection.

get points(): PersistencePointTuple[]

Returns the loaded vtk data as an array of PersistencePointsTuples. Refer to the documentation below.

get bounds(): number[]

Returns the computed point bounds as an one-dimensional array.
Example: [x-min, x-max, y-min, y-max, z-min, z-max]
If no points were loaded min/max will default to -inf | inf.

get persistenceBounds(): Bounds

Returns the computed persistence bounds as an object with keys min and max.

  1. class Bounds {
  2. public readonly min: number;
  3. public readonly max: number;
  4. }

Settings

Default settings:

  1. {
  2. "padding": {
  3. "left": 40,
  4. "top": 10,
  5. "right": 10,
  6. "bottom": 20
  7. },
  8. "canvasWidth": 500,
  9. "canvasHeight": 500,
  10. "strokeStyle": "#000",
  11. "pointDrawFunction": "undefined",
  12. "enableSelectionFilter": false,
  13. "enablePersistenceFilter": false,
  14. "enableAxes": true,
  15. "axesColor": "#000",
  16. "axesTickCount": 5,
  17. "axesTickLength": 5,
  18. "axesTickColor": "#000",
  19. "axesTickFractions": 2,
  20. "axesTextColor": "#000",
  21. "selectionStopPropagation": false,
  22. "selectionMinWidth": 10
  23. }

padding: number | Padding: Padding of the canvas

canvasWidth: number: Canvas width in px
canvasHeight: number: Canvas height in px
strokeStyle: string: Stroke color

pointDrawFunction: Function: Custom function for drawing persistence points on the canvas

enableSelectionFilter: bool: Enable / Disable Selection control element
enablePersistenceFilter: bool: Enable / Disable Slider control element
enableAxes: bool: Enable / Disable Axes drawn on the canvas

axesColor: string: Color of the axes
axesTickCount: number | number[]: Number of ticks on the x/y axis. If argument is an array first index corresponds to number of x-axis ticks
axesTickLength: number: Length of ticks in px. If argument is an array first index corresponds to the length of x-axis ticks
axesTickColor: string: Color of ticks
axesTickFractions: number: Number of fractions on each tick value
axesTextColor: string: Color of tick values

selectionStopPropagation: boolean: Set to true, to stop the mouse down event propagation
selectionMinWidth: number: Min width in px that counts as a selection

pointDrawFunction(point: PersistencePointTuple, renderer: IRenderer)

A custom draw function can be passed to the rendering instance to change / extend the way points are drawn.
The function gets two arguments:

  • point: PersistencePointTuple the current point to draw
  • renderer: IRenderer the current rendering instance
    See the example section for further information.

axesTickFormatter(tickValue: number,prevTickValue: number): string

A custom tick formatting function. Gets called for each tick value.
Must return a string.
Default: return value.toFixed(2);

PersistencePointTuple

  1. class PersistencePointTuple {
  2. readonly persistence: number;
  3. readonly criticalType: {
  4. readonly lower: number;
  5. readonly upper: number;
  6. };
  7. readonly coordinates: {
  8. readonly lower: {
  9. readonly x: number;
  10. readonly y: number;
  11. readonly z: number;
  12. };
  13. readonly upper: {
  14. readonly x: number;
  15. readonly y: number;
  16. readonly z: number;
  17. };
  18. };
  19. /**
  20. * Lower Point
  21. */
  22. readonly lower: {
  23. readonly x: number;
  24. readonly y: number;
  25. readonly z: number;
  26. };
  27. /**
  28. * Upper Point
  29. */
  30. readonly upper: {
  31. readonly x: number;
  32. readonly y: number;
  33. readonly z: number;
  34. };
  35. }

IRenderer

  1. interface IRenderer {
  2. getCanvas(): HTMLCanvasElement;
  3. getContext(): CanvasRenderingContext2D;
  4. readonly defaultDrawFunction;
  5. /**
  6. * Maps a x-position point to a canvas coordinate
  7. */
  8. xPos(x: number): number;
  9. /**
  10. * Maps a y-position point to a canvas coordinate
  11. */
  12. yPos(y: number): number;
  13. }

defaultDrawFunction

This is the default function used to draw persistence points:

  1. (point, renderer) => {
  2. renderer.getContext().beginPath();
  3. renderer.getContext().moveTo(renderer.xPos(point.lower.x), renderer.yPos(point.lower.y));
  4. renderer.getContext().lineTo(renderer.xPos(point.upper.x), renderer.yPos(point.upper.y));
  5. renderer.getContext().stroke();
  6. }

Persistence Filter

The persistence filter is a two-handled slider below the canvas. Its lower and upper bounds equal to the lowest and highest point persistence.
Updating the slider handles will automatically re-draw the canvas with the newly filtered points.

Selection Filter

The selection filter allows to select an arbitrary sized rectangle on the canvas. After the selection has ended only points inside the selection will be drawn.
The current selection can be cleared by right-clicking on the canvas.

Events

Events are dispatched onto the container element set in the constructor.
The following events can be listened to:

VTK file loader

  • vtkdataloaded: VTK File has been fully loaded and processed

Selection control

  • selectionstart: Selection started
  • selectionupdating: Selection size is changing
  • selectionupdating: Selection has been cleared
  • selectionend: Selection has ended
    • Event detail field contains selection bounds

Persistence control

  • sliderdestroyed: Persistence bounds slider has been destroyed (happens upon loading a new vtk file)
  • slidercreated: Slider has been created (after new vtk file load)
  • persistenceboundsupdating: Slider handles are changing
    • Event detail field contains handle values
  • persistenceboundsset: Slider values set
    • Event detail field contains handle values

Renderer

  • pointsdrawn: All vtk points drawn
  • pointscleared: Canvas cleared before re-draw

Example

Listening to selection end:

  1. const renderer = new PersistenceRenderer(document.body, 'unique_id', {
  2. enableSelectionFilter: true
  3. });
  4. renderer.container.addEventListener('selectionend', (event /* CustomEvent */) => {
  5. console.log(`Selection Bounds are: ${event.detail}`);
  6. });

Examples

Minimum needed dependencies:

  1. <head>
  2. ...
  3. <script src="https://unpkg.com/vtk.js@13.7.1/dist/vtk.js"></script>
  4. <script src="PersistenceRenderer.js"></script>
  5. ...
  6. </head>

Simple usage:

  1. const renderer = new PersistenceRenderer(document.body, 'unique_id');
  2. renderer.load('url / path to vtk.js data').then(()=>{
  3. renderer.update();
  4. });

With persistence filter enabled:

The persistence filter adds a two-handled slider below the canvas. The lower bound equals to the lowest persistence, the upper bounds equals to the biggest persistence.
After updating the slider the canvas will re-draw automatically.

  1. <head>
  2. <script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/14.0.3/nouislider.min.js" integrity="sha256-1ubcV7PzqcMhAz7jsoU3QlAfCnUaY7SUffeHa4Nq3ws=" crossorigin="anonymous"></script>
  3. <script src="https://unpkg.com/vtk.js@13.7.1/dist/vtk.js"></script>
  4. <script src="PersistenceRenderer.js"></script>
  5. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/14.0.3/nouislider.min.css" integrity="sha256-IQnSeew8zCA+RvM5fNRro/UY0Aib18qU2WBwGOHZOP0=" crossorigin="anonymous" />
  6. ...
  7. </head>
  1. const renderer = new PersistenceRenderer(document.body, 'unique_id', {
  2. enablePersistenceFilter: true
  3. });
  4. renderer.load('url / path to vtk.js data').then(()=>{
  5. renderer.update();
  6. });
  7. // After using the slider filteredPoints will contain the updated selection
  8. const points = renderer.filteredPoints();

Custom drawing function:

  1. const renderer = new PersistenceRenderer(document.body, 'unique_id', {
  2. /* This function will be called for each point */
  3. pointDrawFunction: (point, renderer) => {
  4. /**
  5. * This function first calls the default drawing function accessible on the Renderer Interface
  6. */
  7. renderer.defaultDrawFunction(point,renderer);
  8. /**
  9. * Example: Don't add custom elements if point persistence is lower than 0.2
  10. */
  11. if (point.persistence < 0.2) {
  12. return;
  13. }
  14. /**
  15. * This draws a blue circle with a radius of 2px on the upper point position
  16. */
  17. const context = renderer.getContext();
  18. context.save();
  19. context.strokeStyle = 'blue';
  20. context.beginPath();
  21. context.ellipse(renderer.xPos(point.upper.x), renderer.yPos(point.upper.y), 2, 2, 0, 0, 2 * Math.PI);
  22. context.stroke();
  23. context.restore();
  24. }
  25. });

All control elements enabled:

  1. const renderer = new PersistenceRenderer(document.body, 'unique_id', {
  2. enablePersistenceFilter: true,
  3. enableSelectionFilter: true
  4. });

Fully custom settings:

  1. const renderer = new PersistenceRenderer('#exampleDiv', 'id', {
  2. canvasWidth: 1500,
  3. canvasHeight: 250,
  4. enablePersistenceFilter: true,
  5. padding: {
  6. left: 100,
  7. top: 10,
  8. right: 10,
  9. bottom: 30,
  10. },
  11. axesTickLength: [10, 25],
  12. axesTickCount: [25, 8],
  13. axesColor: 'red',
  14. axesTickColor: 'green',
  15. pointDrawFunction: (point, renderer) => {
  16. const context = renderer.getContext();
  17. context.save();
  18. context.strokeStyle = 'blue';
  19. context.beginPath();
  20. context.ellipse(renderer.xPos(point.upper.x), renderer.yPos(point.upper.y), 2, 2, 0, 0, 2 * Math.PI);
  21. context.stroke();
  22. context.restore();
  23. }
  24. });