figureone
    Preparing search index...

    2D Shape Primitives API Reference


    Options object for any FigureElementPrimitive.

    These properties are available when defining any FigureElementPrimitive.

    • name: string | undefined

      name of figure element

    • position: TypeParsablePoint | undefined

      position overrides transform translation

    • transform: TypeParsableTransform | undefined

      transform to apply to element

    • color: TypeColor | undefined = is passed as the 'u_color' uniform to the fragment shader

      color to apply to element

    • touch: boolean | OBJ_Touch | undefined = false

      true, number or TypeParsablePoint will set the element as touchable. If number, then element touch volume is the scaled actual volume in x, y, and z. For example, if 2, then the touchable volume is twice the actual volume. If TypeParsablePoint then the x, y, and z scales can be set independantly

    • move: boolean | OBJ_ElementMove | undefined

      setting this to anything but false will set the element as movable. Use OBJ_ElementMove to customize the movement options

    • dimColor: TypeColor | undefined

      RGBA is used when vertex colors are from a uniform, otherwise just the alpha channel is used.

    • defaultColor: TypeColor | undefined
    • scenarios: OBJ_Scenarios | undefined

      Define position/transform/rotation/scale/color scenarios tied to the element

    • scene: Scene | undefined

      Give the element a custom scene that is independant of the figure scene. For example, use this to create a 3D object in a 2D figure.


    Options object for a FigureElementPrimitive of a generic shape

    points will define either triangles or lines which combine to make the shape.

    drawType defines what sort of triangles or lines the points make. The most useful, common and generic drawType is 'TRIANGLES' which can be used to create any shape.

    The shape's points can be duplicated using the copy property to conveniently create multiple copies (like grids) of shapes.

    The shape is colored with either color or texture.

    When shapes move, or are touched, borders are needed to bound their movement, and figure out if a touch happened within the shape. Shapes that do not move, or are not interactive, do not need borders.

    A shape can have several kinds of borders. "Draw borders" (drawBorder and drawBorderBuffer) are sets of points that define reference borders for a shape. The shapes higher level borders border and touchBorder may then use these draw borders to define how a shape will interact with a figure's bounds, or where a shape can be touched.

    drawBorder and drawBorderBuffer are each point arrays that define the outer limits of the shape. For non-contigous shapes (like islands of shapes), an array of point arrays can be used. Both borders can be anything, but typically a drawBorder would define the border of the visible shape, and a drawBorderBuffer would define some extra space, or buffer, around the visible shape (particulaly useful for defining the touchBorder later).

    border is used for checking if the shape is within some bounds. When shapes are moved, if their bounds are limited, this border will define when the shape is at a limit. The border property can be:

    • draw: use drawBorder points
    • buffer: use drawBorderBuffer points
    • rect: use a rectangle bounding drawBorder
    • number: use a rectangle that is number larger than the rectangle bounding drawBorder
    • Array<TypeParsablePoint>: a custom contiguous border
    • Array<Array<TypeParsablePoint>>: a custom border of several contiguous portions

    touchBorder is used for checking if a shape is touched. The touchBorder property can be:

    • draw: use drawBorder points
    • buffer: use drawBorderBuffer points
    • border: use same as border
    • rect: use a rectangle bounding border
    • number: use a rectangle that is number larger than the rectangle bounding border
    • Array<TypeParsablePoint>: a custom contiguous border
    • Array<Array<TypeParsablePoint>>: a custom border of several contiguous portions
    • points: Array<TypeParsablePoint>
    • drawType: TypeGLPrimitive | undefined = 'TRIANGLES'
    • copy: Array<CPY_Step | string> | CPY_Step | undefined = []

      use drawType as 'TRIANGLES' when using copy

    • texture: OBJ_Texture | undefined

      override color with a texture if defined

    • drawBorder: TypeParsableBorder | undefined
    • drawBorderBuffer: TypeParsableBorder | undefined
    • border: TypeParsableBuffer | TypeParsableBorder | 'buffer' | 'draw' | 'rect' | undefined = 'draw'

      defines border of primitive. Use draw to use the drawBorder of the element. Use 'buffer' to use the drawBorderBuffer property of the element. Use 'rect' for the bounding rectangle of drawBorder. Use TypeParsableBuffer for the bounding rectangle of drawBorder. Use TypeParsableBorder for a custom border.

    • touchBorder: TypeParsableBorder | 'rect' | 'border' | 'buffer' | 'draw' | undefined = 'border'

      defines touch border of the primitive. Use border to use the same border as border. Use draw to use the drawBorder of the element. Use 'buffer' to use the drawBorderBuffer property of the element. Use 'rect' for the bounding rectangle of drawBorderBuffer. Use TypeParsableBuffer for the bounding rectangle of drawBorderBuffer. Use TypeParsableBorder for a custom border.

    • pulse: OBJ_PulseScale | number | undefined = number

      set default scale pulse options (OBJ_PulseScale) or pulse scale directly

    figure.add({
    name: 'squareAndTri',
    make: 'generic',
    points: [
    [-1, 0.5], [-1, -0.5], [0, 0.5],
    [0, 0.5], [-1, -0.5], [0, -0.5],
    [0, -0.5], [1, 0.5], [1, -0.5],
    ],
    });
    figure.add({
    name: 'rhombus',
    make: 'generic',
    points: [
    [-0.5, -0.5], [0, 0.5], [1, 0.5],
    [-0.5, -0.5], [1, 0.5], [0.5, -0.5],
    ],
    border: [[
    [-1, -1], [-0.5, 1], [1.5, 1], [1, -1],
    ]],
    mods: {
    isMovable: true,
    move: {
    bounds: 'figure',
    },
    },
    });
    figure.add({
    name: 'gridOfTris',
    make: 'generic',
    points: [
    [-1, -1], [-0.7, -1], [-1, -0.7],
    ],
    copy: [
    { along: 'x', num: 5, step: 0.4 },
    { along: 'y', num: 5, step: 0.4 },
    ],
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Polyline shape options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    A polyline is a series of lines that are connected end to end. It is defined by a series of points which are the ends and corners of the polyline.

    The series of points is a zero width ideal polyline, and so to see it we must give it some width. This width can either be grown on one side of the ideal polyline or grown on both sides of it equally using widthIs.

    A polyline can have a "positive" or "negative" side, and an "inside" or "outside".

    If a line is defined from p1 to p2, then the positive side is the side where the line moves if it is rotated around p1 in the positive (counter clockwise) direction. Thus the order of the points that define the line defines which side is positive and negative. A polyline is made up of many lines end to end, and thus itself will have a positive and negative side dependent on the order of points.

    Similarly we can define a line's side as either inside or outside. Each corner in the polyline will have an angle on the negative side of the line and a explementary angle on the positive side of the line. The inside side of the line is the same as the negative side if the sum of all the negative side angles is smaller than the sum of all positive side angles.

    Both positive/negative and inside/outside are provided to define a line's side as different situations make different side definitions more intuitive. For instance, a closed, simple polygon has an obvious "inside" and "outside", but how the points are ordered would define if the "inside" is "positive" or "negative". In comparison, it would be more intuitive to use "positive" or "negative" for a polyline that has an overall trend in a single direction.

    Therefore, the polyline width can be grown on either the 'positive', 'negative', 'inside', or 'outside' side of the line or around the middle of the line with 'mid'. In addition, a number between 0 and 1 can be used where 0 is the same as 'positive', 1 the same as 'negative' and 0.5 the same as 'mid'.

    Each point, or line connection, creates a corner that will have an inside angle (<180º) and an outside angle (>180º or reflex angle).

    Growing width on an outside corner can be challenging. As the corner becomes sharper, the outside width joins at a point further and further from the ideal corner. Eventually trucating the corner makes more visual sense and therefore, a minimum angle (minAutoCornerAngle) is used to specify when the corner should be drawn, and when it should be truncated.

    By default, the border of the polyline is the line itself (border = 'line'). The border can also just be the points on the positive side of the line, or the negative side of the line. This is useful for capturing the hole shape of a closed polyline within a border. The border can also be the encompassing rectangle of the polyline (border = 'rect') or defined as a custom set of points.

    The touch border can either be the same as the border ('border'), the encompassing rect ('rect'), a custom set of points, or the same as the line but with some buffer that effectively increases the width on both sides of the line.

    • points: Array<TypeParsablePoint>
    • width: number | undefined = 0.01
    • close: boolean | undefined = false

      close the polyline on itself

    • simple: boolean | undefined = false

      simple and minimum computation polyline. Good for large numbers of points that need to be updated every animation frame. widthIs, dash, arrow and all corner and line primitive properties are not available when a polyline is simple.

    • widthIs: 'mid' | 'outside' | 'inside' | 'positive' | 'negative' | number | undefined = "mid"

      defines how the width is grown from the polyline's points. Only "mid" is fully compatible with all options in cornerStyle and dash.

    • drawBorder: 'line' | 'positive' | 'negative' | TypeParsableBorder | undefined = 'line'

      override OBJ_Generic drawBorder with 'line' to make the drawBorder just the line itself, 'positive' to make the drawBorder the positive side of the line, and 'negative' to make the drawBorder the negative side of the line. Use array definition for custom drawBorder

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer the same as the line with additional number thickness on either side

    • cornerStyle: 'auto' | 'none' | 'radius' | 'fill' | undefined = "auto"

      - "auto": sharp corners sharp when angle is less than minAutoCornerAngle, "none": no corners, "radius": curved corners, "fill": fills the gapes between the line ends

    • cornerSize: number | undefined = 0.01

      only used when cornerStyle = radius

    • cornerSides: number | undefined = 10

      number of sides in curve - only used when cornerStyle = radius

    • cornersOnly: boolean | undefined = false

      draw only the corners with size cornerSize

    • cornerLength: number | undefined = 0.1

      use only with cornersOnly = true - length of corner to draw

    • minAutoCornerAngle: number | undefined = π/7

      see cornerStyle = auto

    • dash: TypeDash | undefined

      leave empty for solid line - use array of numbers for dash line where first number is length of line, second number is length of gap and then the pattern repeats - can use more than one dash length and gap - e.g. [0.1, 0.01, 0.02, 0.01] produces a lines with a long dash, short gap, short dash, short gap and then repeats.

    • arrow: OBJ_LineArrows | TypeArrowHead | undefined

      either an object defining custom arrows or a string representing the name of an arrow head style can be used. If a string is used, then the line will have an arrow at both ends. Arrows are only available for close: false, widthIs: 'mid' and linePrimitives: false

    • linePrimitives: boolean | undefined = false

      Use WebGL line primitives instead of triangle primitives to draw the line

    • lineNum: number | undefined = 2

      Number of line primitives to use when linePrimitivs: true

    figure.add(
    {
    name: 'p',
    make: 'polyline',
    points: [[-0.5, -0.5], [-0.1, 0.5], [0.3, -0.2], [0.5, 0.5]],
    width: 0.05,
    },
    );
    figure.add(
    {
    name: 'p',
    make: 'polyline',
    points: [[-0.5, -0.5], [0.5, -0.5], [0.5, 0.5], [-0.5, 0.5]],
    width: 0.05,
    dash: [0.17, 0.05, 0.05, 0.05],
    close: true,
    cornerStyle: 'radius',
    cornerSize: 0.1,
    },
    );
    figure.add(
    {
    name: 'p',
    make: 'polyline',
    points: [[-0.5, -0.5], [0.5, -0.5], [0, 0.5]],
    width: 0.05,
    close: true,
    cornersOnly: true,
    cornerLength: 0.2,
    },
    );
    figure.add({
    name: 'arrowedLine',
    make: 'polyline',
    points: [[0, 0], [1, 0], [0, 0.7], [1, 0.7]],
    width: 0.05,
    cornerStyle: 'fill',
    arrow: {
    scale: 0.7,
    start: {
    head: 'triangle',
    reverse: true,
    },
    end: 'barb',
    },
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Polygon or partial polygon shape options object that extends OBJ_Generic (without drawType)

    • sides: number | undefined = 4
    • radius: number | undefined = 1
    • rotation: number | undefined = 0

      shape rotation during vertex definition (different to a rotation step in a trasform)

    • offset: TypeParsablePoint | undefined = [0, 0]

      shape center offset from origin during vertex definition (different to a translation step in a transform)

    • sidesToDraw: number | undefined = all sides

      number of sides to draw

    • angleToDraw: number | undefined = 2π

      same as sidesToDraw but using angle for the definition

    • direction: -1 | 1 | undefined = [0, 0]

      direction to draw polygon where 1 is counter clockwise and -1 is clockwise (1) center. This is different to position or transform as these translate the vertices on each draw.

    • line: OBJ_LineStyleSimple | undefined

      line style options

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override the OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer a polygon that is wider by number

    figure.add({
    name: 'hexagon',
    make: 'polygon',
    sides: 6,
    radius: 0.5,
    });
    const circ = figure.primitives.polygon({
    sides: 100,
    radius: 0.5,
    line: {
    width: 0.03,
    dash: [0.1, 0.03 ],
    },
    });
    figure.elements.add('circle', circ);
    figure.add({
    name: 'halfOctagon',
    make: 'polygon',
    sides: 8,
    radius: 0.5,
    angleToDraw: Math.PI,
    line: {
    width: 0.03,
    },
    direction: -1,
    rotation: Math.PI / 2,
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Star options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    • sides: number | undefined = 4
    • radius: number | undefined = 1
    • innerRadius: number | undefined = radius / 2
    • rotation: number | undefined = 0

      shape rotation during vertex definition (different to a rotation step in a trasform)

    • offset: TypeParsablePoint | undefined = [0, 0]

      shape center offset from origin during vertex definition (different to a translation step in a transform)

    • line: OBJ_LineStyleSimple | undefined

      line style options

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override the OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer a polygon that is number thicker than the radius

    figure.add({
    name: 's',
    make: 'star',
    radius: 0.5,
    sides: 5,
    });
    figure.add({
    name: 's',
    make: 'star',
    radius: 0.5,
    innerRadius: 0.3,
    sides: 7,
    line: {
    width: 0.02,
    dash: [0.05, 0.01],
    },
    });
    figure.add({
    name: 's',
    make: 'star',
    radius: 0.1,
    sides: 5,
    rotation: -Math.PI / 2,
    // line: { width: 0.01 },
    copy: [
    {
    to: [0.6, 0],
    original: false,
    },
    {
    along: 'rotation',
    num: 16,
    step: Math.PI * 2 / 16,
    start: 1,
    },
    {
    to: new Fig.Transform().scale(3, 3).rotate(Math.PI / 2),
    start: 0,
    end: 1,
    },
    ],
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Rectangle shape options object that extends OBJ_Generic (without `drawType) and OBJ_FigurePrimitive

    • width: number | undefined = 1
    • height: number | undefined = 1
    • yAlign: 'bottom' | 'middle' | 'top' | number | undefined = 'middle'
    • xAlign: 'left' | 'center' | 'right' | number | undefined = 'center'
    • corner: OBJ_CurvedCorner | undefined

      define for rounded corners

    • line: OBJ_LineStyleSimple | undefined

      line style options

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override the OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer a rectangle that is number wider and higher on each side

    • offset: TypeParsablePoint | undefined
    figure.add({
    name: 'r',
    make: 'rectangle',
    width: 1,
    height: 0.5,
    });
    figure.add({
    name: 'r',
    make: 'rectangle',
    width: 0.5,
    height: 0.5,
    line: {
    width: 0.02,
    dash: [0.05, 0.03]
    },
    corner: {
    radius: 0.1,
    sides: 10,
    },
    });
    figure.add({
    name: 'r',
    make: 'rectangle',
    width: 0.5,
    height: 0.5,
    line: {
    width: 0.01,
    },
    copy: {
    along: 'rotation',
    num: 3,
    step: Math.PI / 2 / 3
    },
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Ellipse shape options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    • width: number | undefined = 1
    • height: number | undefined = 1
    • yAlign: 'bottom' | 'middle' | 'top' | number | undefined = 'middle'
    • xAlign: 'left' | 'center' | 'right' | number | undefined = 'center'
    • sides: number | undefined = 20

      number of sides to draw ellipse with

    • line: OBJ_LineStyleSimple | undefined

      line style options

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override the OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer a ellipse that is number thicker around its border

    figure.add({
    name: 'e',
    make: 'ellipse',
    height: 1,
    width: 0.5,
    sides: 100,
    });
    figure.add({
    name: 'e',
    make: 'ellipse',
    height: 1,
    width: 1,
    sides: 100,
    line: {
    width: 0.02,
    dash: [0.05, 0.02],
    },
    });
    figure.add({
    name: 'e',
    make: 'ellipse',
    height: 0.08,
    width: 0.2,
    sides: 20,
    copy: [
    { along: 'x', step: 0.25, num: 5 },
    { along: 'y', step: 0.15, num: 5 },
    ]
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Arc shape options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    • radius: number | undefined
    • sides: number | undefined = 20
    • startAngle: number | undefined = 0
    • angle: number | undefined = 1
    • line: OBJ_LineStyleSimple | undefined

      line style options

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override the OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer a ellipse that is number thicker around its border

    figure.add({
    make: 'arc',
    angle: Math.PI * 2 / 3,
    radius: 1,
    });
    figure.add({
    make: 'arc',
    angle: Math.PI * 2 / 3,
    startAngle: Math.PI / 3,
    radius: 1,
    fillCenter: true,
    });
    figure.add({
    make: 'arc',
    angle: Math.PI / 3,
    radius: 1,
    line: { width: 0.05, widthIs: 'inside' },
    });
    figure.add({
    make: 'arc',
    angle: Math.PI * 3 / 2,
    radius: 1,
    sides: 100,
    line: { width: 0.05, dash: [0.3, 0.1, 0.1, 0.1] },
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Triangle shape options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    The most generic way to define a triangle is with three points (points property). When using points, all the other properties that can also define a triangle are ignored: width, height, top, SSS, ASA, AAS, SAS, direction, rotation, xAlign and yAlign.

    The other ways to define a triangle are (in order of highest override preference to lowest if more than one is defined in the object):

    • ASA or Angle-Side-Angle
    • SAS or Side-Angle-Side
    • AAS or Angle-Angle-Side
    • SSS or Side-Side-Side
    • width, height and top location

    All these methods also use direction to define the triangles, and rotation, xAlign and yAlign to position the triangles. Each corner and side of the triangle is indexed, and can be used for positioning.

    A triangle starts with an angle (a1) at (0, 0) and base side extending along the x axis to a second angle a2. The base side is side 1 (s1).

    Angles a1 and a2 extend the triangle above s1 if direction is 1, and below s1 when direction is -1.

    s2, a3, and s3 are then the consecutive sides and angles.

    Triangles can be defined with a combination of side length and angle using ASA, SAS, AAS and SSS, where the first side or angle is s1 or a1 respectively, and the subsequent sides and angles progress consecutively. For instance, ASA defines the angle a1, then side length s1, then angle a2. SSS defines the side lenghts s1, s2 then s3. All these combinations of three properties are sufficient to define a unique triangle completely.

    When defining the triangle with width, height and top, the base side s1 is the width, and the top point is either aligned with the left, center or right of the base at some height above s1.

    When defined, a triangle's a1 corner will be at (0, 0), and s1 will be along the x axis. Next, a rotation can be applied to the triangle. A rotation can either be a number rotating it relative to its definition, or relative to one of its sides: s1, s2 or s3.

    Finally, the triangle can be positioned (in draw space) using xAlign and yAlign. An xAlign of 'left' will position the triangle so that it's left most point will be at (0, 0). Similarly, a yAlign of 'top' will position the triangle so its top most point is at (0, 0). Triangles can also be aligned by angles (corners) and side mid points. For instance, an xAlign of 'a2', will position the a2 corner at x = 0. Similarly a yAlign of 's3' will position the triangle vertically such that the mid point of s3 is at y = 0. 'centroid' is relative to the geometric center of the triangle.

    Once a triangle is defined and positioned in draw space, it can then be copied (copy) if more than one triangle is desired.

    The triangle(s) can then be positioned (position) or transformed (transform) in the FigureElementPrimitive local space.

    Triangles can either be a solid fill, texture fill or outline. When line is not defined, the triangle will be filled.

    • points: Array<Point> | undefined

      defining points will take precedence over all other ways to define a triangle.

    • width: number | undefined
    • height: number | undefined
    • top: 'left' | 'right' | 'center' | undefined = center
    • SSS: [number, number, number] | undefined
    • ASA: [number, number, number] | undefined
    • AAS: [number, number, number] | undefined
    • SAS: [number, number, number] | undefined
    • direction: 1 | -1 | undefined
    • rotation: number | 's1' | 's2' | 's3' | OBJ_TriangleSideRotationAlignment | undefined
    • xAlign: 'left' | 'center' | 'right' | number | 'a1' | 'a2' | 'a3' | 's1' | 's2' | 's3' | 'centroid' | 'points' | undefined = 'centroid'
    • yAlign: 'bottom' | 'middle' | 'top' | number | 'a1' | 'a2' | 'a3' | 's1'| 's2' | 's3' | 'centroid' | 'points' | undefined = 'centroid'
    • line: OBJ_LineStyleSimple | undefined

      line style options - do not use any corner options

    figure.add({
    name: 't',
    make: 'triangle',
    width: 0.5,
    height: 1,
    top: 'right',
    });
    const t = figure.primitives.triangle({
    ASA: [Math.PI / 2, 1, Math.PI / 6],
    line: {
    width: 0.02,
    dash: [0.12, 0.04],
    },
    });
    figure.elements.add('t', t);
    figure.add({
    name: 'star',
    make: 'triangle',
    SSS: [1, 1, 1],
    xAlign: 'centroid',
    yAlign: 'centroid',
    copy: {
    along: 'rotation',
    num: 3,
    step: Math.PI / 6,
    },
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Line definition options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    A line can either be defined as two points p1 and p2, or a single point p1, a length and an angle.

    The line has some width that will be filled on both sides of the line points evenly ('mid'), or on one side only. The line's 'positive' side is the side to which it rotates toward when rotating in the positive angle direction around p1. Similarly the line's 'negative' side is the opposite.

    The line can be solid or dashed using the dash property.

    The line can have arrows at one or both ends using the arrow property.

    • p1: TypeParsablePoint | undefined

      start point of line

    • p2: TypeParsablePoint | undefined

      end point of line

    • length: number | undefined

      length of line from p1

    • angle: number | undefined

      angle of line from p1

    • width: number | undefined = 0.01
    • widthIs: 'mid' | 'positive' | 'negative' | number | undefined = "mid"

      defines how the width is grown from the polyline's points. Only "mid" is fully compatible with all options in arrow.

    • dash: TypeDash | undefined

      leave empty for solid line - use array of numbers for dash line where first number is length of line, second number is length of gap and then the pattern repeats - can use more than one dash length and gap - e.g. [0.1, 0.01, 0.02, 0.01] produces a lines with a long dash, short gap, short dash, short gap and then repeats.

    • arrow: OBJ_LineArrows | TypeArrowHead | undefined

      either an object defining custom arrows or a string representing the name of an arrow head style can be used. If a string is used, then the line will have an arrow at both ends. Arrows are only available for widthIs: 'mid' and linePrimitives: false

    • linePrimitives: boolean | undefined = false

      Use WebGL line primitives instead of triangle primitives to draw the line

    • lineNum: number | undefined = 2

      Number of line primitives to use when linePrimitivs: true

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer the same as the line with additional number thickness on each side and the ends

    figure.add({
    name: 'l',
    make: 'line',
    p1: [0, 0],
    p2: [0, 1],
    width: 0.02,
    });
    figure.add({
    name: 'l',
    make: 'line',
    p1: [0, 0],
    length: 1,
    angle: Math.PI / 2,
    width: 0.03,
    dash: [0.1, 0.02, 0.03, 0.02],
    });
    figure.add({
    name: 'l',
    make: 'line',
    p1: [0, 0],
    p2: [0, 1],
    width: 0.03,
    arrow: {
    start: 'rectangle',
    end: 'barb',
    },
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Grid shape options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    A grid is a rectangle divided into a series of vertical and horizontal lines.

    The rectangle is defined by bounds.

    xNum and yNum can be used to defined a number of equally spaced lines in the rectangle (including the edges).

    Alternatively xStep and yStep can be used to define the spacing between lines from the bottom left corner.

    The line width and style is defined with line.

    • bounds: TypeParsableRect | undefined

      rectangle definition

    • step: number | undefined

      distance between grid lines

    • xStep: number | undefined

      distance between vertical lines in grid from left - use this instead of xNum. This will override step.

    • yStep: number | undefined

      distance between horizontal lines in grid from bottom - use this instead of yNum. This will override step.

    • num: number | undefined

      number of grid lines. This will override step.

    • xNum: number | undefined

      number of vertical lines in grid including top and bottom lines - overrides num and xStep.

    • yNum: number | undefined

      number of horizontal lines in grid including left and right lines - overrides num and yStep.

    • line: OBJ_LineStyle | undefined

      line style options - do not use any corner options

    • drawBorderBuffer: number | TypeParsableBorder | undefined = 0

      override OBJ_Generic drawBorderBuffer with number to make the drawBorderBuffer the same as the grid outline with additional number buffer each side

    figure.add({
    name: 'g',
    make: 'grid',
    bounds: [-0.5, -0.5, 1, 1],
    xStep: 0.25,
    yStep: 0.25,
    line: {
    width: 0.03,
    },
    });
    const grid = figure.primitives.grid({
    bounds: [-0.5, -0.5, 1, 1],
    xNum: 4,
    yNum: 4,
    line: {
    width: 0.03,
    dash: [0.1, 0.02],
    },
    });
    figure.elements.add('g', grid);
    figure.add({
    name: 'g',
    make: 'grid',
    bounds: [-0.7, -0.7, 0.6, 0.6],
    xNum: 4,
    yNum: 4,
    line: {
    width: 0.03,
    },
    copy: [
    { along: 'x', num: 1, step: 0.8},
    { along: 'y', num: 1, step: 0.8},
    ],
    });

    To test examples, append them to the boilerplate


    Extends OBJ_Generic

    Arrow options object that extends OBJ_Generic (without drawType) and OBJ_FigurePrimitive

    An arrow has a head, tail, length and width. The head defines the head style of the arrow. The length, width (or radius for polygon and circle head styles) define the size of the arrow and tail defines wether it has a tail and how long it is.

    All properties have default values that can be scaled with the scale property. So a scale of 2 will double the size of the default arrow.

    An arrow can be aligned and oriented with align and angle. align positions the tip, start, tail or middle part of the arrow at (0, 0) in draw space. This part of the arrow will therefore be at the position or translation of the transform. angle then gives the arrow some drawn rotation.

    Alignment definitions are:

    • tip: arrow tip
    • start: opposite side of tip
    • mid: mid points between start and tip - useful for polygon, circle and bar arrows without tails when the head should be on a point, not next to it
    • tail: the end of the tail when a tail exists, or where a tail would start if it doesn't exist.

    Setting the tail property to false will draw only the arrow head, true will draw a tail of length 0, and a tail with a custom length can be defined with a number. A tail length of 0 will only extend a tail to the boundaries of the head. A positive tail, will extend it beyond the boundaries.

    For arrow heads that use length and width properties, the length is the dimension along the line. It includes both the head and the tail, so an arrow with length 1 and tailLength 0.4 will have a head length of 0.6.

    For polygon and circle arrows, only radius and tail are used to determine the dimension of the arrow (length and width are ignored).

    • head: TypeArrowHead | undefined = 'triangle'

      head style

    • scale: number | undefined

      scale the default dimensions of the arrow

    • length: number | undefined

      dimension of the arrow head along the line

    • width: number | undefined

      dimension of the arrow head along the line width

    • rotation: number | undefined

      rotation of the polygon when head = 'polygon'

    • sides: number | undefined

      number of sides in polygon or circle arrow head

    • radius: number | undefined

      radius of polygon or circle arrow head

    • barb: number | undefined

      barb length (along the length of the line) of the barb arrow head

    • tailWidth: number | undefined

      width of the line that joins the arrow - if defined this will create minimum dimensions for the arrow

    • tail: boolean | number | undefined

      true includes a tail in the arrow of with tailWidth. A number gives the tail a length where 0 will not extend the tail beyond the boundaries of the head

    • align: 'tip' | 'start' | 'mid' | 'tail' | undefined = 'tip'

      define which part of the arrow is aligned at (0, 0) in draw space

    • angle: number | undefined = 0

      angle the arrow is drawn at

    figure.add({
    name: 'a',
    make: 'arrow',
    head: 'triangle',
    tail: 0.15,
    length: 0.5,
    });
    figure.add({
    name: 'a',
    make: 'arrow',
    head: 'barb',
    angle: Math.PI / 2,
    tail: 0,
    });
    // transforms defining the position, rotation and scale of the arrows

    // Create transforms to apply to each arrow
    const r = Fig.range(0, Math.PI / 2, Math.PI / 18);
    const x = [0, 1, 2, 0, 1, 2, 0, 1, 2];
    const y = [0, 0, 0, 1, 1, 1, 2, 2, 2];
    const s = [0.5, 0.8, 0.4, 0.6, 0.8, 0.6, 0.5, 0.8, 0.6];
    const transforms = [];
    for (let i = 0; i < 9; i += 1) {
    transforms.push(new Fig.Transform().scale(s[i], s[i]).rotate(r[i]).translate(x[i], y[i]));
    }

    // Create arrow and copy to transforms
    figure.add({
    name: 'a',
    make: 'arrow',
    head: 'barb',
    align: 'mid',
    length: 0.7,
    copy: {
    to: transforms,
    original: false,
    },
    });