Skip to content

Commit 7775dec

Browse files
authored
Merge pull request #1069 from louis-e/feat/stadium-archetype
Feat/stadium archetype
2 parents 89a0981 + 7900dcc commit 7775dec

9 files changed

Lines changed: 1210 additions & 57 deletions

File tree

src/data_processing.rs

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -129,43 +129,20 @@ pub fn generate_world_with_options(
129129
let pb_batch_size: u64 = (elements_count as u64 / desired_updates).max(1);
130130
let mut element_counter: u64 = 0;
131131

132-
// Pre-scan 3DMR-tagged elements first; 3DMR wins over Wikidata on conflict.
133-
let three_dmr_prescan = if args.use_3d {
134-
Some(crate::models_3d::three_dmr::prescan(
135-
&elements,
136-
args.rotation,
137-
))
138-
} else {
139-
None
140-
};
132+
let models_3d_pipeline = args
133+
.use_3d
134+
.then(|| crate::models_3d::Models3dPipeline::prescan(&elements, args));
141135
let empty_suppressed: HashSet<(&'static str, u64)> = HashSet::new();
142-
let three_dmr_suppressed: &HashSet<(&'static str, u64)> = three_dmr_prescan
143-
.as_ref()
144-
.map(|p| &p.suppressed_ids)
145-
.unwrap_or(&empty_suppressed);
146-
147-
// Wikidata pre-scan runs after 3DMR's, skipping any element 3DMR already claimed.
148-
let wikidata_prescan = if args.use_3d {
149-
Some(crate::models_3d::wikidata::prescan(
150-
&elements,
151-
three_dmr_suppressed,
152-
args.rotation,
153-
args.scale,
154-
))
155-
} else {
156-
None
157-
};
158-
let wikidata_suppressed: &HashSet<(&'static str, u64)> = wikidata_prescan
136+
let models_3d_suppressed: &HashSet<(&'static str, u64)> = models_3d_pipeline
159137
.as_ref()
160-
.map(|p| &p.suppressed_ids)
138+
.map(|p| p.suppressed())
161139
.unwrap_or(&empty_suppressed);
162140

163141
// Process all elements
164142
for element in elements.into_iter() {
165143
element_counter += 1;
166144
let suppression_key = (element.kind(), element.id());
167-
if three_dmr_suppressed.contains(&suppression_key)
168-
|| wikidata_suppressed.contains(&suppression_key)
145+
if models_3d_suppressed.contains(&suppression_key)
169146
|| outline_suppression.contains(&suppression_key)
170147
{
171148
continue;
@@ -439,15 +416,8 @@ pub fn generate_world_with_options(
439416
}
440417

441418
// Run after ground generation so anchor Y reflects the final terrain.
442-
if let Some(prescan) = three_dmr_prescan.as_ref() {
443-
if prescan.placement_count() > 0 {
444-
crate::models_3d::three_dmr::place_three_dmr_models(&mut editor, args, prescan);
445-
}
446-
}
447-
if let Some(prescan) = wikidata_prescan.as_ref() {
448-
if prescan.placement_count() > 0 {
449-
crate::models_3d::wikidata::place_wikidata_models(&mut editor, args, prescan);
450-
}
419+
if let Some(p) = models_3d_pipeline.as_ref() {
420+
p.place(&mut editor, args);
451421
}
452422

453423
// Save world

src/models_3d/custom/client.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! Shared HTTP fetch + on-disk cache for Arnis-hosted archetype models.
2+
3+
use reqwest::blocking::ClientBuilder;
4+
use std::fs;
5+
use std::io::Read;
6+
use std::path::PathBuf;
7+
use std::time::Duration;
8+
9+
const CACHE_SUBDIR: &str = "arnis/custom_models";
10+
const REQUEST_TIMEOUT_SECS: u64 = 20;
11+
const MAX_GLB_BYTES: u64 = 16 * 1024 * 1024;
12+
13+
pub(crate) fn cache_root() -> PathBuf {
14+
dirs::cache_dir()
15+
.map(|d| d.join(CACHE_SUBDIR))
16+
.unwrap_or_else(|| PathBuf::from("./.arnis_custom_cache"))
17+
}
18+
19+
pub(super) fn fetch_glb(url: &str, filename: &str) -> Result<Vec<u8>, String> {
20+
let dir = cache_root();
21+
let path = dir.join(filename);
22+
if let Ok(bytes) = fs::read(&path) {
23+
if !bytes.is_empty() {
24+
return Ok(bytes);
25+
}
26+
}
27+
28+
let client = ClientBuilder::new()
29+
.timeout(Duration::from_secs(REQUEST_TIMEOUT_SECS))
30+
.user_agent(concat!(
31+
"Arnis/",
32+
env!("CARGO_PKG_VERSION"),
33+
" (+https://github.com/louis-e/arnis)"
34+
))
35+
.build()
36+
.map_err(|e| e.to_string())?;
37+
let mut resp = client.get(url).send().map_err(|e| e.to_string())?;
38+
if !resp.status().is_success() {
39+
return Err(format!("HTTP {}", resp.status()));
40+
}
41+
if let Some(len) = resp.content_length() {
42+
if len > MAX_GLB_BYTES {
43+
return Err(format!(
44+
"exceeds {MAX_GLB_BYTES}-byte cap (advertised {len})"
45+
));
46+
}
47+
}
48+
let mut buf: Vec<u8> = Vec::new();
49+
let mut taken = (&mut resp).take(MAX_GLB_BYTES + 1);
50+
taken.read_to_end(&mut buf).map_err(|e| e.to_string())?;
51+
if buf.len() as u64 > MAX_GLB_BYTES {
52+
return Err(format!("exceeds {MAX_GLB_BYTES}-byte cap"));
53+
}
54+
let _ = fs::create_dir_all(&dir);
55+
let _ = fs::write(&path, &buf);
56+
Ok(buf)
57+
}

src/models_3d/custom/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! Arnis-hosted archetype models triggered by OSM tags (stadiums, etc.).
2+
3+
pub(crate) mod client;
4+
pub(crate) mod stadium;

0 commit comments

Comments
 (0)