PolyLine

Introduction

vtkPolyLine is a cell which representant a poly line.

See Also

vtkCell

Methods

evaluateLocation

Determine global coordinate (x[3]) from subId and parametric coordinates.
Also set interpolation weights. (There are two weights for the two
points of the line segment specified by subId)

Argument Type Required Description
subId number Yes
pcoords Vector3 Yes The parametric coordinates
x Vector3 Yes The global coordinate
weights Vector2 Yes The interpolation weights

evaluateOrientation

Determine global orientation (q[3]) from subId and parametric coordinates.
This uses the same algorithm as vtkLine (interpolates using slerp).
Also set interpolation weights. (There are two weights for the two
points of the line segment specified by subId)

Argument Type Required Description
subId number Yes
pcoords Vector3 Yes The parametric coordinates
q Vector3 Yes The global orientation
weights Vector2 Yes The interpolation weights

Returns

Type Description
boolean Wether the orientation has been set in `q’

extend

Method used to decorate a given object (publicAPI+model) with vtkPolyLine characteristics.

Argument Type Required Description
publicAPI Yes object on which methods will be bounds (public)
model Yes object on which data structure will be bounds (protected)
initialValues IPolyLineInitialValues No (default: {})

findPointIdAtDistanceFromFirstPoint

Returns the subId of the segment at the given distance from the first
point of the polyline
If the distance is negative or greater than the total length of the
polyline, returns -1

Argument Type Required Description
distance Yes The distance from the first point of the polyline

getCellDimension

Get the topological dimensional of the cell (0, 1, 2 or 3).

getDistanceFunction

The function used in getDistancesToFirstPoint and in findPointIdAtDistanceFromFirstPoint
Defaults to vec3.dist of gl-matrix

getDistancesToFirstPoint

Returns an array containing for each pointIdx between 0 (included) and
numberOfPoints (excluded) the distance from the first point of the
polyline to the point at pointIdx
In particular if tda = publicAPI.getDistancesToFirstPoint(), then tda[0] = 0
and tda[tda.length - 1] is the total length of the polyline

getOrientations

An array of quaternions used to orient the polyline at each of its point
The length of the array has to be the same size as the number of points
Defaults to null.

intersectWithLine

Argument Type Required Description
t1 number Yes
t2 number Yes
p1 Vector3 Yes The first point coordinate.
p2 Vector3 Yes The second point coordinate.
tol Number Yes The tolerance to use.
x Vector3 Yes The point which intersect the line.
pcoords Vector3 Yes The parametric coordinates.

newInstance

Method used to create a new instance of vtkPolyLine.

Argument Type Required Description
initialValues IPolyLineInitialValues No for pre-setting some of its content

setDistanceFunction

Argument Type Required Description
f Yes

setOrientations

Argument Type Required Description
orientations Yes

Source

index.d.ts
import { quat, vec3 } from 'gl-matrix';
import { Nullable, Vector2, Vector3 } from '../../../types';
import vtkCell, { ICellInitialValues } from '../Cell';
import { IIntersectWithLine } from '../Line';

export interface IPolyLineInitialValues extends ICellInitialValues {}

export interface vtkPolyLine extends vtkCell {
/**
* Get the topological dimensional of the cell (0, 1, 2 or 3).
*/
getCellDimension(): number;

/**
* @param {number} t1
* @param {number} t2
* @param {Vector3} p1 The first point coordinate.
* @param {Vector3} p2 The second point coordinate.
* @param {Number} tol The tolerance to use.
* @param {Vector3} x The point which intersect the line.
* @param {Vector3} pcoords The parametric coordinates.
*/
intersectWithLine(
t1: number,
t2: number,
p1: Vector3,
p2: Vector3,
tol: number,
x: Vector3,
pcoords: Vector3
): IIntersectWithLine;

/**
* Determine global coordinate (x[3]) from subId and parametric coordinates.
* Also set interpolation weights. (There are two weights for the two
* points of the line segment specified by subId)
*
* @param {number} subId
* @param {Vector3} pcoords The parametric coordinates
* @param {Vector3} x The global coordinate
* @param {Vector2} weights The interpolation weights
*/
evaluateLocation(
subId: number,
pcoords: Vector3,
x: Vector3,
weights: Vector2
): void;

/**
* Determine global orientation (q[3]) from subId and parametric coordinates.
* This uses the same algorithm as vtkLine (interpolates using slerp).
* Also set interpolation weights. (There are two weights for the two
* points of the line segment specified by subId)
*
* @param {number} subId
* @param {Vector3} pcoords The parametric coordinates
* @param {Vector3} q The global orientation
* @param {Vector2} weights The interpolation weights
* @returns {boolean} Wether the orientation has been set in `q'
*/
evaluateOrientation(
subId: number,
pcoords: Vector3,
q: quat,
weights: Vector2
): boolean;

/**
* Returns an array containing for each pointIdx between 0 (included) and
* numberOfPoints (excluded) the distance from the first point of the
* polyline to the point at pointIdx
* In particular if tda = publicAPI.getDistancesToFirstPoint(), then tda[0] = 0
* and tda[tda.length - 1] is the total length of the polyline
*/
getDistancesToFirstPoint(): number[];

/**
* Returns the subId of the segment at the given distance from the first
* point of the polyline
* If the distance is negative or greater than the total length of the
* polyline, returns -1
*
* @param distance The distance from the first point of the polyline
*/
findPointIdAtDistanceFromFirstPoint(distance: number): number;

/**
* An array of quaternions used to orient the polyline at each of its point
* The length of the array has to be the same size as the number of points
* Defaults to null.
*/
getOrientations(): Nullable<quat[]>;

/**
* @see getOrientations
* @param orientations
*/
setOrientations(orientations: Nullable<quat[]>): boolean;

/**
* The function used in getDistancesToFirstPoint and in findPointIdAtDistanceFromFirstPoint
* Defaults to vec3.dist of gl-matrix
*/
getDistanceFunction(): (a: vec3, b: vec3) => number;

/**
* @see getDistanceFunction
* @param f
*/
setDistanceFunction(f: (a: vec3, b: vec3) => number): boolean;
}

/**
* Method used to decorate a given object (publicAPI+model) with vtkPolyLine characteristics.
*
* @param publicAPI object on which methods will be bounds (public)
* @param model object on which data structure will be bounds (protected)
* @param {IPolyLineInitialValues} [initialValues] (default: {})
*/
export function extend(
publicAPI: object,
model: object,
initialValues?: IPolyLineInitialValues
): void;

/**
* Method used to create a new instance of vtkPolyLine.
* @param {IPolyLineInitialValues} [initialValues] for pre-setting some of its content
*/
export function newInstance(
initialValues?: IPolyLineInitialValues
): vtkPolyLine;

/**
* vtkPolyLine is a cell which representant a poly line.
*
* @see vtkCell
*/
export declare const vtkPolyLine: {
newInstance: typeof newInstance;
extend: typeof extend;
};

export default vtkPolyLine;
index.js
import macro from 'vtk.js/Sources/macros';
import vtkCell from 'vtk.js/Sources/Common/DataModel/Cell';
import vtkLine from 'vtk.js/Sources/Common/DataModel/Line';
import { vec3 } from 'gl-matrix';

function vtkPolyLine(publicAPI, model) {
model.classHierarchy.push('vtkPolyLine');

const line = vtkLine.newInstance();
line.getPoints().setNumberOfPoints(2);

publicAPI.getCellDimension = () => 1;
publicAPI.intersectWithLine = (t1, t2, p1, p2, tol, x, pcoords) => {
const outObj = {
intersect: 0,
t: Number.MAX_VALUE,
subId: 0,
betweenPoints: null,
};

const numLines = publicAPI.getNumberOfPoints() - 1;
let pDistMin = Number.MAX_VALUE;
const minXYZ = [0, 0, 0];
const minPCoords = [0, 0, 0];
for (let subId = 0; subId < numLines; subId++) {
const pCoords = [0, 0, 0];

line
.getPoints()
.getData()
.set(model.points.getData().subarray(3 * subId, 3 * (subId + 2)));

const lineIntersected = line.intersectWithLine(p1, p2, tol, x, pcoords);

if (
lineIntersected.intersect === 1 &&
lineIntersected.t <= outObj.t + tol &&
lineIntersected.t >= t1 &&
lineIntersected.t <= t2
) {
outObj.intersect = 1;
const pDist = line.getParametricDistance(pCoords);
if (
pDist < pDistMin ||
(pDist === pDistMin && lineIntersected.t < outObj.t)
) {
outObj.subId = subId;
outObj.t = lineIntersected.t;
pDistMin = pDist;
for (let k = 0; k < 3; k++) {
minXYZ[k] = x[k];
minPCoords[k] = pCoords[k];
}
}
}
}

return outObj;
};

publicAPI.evaluateLocation = (subId, pcoords, x, weights) => {
line
.getPoints()
.getData()
.set(model.points.getData().subarray(3 * subId, 3 * (subId + 2)));

return line.evaluateLocation(pcoords, x, weights);
};

publicAPI.evaluateOrientation = (subId, pcoords, q, weights) => {
if (model.orientations) {
line.setOrientations([
model.orientations[subId],
model.orientations[subId + 1],
]);
} else {
line.setOrientations(null);
}

return line.evaluateOrientation(pcoords, q, weights);
};

publicAPI.getDistancesToFirstPoint = () => {
const dTime = model.distancesTime.getMTime();
if (dTime < model.points.getMTime() || dTime < publicAPI.getMTime()) {
const numPoints = publicAPI.getNumberOfPoints();
if (!model.distances) {
model.distances = new Array(numPoints);
} else {
model.distances.length = numPoints;
}
if (numPoints > 0) {
const previousPoint = new Array(3);
const currentPoint = new Array(3);
let totalDistance = 0;
model.distances[0] = totalDistance;
model.points.getPoint(0, previousPoint);
for (let i = 1; i < numPoints; ++i) {
model.points.getPoint(i, currentPoint);
totalDistance += model.distanceFunction(previousPoint, currentPoint);
model.distances[i] = totalDistance;
vec3.copy(previousPoint, currentPoint);
}
}
model.distancesTime.modified();
}
return model.distances;
};

publicAPI.findPointIdAtDistanceFromFirstPoint = (distance) => {
const distances = publicAPI.getDistancesToFirstPoint();
// At least two points to return an ID
if (distances.length < 2) {
return -1;
}
// Binary search in the distance array
let minId = 0;
let maxId = distances.length - 1;
if (
distance < distances[minId] ||
distance > distances[maxId] ||
distances[maxId] === 0
) {
return -1;
}
while (maxId - minId > 1) {
const midId = Math.floor((minId + maxId) / 2);
if (distances[midId] <= distance) {
minId = midId;
} else {
maxId = midId;
}
}
return minId;
};
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
orientations: null, // an array of quat or null
distanceFunction: vec3.dist,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

vtkCell.extend(publicAPI, model, initialValues);

macro.setGet(publicAPI, model, ['orientations', 'distanceFunction']);

model.distancesTime = {};
macro.obj(model.distancesTime, { mtime: 0 });

vtkPolyLine(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend, 'vtkPolyLine');

// ----------------------------------------------------------------------------

export default { newInstance, extend };