# Native components, tracks, and waves

These 23 additions are ordinary named TikZ nodes. They extend mechanics,
fluids, solids, and ramps and add the `tikzphysics.waves` library. Existing
path styles and apparatus pics remain available. All actual diagrams default
to black outlines and no fill. Colors are optional document-level TikZ overrides.

```tex
\usepackage{tikzphysics}
% Or load only the required module after loading TikZ:
% \usetikzlibrary{tikzphysics.waves}
```

Every style has a collision-safe `physics...node` alias, a matching
`every <style>` hook, `show anchors` / `show keys` support, and a
`\physicshelp{<style>}` reference card. Geometry keys have equivalent
`physics <key>` aliases. Bare lengths are centimetres; explicit units are
respected. Shape dimensions are explicit: `minimum width`, text size, and
`inner sep` do not resize these components. Place longer labels externally.

All documented percentage families accept **integer values 0 through 100**.
There is no bare numeric percentage shorthand on the new components.
Rotation, reflection, and scaling transform the anchors with the object.
State is saved per node; later key changes do not move earlier anchors.
Physical attachment anchors ignore text and outer separation. Automatic
border intersections use a bounding rectangle; use physical anchors for
precise contacts. Guide normals remain perpendicular after rotation or
uniform scaling, but not generally after nonuniform scaling.

See [the shape gallery](native-components.pdf) and
[the composition gallery](native-component-scenes.pdf). Their editable
sources are in `examples/native-components.tex` and
`examples/native-component-scenes.tex`.

## Mechanics: connections and rigid bodies

`beam` is a finite-thickness rectangular rod. `rod node` is its convenience
alias; the existing `\draw[rod] ...` path is unchanged. Beam `axis` runs left
to right. `physical pendulum` represents a uniform bar; `axis` runs top to
bottom, `mass-center` is the geometric centre, and the pivot fraction is
measured down from the top. It does not calculate moment of inertia.

```tex
\node[beam,beam length=4] (B) {};
\node[damper,anchor=start,damper position=.7] (D) at (B.end) {};
\node[physical pendulum,anchor=pivot,rotate=25,
      physical pendulum length=2] (P) at (B.start) {};
```

The damper is a schematic dashpot with a movable piston inside an open
housing. Position must be strictly between 0 and 1; it controls the visual
stroke, not force or damping. Its piston family runs bottom to top.

`compound pulley` means **two concentric drums on one axle**, often used
in wheel-and-axle problems. Inner radius must be positive and smaller than
the outer radius. It is not a fixed/moving block-and-tackle assembly.
Use `rim-*` and `inner-rim-*` for chosen attachment points. The existing
`over pulley` automatic tangent routing applies to ordinary circular pulley
nodes, not this compound node. Both rim families start at the right and
run counterclockwise. No rope route or mechanical advantage is inferred.

## Fluids: reusable apparatus components

`piston cylinder` has an open top, a lower piston contact face, and a rod.
Piston position must be between .1 and .9 of the cylinder height from the
bottom. `piston-*` runs left to right along the lower contact face;
`rod-end` is the upper end of the rod. `top-*` spans the open mouth.

`capillary tube` has independently set height, width, liquid level, and
meniscus sag. Positive sag produces a concave surface; negative sag produces
a convex one. Level is measured from the bottom. The sag magnitude must be
less than both the level and headroom distances, so the entire meniscus
stays inside the tube. Sag may be zero. The model does not compute capillary
rise or contact angle from material properties.

`nozzle` narrows smoothly from inlet to outlet. `venturi` narrows to the
midpoint throat and then widens symmetrically. A cosine profile gives smooth
wall slopes. The throat diameter must be positive and no larger than the
inlet diameter. Wall percentages use axial position, not arc length; both
`top-*` and `bottom-*` run inlet to outlet. Cross-section families run
bottom to top. Flow speed and pressure are supplied by the author.

`layered tank` shows two liquid layers without color. The interface fraction
must lie strictly below the surface fraction, both between 0 and 1.
`interface-*` and `surface-*` run left to right. `lower-center` and
`upper-center` are label positions in the respective liquid regions.

```tex
\node[layered tank,layered tank interface=.3,
      layered tank level=.8] (T) {};
\node at (T.lower-center) {$\rho_1$};
\node at (T.upper-center) {$\rho_2$};
\node[capillary tube,capillary sag=-.1] (C) at (4,0) {};
\node[venturi,venturi throat diameter=.35,rotate=15] (V) at (8,0) {};
```

## Solids: projected wireframes

`solid cylinder`, `solid cone`, `solid frustum`, `hemisphere`,
`cylindrical shell`, and `conical shell` are native node forms for
composition. They complement the existing differential-element diagram pics.

The projection is schematic: circular horizontal rims become ellipses with
a configurable depth ratio between 0 and 1. Both halves of each rim are
visible wireframe lines. It is not a 3D renderer and does not infer occlusion.
Keep `fill=none` for the wireframe representation. Rims are parameterized by
ellipse angle from the rightmost point, counterclockwise. The `axis` runs
bottom to top; `generator` follows the right silhouette from base to top.
On a cone the top rim collapses to its apex.

Frustum top ratio is strictly between 0 and 1. Shell thickness is radial at
the base, strictly between zero and the base radius. A `conical shell` is a
hollow frustum; its inner and outer top radii scale by the same top ratio,
so radial thickness scales toward the top. It is not constant normal-wall
thickness. `hemisphere` has its centre at the base centre; its `meridian`
runs left to right over the dome, and `axis` ends at the apex.

```tex
\node[solid frustum,solid frustum top ratio=.4,
      solid frustum height=3] (F) {};
\draw[->] (F.axis-50) -- (F.generator-50);
\node[cylindrical shell,cylindrical shell thickness=.15] (S) at (4,0) {};
```

## Tracks: distance, tangents, and rough regions

`track` has a horizontal entry, straight incline, and horizontal exit. Each
section occupies one third of the horizontal length. Rise may be zero.
The `surface-*` family advances by **total path distance**, not horizontal
position. At a sharp join the tangent belongs to the outgoing segment.
Use `start` and `end` to join separate nodes exactly:

```tex
\node[track,track rough start=20,track rough end=80] (T) {};
\node[track,track length=3,track rise=0,anchor=start] (U) at (T.end) {};
\draw[->] (T.surface-50) -- (T.normal-50);
```

`circular bowl` follows the lower semicircle, from left to right.
`loop track` starts at the bottom and runs counterclockwise around a full
circle; start and end coincide. Circle percentages are arc-length fractions.
All three provide `tangent-before-*`, `tangent-after-*`, and `normal-*`.
These are **points 0.2 cm from contact**, not vectors or angle values.
Normals point to the left of travel: into the circular track for bowl/loop.

Each track's `rough start` and `rough end` keys use percentages from 0 to 100.
Equal values produce a smooth track. An ordered nonzero interval produces
short hatches spaced by at most five percentage points, including both
ends of the interval. Hatching is a visual designation; it does not set a
coefficient of friction. Use the explicit
shape prefix, for example `loop track rough start=25`.

## Waves and pipe modes

`transverse wave` uses a sinusoidal displacement snapshot. `wave length`
is the total drawn length, and `wave cycles` is the number of full cycles
in that span, not the wavelength. `wave phase` is in degrees. Amplitude and
length must be positive; cycles must lie in (0,100].

`standing wave` is a fixed-end pattern. `standing wave lobes` is an integer
from 1 to 100, giving that many half-wavelength loops. Its indexed anchors
`node-0` through `node-lobes` and `antinode-0` through `antinode-(lobes-1)`
lie on the axis. They locate nodes and antinode positions, not the actual
displacement peaks. `curve-*` follows the displacement snapshot.

`longitudinal wave` is a schematic spring with varying turn spacing.
`wave coils` is an integer from 1 to 100; cycles must also be integer.
`wave compression` lies in [0,1), which keeps the longitudinal coordinate
monotone. `wave amplitude` sets the transverse coil size. Curve percentages
follow the spring parameter; axis percentages follow uniform axial distance.

`open pipe` is open at both ends. `closed pipe` is closed at its left end.
The drawn curve is **displacement**, not pressure: open ends are antinodes
and closed ends are nodes. `pipe mode` is an integer from 1 to 50. Open pipe
mode m gives harmonic m; closed pipe mode m gives harmonic 2m-1.

| Pattern | Valid node indices | Valid antinode indices |
|---|---|---|
| Standing wave with n lobes | 0..n | 0..n-1 |
| Open pipe, mode m | 0..m-1 | 0..m |
| Closed pipe, mode m | 0..m-1 | 0..m-1 |

These indexed anchors are **not percentage families**. Invalid indices
raise a package error. Pipe displacement amplitude is 35% of the pipe width.
Uniform percentage families are `axis-*`, `curve-*`, `top-*`, and `bottom-*`.
Pipe walls run left to right. No frequency, propagation speed, or time
integration is calculated.

```tex
\node[closed pipe,pipe mode=2,pipe length=6] (P) {};
\foreach \i in {0,1}{
  \fill (P.node-\i) circle (2pt);
  \draw (P.antinode-\i) circle (2pt);
}
```

## Debugging and reproducible installation

```tex
\node[beam,show anchors,show keys,
      physics debug/anchor families={axis,top,bottom},
      physics debug/anchor samples={0,25,50,75,100}] (B) {};
```

Use one debug object per picture when displaying full reference cards.
The package's debug colors are diagnostic overlays, separate from the
black-and-white physical drawing defaults. To inspect a few anchors without
any overlay styling, draw black dots at the requested family coordinates.

The generated `output/overleaf/tikzphysics.sty` includes the waves library
and all component definitions. Upload it beside the project's main file.
The upload ZIP also contains the editable galleries and this guide.
Published CTAN/TeX Live copies are updated independently.

Developer checks:

```sh
python3 scripts/generate_reference.py --check
python3 scripts/build_overleaf_bundle.py --check
l3build check
python3 scripts/verify_components.py
```

## Complete new-style parameter reference

The following defaults are the package defaults, not live values from a node.

### beam

Collision-safe style: `physicsbeamnode`.

| Key | Default |
|---|---|
| `beam length` | `3cm` |
| `beam thickness` | `.25cm` |

Percentage families: `bottom-0..100`, `right-0..100`, `top-0..100`, `left-0..100`, `axis-0..100`.

axis runs left to right; boundary families run counterclockwise. rod node preserves the existing rod path style.

### damper

Collision-safe style: `physicsdampernode`.

| Key | Default |
|---|---|
| `damper length` | `3cm` |
| `damper width` | `.7cm` |
| `damper position` | `.5` |

Percentage families: `axis-0..100`, `piston-0..100`, `top-0..100`, `bottom-0..100`.

piston runs bottom to top; position is a visual stroke fraction, not a force law.

### compound pulley

Collision-safe style: `physicscompoundpulleynode`.

| Key | Default |
|---|---|
| `compound pulley radius` | `1cm` |
| `compound pulley inner radius` | `.55cm` |

Percentage families: `rim-0..100`, `inner-rim-0..100`.

Two concentric drums share one axle. Both rims start at the rightmost point and run counterclockwise. This is a stepped pulley, not an automatically routed tackle.

### physical pendulum

Collision-safe style: `physicsphysicalpendulumnode`.

| Key | Default |
|---|---|
| `physical pendulum length` | `3cm` |
| `physical pendulum width` | `.45cm` |
| `physical pendulum pivot` | `.1` |

Percentage families: `bottom-0..100`, `right-0..100`, `top-0..100`, `left-0..100`, `axis-0..100`.

Uniform rigid bar. axis runs top to bottom; pivot is a fraction from the top. Use anchor=pivot and rotate to suspend it.

### piston cylinder

Collision-safe style: `physicspistoncylindernode`.

| Key | Default |
|---|---|
| `piston cylinder width` | `1.8cm` |
| `piston cylinder height` | `3cm` |
| `piston position` | `.65` |

Percentage families: `bottom-0..100`, `right-0..100`, `top-0..100`, `left-0..100`, `piston-0..100`, `axis-0..100`, `wall-left-0..100`, `wall-right-0..100`.

Piston family is the lower gas-contact face, left to right; position is measured from the bottom. Cylinder top is open.

### capillary tube

Collision-safe style: `physicscapillarytubenode`.

| Key | Default |
|---|---|
| `capillary width` | `.5cm` |
| `capillary height` | `3cm` |
| `capillary level` | `.6` |
| `capillary sag` | `.12cm` |

Percentage families: `surface-0..100`, `wall-left-0..100`, `wall-right-0..100`, `axis-0..100`.

surface runs left to right by horizontal position. Positive sag gives a concave meniscus; negative sag a convex meniscus. Heights are illustrative, not computed from surface tension.

### nozzle

Collision-safe style: `physicsnozzlenode`.

| Key | Default |
|---|---|
| `nozzle length` | `4cm` |
| `nozzle diameter` | `1.4cm` |
| `nozzle throat diameter` | `.55cm` |

Percentage families: `axis-0..100`, `top-0..100`, `bottom-0..100`, `inlet-0..100`, `outlet-0..100`, `throat-0..100`.

Wall families run inlet to outlet by axial position. Cross-sections run bottom to top. Cosine profiles join smoothly; flow is not solved.

### venturi

Collision-safe style: `physicsventurinode`.

| Key | Default |
|---|---|
| `venturi length` | `4cm` |
| `venturi diameter` | `1.4cm` |
| `venturi throat diameter` | `.55cm` |

Percentage families: `axis-0..100`, `top-0..100`, `bottom-0..100`, `inlet-0..100`, `outlet-0..100`, `throat-0..100`.

Wall families run inlet to outlet by axial position. Cross-sections run bottom to top. Cosine profiles join smoothly; flow is not solved.

### layered tank

Collision-safe style: `physicslayeredtanknode`.

| Key | Default |
|---|---|
| `layered tank width` | `3cm` |
| `layered tank height` | `2.5cm` |
| `layered tank interface` | `.35` |
| `layered tank level` | `.75` |

Percentage families: `bottom-0..100`, `right-0..100`, `top-0..100`, `left-0..100`, `interface-0..100`, `surface-0..100`.

Two liquid layers; interface and surface run left to right. Separate centre anchors support density labels without color.

### solid cylinder

Collision-safe style: `physicssolidcylindernode`.

| Key | Default |
|---|---|
| `solid cylinder radius` | `1cm` |
| `solid cylinder height` | `2.5cm` |
| `solid cylinder depth` | `.25` |

Percentage families: `axis-0..100`, `bottom-rim-0..100`, `top-rim-0..100`, `generator-0..100`.

Projected wireframe: rims start at the right and run counterclockwise; axis and right generator run bottom to top. Depth is ellipse compression, not a 3D camera.

### solid cone

Collision-safe style: `physicssolidconenode`.

| Key | Default |
|---|---|
| `solid cone radius` | `1cm` |
| `solid cone height` | `2.5cm` |
| `solid cone depth` | `.25` |

Percentage families: `axis-0..100`, `bottom-rim-0..100`, `top-rim-0..100`, `generator-0..100`.

Projected wireframe: rims start at the right and run counterclockwise; axis and right generator run bottom to top. Depth is ellipse compression, not a 3D camera.

### solid frustum

Collision-safe style: `physicssolidfrustumnode`.

| Key | Default |
|---|---|
| `solid frustum radius` | `1cm` |
| `solid frustum height` | `2.5cm` |
| `solid frustum depth` | `.25` |
| `solid frustum top ratio` | `.5` |

Percentage families: `axis-0..100`, `bottom-rim-0..100`, `top-rim-0..100`, `generator-0..100`.

Projected wireframe: rims start at the right and run counterclockwise; axis and right generator run bottom to top. Depth is ellipse compression, not a 3D camera.

### cylindrical shell

Collision-safe style: `physicscylindricalshellnode`.

| Key | Default |
|---|---|
| `cylindrical shell radius` | `1cm` |
| `cylindrical shell height` | `2.5cm` |
| `cylindrical shell depth` | `.25` |
| `cylindrical shell thickness` | `.2cm` |

Percentage families: `axis-0..100`, `bottom-rim-0..100`, `top-rim-0..100`, `generator-0..100`, `inner-bottom-rim-0..100`, `inner-top-rim-0..100`.

Projected wireframe: rims start at the right and run counterclockwise; axis and right generator run bottom to top. Depth is ellipse compression, not a 3D camera.

### conical shell

Collision-safe style: `physicsconicalshellnode`.

| Key | Default |
|---|---|
| `conical shell radius` | `1cm` |
| `conical shell height` | `2.5cm` |
| `conical shell depth` | `.25` |
| `conical shell top ratio` | `.5` |
| `conical shell thickness` | `.2cm` |

Percentage families: `axis-0..100`, `bottom-rim-0..100`, `top-rim-0..100`, `generator-0..100`, `inner-bottom-rim-0..100`, `inner-top-rim-0..100`.

Projected wireframe: rims start at the right and run counterclockwise; axis and right generator run bottom to top. Depth is ellipse compression, not a 3D camera. Conical shell is a hollow frustum; thickness is radial at the base and scales with top ratio.

### hemisphere

Collision-safe style: `physicshemispherenode`.

| Key | Default |
|---|---|
| `hemisphere radius` | `1.2cm` |
| `hemisphere depth` | `.25` |

Percentage families: `rim-0..100`, `meridian-0..100`, `axis-0..100`.

Upper hemisphere in wireframe projection; meridian runs left to right over the dome, rim counterclockwise, axis from base centre to apex.

### track

Collision-safe style: `physicstracknode`.

| Key | Default |
|---|---|
| `track length` | `4cm` |
| `track rise` | `1cm` |
| `track rough start` | `0` |
| `track rough end` | `0` |

Percentage families: `surface-0..100`, `tangent-before-0..100`, `tangent-after-0..100`, `normal-0..100`.

surface is distance along the three joined straight segments, left to right. At joints tangent uses the outgoing section. Connect another node with anchor=start at the preceding end. Tangent and inward/left-normal guide points are 0.2 cm from contact. Optional rough interval is a percentage range marked with hatching.

### circular bowl

Collision-safe style: `physicscircularbowlnode`.

| Key | Default |
|---|---|
| `circular bowl radius` | `1.4cm` |
| `circular bowl rough start` | `0` |
| `circular bowl rough end` | `0` |

Percentage families: `surface-0..100`, `tangent-before-0..100`, `tangent-after-0..100`, `normal-0..100`.

surface follows the lower semicircle left to right. Tangent and inward/left-normal guide points are 0.2 cm from contact. Optional rough interval is a percentage range marked with hatching.

### loop track

Collision-safe style: `physicslooptracknode`.

| Key | Default |
|---|---|
| `loop track radius` | `1.4cm` |
| `loop track rough start` | `0` |
| `loop track rough end` | `0` |

Percentage families: `surface-0..100`, `tangent-before-0..100`, `tangent-after-0..100`, `normal-0..100`.

surface starts at the bottom and runs counterclockwise around the full loop. Tangent and inward/left-normal guide points are 0.2 cm from contact. Optional rough interval is a percentage range marked with hatching.

### transverse wave

Collision-safe style: `physicstransversewavenode`.

| Key | Default |
|---|---|
| `wave length` | `4cm` |
| `wave amplitude` | `.4cm` |
| `wave cycles` | `2` |
| `wave phase` | `0` |

Percentage families: `axis-0..100`, `curve-0..100`.

Axis runs left to right; curve is a snapshot, not a time simulation.

### standing wave

Collision-safe style: `physicsstandingwavenode`.

| Key | Default |
|---|---|
| `wave length` | `4cm` |
| `wave amplitude` | `.4cm` |
| `standing wave lobes` | `3` |

Percentage families: `axis-0..100`, `curve-0..100`.

Axis runs left to right; curve is a snapshot, not a time simulation. Fixed endpoints. lobes controls half-wavelengths; node-N indexes 0..lobes and antinode-N indexes 0..lobes-1 on the axis.

### longitudinal wave

Collision-safe style: `physicslongitudinalwavenode`.

| Key | Default |
|---|---|
| `wave length` | `4cm` |
| `wave amplitude` | `.4cm` |
| `wave cycles` | `2` |
| `wave coils` | `16` |
| `wave compression` | `.65` |

Percentage families: `axis-0..100`, `curve-0..100`.

Axis runs left to right; curve is a snapshot, not a time simulation. curve follows a schematic variable-spacing spring; compression below 1 prevents reversal of the longitudinal coordinate.

### open pipe

Collision-safe style: `physicsopenpipenode`.

| Key | Default |
|---|---|
| `pipe length` | `4cm` |
| `pipe width` | `.8cm` |
| `pipe mode` | `1` |

Percentage families: `axis-0..100`, `curve-0..100`, `top-0..100`, `bottom-0..100`.

Displacement pattern: open ends are antinodes, the closed left end is a node. mode selects harmonics; closed-pipe harmonics are odd. node-N and antinode-N are zero-based ordinal locations on the axis, not percentages.

### closed pipe

Collision-safe style: `physicsclosedpipenode`.

| Key | Default |
|---|---|
| `pipe length` | `4cm` |
| `pipe width` | `.8cm` |
| `pipe mode` | `1` |

Percentage families: `axis-0..100`, `curve-0..100`, `top-0..100`, `bottom-0..100`.

Displacement pattern: open ends are antinodes, the closed left end is a node. mode selects harmonics; closed-pipe harmonics are odd. node-N and antinode-N are zero-based ordinal locations on the axis, not percentages.

