diff --git a/libs/map-editor/src/lib/ai/annotations.ts b/libs/map-editor/src/lib/ai/annotations.ts index d9798910f08..433d0e63ecf 100644 --- a/libs/map-editor/src/lib/ai/annotations.ts +++ b/libs/map-editor/src/lib/ai/annotations.ts @@ -19,6 +19,18 @@ export function annotationColour(mark: MapAIAnnotation): string { ); } +/** Every point a mark covers in viewBox units: its path, its box corners and an arrow's tip. */ +export function annotationPoints(mark: MapAIAnnotation): [number, number][] { + const points: [number, number][] = [...(mark.points || [])]; + if (mark.x !== undefined && mark.y !== undefined) { + points.push([mark.x, mark.y]); + points.push([mark.x + (mark.width || 0), mark.y + (mark.height || 0)]); + } + if (mark.x2 !== undefined && mark.y2 !== undefined) + points.push([mark.x2, mark.y2]); + return points.filter(([x, y]) => Number.isFinite(x) && Number.isFinite(y)); +} + /** The same marks on the canvas overlay and the uploaded snapshot, in viewBox units. */ export function drawAnnotations( overlay: SVGElement, diff --git a/libs/map-editor/src/lib/ai/context.ts b/libs/map-editor/src/lib/ai/context.ts index c86ef64b038..4447fd55ff0 100644 --- a/libs/map-editor/src/lib/ai/context.ts +++ b/libs/map-editor/src/lib/ai/context.ts @@ -1,6 +1,7 @@ import { MapDocument, stripEditorAttributes, ViewBox } from '../map-document'; import { MapIndex, MapIndexEntry } from '../map-index'; import { formatDeclarations, StyleRule } from '../style-resolution'; +import { annotationPoints } from './annotations'; import { snapshotSize, SnapshotSize } from './snapshot'; import { MAP_AI_CONTEXT_SCHEMA, @@ -721,25 +722,15 @@ export function buildContext( .slice(0, MAX_MENTIONS) .map((entry) => entry.anchor); const box = doc.view_box; - const outside = (options.annotations || []).some((mark) => { - const points = [...(mark.points || [])]; - if (mark.x !== undefined && mark.y !== undefined) { - points.push([mark.x, mark.y]); - points.push([ - mark.x + (mark.width || 0), - mark.y + (mark.height || 0), - ]); - } - if (mark.x2 !== undefined && mark.y2 !== undefined) - points.push([mark.x2, mark.y2]); - return points.some( + const outside = (options.annotations || []).some((mark) => + annotationPoints(mark).some( ([x, y]) => x < box.x || y < box.y || x > box.x + box.width || y > box.y + box.height, - ); - }); + ), + ); const include_root = !!root_entry && (outside || /\b(expand|extend|enlarge)\b/.test(instruction)); diff --git a/libs/map-editor/src/lib/ai/snapshot.ts b/libs/map-editor/src/lib/ai/snapshot.ts index 0de146f65dc..28fff287c97 100644 --- a/libs/map-editor/src/lib/ai/snapshot.ts +++ b/libs/map-editor/src/lib/ai/snapshot.ts @@ -1,6 +1,6 @@ import { SVG_NS } from '../constants'; import { MapDocument, stripEditorAttributes, ViewBox } from '../map-document'; -import { drawAnnotations } from './annotations'; +import { annotationPoints, drawAnnotations } from './annotations'; import { MapAIAnnotation } from './types'; export const SNAPSHOT_LONG_SIDE = 2048; @@ -65,21 +65,7 @@ export function snapshotMarkup( options: SnapshotMarkupOptions = {}, ): SnapshotMarkup { const bounds = { ...doc.view_box }; - const points = (options.annotations || []) - .flatMap((mark) => { - const result = [...(mark.points || [])]; - if (mark.x !== undefined && mark.y !== undefined) { - result.push([mark.x, mark.y]); - result.push([ - mark.x + (mark.width || 0), - mark.y + (mark.height || 0), - ]); - } - if (mark.x2 !== undefined && mark.y2 !== undefined) - result.push([mark.x2, mark.y2]); - return result; - }) - .filter(([x, y]) => Number.isFinite(x) && Number.isFinite(y)); + const points = (options.annotations || []).flatMap(annotationPoints); for (const [x, y] of points) { const right = Math.max(bounds.x + bounds.width, x); const bottom = Math.max(bounds.y + bounds.height, y);