Multi-Stop Trip Planning
Relevant source files
The following files were used as context for generating this wiki page:
Multi-Stop Trip Planning is the core functional module of the P4N Map application. It allows users to define a sequence of waypoints (A → B → C), generate a routing polyline via OSRM, and discover relevant Park4Night spots and OpenStreetMap (OSM) amenities within a specific corridor distance from the road. The system prioritizes "van-life" specific needs, such as filtering for dog-friendly spots and ensuring amenities like water or fuel are available along the route.
Sources: README.md:10-15, src/components/Planner.tsx:288-305
Core Architecture and Data Flow
The planning process is initiated on the client-side within the Planner component. It coordinates between user input, the map interface, and the backend API to transform a list of stops into a detailed trip itinerary.
Planning Logic Flow
The following diagram illustrates the sequence of operations when a user initiates a plan.
The system samples the polyline approximately every 20 km to query the Park4Night API. Results are then deduped and filtered based on their perpendicular distance to the road.
Sources: README.md:46-51, src/app/api/plan/route.ts:25-30
Multi-Stop Data Structures
The system uses several key interfaces to manage trip data and routing geometry.
| Data Structure | Description | Key Fields |
|---|---|---|
Stop | Represents an individual waypoint in the trip sequence. | id, label, lat, lng |
RouteSummary | Summary of the OSRM routing result. | polyline, distanceKm, durationMin |
ScoredPlace | A P4nPlace enriched with trip-relative geometry and ranking. | kmFromRoad, progressKm, score |
LookAhead | Defines a search window relative to trip progress. | enabled, origin, lead, band |
Sources: src/lib/types.ts:98-103, src/lib/types.ts:162-166, src/lib/types.ts:74-83
Routing and Corridor Filtering
The system implements a "corridor" approach, where only spots within a defined distance (e.g., 5km) of the generated path are considered.
Distance and Progress Calculation
The engine uses pointToPolyline to project points onto the route. This provides two critical values:
- kmFromRoad: Perpendicular distance from the route, used for hard filtering.
- progressKm: The distance traveled along the route to reach the projection point, used for sequencing and ETA calculation.
Sources: src/lib/planner.ts:63-65, src/components/Planner.tsx:106-113
The Look-Ahead Window
A specialized feature of the planner is the LookAhead window. This allows users to plan a "day" by driving for a set duration or distance before beginning a search for overnight spots.
The resolveLookAheadWindow function converts time or distance measurements into absolute progressKm ranges.
Sources: src/lib/types.ts:145-156, src/lib/planner.ts:68-70
Spot Ranking and Scoring
Rather than simple filtering, the module uses a composite scoring engine to rank potential stops. A lower score indicates a more desirable spot.
Scoring Formula
The score is calculated based on several weights:
- Base Cost: The
kmFromRoad(detour distance). - Rating Bonus: Up to -1.5 km equivalent for a 5-star rating.
- Service Bonus: -0.4 km for every required service (e.g., water, electric) matched.
- Dog Park Bonus: A proximity-based reward (up to -1.2 km) if a dog park is nearby.
Sources: src/lib/planner.ts:108-124
Visualization and Interaction
The planning results are visualized on a MapLibre-based map and a persistent sidebar.
Map Rendering Layers
The MapView component manages multiple GeoJSON layers to distinguish between different types of stops and route information.
| Layer ID | Source | Description |
|---|---|---|
route-line | route | The primary OSRM polyline (green). |
band-line | band | The look-ahead window highlight (yellow). |
corridor | route | A visual hint showing the maxKmFromRoad buffer. |
p4n-places-lyr | p4n-places | GPU-rendered symbols for overnight spots. |
p4n-stops-lyr | p4n-stops | Circled letter markers (A, B, C) for trip waypoints. |
Sources: src/components/MapView.tsx:505-535, src/components/MapView.tsx:556-568
User Interaction Workflow
Users can manipulate the trip through the sidebar editor, which supports adding, removing, and reordering stops.
Adding a spot to the trip inserts it as a new waypoint before the final destination if more than two stops exist.
Sources: src/components/Planner.tsx:216-224, src/components/Planner.tsx:516-524
Technical Implementation Summary
- API Endpoint:
POST /api/planhandles the heavy lifting of routing and searching. - Client helper:
plan()insrc/lib/client.tswraps the fetch call. - State Management:
Planner.tsxmaintains thestate.stopsarray andresults(ScoredPlaces). - Navigation: Uses
navUrlto hand off coordinates to TomTom or Google Maps for turn-by-turn guidance.
Sources: src/app/api/plan/route.ts:18-35, src/lib/client.ts:133-157, src/components/Planner.tsx:130-150
Trip planning in this application effectively bridges the gap between static spot discovery and dynamic route-based travel, ensuring that van travelers can find accommodations and services precisely when and where they need them along their journey.