Skip to content

Commit 45552c4

Browse files
committed
Fix: Polygon's inner circles are excluded
1 parent c3f8db1 commit 45552c4

File tree

7 files changed

+220
-4
lines changed

7 files changed

+220
-4
lines changed

app/source/utilities/getData.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,43 @@ function makeOverpassQuery({
206206
);
207207
}
208208

209+
/*
210+
A polygon may have an outer ring and (optional) inner rings (to exclude). We use the "stitched
211+
path" trick to exlude any inner rings. All rings get converted to`lat1 lng1 lat2 lng2..`, but
212+
we also repeat the first (outer) vertice before and after each inner ring.
213+
214+
Examples:
215+
- Simple polygon: `lat1 lng1 lat2 lng2...`
216+
- Polygon with two inner rings:
217+
```
218+
outer-lat1 outer-lng1 outer-lat2 outer-lng2...
219+
outer-lat1 outer-lng1
220+
inner1-lat1 inner1-lng1 inner1-lat2 inner1-lng2...
221+
outer-lat1 outer-lng1
222+
inner2-lat1 inner2-lng1 inner2-lat2 inner2-lng2...
223+
outer-lat1 outer-lng1
224+
```
225+
Note: the newlines wouldn't actually exist
226+
*/
209227
spatialModifiers = areaSelection.feature.geometry.coordinates.map(
210-
(polygonCoordinates) => {
211-
const polyModifierValue = polygonCoordinates[0]
212-
.map(([lng, lat]) => `${lat} ${lng}`)
213-
.join(" ");
228+
(polygons) => {
229+
let polyModifierValue = "";
230+
let firstLatLngPair: string | undefined;
231+
232+
for (let i = 0; i < polygons.length; i++) {
233+
const latLngPairs = polygons[i].map(([lng, lat]) => `${lat} ${lng}`);
234+
235+
firstLatLngPair ??= latLngPairs[0];
236+
if (i) {
237+
latLngPairs.unshift(firstLatLngPair);
238+
}
239+
polyModifierValue += latLngPairs.join(" ");
240+
}
241+
242+
if (polygons.length > 1) {
243+
polyModifierValue += firstLatLngPair;
244+
}
245+
214246
return `(poly:"${polyModifierValue}")`;
215247
},
216248
);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default new Map();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default new Map();

marketing-site/.astro/content.d.ts

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
3+
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
*
5+
* Project: Back Of Your Hand (https://backofyourhand.com)
6+
* Repository: https://github.com/adam-lynch/back-of-your-hand
7+
* Copyright © 2025 Adam Lynch (https://adamlynch.com)
8+
*/
9+
10+
declare module 'astro:content' {
11+
export interface RenderResult {
12+
Content: import('astro/runtime/server/index.js').AstroComponentFactory;
13+
headings: import('astro').MarkdownHeading[];
14+
remarkPluginFrontmatter: Record<string, any>;
15+
}
16+
interface Render {
17+
'.md': Promise<RenderResult>;
18+
}
19+
20+
export interface RenderedContent {
21+
html: string;
22+
metadata?: {
23+
imagePaths: Array<string>;
24+
[key: string]: unknown;
25+
};
26+
}
27+
}
28+
29+
declare module 'astro:content' {
30+
type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
31+
32+
export type CollectionKey = keyof AnyEntryMap;
33+
export type CollectionEntry<C extends CollectionKey> = Flatten<AnyEntryMap[C]>;
34+
35+
export type ContentCollectionKey = keyof ContentEntryMap;
36+
export type DataCollectionKey = keyof DataEntryMap;
37+
38+
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
39+
type ValidContentEntrySlug<C extends keyof ContentEntryMap> = AllValuesOf<
40+
ContentEntryMap[C]
41+
>['slug'];
42+
43+
export type ReferenceDataEntry<
44+
C extends CollectionKey,
45+
E extends keyof DataEntryMap[C] = string,
46+
> = {
47+
collection: C;
48+
id: E;
49+
};
50+
export type ReferenceContentEntry<
51+
C extends keyof ContentEntryMap,
52+
E extends ValidContentEntrySlug<C> | (string & {}) = string,
53+
> = {
54+
collection: C;
55+
slug: E;
56+
};
57+
58+
/** @deprecated Use `getEntry` instead. */
59+
export function getEntryBySlug<
60+
C extends keyof ContentEntryMap,
61+
E extends ValidContentEntrySlug<C> | (string & {}),
62+
>(
63+
collection: C,
64+
// Note that this has to accept a regular string too, for SSR
65+
entrySlug: E,
66+
): E extends ValidContentEntrySlug<C>
67+
? Promise<CollectionEntry<C>>
68+
: Promise<CollectionEntry<C> | undefined>;
69+
70+
/** @deprecated Use `getEntry` instead. */
71+
export function getDataEntryById<C extends keyof DataEntryMap, E extends keyof DataEntryMap[C]>(
72+
collection: C,
73+
entryId: E,
74+
): Promise<CollectionEntry<C>>;
75+
76+
export function getCollection<C extends keyof AnyEntryMap, E extends CollectionEntry<C>>(
77+
collection: C,
78+
filter?: (entry: CollectionEntry<C>) => entry is E,
79+
): Promise<E[]>;
80+
export function getCollection<C extends keyof AnyEntryMap>(
81+
collection: C,
82+
filter?: (entry: CollectionEntry<C>) => unknown,
83+
): Promise<CollectionEntry<C>[]>;
84+
85+
export function getEntry<
86+
C extends keyof ContentEntryMap,
87+
E extends ValidContentEntrySlug<C> | (string & {}),
88+
>(
89+
entry: ReferenceContentEntry<C, E>,
90+
): E extends ValidContentEntrySlug<C>
91+
? Promise<CollectionEntry<C>>
92+
: Promise<CollectionEntry<C> | undefined>;
93+
export function getEntry<
94+
C extends keyof DataEntryMap,
95+
E extends keyof DataEntryMap[C] | (string & {}),
96+
>(
97+
entry: ReferenceDataEntry<C, E>,
98+
): E extends keyof DataEntryMap[C]
99+
? Promise<DataEntryMap[C][E]>
100+
: Promise<CollectionEntry<C> | undefined>;
101+
export function getEntry<
102+
C extends keyof ContentEntryMap,
103+
E extends ValidContentEntrySlug<C> | (string & {}),
104+
>(
105+
collection: C,
106+
slug: E,
107+
): E extends ValidContentEntrySlug<C>
108+
? Promise<CollectionEntry<C>>
109+
: Promise<CollectionEntry<C> | undefined>;
110+
export function getEntry<
111+
C extends keyof DataEntryMap,
112+
E extends keyof DataEntryMap[C] | (string & {}),
113+
>(
114+
collection: C,
115+
id: E,
116+
): E extends keyof DataEntryMap[C]
117+
? string extends keyof DataEntryMap[C]
118+
? Promise<DataEntryMap[C][E]> | undefined
119+
: Promise<DataEntryMap[C][E]>
120+
: Promise<CollectionEntry<C> | undefined>;
121+
122+
/** Resolve an array of entry references from the same collection */
123+
export function getEntries<C extends keyof ContentEntryMap>(
124+
entries: ReferenceContentEntry<C, ValidContentEntrySlug<C>>[],
125+
): Promise<CollectionEntry<C>[]>;
126+
export function getEntries<C extends keyof DataEntryMap>(
127+
entries: ReferenceDataEntry<C, keyof DataEntryMap[C]>[],
128+
): Promise<CollectionEntry<C>[]>;
129+
130+
export function render<C extends keyof AnyEntryMap>(
131+
entry: AnyEntryMap[C][string],
132+
): Promise<RenderResult>;
133+
134+
export function reference<C extends keyof AnyEntryMap>(
135+
collection: C,
136+
): import('astro/zod').ZodEffects<
137+
import('astro/zod').ZodString,
138+
C extends keyof ContentEntryMap
139+
? ReferenceContentEntry<C, ValidContentEntrySlug<C>>
140+
: ReferenceDataEntry<C, keyof DataEntryMap[C]>
141+
>;
142+
// Allow generic `string` to avoid excessive type errors in the config
143+
// if `dev` is not running to update as you edit.
144+
// Invalid collection names will be caught at build time.
145+
export function reference<C extends string>(
146+
collection: C,
147+
): import('astro/zod').ZodEffects<import('astro/zod').ZodString, never>;
148+
149+
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
150+
type InferEntrySchema<C extends keyof AnyEntryMap> = import('astro/zod').infer<
151+
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
152+
>;
153+
154+
type ContentEntryMap = {
155+
156+
};
157+
158+
type DataEntryMap = {
159+
160+
};
161+
162+
type AnyEntryMap = ContentEntryMap & DataEntryMap;
163+
164+
export type ContentConfig = typeof import("../src/content.config.mjs");
165+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.8.0","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[]},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"responsiveImages\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false},\"legacy\":{\"collections\":false}}"]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"_variables": {
3+
"lastUpdateCheck": 1749763261667
4+
}
5+
}

marketing-site/.astro/types.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
3+
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
*
5+
* Project: Back Of Your Hand (https://backofyourhand.com)
6+
* Repository: https://github.com/adam-lynch/back-of-your-hand
7+
* Copyright © 2025 Adam Lynch (https://adamlynch.com)
8+
*/
9+
10+
/// <reference types="astro/client" />
11+
/// <reference path="content.d.ts" />

0 commit comments

Comments
 (0)