Class: Polyline

PD. Polyline

Defines a run of one or more lines connecting a sequence of points in space.

A polyline is a flexible representation of how a series of points in space are connected. It can define a single line between two points, a continuous line between multiple points or a series of separate continuous lines. When the 'isPolygon` flag is set, it can even define a closed polygon with one or more holes or openings within it.

The basic rules of a polyline/polygon are:

  • Polylines may contain any number of contours, where a contour is an array of sequentially connected 3D points. If the isClosed property is true, then the end point of each contour is automatically connected back to the first point in that contour to form a closed loop.

  • Polylines are always created in 3D, even if all their points lie flat in the XY plane. Thus, all vertices in a contour must be instances of THREE.Vector3 or a subclass such as PD.Point, PD.PathPoint or BIM.Junction.

  • Unless the isPolygon flag is set, each contour in a polyline is relatively independent of all others. Whilst the 3D points within each contour are connected together with lines, individual contours need not be connected to each other in any way.

  • If the isPolygon flag is set, then the contours become related. When a polygon has more than one contour, the first MUST define its exterior boundary, and all subsequent contours MUST define only interior boundaries. The exterior contour bounds the surface and interior contours bound holes or openings within that surface.

  • If the isPolygon flag is set, then each contour SHOULD follow the right-hand rule with respect to the area it bounds. This means that exterior contours should run counterclockwise with respect to the plane normal and holes should run clockwise. In many situations the winding order of polygons is not that important as tesselation and rendering are not sensitive to this, though it will affect the visibility of surfaces in shells/meshes that use single-sided materials.

  • Even though polylines do not need to be coplanar, a plane equation and major axis value will always be calculated to assist with mapping the polyline from 3D to 2D and back when required, and helping to determine relative winding order.

  • If the isPlanar flag is set, all vertices in the polyline will be projected onto the current plane whenever they are moved or added. When not set, you are free to place points anywhere in 3D space. In such cases, the plane.normal vector stores the unchanging plane equation the contours will be moved to and the normal vector will store the computed normal of the moved contours. This means that sometimes the computed normal vector will be in the opposite direction to the plane.normal vector, indicating that the contours are ordered in the opposite direction to the given plane normal.

  • Even if the vertices in each contour are not co-planar or the contours themselves are self-intersecting, you are still free to set the isClosed and/or isPolygon flags to try to generate surfaces and the tesselator will do its best to work out whatever is appropriate in each case. Obviously some weird shape configurations will work as expected and others may not, however the algorithm is pretty robust so the worst that can happen is simply an empty triangle list.


new Polyline( [config])

Creates a new polyline.

Parameters:
Name Type Argument Description
config object <optional>

An optional configuration object.

Properties of config:
Name Type Argument Description
contours Array <optional>

An array to be used to store linear contours.

lineColor THREE.Color <optional>

A color to use when rendering the outline, defaults to null.

fillColor THREE.Color <optional>

A color to use when rendering the closed surface, defaults to null.

extents THREE.Box3 <optional>

An optional box instance to store the calculated extents.

plane THREE.Plane <optional>

An optional plane to store the calculated plane equation.

normal THREE.Vector3 <optional>

An optional vector to store the calculated normal.

center PD.Point <optional>

An optional vector to store the calculated center point.

isClosed boolean <optional>

Whether or not each contour forms a closed loop, defaults to false.

isPlanar boolean <optional>

Forces all points in the polyline/polygon to lie on its plane, defaults to false.

isPolygon boolean <optional>

Whether or not the contours form a single polygon, defaults to false.

keepVertical boolean <optional>

Ensures that the plane normal and up-vector are always vertical, defaults to false.

showOutline boolean <optional>

A flag indicating whether or not to render outlines, defaults to true.

showSurface boolean <optional>

A flag indicating whether or not to render surfaces, defaults to true.

isRect boolean <optional>

Whether or not a polygon should be rectilinear when possible, defaults to false.

Author:
  • drajmarsh
Example
let square = [
    [
        new PD.Point(-1000.0, -1000.0, 0.0),
        new PD.Point( 1000.0, -1000.0, 0.0),
        new PD.Point( 1000.0,  1000.0, 0.0),
        new PD.Point(-1000.0,  1000.0, 0.0)
    ]
];

const line = new PD.Polyline({
     contours: square
});

const closed_polyline = new PD.Polyline({
     contours: square,
     isClosed: true
});

const polygon = new PD.Polygon({
     contours: square
});

Members


:PD.AXIS

axis

The major cartesian axis of the polygon (-3 to 3), defaults to zero.

This is mainly used to select the optimum cartesian plane to project the polyline onto when performing 3D->2D->3D operations such as clipping and offsetting. It is stored an a PD.AXIS whose values have the following meaning - 0:not_yet_known, 1:+X, -1:-X, 2:+Y, -2:-Y, 3:+Z, -3:-Z.

Type

:PD.Point

center

Stores the calculated center position of the polygon.

The position of the center is automatically computed during a normal update if the polygon has changed.

Type

:Array

contours

An array of contour arrays.

Each contour is an array of THREE.Vector3 instances or a subclass of that type, that are connected by a continuous line or a loop if the polyline is closed. To have multiple separate lines or loops, just add more contours to this array.

Contours within a polygon are slightly different in that the first contour always defines its outer boundary, and any subsequent contours define the inner boundaries of any holes or voids within it.

Type
  • Array

:THREE.Box3

extents

The maximum and minimum extents of all contours.

Type
  • THREE.Box3

:THREE.Color|null

fillColor

An optional color to use for the polygon surface.

Type
  • THREE.Color | null

:boolean

hasChanged

Whether or not any contours have changed since last updated.

Type
  • boolean

:boolean

isChanging

Whether or not the polygon is being interactively edited.

Type
  • boolean

:boolean

isClosed

Whether or not each contour is a closed loop.

When a polyline is closed, the last point in each of its contours is always joined back to the first to form a closed loop. This affects rendering, snapping, offsetting and extrusion.

When the isPolygon flag is set, this value will always be true as polygons must always have closed loop boundaries.

Type
  • boolean

:boolean

isCurved

Whether or not the surface is curved with triangles already generated.

If this is set on a polygon, then it is assumed that the surface is not flat and has been (or soon will be) triangulated using an external method. The default surface tesselation cannot automatically discern how to best triangulate non-planar surface boundaries.

Type
  • boolean

:boolean

isPlanar

Whether or not all vertices lie in the same plane.

If this is set, all vertices in the polyline will be projected onto the current plane whenever they are moved or added. When not set, the plane equation is automatically calculated from the vertices, even if they are not co-planar. This give an 'average' plane that can be used as a normal for determining the directionality of the polyline.

Type
  • boolean

:boolean

isPolygon

Whether or not the contours form a single polygon.

A polygon differs from a polyline in that it is always closed and it represents a single shape, with the first contour defining its outer boundary and any subsequent contours defining holes or voids within it.

Type
  • boolean

:boolean

isPolyline <readonly>

A flag identifying this object as a polyline.

Type
  • boolean

:boolean

isRect

Whether or not the polygon is rectilinear.

Type
  • boolean

:boolean

keepVertical

Whether or not to keep the plane normal always vertical.

When this flag is set, the normal vector will always point in the direction of the vertical +Z axis regardless of the position of contour points. Whilst this may seem a bit esoteric, being able to specify it in a base polyline (or the BIM.Path subclass) has a whole range of uses, such as when defining railings that follow a stepped staircase, walls that follow an incline, columns at different levels and all sorts of other instances.

Type
  • boolean

:THREE.Color|null

lineColor

The color to use when rendering the lines.

This value defaults to null and is only used if it is assigned.

Type
  • THREE.Color | null

:THREE.Vector3

normal

The direction of the normal to this polyline, defaults to +Z axis.

The polygon normal (this value) and the plane normal are two separate objects. The two will typically coincide, but the polygon normal will always be calculated from boundary points even when isPlanar is set as this is used to detect if any points need adjusting back into the plane.

The only caveat to this is when keepVertical is set, in which case the polygon normal is always set to the +Z axis.

Type
  • THREE.Vector3

:THREE.Plane|null

plane

The average plane equation of the outer boundary of the polygon.

If isPlanar is false (the default), the plane equation is recalculated as the average of all points in the outer boundary each time the polyline changes.

If isPlanar is true, all points in each contour of the polygon will be projected onto this plane whenever they are moved. In order to maintain dimensions and snap positions, this projection is always done along one of the major axis. This means that polygons with large variations in the XY plane and only small variation in the Z axis will be projected onto their plane in the Z axis, and the same for other axis.

Also, the polygon normal and the plane normal (this value) are two separate objects. The two will typically coincide, but the polygon normal will always be calculated from boundary points even when isPlanar is set as this is used to detect if any points need adjusting back into the plane.

The only caveat to this is when keepVertical is set, in which case the polygon normal is always set to the +Z axis.

Type
  • THREE.Plane | null

:boolean

showOutline

Whether or not the polyline should include its outline(s) when meshed.

Type
  • boolean

:boolean

showSurface

Whether or not the polyline should include its surface(s) when meshed.

Type
  • boolean

:Array|null

triangles

A list of triangles that define a tessellated surface.

This is a flat array where each consecutive triplet of points form a separate triangle. Triangles are stored using the same point objects as used in the contour arrays. In fact, apart from some specific cases where the tesselation process may need to create a new interpolated vertex, they will almost always be pointers to the exact same point objects from within the contours array.

Triangles can only be calculated for closed polylines with contours that have at least three vertices (to form at least one triangle). You can compute the triangles for such a polyline using the tesselate() method.

When the isPolygon flag is set, triangles will be automatically computed during each update whenever its geometry has changed. For polylines when the isPolygon flag is not set, you must call the tesselate() method manually.

If the isCurved flag is also set on a polygon, then it is assumed that some other external tesselation method has been or will be used as the internal method cannot automatically discern how best to triangulate non-planar surface boundaries.

Type
  • Array | null

Methods


addContour(contour [, index])

Append the given contour to the polyline's contour array.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

Parameters:
Name Type Argument Description
contour Array

An array of two or more instances of THREE.Vector3 or a subclass.

index Array <optional>

An optional array index to insert at, defaults to the end of the array.

Throws:

Occurs if the contour is not an array or contains less than two points.

Type
TypeError
Returns:

Returns the index at which the contour was added.

Type
number

addContourOrientedToAxis(contour [, index])

Append the given contour to the polyline's contour array.

If the normal of the contour does not match the current polyline axis, the order of points in the contour will be reversed so that it does.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

Parameters:
Name Type Argument Description
contour Array

An array of two or more instances of THREE.Vector3 or a subclass.

index Array <optional>

An optional array index to insert at, defaults to the end of the array.

Throws:

Occurs if the contour is not an array or contains less than two points.

Type
TypeError
Returns:

Returns the index at which the contour was added.

Type
number

addContourPoint(contourIndex, point)

Appends a point to the contour at the given index in the polyline.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

Parameters:
Name Type Description
contourIndex number

The numeric index of the contour in the contours array.

point THREE.Vector3

The point to append to the contour.

Returns:

Returns the index at which the vertex was added, or -1 if contour and/or vertex was invalid.

Type
number

bothPointsOnSameBoundaryXY(point1, point2 [, tolerance])

Determines if the given points are on or close to the same facet boundary in the XY plane.

Parameters:
Name Type Argument Description
point1 THREE.Vector3

The first point to to check if on boundary.

point2 THREE.Vector3

The second point to to check if on boundary.

tolerance number <optional>

The distance threshold to define closeness, defaults to 1e-3.

Returns:

Returns true if both points on the same boundary in the XY plane, otherwise false.

Type
boolean

clearContours()

Removes all existing contours within the polyline.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

computeArea()

Calculates the surface area of a closed polyline in metres squared (m2).

If the isPolygon flag is set, the area of each contour after the first will be subtracted from the area of the first contour, as they are assumed to represent holes or voids within the outer polygonal area. If not set, then the areas of each contour are summed together.

Returns:

Returns the surface area in metres squared (m2).

Type
number

computeAxis( [update_plane_eqn])

Calculates the extents and major axis in which the polyline sits.

This first computes the average normal of all points in the polyline using Newell's Method. From this it can determine the most appropriate axis to project the line in when performing 3D->2D->3D operations.

This method is typically called without any arguments. You should only set update_plane_eqn to true if you need to recompute the plane equation of a polyline whose PD.Polyline#isPlanar flag is true. This may be needed after having programmatically rotated or transformed the entire polyline.

Parameters:
Name Type Argument Description
update_plane_eqn boolean <optional>

An optional flag to force a recalculation of the plane equation even if the polyline is planar.

Returns:

Returns true if a valid axis was calculated or false if insufficient points or they are all co-linear.

Type
boolean

computeBoundaryIntersectionPoint(from, to, target)

Computes the closest point that lies on the boundary of the polygon.

Parameters:
Name Type Description
from THREE.Vector3

The first point in the line.

to THREE.Vector3

The second point in the line.

target THREE.Vector3

The vector to receive the intersection point, may be the same as to.

Returns:

Returns true if an intersection point was found.

Type
boolean

computeBounds(min, max)

Computes the bounding extents of the polyline/polygon.

For polygons, this method checks only the outer (first) contour. For polylines, all of the contours are checked.

Parameters:
Name Type Description
min THREE.Vector3

The point to receive the minimum extent.

max THREE.Vector3

The point to receive the maximum extent.

Returns:

Returns true if min/max were set.

Type
boolean

computeClosestPointOnBoundary(point, target)

Computes the closest point that lies on the boundary of the polygon.

Parameters:
Name Type Description
point THREE.Vector3

The point to check if on boundary.

target THREE.Vector3

The vector to receive the closest point, may be the same as point.

Returns:

Returns true if a closest point was found.

Type
boolean

computeContourNormal(contour_index, normal)

Calculates the surface normal of the given contour.

This method computes the average normal of all points in the list using Newell's Method.

Parameters:
Name Type Description
contour_index number

The ordinal index of the contour to check.

normal THREE.Vector3

A vector to receive the calculated normal.

Returns:

Returns true if a valid normal was calculated or false if insufficient points or they are all co-linear.

Type
boolean

computeGeometricCenter(center)

Computes the geometric center of the polyline/polygon.

Parameters:
Name Type Description
center THREE.Vector3

The point to receive the center position.

Returns:

Returns true if the center point was set.

Type
boolean

copyDashedOutlineToPolyMesh(mesh, size)

Adds the outline of the polyline to the given dynamic mesh.

This method does NOT respect the showOutline flag as it is often used to highlight a polyline even if its outline is not normally shown.

Parameters:
Name Type Description
mesh PD.PolyMesh

The dynamic mesh to add the polyline to.

size number

The size of each dash in model units.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copyDraftingLinesToPolyMesh(mesh, size)

Adds the outline as architectural-style extended lines to the given dynamic mesh.

This method does NOT respect the showOutline flag as it is often used to given indicative visual feedback in plan view.

Parameters:
Name Type Description
mesh PD.PolyMesh

The dynamic mesh to add the polyline to.

size number

The size of the extended overrun, in model coordinates.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copyHilightLinesToPolyMesh(mesh, size)

Adds the outline as highlight lines to the given dynamic mesh.

This method does NOT respect the showOutline flag as it is often used to outline selected items in plan view.

Parameters:
Name Type Description
mesh PD.PolyMesh

The dynamic mesh to add the lines to.

size number

The width of the line, in model coordinates.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copyOutlineToPolyMesh(mesh [, color] [, update])

Adds the outline of the polyline to the given dynamic mesh.

This method does NOT respect the showOutline flag as it is often used to highlight a polyline even if its outline is not normally shown.

Parameters:
Name Type Argument Default Description
mesh PD.PolyMesh

The dynamic mesh to add the polyline to.

color THREE.Color <optional>
null

An optional color to render the triangles, defaults to null.

update boolean <optional>
true

Whether or not to check if changed and include normal and line color, defaults to true.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copyOutlineToPolyMeshWithCallback(mesh, callback)

Add a dynamically transformed polyline to the given dynamic mesh.

This method does NOT respect the showOutline flag as it is often used to highlight a polyline even if its outline is not normally shown.

Parameters:
Name Type Default Description
mesh PD.PolyMesh

The dynamic mesh to add the polyline to.

callback function null

A callback function that takes a point/vertex and returns a THREE.Vector3.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copySurfaceToPolyMesh(mesh [, color] [, update])

Adds any triangles the polyline has to the given dynamic mesh.

The method does NOT respect the showSurface flag as it is often used to highlight a polygon even if its surface is not normally shown.

To have a surface, the polyline must have isClosed set and the tesselate() method already called to generate its triangles. If the isPolygon flag is set, then triangles will be automatically computed if anything has changed.

Parameters:
Name Type Argument Default Description
mesh PD.PolyMesh

The dynamic mesh to add the triangles to.

color THREE.Color <optional>
null

An optional color to render the triangles, defaults to null.

update boolean <optional>
true

Whether or not to check if changed and include normal and line color, defaults to true.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copySurfaceToPolyMeshReversed(mesh [, color] [, update])

Adds any triangles the polyline has to the given dynamic mesh in reverse orientation.

The method does NOT respect the showSurface flag as it is often used to highlight a polygon even if its surface is not normally shown.

To have a surface, the polyline must have isClosed set and the tesselate() method already called to generate its triangles. If the isPolygon flag is set, then triangles will be automatically computed if anything has changed.

Parameters:
Name Type Argument Default Description
mesh PD.PolyMesh

The dynamic mesh to add the triangles to.

color THREE.Color <optional>
null

An optional color to render the triangles, defaults to null.

update boolean <optional>

Whether or not to check if changed and include normal and line color, defaults to true.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copyThickLinesToPolyMesh(mesh, size [, endcap])

Adds the outline as thick lines to the given dynamic mesh.

This method does NOT respect the showOutline flag as it is often used to outline selected items in plan view.

Parameters:
Name Type Argument Description
mesh PD.PolyMesh

The dynamic mesh to add the lines to.

size number

The width of the line, in model coordinates.

endcap PD.ENDCAP <optional>

How to start/end the line, defaults based on isClosed.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copyToPolyMesh(mesh, no_color)

Add the polyline to the given dynamic mesh.

The method adds the outline to the mesh, as well as the surface if it has one. This method respects the showOutline and showSurface flags when rendering either component.

To have a surface, the polyline must have isClosed set and the tesselate() method already called to generate its triangles. If the isPolygon flag is set, then triangles will be automatically computed if anything has changed.

Parameters:
Name Type Description
mesh PD.PolyMesh

The dynamic mesh to add the polyline to.

no_color boolean

Whether to render without fill color, defaults to false.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

copyToPolyMeshWithCallback(mesh, callback)

Add a dynamically transformed polyline to the given mesh.

The method adds the outline to the mesh, as well as the surface if it has one. This method respects the showOutline and showSurface flags when rendering either component.

To have a surface, the polyline must have isClosed set and the tesselate() method already called to generate its triangles. If the isPolygon flag is set, then triangles will be automatically computed if anything has changed.

Parameters:
Name Type Default Description
mesh PD.PolyMesh

The dynamic mesh to add the polyline to.

callback function null

A callback function that takes a point/vertex and returns a THREE.Vector3.

Returns:

Returns true if geometry was added to the mesh.

Type
boolean

distanceToBoundaryXY(point [, tolerance])

Calculates the shortest distance from the point to the facet boundary in the XY plane.

Parameters:
Name Type Argument Description
point THREE.Vector3

The point to to check if inside.

tolerance number <optional>

The distance threshold to define closeness, defaults to 1e-3.

Returns:

Returns true if on boundary in the XY plane, otherwise false.

Type
boolean

distributePointsByDistance(shell, spacing [, index])

Distributes points along a polyline at fixed intervals defined by a given spacing.

Parameters:
Name Type Argument Description
shell PD.Shell

The shell to reuse points from.

spacing number

The distance between distributed points.

index number <optional>

The index of the contour to use, defaults to 0.

Returns:

The new array of points placed at the given intervals.

Type
Array.<PD.Point>

ensureDownwardsNormal( [update] [, reverseInner])

Checks the direction of the surface normal and reverses contour(s) such that the Z component of its normal is negative.

This method will ensure that the first contour is oriented such that its normal faces downwards in the negative Z axis, as per the right-hand rule. This works with any polyline at any orientation and tilt angle other than vertical. It does not rotate the position of vertices, but simply reverses the order of vertices within the contour and negates the normal vector so that its Z component is negative rather than positive.

If reverseInner is set to true and the isPolygon flag is set, then any internal contours will be reversed so that their normals face upwards instead. Whilst this framework does not particularly care about the orientation of internal contours, there are some processes that require internal hole contours to be oriented opposite to the boundary contour, which this will do.

If reverseInner is set to false (the default) or the isPolygon flag is not set, then subsequent/internal contours will be reversed so that their normals face downwards to match the first/boundary contour.

Parameters:
Name Type Argument Default Description
update boolean <optional>

When true, the path will update when changed, defaults to false.

reverseInner boolean <optional>
false

When true, internal contours of polygonal paths will be made to face upwards, defaults to false.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

ensureUpwardsNormal( [update] [, reverseInner])

Checks the direction of the surface normal and reverses contour(s) such that the Z component of its normal is positive.

This method will ensure that the first contour is oriented such that its normal faces upwards in the positive Z axis, as per the right-hand rule. This works with any polyline at any orientation and tilt angle other than vertical. It does not rotate the position of vertices, but simply reverses the order of vertices within the contour and negates the normal vector so that its Z component is positive rather than negative.

If reverseInner is set to true and the isPolygon flag is set, then any internal contours will be reversed so that their normals face downwards instead. Whilst this framework does not particularly care about the orientation of internal contours, there are some processes that require internal hole contours to be oriented opposite to the boundary contour, which this will do.

If reverseInner is set to false (the default) or the isPolygon flag is not set, then subsequent/internal contours will be reversed so that their normals face upwards to match the first/boundary contour.

Parameters:
Name Type Argument Default Description
update boolean <optional>

When true, the path will update when changed, defaults to false.

reverseInner boolean <optional>
false

When true, internal contours of polygonal paths will be made to face downwards, defaults to false.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

findContourAndIndex(point)

Determines which contour the given point belongs to and its ordinal index within that contour.

This method iterates through contours of the polyline, and checks if they contain the point. If found, it returns an array with the contour as the first item and the index of the point within that contour as the second item.

Parameters:
Name Type Description
point PD.Point

The point to determine the contour and index of.

Returns:

Returns a [contour,index] array.

Type
Array

fromClipperPaths(paths, plane [, shell] [, offset] [, quaternion])

Converts one or more 2D ClipperLib paths back into polygon contours.

As ClipperLib creates paths based on 2D {X,Y} objects, converting back to 3D [x,y,z] coordinates requires projecting them back onto a 3D plane. This method uses the the plane equation to determine the most suitable cartesian axis to use, the axis of greatest surface exposure.

If no plane equation is given, the XY plane is assumed (Z=0). If a number is given in place of the plane equation, then that number is used a Z-axis offset in the XY plane (Z = toNumber(plane)).

Converting to 2D and then back to 3D in the axis with the largest surface exposure involves only a small amount of maths so is very quick and accuracy is way more than acceptable. It is required when performing operations on multiple shapes that may not be on exactly the same plane - or on polylines whose points may not all be exactly co-planar - as positions will be very stable even after multiple conversions. However, if the plane normal is not exactly aligned with one of the cartesian axis, then the 2D point positions will be skewed slightly compared to their positions on the surface of the plane.

Using quaternions to rotate the points to and from the XY plane results in the 2D rotated positions always align correctly with their 3D positions on the surface of the plane. However, if polygons have slightly different plane equations or their points are not all exactly co-planar, then small cumulative inaccuracies can build up over multiple conversions, far more than the with axis-based conversion.

Parameters:
Name Type Argument Description
paths Array

One or more ClipperLib paths containing {X,Y} Clipper points.

plane THREE.Plane | number

The plane equation to project points onto or a Z-axis height.

shell PD.Shell <optional>

An optional shell to reuse vertices from.

offset number <optional>

An offset value from the plane in its axial direction.

quaternion THREE.Quaternion <optional>

An optional quaternion to use rather than computing it.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

fromClipperPathsByAxis(paths, plane [, shell] [, offset])

Converts one or more 2D ClipperLib paths back into polygon contours.

As ClipperLib creates paths based on 2D {X,Y} objects, converting back to 3D [x,y,z] coordinates requires projecting them back onto a 3D plane. This method uses the the plane equation to determine the most suitable cartesian axis to use, the axis of greatest surface exposure.

If no plane equation is given, the XY plane is assumed (Z=0). If a number is given in place of the plane equation, then that number is used a Z-axis offset in the XY plane (Z = toNumber(plane)).

Converting to 2D and then back to 3D in the axis with the largest surface exposure involves only a small amount of maths so is very quick and accuracy is way more than acceptable. It is required when performing operations on multiple shapes that may not be on exactly the same plane - or on polylines whose points may not all be exactly co-planar - as positions will be very stable even after multiple conversions. However, if the plane normal is not exactly aligned with one of the cartesian axis, then the 2D point positions will be skewed slightly compared to their positions on the surface of the plane.

Using quaternions to rotate the points to and from the XY plane results in the 2D rotated positions always align correctly with their 3D positions on the surface of the plane. However, if polygons have slightly different plane equations or their points are not all exactly co-planar, then small cumulative inaccuracies can build up over multiple conversions, far more than the with axis-based conversion.

Parameters:
Name Type Argument Description
paths Array

One or more ClipperLib paths containing {X,Y} Clipper points.

plane THREE.Plane | number

An optional plane equation to project points onto or a Z-axis height.

shell PD.Shell <optional>

An optional shell to reuse vertices from.

offset number <optional>

An offset value from the plane in its axial direction.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

fromJSON(data [, no_contours])

Safely copy properties from a source object.

See the PD.Base#fromJSON method for more details.

Override this method in derived classes to read additional properties, but call super.fromJSON(data); at the top of the method.

Parameters:
Name Type Argument Description
data object

The source object containing data to copy.

no_contours boolean <optional>

An optional flag to allow a subclass to process contours, defaults to false.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline
Example
// Overriding this method.

class MyPolyline extends PD.Polyline {
     /// ...
     fromJSON(data) {

         super.fromJSON(data);

         if ('extraData' in data) {
             this.extraData = PD.Utils.toIntegerInRange(data.extraData, this.extraData, 0, 16);
         }

         if ('evenMoreData' in data) {
             this.evenMoreData = PD.Utils.toNumber(data.evenMoreData, this.evenMoreData);
         }

         return this;

     };
     /// ...
 };

getContour(contourIndex [, wantNull])

Retrieves the contour at the given index within the polyline.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

Parameters:
Name Type Argument Default Description
contourIndex number

The numeric index of the required contour in the contours array.

wantNull boolean <optional>
false

When true, returns null instead of an empty array when index out of range, defaults to false.

Returns:

Returns a contour if found, which is basically an array of connected points, or an empty array / null.

Type
Array

getContourCount()

Retrieves the number of contours within the contour list of a polyline.

Returns:

Returns the number of contours in the polyline.

Type
number

getContourIndexContainingPoint(point)

Determines the index of the contour that the given point belongs to, if any.

Parameters:
Name Type Description
point PD.Point

The point to determine the contour index of.

Returns:

Returns the index of the contour, or -1 if point is not in this polyline.

Type
number

getContourPoint(contourIndex, vertexIndex)

Retrieves a point at the given index in a contour of the polyline.

If either the contour or vertex index is negative, it is treated as an offset from the end of the corresponding array, such that -1 is always the last contour or vertex in the contour.

Parameters:
Name Type Description
contourIndex number

The numeric index of the required contour in the contours array.

vertexIndex number

The numeric index of the required vertex within the contour array, may be negative.

Returns:

Returns a vertex, or null if contour and/or vertex index is invalid.

Type
THREE.Vector3 | null

getContourPointCount(contourIndex)

Retrieves the number of points in the contour at the given index.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

Parameters:
Name Type Description
contourIndex number

The numeric index of the required contour in the contours array.

Returns:

Returns a contour, which is basically an array of points.

Type
number

getContours()

Retrieves the contours array for the polyline.

A polyline's contours is basically an array of zero or more point arrays.

Returns:

Returns the contours array.

Type
Array.<Array>

getPointOnBoundary(point [, tolerance])

Determines if the given point is on or close the polyline boundary and returns segment start.

Parameters:
Name Type Argument Description
point THREE.Vector3

The point to check if on boundary.

tolerance number <optional>

The distance threshold to define closeness, defaults to 1e-3.

Returns:

Returns the start of the found boundary segment.

Type
THREE.Vector3

getPointOnBoundaryXY(point [, tolerance])

Determines if the given point lies on or close to the facet boundary in the XY plane and returns segment start.

Parameters:
Name Type Argument Description
point THREE.Vector3

The point to to check if on boundary.

tolerance number <optional>

The distance threshold to define closeness, defaults to 1e-3.

Returns:

Returns true if on boundary in the XY plane, otherwise false.

Type
boolean

hasContent()

Determines whether or not the polyline has valid content.

Returns:

Returns true if contours have more than one point.

Type
boolean

isDownwardsFacing()

Returns true if the polyline normal is facing downwards.

All polylines, closed or open, have a normal direction computed for them and stored in its normal property. Even a single point polyline will use the +Z axis as its normal direction. If consecutive points in a polyline are arranged in a counter-clockwise direction around the +Z axis, then according to the right-hand rule, the normal will point upwards (+Z).

If the points are arranged in a clockwise direction, then the normal will point downwards (-Z). This getter returns true if the Z component of the normal direction is less than zero.

Returns:

Returns true if the polyline normal is facing downwards.

Type
boolean

isInsideContour(point [, index])

Determines whether or not the given point is within a contour of this polygon.

This method sums the signed angle between the given point and each line segment of the given contour boundary. If the total angle is near zero, then the point must be outside. If near 360, it must be inside.

Parameters:
Name Type Argument Description
point THREE.Vector3

The point to to check if inside.

index number <optional>

The index of the contour within the polyline, defaults to 0.

Returns:

Returns true if inside, otherwise false.

Type
boolean

isInsideFrustum(frustum, intersect)

Determines whether or not the polygon is inside the given frustum or, when intersection is set, if it is intersected.

Parameters:
Name Type Description
frustum THREE.Frustum

The frustum to check if inside.

intersect boolean

Whether to also check for intersection selection.

Returns:

Returns true if inside, otherwise false.

Type
boolean

isPointInside(point [, selecting])

Determines whether or not the given point is within the surface of this polygon.

As triangles in a planar polygon are assumed to all share the same surface normal, this calculation can be much faster. This method also excludes points that are inside internal holes/contours if the polygon has been triangulated already - except when selecting a polygon-based element.

When the selecting argument is true, only the outer boundary of a polygon is tested as this allows for subsequent drilling down into holes and openings. This means that triangle intersection is not used when selecting as triangles are not generated inside holes or openings.

Parameters:
Name Type Argument Default Description
point THREE.Vector3

The point to to check if inside.

selecting boolean <optional>
false

Whether or not this is being use to select a polygon, defaults to false.

Returns:

Returns true if inside, otherwise false.

Type
boolean

isPointOnBoundary(point [, tolerance])

Determines if the given point is on the polyline boundary.

Parameters:
Name Type Argument Description
point THREE.Vector3

The point to to check if on boundary.

tolerance number <optional>

The distance threshold to define closeness, defaults to 1e-3.

Returns:

Returns true if on boundary, otherwise false.

Type
boolean

isPointOnBoundaryXY(point [, tolerance])

Determines if the given point lies on or close to the facet boundary in the XY plane.

Parameters:
Name Type Argument Description
point THREE.Vector3

The point to to check if on boundary.

tolerance number <optional>

The distance threshold to define closeness, defaults to 1e-3.

Returns:

Returns true if on boundary in the XY plane, otherwise false.

Type
boolean

isUpwardsFacing()

Returns true if the polyline normal is facing upwards.

All polylines, closed or open, have a normal direction computed for them and stored in its normal property. Even a single point polyline will use the +Z axis as its normal direction. If consecutive points in a polyline are arranged in a counter-clockwise direction around the +Z axis, then according to the right-hand rule, the normal will point upwards (+Z).

If the points are arranged in a clockwise direction, then the normal will point downwards (-Z). This getter returns true if the Z component of the normal direction is greater than or equal to zero.

Returns:

Returns true if the polyline orientation is upwards.

Type
boolean

keepAspectRatio(aspect, index [, axis])

Maintains the relative aspect ratio of a closed rectangular contour.

Parameters:
Name Type Argument Description
aspect number

The aspect ratio (h/w) to maintain.

index number

The index of the outer contour vertex that was moved.

axis PD.AXIS <optional>

An optional axis override, defaults to X axis.

Returns:

Returns true if the polygon is rectangular and its width/height changed.

Type
boolean

keepRectangular(index)

Maintains a polygon as rectangular by adjusting its bounding box.

This is used when the position of one corner of a rectangular polygon is changed. It computes the bounding box using the opposite corner and maintains its rectangular shape.

NOTE: The behaviour of this method is different to makeRectangularByCorners() in that the space size is limited to a minimum value and the opposite corners always remain opposite.

Parameters:
Name Type Description
index number

The index of the outer contour vertex that was moved.

Returns:

Returns true if the polygon is rectangular and its width/height changed.

Type
boolean

makePlanar( [newPlane])

Ensures that all points in the polyline sit on the same plane.

If a new plane is given, it will be copied to both the polyline's own plane and normal, and the isPlanar flag set to true. This will ensure that the polyline remains planar with this plane.

You can also use this method to ensure that all points in the polyline are made coplanar with it's own plane as a one-off process, without setting the isPlanar flag, by simply not including the newPlane argument.

Parameters:
Name Type Argument Description
newPlane THREE.Plane <optional>

The plane to use, defaults to the polyline's own plane.

Returns:

Returns true if any points were not coplanar and had to be moved into the plane, otherwise false.

Type
boolean

makeRectangularByCorners(contour, corner1, corner2 [, min_size])

Maintains a polygon as rectangular by adjusting its bounding box.

Parameters:
Name Type Argument Description
contour Array

The actual contour to keep rectangular.

corner1 THREE.Vector3

The first corner of the rectangle.

corner2 THREE.Vector3

The second corner of the rectangle.

min_size number <optional>

An optional minimum rectangle size, defaults to 25mm or 1".

Returns:

Returns true if the polygon is rectangular and its width/height changed.

Type
boolean

moveBy(dx [, dy] [, dz])

Move all vertices by a relative vector.

Parameters:
Name Type Argument Description
dx number | THREE.Vector3

Either the X-axis movement component or a vector.

dy number <optional>

The Y-axis movement component.

dz number <optional>

The Z-axis movement component.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

overlapsXY(poly)

Determines if the given polygon/polyline overlaps this in the XY plane.

NOTE: If this polygon/polyline is not closed, this method will always return false.

Parameters:
Name Type Description
poly PD.Polyline

The polyline to check for overlap.

Returns:

Returns true is polyline overlap in the XY plane, otherwise false.

Type
boolean

removeContour(contourIndex)

Removes a contour at the given index from the polyline's contour array.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

Parameters:
Name Type Description
contourIndex number

The numeric index of the required contour in the contours array.

Returns:

Returns true if the contour index was valid and the contour removed.

Type
boolean

reverse( [forceUpdate])

Reverses the order of vertices as well as the normal orientation.

Parameters:
Name Type Argument Description
forceUpdate boolean <optional>

Whether or not to update even if polyline has not changed, defaults to false.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

reverseContour(contourIndex)

Reverses the order of vertices in the contour at the given index.

Parameters:
Name Type Description
contourIndex number

The numeric index of the required contour in the contours array.

Returns:

Returns true if the contour index was valid and the contour reversed.

Type
boolean

setContour(contourIndex, contour)

Replaces the contour at the given index within the polyline.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

Parameters:
Name Type Description
contourIndex number

The numeric index of the required contour in the contours array.

contour Array

A new contour, which is basically an array of connected points.

Throws:

Occurs if the contour is not a valid array.

Type
TypeError
Returns:

Returns true if the contour was replaced.

Type
boolean

setContours(contours)

Sets the array of contours that make up the polyline.

Parameters:
Name Type Description
contours Array

An array of one or more contours containing at least two points.

Throws:

Occurs if contours is not a valid list of contours.

Type
TypeError
Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

shuffleContour(contourIndex, direction)

Shuffled the order of vertices in the contour at the given index.

Parameters:
Name Type Description
contourIndex number

The numeric index of the required contour in the contours array.

direction number

The direction of shuffle (1:Forwards/Right, -1:Backwards/Left).

Returns:

Returns true if the contour index was valid and the contour reversed.

Type
boolean

tesselate()

Tessellates closed contours using the robust LibTess algorithm.

For closed polylines, each contour is treated as an independent and separate closed shape.

                             +----+                  +
            +-------+        |    |                _/ \
          _/        |   +----+    +----+         _/    \
        _/          +   |  contour[1]  |       _/       \
      _/ contour[0] |   +----+    +----+     _/          \
     +--------------+        |    |        _/  contour[2] \
                             +----+       +----------------+

For closed polygons, the first contour is treated as an outer boundary and each subsequent contour as a hole or void within that boundary. As polygons are assumed to have a surface, this method is automatically called during its normal update process, whenever its geometry has changed.

    +----------------------+
    | contour[0]           |
    |                      |
    |    +------------+    |
    |    | contour[1] |    |
    |    +------------+    +-------+
    |                              |
    |    +--------------------+    |
    |    |     contour[2]     |    |
    |    +--------------------+    |
    |                              |
    +------------------------------+

The vertices in each contour do not have to be co-planar or non-self-intersecting as the tesselator will do its best to work out what is appropriate in each case. However, some weird shape configurations will work and others won't, but the algorithm is pretty robust so the worst that can happen is simply an empty triangle list.

Returns:

Returns a flat array of THREE.Vector3 objects from the contours array, where each consecutive triplet forms a triangle.

Type
Array

to2D_AsArrays( [axis])

Converts the contours in a polyline into an array of 2D vector arrays.

This method creates contours arrays of [x,y] vector arrays for use with 2D libraries. This differs from the ClipperLib-related methods which create {X,Y} point objects.

A 3D polyline is projected into a 2D cartesian plane using its plane equation to determine the most suitable cartesian axis to use. If no plane equation is available, the x and y components of the 3D points are used.

Parameters:
Name Type Argument Description
axis PD.AXIS <optional>

The axis to use when converting, defaults to this.axis.

Returns:

Returns an array of one or more contour arrays, each containing [x,y] 2D vector arrays.

Type
Array

to2D_AsVectors( [axis])

Converts the contours in a polyline into an array of 2D points.

This method creates contours arrays of {x,y} point objects for use with 2D libraries. This differs from the ClipperLib-related methods which create {X,Y} point objects.

A 3D polyline is projected into a 2D cartesian plane using its plane equation to determine the most suitable cartesian axis to use. If no plane equation is available, the x and y components of the 3D points are used.

Parameters:
Name Type Argument Description
axis PD.AXIS <optional>

The axis to use when converting, defaults to this.axis.

Returns:

Returns an array of one or more contour arrays, each containing {x,y} 2D point objects.

Type
Array

toClipperPaths( [clipCache])

Converts the contours in a polyline into 2D ClipperLib.Path arrays.

As ClipperLib works with 2D {X,Y} objects, the 3D polyline must be translated into a 2D cartesian plane. This method uses the surface normal to compute a quaternion to rotate contour points flat in the XY plane.

This quaternion is then applied to each point in the polyline. This is more computationally expensive than using the axis of greatest surface exposure, but better retains the orientation and winding order of points.

Using quaternions to rotate the points to and from the XY plane results in the 2D rotated positions always align correctly with their 3D positions on the surface of the plane. However, if polygons have slightly different plane equations or their points are not all exactly co-planar, then small cumulative inaccuracies can build up over multiple conversions, far more than the with axis-based conversion. Thus, use this method only if you know that the plane equations you are using are consistent across all faces.

Parameters:
Name Type Argument Description
clipCache PD.Clipper.Cache <optional>

An optional cache for reusing 2D clipper points.

Returns:

Returns an array of one or more ClipperLib.Path arrays, each containing {X,Y} Clipper points, one for each contour in the polyline/polygon.

Type
Array

toClipperPathsByAxis( [axis] [, clipCache])

Converts the contours in a polyline into 2D ClipperLib.Path arrays using the axis of greatest surface exposure.

As ClipperLib works with 2D {X,Y} objects, the 3D polyline must be translated into a 2D cartesian plane. This method uses the given axis or, if no axis is given, the polyline's current calculated axis.

Converting to 2D and then back to 3D in the axis with the largest surface exposure involves only a small amount of maths so is very quick and accuracy is way more than acceptable. It is required when performing operations on multiple shapes that may not be on exactly the same plane - or on polylines whose points may not all be exactly co-planar - as positions will be very stable even after multiple conversions. However, if the plane normal is not exactly aligned with one of the cartesian axis, then the 2D point positions will be skewed slightly compared to their positions on the surface of the plane.

Using quaternions to rotate the points to and from the XY plane results in the 2D rotated positions always align correctly with their 3D positions on the surface of the plane. However, if polygons have slightly different plane equations or their points are not all exactly co-planar, then small cumulative inaccuracies can build up over multiple conversions, far more than the with axis-based conversion.

Parameters:
Name Type Argument Description
axis PD.AXIS <optional>

The axis to use when converting, defaults to this.axis.

clipCache PD.Clipper.Cache <optional>

An optional cache for reusing 2D clipper points.

Returns:

Returns an array of one or more ClipperLib.Path arrays, each containing {X,Y} Clipper points.

Type
Array

toGeoJSON()

Generates a GeoJSON object from this polyline or polygon.

The type of GeoJSON object depends on the type of polyline. A normal non-closed polyline is created as a GeoJSON.LineString if it has just a single contour, or a GeoJSON.MultiLineSTring if it has more than one.

If the isPolygon flag is set, a GeoJSON.Polygon object will be created with a boundary and any internal holes or voids the polygon has. If isPolygon flag is not set, but isClosed is, then either a single contour GeoJSON.Polygon is created or a GeoJSON.MultiPolygon with one polygon per contour.

Returns:

Returns an object with type and coordinates properties.

Type
object
Examples
// LineString
{
  'type': 'LineString',
  'coordinates': [
     [ 0.0, 0.0 ], [ 2000.0, 0.0 ], [ 2000.0, 1000.0 ], [ 0.0, 1000.0 ]
  ]
}
// MultiLineString
{
  'type': 'MultiLineString',
  'coordinates': [
    [ [ 2500.0, 250.0 ], [ 4500.0, 250.0 ], [ 4500.0, 750.0 ], [ 2500.0, 750.0 ] ],
    [ [ 0.0, 0.0 ], [ 2000.0, 0.0 ], [ 2000.0, 1000.0 ], [ 0.0, 1000.0 ] ]
  ]
}

GeoJSON polygons are slightly different to LineStrings in that:

- Each linear ring is a closed LineString, with the first coordinate included
  and repeated as the last coordinate.

- The first and last positions MUST contain identical values and their
  representation SHOULD also be identical.

- Each linear ring MUST follow the right-hand rule with respect to the area it
  bounds, so exterior rings must be counterclockwise and holes are clockwise.

- For Polygons with more than one of these rings, the first MUST be the exterior
  ring, and any others MUST be interior rings.  The exterior ring bounds the surface,
  and the interior rings (if any) bound holes within the surface.
// Polygon
{
  'type': 'Polygon',
  'coordinates': [
    [ [ 0.0, 0.0 ], [ 2000.0, 0.0 ], [ 2000.0, 1000.0 ], [ 0.0, 1000.0 ] ],
    [ [ 500.0, 250.0 ], [ 500.0, 750.0 ], [ 1500.0, 750.0 ], [ 1500.0, 250.0 ] ]
  ]
}
// MultiPolygon
{
  'type': 'MultiPolygon',
  'coordinates': [
    [
      [ [ 0.0, 0.0 ], [ 2000.0, 0.0 ], [ 2000.0, 1000.0 ], [ 0.0, 1000.0 ] ],
      [ [ 500.0, 250.0 ], [ 500.0, 750.0 ], [ 1500.0, 750.0 ], [ 1500.0, 250.0 ] ]
    ],
    [
      [ [ 2500.0, 250.0 ], [ 4500.0, 250.0 ], [ 4500.0, 750.0 ], [ 2500.0, 750.0 ] ]
    ]
  ]
}

toJSON( [data] [, no_contours])

Converts the polyline to a simple POJO for conversion to JSON.

This method is used to copy, store and save the data for a polyline, so the returned object must have all the properties required be able to rebuild this instance in its entirety when passed to the class constructor.

Override this method in derived classes to add additional properties, but call data = super.toJSON(data); at the top of the method, as shown in the example below.

Parameters:
Name Type Argument Default Description
data object <optional>

An optional parent object to append this data to.

no_contours boolean <optional>
false

An optional flag to allow a subclass to process contours, defaults to false.

Returns:

Returns a Plain Old Javascript Object (POJO).

Type
object
Example
// Overriding this method.

class MyPolyline extends PD.Polyline {
     /// ...
     toJSON(data) {

         data = super.toJSON(data);

         data.extraData = this.extraData;
         data.evenMoreData = this.evenMoreData;
         return data;

     };
     /// ...
 };

translateInNormalDirection(distance)

Move all vertices by the given distance in the plane normal direction.

Parameters:
Name Type Description
distance number

The distance to move.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

trimContourPointCount(contourIndex, count)

Trims the number of points in the contour at the given index.

If the given contour index is negative, it is treated as an offset from the end of the array, such that -1 is always the last contour.

You can only trim a contour to less points than it currently has, so the count value must be less than the contour array size.

Parameters:
Name Type Description
contourIndex number

The numeric index of the required contour in the contours array.

count number

The new number of points in contours array.

Returns:

Returns the new number of points in the contour.

Type
number

unifyOrientation( [update])

Checks the direction of the surface normal and reverses each contour.

Parameters:
Name Type Argument Description
update boolean <optional>

When true, the path will update when changed, defaults to false.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

update( [forceUpdate])

Checks for changes and finalises the polyline ready for rendering.

For a polygon, this will update its normal and axis value.

Parameters:
Name Type Argument Default Description
forceUpdate boolean <optional>
false

Whether or not to update even if polyline has not changed, defaults to false.

Returns:

Returns this polyline to support method chaining.

Type
PD.Polyline

fromShape(shape, position, scale) <static>

Creates a new polygon from the given shape at the new position and size.

Parameters:
Name Type Description
shape THREE.Shape

The shape to generate the polygon from.

position THREE.Vector3

The position of the shape in model coordinates.

scale THREE.Vector3 | number

The scale factor to apply to the shape.

Returns:

Returns a new polyline or polygon.

Type
PD.Polyline

fromShapeWithCallback(shape, callback) <static>

Creates a new polygon from a dynamically shape.

Parameters:
Name Type Default Description
shape THREE.Shape

The shape to generate the polygon from.

callback function null

A callback function that takes a THREE.Vector2 and returns a new THREE.Vector3.

Returns:

Returns a new polyline or polygon.

Type
PD.Polyline