Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
f4d9dd6
feat: add initial documentation for manual reference distance feature…
cs-util Dec 21, 2025
986951f
refined the spec further: enhance user experience by adding zoom func…
cs-util Dec 21, 2025
3dc224d
feat: enhance manual reference distance feature with scale stabilizat…
cs-util Dec 21, 2025
34be6b6
feat: add fitSimilarityFixedScale function for fixed scale similarity…
cs-util Dec 21, 2025
2ac9f13
feat: implement fixed scale similarity transformation and add corresp…
cs-util Dec 21, 2025
99a2823
feat: document implementation progress for manual reference distance …
cs-util Dec 21, 2025
922e1f4
feat: simplify error handling in fetch event and geolocation prompt
cs-util Dec 21, 2025
9272d65
refactor to extract the shared centroid computation into a helper fun…
cs-util Dec 21, 2025
134e175
feat: refactor fitSimilarityFixedScale to use computeWeightedCentroid…
cs-util Dec 21, 2025
b248c12
feat: improve user instructions for setting reference distances and m…
cs-util Dec 21, 2025
d325a8a
feat: enhance rotation computation test for fitSimilarityFixedScale w…
cs-util Dec 21, 2025
b979daa
feat: expand unit tests for fitSimilarityFixedScale to document geome…
cs-util Dec 21, 2025
f62b458
feat: update reference distance calculations to use metersPerPixel fo…
cs-util Dec 21, 2025
a0fc40e
feat: update fitSimilarityFixedScale to handle negative fixedScale va…
cs-util Dec 21, 2025
808b136
feat: handle degenerate cases in fitSimilarityFixedScale by returning…
cs-util Dec 21, 2025
46497dc
feat: update documentation to clarify handling of degenerate coincide…
cs-util Dec 21, 2025
8cc2bce
feat: enhance measurement mode to prioritize manual reference distanc…
cs-util Dec 21, 2025
2c6c538
feat: enhance reference distance feature with scale source indicators…
cs-util Dec 21, 2025
9642113
feat: implement scale management utilities and extend application sta…
cs-util Dec 21, 2025
3c22454
feat: add scale and measure mode buttons with functionality for setti…
cs-util Dec 21, 2025
80d3fad
feat: extract scale and measure mode logic into dedicated state machi…
cs-util Dec 21, 2025
437aeac
feat: complete UI layer integration for reference distance feature wi…
cs-util Dec 21, 2025
047446c
feat: replaced the native prompt() with a custom modal dialog - add d…
cs-util Dec 21, 2025
50f005d
feat: refactoring by adding CSS classes to the HTML - add custom styl…
cs-util Dec 21, 2025
6e5315d
feat: refactor measure mode drag handling - extract drag event logic …
cs-util Dec 21, 2025
8c0efca
feat: remove unused API exports from scale and scale-mode modules for…
cs-util Dec 21, 2025
4e0f115
feat: remove 'Ft & In' option from distance selection for simplified …
cs-util Dec 21, 2025
7caf5fa
feat: streamline distance input handling - remove validation logic an…
cs-util Dec 21, 2025
bb758af
feat: implement convertToMeters function - add distance conversion ut…
cs-util Dec 22, 2025
8f84fdc
feat: remove Escape key handling from distance input modal for stream…
cs-util Dec 22, 2025
f402fbf
feat: refactor geolocation handling and improve user marker accuracy …
cs-util Dec 22, 2025
646e385
feat: enhance service worker fetch handling and add calibration readi…
cs-util Dec 22, 2025
0a1418b
feat: enhance distance input validation to support unit conversion
cs-util Dec 22, 2025
e649d37
feat: improve response handling in fetch navigation logic
cs-util Dec 22, 2025
63c4945
feat: adjust distance label positioning for improved visibility
cs-util Dec 22, 2025
f16b3ec
State Initialization: Updated the state object to use the new nested …
cs-util Dec 22, 2025
e225a41
feat: refactor color management by introducing COLORS object for cons…
cs-util Dec 22, 2025
7024bf0
feat: complete Phase 3 with persistence, scale validation, and measur…
cs-util Dec 22, 2025
81cdbba
feat: enhance computeReferenceScale validation and add property-based…
cs-util Dec 22, 2025
41465b7
feat: add scale and measure UI integration tests with persistence and…
cs-util Dec 22, 2025
b4d3da2
feat: add property-based tests for scale module and update existing t…
cs-util Dec 22, 2025
b6a8554
refactor: streamline module loading by consolidating setup functions
cs-util Dec 22, 2025
62f8572
updated the test case in index.scale.test.js:243-252 to set an initia…
cs-util Dec 22, 2025
55dfaeb
Updated Event Listener: Modified the change event handler for globalU…
cs-util Dec 22, 2025
3f3de48
refactored the code to address these issues by:
cs-util Dec 22, 2025
a00221c
Replaced the manual template string for newHtml with a call to create…
cs-util Dec 23, 2025
ce0cf83
Improved Code Coverage:
cs-util Dec 23, 2025
a761f96
Add feature specification for Instant Usage with 0-1 Point Calibration
cs-util Dec 23, 2025
41d5131
Update feature specification for Instant Usage: refine assumptions an…
cs-util Dec 23, 2025
40fd8d5
Enhance UI for Instant Usage: add prompts for scale setting and one-t…
cs-util Dec 23, 2025
3b85d69
Refine 1-Point Calibration Logic: clarify scale requirements for live…
cs-util Dec 23, 2025
fa18190
Implement 1-point calibration support and enhance UI prompts for inst…
cs-util Dec 23, 2025
aa97551
Enhance instant usage prompts: show/hide based on calibration state a…
cs-util Dec 23, 2025
4b00930
Refactor one-tap mode cancellation function and update related test c…
cs-util Dec 23, 2025
eb917f2
Add debug logs for instant usage prompts visibility check
cs-util Dec 23, 2025
7076c8d
Update instant usage prompts visibility logic to show only when no sc…
cs-util Dec 23, 2025
94011cc
Remove debug log for instant usage prompts visibility and add test lo…
cs-util Dec 23, 2025
c9f0d14
Show/hide instant usage prompts based on scale and pairs state in loa…
cs-util Dec 23, 2025
e6e636b
Refactor instant usage prompts visibility logic in loadPhotoMap funct…
cs-util Dec 23, 2025
625f13d
Update instant usage prompts visibility check in scale test; ensure t…
cs-util Dec 23, 2025
18b03d2
Refactor instant usage prompts visibility check in loadPhotoMap test;…
cs-util Dec 23, 2025
c6d2d14
Remove unused handleOneTapClick variable from Scale and Measure UI in…
cs-util Dec 23, 2025
0789cd9
Add calibrate1Point function for 1-point calibration logic; refactor …
cs-util Dec 23, 2025
0906847
Refactor calibration status updates; separate logic for no calibratio…
cs-util Dec 23, 2025
055fc1e
Refactor global unit change handling and modal event setup; improve c…
cs-util Dec 23, 2025
db25863
Add development progress notes for Instant Usage feature; document ph…
cs-util Dec 23, 2025
f4e391b
Enhance Instant Usage feature with 1-point calibration improvements; …
cs-util Dec 23, 2025
4291aa6
Documentation: I have updated the example in feat-reference-distances…
cs-util Dec 27, 2025
6361064
Updated Documentation: I updated feat-reference-distances.md:149-185 …
cs-util Dec 27, 2025
8cda078
Refine Quick Start Flow instructions for Instant Usage feature; clari…
cs-util Dec 27, 2025
5a73275
Math Layer: Updated the fitSimilarity1Point snippet to match the impl…
cs-util Dec 27, 2025
1335e37
I have refactored the code by:
cs-util Dec 27, 2025
d0d7f35
Added getRotationLabel helper: Created a function in index.js:231 to …
cs-util Dec 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions docs/feat-instant-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Feature Specification: Instant Usage (0-1 Point Calibration)

## 1. Overview
The "Instant Usage" feature aims to provide immediate value to the user after importing a map, even before they have provided the minimum required two GPS reference points. By making sensible assumptions (perfect top down view and North is up) and only asking the user to provide a reference scale, the app can enable the measurement tool and live position tracking earlier in the workflow.

## 2. Functional Requirements

### 2.1 Zero GPS Points
* **Measurement Tool**: Enabled if a manual `referenceDistance` (Set Scale) has been provided.
* **Live Position**: Disabled.

### 2.2 One GPS Point
* **Measurement Tool**: Enabled if a manual `referenceDistance` has been provided.
* **Live Position**: **Enabled** if a manual `referenceDistance` has been provided, using a fallback calibration.
* **Fallback Calibration (1-Point Similarity)**:
* **Translation**: Fixed by the single GPS reference point.
* **Rotation**: Assumed to be **0° (North is Up)**.
* **Scale**: Use `referenceDistance.metersPerPixel`.
* **User Feedback**: Display a banner/toast: *"Using 1-point calibration (North-up). Add a second point to fix orientation and scale."*

### 2.3 Two+ GPS Points
* **Standard Calibration**: Use the existing robust Similarity/Affine/Homography pipeline.
* **Scale Harmonization**: If a manual `referenceDistance` is provided, it can be used to constrain the Similarity fit (Phase 2).

### 2.4 Quick Start Flow
1. **Import Map**: User selects an image (of a map or floorplan).
2. Ask the user to provide a reference scale, which will enable distance measurement on the image.
3. **Initial Suggestion**: App asks: "Are you currently on this map? If so, where?".
1. **One-Tap Calibration**: If the user says yes, ask them to tap their current location on the photo.
2. **Immediate Live View**: The app immediately starts showing the live GPS position on the photo using the 1-point fallback.
3. **Refinement**: As the user moves, they can see if the dot follows the map. If not, they add a second point to "pin" the scale and rotation.


## 3. Technical Implementation

### 3.1 Math Layer ([src/geo/transformations.js](src/geo/transformations.js))
Implement `fitSimilarity1Point(pair, scale, rotation)` which returns a standard transform object.

```javascript
/**
* Creates a similarity transform from a single point, scale, and rotation.
* @param {Object} pair - { pixel: {x, y}, enu: {x, y} }
* @param {number} scale - Meters per pixel
* @param {number} [rotation=0] - Rotation in radians (0 = North is Up)
*/
export function fitSimilarity1Point(pair, scale, rotation = 0) {
if (!pair || !pair.pixel || !pair.enu || !Number.isFinite(scale) || scale <= 0) {
return null;
}

const cos = Math.cos(rotation);
const sin = Math.sin(rotation);

const tx = pair.enu.x - scale * (cos * pair.pixel.x - sin * pair.pixel.y);
const ty = pair.enu.y - scale * (sin * pair.pixel.x + cos * pair.pixel.y);

return {
type: 'similarity',
scale,
rotation,
cos,
sin,
translation: { x: tx, y: ty },
};
}
```

### 3.2 Calibration Layer ([src/calibration/calibrator.js](src/calibration/calibrator.js))
Update `calibrateMap` to handle the 1-point case using a helper function.

```javascript
function calibrate1Point(enrichedPairs, origin, referenceScale, userOptions) {
if (!referenceScale) {
return {
status: 'insufficient-pairs',
message: 'A reference scale is required for 1-point calibration.',
};
}
const rotation = userOptions.defaultRotation || 0;
const model = fitSimilarity1Point(enrichedPairs[0], referenceScale, rotation);
if (!model) {
return {
status: 'fit-failed',
message: '1-point calibration failed.',
};
}
return {
status: 'ok',
origin,
kind: 'similarity',
model,
metrics: {
rmse: 0,
maxResidual: 0,
inliers: enrichedPairs,
residuals: [0],
},
quality: {
rmse: 0,
maxResidual: 0,
},
statusMessage: { level: 'low', message: '1-point calibration (North-up). Add a second point to fix orientation and scale.' },
residuals: [0],
inliers: enrichedPairs,
};
}

export function calibrateMap(pairs, userOptions = {}) {
// ...
if (enrichedPairs.length === 1) {
return calibrate1Point(enrichedPairs, origin, referenceScale, userOptions);
}
// ...
}
```

### 3.3 UI Layer ([src/index.js](src/index.js))
* **Post-Import Prompt**: Immediately after map import (no scale is set yet), display a prominent "Set Scale" button.
* **Location Prompt**: In parallel show a button *"Are you currently on this map?"*
* If Clicked, enter **One-Tap Calibration** mode.
* **One-Tap Calibration UI**:
* When active, the next tap on the photo captures the current GPS position (waiting for accuracy if needed) and creates a single reference pair.
* Automatically trigger `calibrateMap()` and enable "Live" mode.
* **Fallback Indicator**:
* When `state.pairs.length === 1`, show a status badge: "1-Point Calibration (North-up)".
* **Live Button**: Enable when `state.pairs.length >= 1` AND a manual scale is set.
* **Settings**: Add a "Default Rotation" (default: 0°).

## 4. Edge Cases & Considerations
* **Unstable 2-Point Fit**: If two GPS points are extremely close together, the rotation becomes numerically unstable. In this case, the system should either warn the user or offer to stick to the "North-up" assumption.
* **Missing Scale**: If the user provides 1 GPS point but hasn't set a scale yet, the "Live" mode remains disabled until the scale is defined (either because the user later decided to set the reference scale or because he decided to set a second gps reference point).

## 5. Development Progress Notes

### Phase 1: Math & Logic (Completed)
- **1-Point Similarity**: Implemented `fitSimilarity1Point` in [src/geo/transformations.js](src/geo/transformations.js). It creates a transform from a single point, a fixed scale, and an assumed 0° rotation.
- **Fixed-Scale Similarity**: Implemented `fitSimilarityFixedScale` to allow 2+ point calibration while constraining the scale to a manual reference value.
- **Calibrator Update**: Updated `calibrateMap` in [src/calibration/calibrator.js](src/calibration/calibrator.js) to support the 1-point fallback when `referenceScale` is provided.

### Phase 2: UI Integration (Completed)
- **Quick Start Prompts**: Added a dedicated prompt area in [index.html](index.html) that appears immediately after map import.
- **One-Tap Calibration**: Implemented `startOneTapMode` and `handleOneTapClick` in [src/index.js](src/index.js). This allows users to "pin" their current GPS location to a spot on the photo with a single tap.
- **Scale & Measure Modes**: Integrated the state machine from [src/scale/scale-mode.js](src/scale/scale-mode.js) to handle "Set Scale" and "Measure" interactions.
- **Persistence**: Manual scale and preferred units are now persisted in `localStorage`.

### Phase 3: Quality & Validation (Completed)
- **Unit Tests**: Added comprehensive tests for 1-point and fixed-scale transformations in [src/geo/transformations.test.js](src/geo/transformations.test.js).
- **Integration Tests**: Created [src/index.scale.test.js](src/index.scale.test.js) to verify the end-to-end "Instant Usage" flow, including prompt visibility and one-tap calibration.
- **Complexity Management**: Refactored `updateStatusText`, `recalculateCalibration`, and `setupEventHandlers` in [src/index.js](src/index.js) to keep cyclomatic complexity within limits (<= 10).
- **Coverage**: Maintained >99% statement coverage across all modified files.
- **Validation**: Verified all quality checks (`lint`, `check:dup`, `check:cycles`, `check:boundaries`) pass successfully.

### Phase 4: Expert Review & Refinement (Completed)
- **Robust One-Tap Calibration**: Improved `handleOneTapClick` to explicitly wait for a fresh GPS fix using `getCurrentPosition`, ensuring accuracy even if the background watch hasn't updated yet.
- **Intelligent Prompt Visibility**: Refactored visibility logic into `updateInstantUsagePromptsVisibility`. Prompts now stay visible until a valid 1-point or 2-point calibration is fully active (e.g., "Set Scale" stays visible if only a GPS point was added).
- **Default Rotation Setting**: Added a UI selector and persistence for "Default Rotation", allowing 1-point calibration to work for maps that are not North-up.
- **Enhanced Feedback**: Added the required instructional toast messages for 1-point calibration states to guide the user toward adding a second point.
- **Persistence**: Extended `localStorage` sync to include the new rotation setting.
Loading