mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
let building words pass only on single-structure results
A building word ending the ask ('… Chapel', '… Library', '… Hall') now
passes the last-word rule only when the result is one a building ask
would accept, so a campus, zoo or district whose name merely starts the
ask (Duke University, Old Town) no longer answers it.
This commit is contained in:
1 parent
c059e12a11
commit
64c9f4cfa5
3 files changed
+18
-10
No files matched your search
@@ -5510,7 +5510,7 @@ request viewbox and continues searching without that geographic preference.
|
|||||||
|
|
||||||
- Runtime entry: `src/main.js` calls `initAnnotations({ viewer, tileset })`, exposes `window.__gevAnnotations`, and passes the engine into the voice action runner.
|
- Runtime entry: `src/main.js` calls `initAnnotations({ viewer, tileset })`, exposes `window.__gevAnnotations`, and passes the engine into the voice action runner.
|
||||||
- Engine contract: `src/annotations/annotationEngine.js` owns annotation state, TTL/fade lifecycle, concurrent anchor resolution, duplicate detection keyed on geometry, cancellation on clear/newer generations, and a hard cap of 120 live marks. Deferred outline upgrades drain FIFO at concurrency 2; queued work retains the owning abort controller and is discarded on a generation change before it can fetch.
|
- Engine contract: `src/annotations/annotationEngine.js` owns annotation state, TTL/fade lifecycle, concurrent anchor resolution, duplicate detection keyed on geometry, cancellation on clear/newer generations, and a hard cap of 120 live marks. Deferred outline upgrades drain FIFO at concurrency 2; queued work retains the owning abort controller and is discarded on a generation change before it can fetch.
|
||||||
- Resolver contract: `src/annotations/resolver.js` converts names, coordinates and screen pixels into world anchors and optional geometry. Google Geocode/Places supplies a centroid and scope; route requests use `/api/route`; ambiguous or distant results are rejected or recovered near the current view instead of drawing misleading blobs. Outline resolution keeps this order: bundled admin/place/neighborhood/Natural Earth geometry; OpenFreeMap street or pointed-building geometry where applicable; the configured OSM/Overpass admin/place/footprint/street/enclosing-area ladder; guarded Nominatim for eligible named cities, admin units, landmarks, buildings and grounds; then an OpenFreeMap building fallback that accepts a named building only when its resolved anchor lies in the selected filled footprint. Pointed-at building requests retain nearby selection within 40 m. Tile building and grounds answers also need the tile holding the anchor: when that tile fails to load and only neighbours arrive, no neighbouring building or area stands in. Tile grounds answer a named grounds ask only from an area of the same name, or, when the ask's head noun names a kind of grounds (school, university/college, hospital, cemetery, stadium, zoo; "campus" alone names none), from the part of the smallest unnamed area of that class that holds the anchor (a class word elsewhere in a name, as in "University Avenue Park", does not count); a differently named area never answers. If no rung can supply honest geometry, the mark remains a point or reports the capability unavailable. A real polygon, definitive miss, configured-ladder approximation, rate limit or transient result keeps its existing finality; Nominatim is only tried after higher-priority configured sources cannot answer. Building tile selection returns the selected component and its holes; a shared vector feature ID does not establish that unrelated components are one building. Other trusted multi-part outlines and holes are retained in `anno.polygons`, with `ring` anchored to the part whose filled area contains the resolved point, outside its holes, when possible. Guarded Nominatim keeps every accepted result for an ask, ranks an exact name first, then a name holding every asked word, then a partial match; a partial landmark match whose name lacks the ask's last word is refused unless that word appears in the result's address or type (the place around a feature, such as a park around its zoo, is not the feature, while "Space Needle Seattle" still finds the Space Needle). A building word ("Burj Khalifa Tower") also passes on a building-like result. Each ask is answered with the cached result among the best-named ones whose filled area holds the resolved anchor (read across the antimeridian), else the first; a worse name never wins by containment alone. Nominatim name checks use the bundled packs' place-name key, so "St. Paul" and "Saint Paul" agree there. A street ribbon that holds neither its ring mean nor the anchor is centred on the street's nearest point to the anchor when the street runs within 100 m of it. In tile street names a lone letter is a direction only beside another name word ("N Lamar Blvd"), so "E Street" is not "East Street", and a quadrant ("E St NW", "SE Main St") may go unsaid in the ask, which then takes only the quadrant of the matching street nearest the point. A building or area cut at the tile edge is not complete (past a tile buffer any vertex on the cut line marks it; on an unbuffered edge, an edge running along the boundary does, not a corner that merely touches it): a cut building nearer the point than any whole one leaves the point, and a cut area does not answer grounds. Missing capability never invents a radius outline. Only explicitly country/state/county-scoped asks bypass near-view recovery and proximity gating; state scope requires a leading `state of …`/`the state of …` phrase, while bare names, proper names ending in “State,” and administrative geocode result types alone remain guarded. Overpass throttles remain distinct from normal transients: `Retry-After` is honored for one retry, and a repeated throttle ends only that mark's outline upgrade.
|
- Resolver contract: `src/annotations/resolver.js` converts names, coordinates and screen pixels into world anchors and optional geometry. Google Geocode/Places supplies a centroid and scope; route requests use `/api/route`; ambiguous or distant results are rejected or recovered near the current view instead of drawing misleading blobs. Outline resolution keeps this order: bundled admin/place/neighborhood/Natural Earth geometry; OpenFreeMap street or pointed-building geometry where applicable; the configured OSM/Overpass admin/place/footprint/street/enclosing-area ladder; guarded Nominatim for eligible named cities, admin units, landmarks, buildings and grounds; then an OpenFreeMap building fallback that accepts a named building only when its resolved anchor lies in the selected filled footprint. Pointed-at building requests retain nearby selection within 40 m. Tile building and grounds answers also need the tile holding the anchor: when that tile fails to load and only neighbours arrive, no neighbouring building or area stands in. Tile grounds answer a named grounds ask only from an area of the same name, or, when the ask's head noun names a kind of grounds (school, university/college, hospital, cemetery, stadium, zoo; "campus" alone names none), from the part of the smallest unnamed area of that class that holds the anchor (a class word elsewhere in a name, as in "University Avenue Park", does not count); a differently named area never answers. If no rung can supply honest geometry, the mark remains a point or reports the capability unavailable. A real polygon, definitive miss, configured-ladder approximation, rate limit or transient result keeps its existing finality; Nominatim is only tried after higher-priority configured sources cannot answer. Building tile selection returns the selected component and its holes; a shared vector feature ID does not establish that unrelated components are one building. Other trusted multi-part outlines and holes are retained in `anno.polygons`, with `ring` anchored to the part whose filled area contains the resolved point, outside its holes, when possible. Guarded Nominatim keeps every accepted result for an ask, ranks an exact name first, then a name holding every asked word, then a partial match; a partial landmark match whose name lacks the ask's last word is refused unless that word appears in the result's address or type (the place around a feature, such as a park around its zoo, is not the feature, while "Space Needle Seattle" still finds the Space Needle). A building word ("Burj Khalifa Tower") also passes on a single-structure result (one a building ask would accept), never on a campus, zoo or district. Each ask is answered with the cached result among the best-named ones whose filled area holds the resolved anchor (read across the antimeridian), else the first; a worse name never wins by containment alone. Nominatim name checks use the bundled packs' place-name key, so "St. Paul" and "Saint Paul" agree there. A street ribbon that holds neither its ring mean nor the anchor is centred on the street's nearest point to the anchor when the street runs within 100 m of it. In tile street names a lone letter is a direction only beside another name word ("N Lamar Blvd"), so "E Street" is not "East Street", and a quadrant ("E St NW", "SE Main St") may go unsaid in the ask, which then takes only the quadrant of the matching street nearest the point. A building or area cut at the tile edge is not complete (past a tile buffer any vertex on the cut line marks it; on an unbuffered edge, an edge running along the boundary does, not a corner that merely touches it): a cut building nearer the point than any whole one leaves the point, and a cut area does not answer grounds. Missing capability never invents a radius outline. Only explicitly country/state/county-scoped asks bypass near-view recovery and proximity gating; state scope requires a leading `state of …`/`the state of …` phrase, while bare names, proper names ending in “State,” and administrative geocode result types alone remain guarded. Overpass throttles remain distinct from normal transients: `Retry-After` is honored for one retry, and a repeated throttle ends only that mark's outline upgrade.
|
||||||
- With no detailed-feature capability, annotations retain their pins and say
|
- With no detailed-feature capability, annotations retain their pins and say
|
||||||
"Detailed outline unavailable"; location focus reports the same result without
|
"Detailed outline unavailable"; location focus reports the same result without
|
||||||
retrying. Missing capability never synthesizes an outline from a radius.
|
retrying. Missing capability never synthesizes an outline from a radius.
|
||||||
|
|||||||
@@ -279,13 +279,6 @@ const BUILDING_WORDS = [
|
|||||||
'hall',
|
'hall',
|
||||||
'library',
|
'library',
|
||||||
];
|
];
|
||||||
const BUILDING_LIKE_CLASSES = new Set([
|
|
||||||
'building',
|
|
||||||
'amenity',
|
|
||||||
'man_made',
|
|
||||||
'tourism',
|
|
||||||
'historic',
|
|
||||||
]);
|
|
||||||
|
|
||||||
/** How well a result's names answer the ask. */
|
/** How well a result's names answer the ask. */
|
||||||
const NAME_MISS = 0;
|
const NAME_MISS = 0;
|
||||||
@@ -322,7 +315,7 @@ function outlineNameMatch(row, query, kind) {
|
|||||||
// The last word usually names the feature ("Zoo", "Arch"): a name without
|
// The last word usually names the feature ("Zoo", "Arch"): a name without
|
||||||
// it is the place around the feature ("Central Park"), unless the word is
|
// it is the place around the feature ("Central Park"), unless the word is
|
||||||
// where the result is ("Space Needle Seattle"), what it is ("… Bridge"), or
|
// where the result is ("Space Needle Seattle"), what it is ("… Bridge"), or
|
||||||
// a building word on a building-like result ("Burj Khalifa Tower").
|
// a building word on a single-structure result ("Burj Khalifa Tower").
|
||||||
const context = new Set(
|
const context = new Set(
|
||||||
normalizePlaceName(
|
normalizePlaceName(
|
||||||
[
|
[
|
||||||
@@ -337,7 +330,9 @@ function outlineNameMatch(row, query, kind) {
|
|||||||
.replace(/_/g, ' '),
|
.replace(/_/g, ' '),
|
||||||
).split(' '),
|
).split(' '),
|
||||||
);
|
);
|
||||||
if (BUILDING_LIKE_CLASSES.has(String(row?.category || row?.class)))
|
// Only a single structure, as a building ask would accept: never a campus,
|
||||||
|
// zoo or district whose name merely starts the ask ("Duke University").
|
||||||
|
if (acceptsOutlineClass('building', row?.category || row?.class, row?.type))
|
||||||
for (const word of BUILDING_WORDS) context.add(word);
|
for (const word of BUILDING_WORDS) context.add(word);
|
||||||
let match = NAME_MISS;
|
let match = NAME_MISS;
|
||||||
for (const name of names) {
|
for (const name of names) {
|
||||||
|
|||||||
@@ -1370,6 +1370,19 @@ test('a landmark ask is not answered by the place around it', () => {
|
|||||||
.outline,
|
.outline,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
// Nor on a campus or district whose name merely starts the ask.
|
||||||
|
for (const [query, name, category, type] of [
|
||||||
|
['Duke University Chapel', 'Duke University', 'amenity', 'university'],
|
||||||
|
['Old Town Hall', 'Old Town', 'historic', 'district'],
|
||||||
|
])
|
||||||
|
assert.equal(
|
||||||
|
selectOutlineResult(
|
||||||
|
[at(name, `${name}, Somewhere`, { category, type })],
|
||||||
|
landmark(query),
|
||||||
|
).outline,
|
||||||
|
null,
|
||||||
|
query,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('a worse name never wins the anchor by containment alone', () => {
|
test('a worse name never wins the anchor by containment alone', () => {
|
||||||
|
|||||||
Reference in new issue
Block a user