Linear Elements
Vector paths, line heads, element binding, and step-by-step programmatic construction of straight, curved, and networked linear paths.
Overview
In .duc, a Linear Element (DucLinearElement with type: "line", or DucArrowElement with type: "arrow") represents vector paths.
Unlike conventional graphics formats that restrict paths to simple 2-point segments or raw SVG command strings (d="M... L... C..."), .duc structures linear geometry using relational data arrays. This allows a single element to represent straight lines, polylines, smooth Bezier curves, and complex networks of interconnected line webs.
Line Heads (DucHead)
Linear elements support visual head attachments at their start (startBinding.head) and end (endBinding.head) endpoints.
- Standard Enum Heads: Built-in geometric indicators.
- Custom Block Heads (
blockId): References a master Block definition ID to render custom architectural or engineering symbols as line heads. - Size Scaling (
size): Proportional scaling factor for the head marker.
Line Head Reference Table
| Enum Name | Value | Visual Description |
|---|---|---|
ARROW | 10 | Solid filled directional arrow |
BAR | 11 | Perpendicular T-bar cap |
CIRCLE | 12 | Solid filled circle dot |
CIRCLE_OUTLINED | 13 | Outlined hollow circle |
TRIANGLE | 14 | Solid filled equilateral triangle |
TRIANGLE_OUTLINED | 15 | Outlined hollow triangle |
DIAMOND | 16 | Solid filled rhombus |
DIAMOND_OUTLINED | 17 | Outlined hollow rhombus |
CROSS | 18 | Perpendicular cross mark |
OPEN_ARROW | 19 | Unfilled V-shaped open arrow |
REVERSED_ARROW | 20 | Inverted directional arrow pointing backward |
REVERSED_TRIANGLE | 21 | Solid inverted triangle |
REVERSED_TRIANGLE_OUTLINED | 22 | Outlined inverted triangle |
CONE | 23 | Solid narrow cone head |
HALF_CONE | 24 | Asymmetric half-cone head |
Element Binding
Linear elements can bind their endpoints (startBinding and endBinding) to target canvas elements (DucBindableElement).
- Target Association (
elementId): Binds the endpoint to a target element ID. - Border Focus (
focus): Defines a fractional offset (-1to1) along the target element’s border where the line attaches. - Clearance Gap (
gap): Maintains a defined distance between the line head and the target element boundary. - Fixed Position (
fixedPoint): Defines normalized internal coordinates[x, y](0.0to1.0) inside the target element. When set, it overridesfocusto pin the endpoint to a fixed location. - Linear Point Binding (
point): Binds the endpoint to a specific vertexindexand segmentoffsetof another linear element. - Dynamic Updates: When a target element moves, rotates, or scales, bound linear elements re-evaluate endpoint positions and update their geometry automatically.
How Linear Path Geometry is Constructed
Path geometry in .duc is composed of two relational arrays:
points: DucPoint[]: Array of discrete spatial vertices[Point 0, Point 1, Point 2, ...].lines: DucLine[]: Array of line segment connections referencing point indices[startReference, endReference].
Here is how different linear path geometries are constructed step-by-step:
Step 1: Constructing a Straight Line Segment
To construct a straight line segment between two vertices, define two points in points and connect their indices in lines with handle: null on both ends.
Step 2: Constructing Curved Bezier Paths (Single-Handle & Dual-Handle)
In .duc, Bezier control handles on a line segment are independent per endpoint. A line segment does not require handles on both ends.
Control handles define path curvature:
start.handle(handleOut): Outgoing control handle extending from the start point toward the end point.end.handle(handleIn): Incoming control handle extending into the end point from the start point.
A. Single-Handle Bezier Segments (handle: null on one end)
A segment can have handle: null on one end and a populated control handle on the other:
start.handle = nullandend.handle = { x, y }: The line leaves Point 0 cleanly without an outgoing handle, but curves into Point 1 via an incoming control handle (handleIn).start.handle = { x, y }andend.handle = null: The line leaves Point 1 via an outgoing control handle (handleOut), but enters Point 2 cleanly as a sharp connection without an incoming handle.
B. Complete Curved Path Example with Mixed Handles
Here is a 4-point closed path demonstrating mixed single-handle and dual-handle Bezier segments:
Bezier Mirroring Modes (mirroring)
When a point connects two curved segments, mirroring controls handle symmetry during edits:
NONE(10): Handles move independently, creating sharp corners or asymmetrical curves.ANGLE(11): Handles mirror rotation angle, while handle lengths vary independently.ANGLE_LENGTH(12): Handles mirror both rotation angle and length symmetrically, producing smooth continuous curves.
Step 3: Constructing a Polyline or Closed Shape
Multiple line segments can be chained together across sequential point indices to construct a polyline or closed loop:
Step 4: Constructing a Complex Web or Network
Unlike SVG paths that must follow a single continuous sequence of points, .duc allows multiple lines in the lines array to reference the exact same point index.
This enables a single Linear Element to represent a T-junction, star network, or interconnected web of lines:
Additional Path Properties
pathOverrides(DucPath[]): Overrides background and stroke properties for specific sub-paths within a line network.wipeoutBelow: Boolean flag onDucLinearElementthat masks out underlying canvas content beneath the stroke path.
Last updated on
Overview
An element is a fundamental spatial building blocks of .duc, base properties (_DucElementBase), and full catalog of geometric, document, model, and layout elements.
Model Elements
Parametric CAD models, procedural Python scripting, external file references, and 3D viewer state data structures in .duc.