# Pin Profile SVG – Requirements and Construction Rules

This document captures the exact requirements for the pin profile 2D vector web page, including full rebuild capabilities and the path geometry.

---

## 1. Web Page – Full Rebuild Capabilities

### 1.1 Page Structure

- **Title:** "Pin profile (2D vector)" or "Pin profile – 2D vector"
- **Layout:** Flex container, two main panels side by side (wrapping on small screens)
- **Theme:** Dark background (#1a1a1a), light text (#e0e0e0), panels with border (#333)

### 1.2 Dimensions Panel (Left)

All input fields, each with label and number input. Default values and validation constraints:

| ID | Label | Default | Step | Min | Notes |
|----|-------|---------|------|-----|------|
| overallLength | Overall length | 31 | 0.01 | 0.01 | |
| mainBodyDia | Main body diameter | 6 | 0.01 | 0.01 | |
| leftFillet | Left chamfer (0.50) | 0.5 | 0.01 | 0 | |
| rightSectionLen | Right section length | 6 | 0.01 | 0.01 | |
| interCylLen | Intermediate cylinder length | 5.76 | 0.01 | 0 | |
| interCylDia | Intermediate cylinder diameter (5.51) | 5.51 | 0.01 | 0.01 | |
| taperEndDia | Diameter at taper end | 3.53 | 0.01 | 0.01 | |
| tipLength | Final tip length | 0.13 | 0.01 | 0 | |
| tipDia | Final tip diameter (3.53) | 3.53 | 0.01 | 0.01 | |
| endRadius | End radius (R 12) | 12 | 0.01 | 0.01 | |
| transitionFillet | Transition fillet (R 0.30) | 0.3 | 0.01 | 0 | |

### 1.3 Default Values (DEFAULTS)

A `DEFAULTS` object holds all dimension defaults. Reset uses these values; any rebuild must use the same structure.

### 1.4 Actions

- **Update** button – triggers redraw (primary style)
- **Reset to defaults** – restores all inputs to DEFAULTS and redraws (secondary style)

### 1.5 Error Display

- Element `#errorMsg` below actions
- Shows validation errors (e.g. "All lengths, diameters and radii must be positive.")
- `aria-live="polite"` for accessibility
- Hidden when empty

### 1.6 Profile Display (Right Panel)

- **SVG container** (`#svgWrap`): fixed height (e.g. 280px), overflow hidden, dark background (#0d0d0d)
- **SVG** (`#profileSvg`): `preserveAspectRatio="xMidYMid meet"`, `shape-rendering="geometricPrecision"`
- **Path** (`#profilePath`): fill rgba(0,204,102,0.35), stroke #00cc66, stroke-linejoin/linecap round
- **ViewBox:** Computed dynamically by `updateViewBox(v)` to fit the profile with margin (e.g. margin = max(1, profileH * 0.2); minX = -margin; minY = -profileH/2 - margin; vbW = L + 2*margin; vbH = profileH + 2*margin)

### 1.7 Path Route List

- **Element:** `#routeList` – ordered list
- **Content:** Each path segment as a list item (e.g. "M (0, 0)", "L (0, 2.5000) left edge", …)
- **Source:** Populated from `lastPathRoute` array after each `buildPath()` call
- **Style:** Monospace, small font, scrollable if long

### 1.8 Validation Rules

- All lengths, diameters, radii > 0 (except leftFillet, interCylLen, tipLength, transitionFillet which can be 0)
- overallLength > rightSectionLen
- leftFillet < mainBodyDia/2 (chamfer smaller than body radius)
- interCylLen ≤ rightSectionLen
- tipLength ≤ rightSectionLen − interCylLen (tip fits within taper section)
- Lengths and fillets cannot be negative

### 1.9 Redraw Behavior

- **On load:** Call `redraw()` once
- **On Update click:** Call `redraw()`
- **On Reset click:** Restore DEFAULTS to all inputs, then `redraw()`
- **On input change:** Call `redraw()` (optional: for live update as user types)

### 1.10 Redraw Logic

1. `getValues()` – read all inputs as numbers
2. `validate(v)` – return error string or null
3. If error: show in `#errorMsg`, return
4. If valid: clear error, call `buildPath(v)`, set `profilePath.setAttribute('d', d)`, call `updateViewBox(v)`, populate `routeList` from `lastPathRoute`
5. On exception: show "Could not build shape: …" in error area

### 1.11 Debug Mode

- If URL contains `?debug`, show debug info (e.g. container dimensions)
- Debug info element inside `#svgWrap`, normally hidden
- Add `.debug` class to `#svgWrap` when debug is on

---

## 2. Path Route (Exact Segment Sequence)

The SVG path must be built in this order. The "Path route" list and the `d` attribute must match.

| # | Command | To point | Label |
|---|---------|----------|-------|
| 1 | M | (0, 0) | (start) |
| 2 | L | (0, Rbody − Rleft) | left edge |
| 3 | L | (Rleft, Rbody) | chamfer |
| 4 | L | (rightStart, Rbody) | top |
| 5 | A R0.3 | (T_topX, T_topY) | shoulder fillet |
| 6 | L | (tipEndX, Rtaper) | top taper |
| 7 | A Rbig | (tipEndX, −Rtaper) | end arc |
| 8 | L | (T_botX, T_botY) | bottom taper |
| 9 | A R0.3 | (rightStart, −Rbody) | shoulder fillet |
| 10 | L | (Rleft, −Rbody) | bottom |
| 11 | L | (0, −Rbody + Rleft) | chamfer |
| 12 | L | (0, 0) | left edge close |

Then close with **Z**.

**Symbols:** `rightStart = L − rightSectionLen`, `Rbody = mainBodyDia/2`, `Rleft = left chamfer`, `Rtaper = taperEndDia/2`, `tipEndX = L − tipLength`, `Rbig = endRadius`.

**When no left chamfer:** Omit segment 3; segment 2 goes to (0, Rbody); segment 10 to (0, −Rbody); segment 11 to (0, 0).

---

## 3. Shoulder Fillet (R0.3) – Construction Rule

The shoulder fillet is **not** tangent to the body. The joint to the body is **just its endpoint**.

- **Arc starts at:** body corner `(rightStart, Rbody)` or `(rightStart, −Rbody)` – endpoint only, no tangency requirement.
- **Arc radius:** 0.3 (fixed).
- **Arc is tangent only to the taper** – it ends at the point where the circle is tangent to the taper line (foot of perpendicular from circle centre to taper).

### Geometry

- **Centres:** Two candidates: `C = (rightStart, Rbody) ± 0.3·n` (top) or `(rightStart, −Rbody) ± 0.3·n_bot` (bottom), where `n` / `n_bot` is unit normal to the taper.
- **Tangent point:** For each centre, the foot of the perpendicular from the centre to the taper line. Only use centres whose foot lies on the taper segment.
- **Centre choice:** When both centres are valid, prefer the tangent point **further from the body** (closer to the tip).
- **Degenerate case:** If the taper passes through the body corner, the foot can equal the body corner (zero-length arc). In that case, **fallback** to the “tangent to both body and taper” construction (centre on offset from body and taper; two centres; pick by `t` on taper segment).

### Arc Flags (SVG A Command)

From the chosen centre, compute the angles to the arc start and end points. Set `large-arc-flag` and `sweep-flag` so the SVG draws the **short arc** on **that** circle (the correct centre and direction). This avoids SVG picking the wrong circle.

---

## 4. Taper Lines (Top vs Bottom)

### Top Taper

- From `(rightStart, Rbody)` to `(tipEndX, Rtaper)`.
- Vector: `V = (rightStart − tipEndX, Rbody − Rtaper)`.
- Parameterized from tip: `(tipEndX, Rtaper) + u·(tX, tY)` with `u` in `[0, Vlen]` (or `[0, 1]` when normalized).
- Unit tangent: `t = V/Vlen`; unit normal: `n = (−tY, tX)`.

### Bottom Taper

- From `(rightStart, −Rbody)` to `(tipEndX, −Rtaper)`.
- Direction from body to tip: **(−Vx, Vy)** (not (−Vx, −Vy)).
- Parameterized from body: `(rightStart, −Rbody) + s·(−Vx, Vy)` with `s` in `[0, 1]`.
- Foot from centre `(Cx, Cy)` to this line:
  - `s = ((rightStart − Cx)·Vx + (Cy + Rbody)·Vy) / Vlen²`
  - Foot point: `(rightStart − s·Vx, −Rbody + s·Vy)` (use **+** `s·Vy` for y, not minus).

---

## 5. Target / Reference Path

Example path (for validation):

```
L (0, 2.5000) left edge
L (0.5000, 3.0000) chamfer
L (25.0000, 3.0000) top
A R0.3000 → (25.2430, 2.7570) shoulder fillet
L (30.8690, 1.7650) top taper
A R12.0000 → (30.869, -1.7650) end arc
L (25.2430, -2.7570) bottom taper
A R0.3000 → (25.0000, -3.0000) shoulder fillet
L (0.5000, -3.0000) bottom
L (0, -2.5000) chamfer
L (0, 0) left edge close
```

Top and bottom shoulder fillets should be symmetric in construction and produce tangent points that lie on the taper lines.

---

## 6. Visual Reference

The profile should look like:

- Left: vertical edge, chamfer, horizontal body.
- Right: shoulder fillets (small R0.3 arcs) connecting body to taper; taper lines; large end arc (R12) at the tip.
- The fillets should appear smooth and tangent to the taper, with no visible kink.
- Top and bottom fillets should look the same (mirrored).

---

## 7. Single Source of Truth

- All coordinates (`T_topX`, `T_topY`, `T_botX`, `T_botY`) and arc flags come from the same construction.
- The “Path route” strings must use the same `n()`-formatted values as the `segs` array so the displayed route matches the actual `d` attribute.

---

## 8. Optional: Centre-Point Specification (I, J Style)

The user expressed interest in specifying the fillet arc by centre point (like CNC G-code I, J). That would define the arc by centre + radius instead of endpoint + radius, giving an unambiguous arc. For now the construction above is used; centre-point input could be added later.
