From cc1eef2a28fd631c08d5e57ee0a31b30bfb531b8 Mon Sep 17 00:00:00 2001 From: Bella-Q77 Date: Mon, 27 Apr 2026 16:45:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9C=AC=E8=BD=AE?= =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/comprehensive-map-app/config.ts | 12 + .../src/comprehensive-map-app/index.ts | 510 ++++++++++++++++++ .../src/comprehensive-map-app/thumbnail.png | Bin 0 -> 475474 bytes 3 files changed, 522 insertions(+) create mode 100644 @flywave/flywave-examples/src/comprehensive-map-app/config.ts create mode 100644 @flywave/flywave-examples/src/comprehensive-map-app/index.ts create mode 100644 @flywave/flywave-examples/src/comprehensive-map-app/thumbnail.png diff --git a/@flywave/flywave-examples/src/comprehensive-map-app/config.ts b/@flywave/flywave-examples/src/comprehensive-map-app/config.ts new file mode 100644 index 0000000..260de92 --- /dev/null +++ b/@flywave/flywave-examples/src/comprehensive-map-app/config.ts @@ -0,0 +1,12 @@ +import thumbnail from "./thumbnail.png"; + +export default { + "title": "Comprehensive Map Application", + "titleZh": "综合地图应用", + "description": "A comprehensive map application featuring 3D model loading, post-processing effects, data markers, and map browsing capabilities.", + "descriptionZh": "一个综合地图应用,包含3D模型加载、后处理特效、数据标记和地图浏览功能。", + "thumbnail": thumbnail, + "code": "comprehensive-app", + "category": "real-world-applications", + "order": 100 +}; diff --git a/@flywave/flywave-examples/src/comprehensive-map-app/index.ts b/@flywave/flywave-examples/src/comprehensive-map-app/index.ts new file mode 100644 index 0000000..ea283a5 --- /dev/null +++ b/@flywave/flywave-examples/src/comprehensive-map-app/index.ts @@ -0,0 +1,510 @@ +import { + MapView, + GeoCoordinates, + MapControls, + MapControlsUI, + DEMTerrainSource, + ArcGISTileProvider, + MapViewEventNames, + PostProcessingGUIModule, + FeaturesDataSource, + ArcGISWebTileDataSource, + sphereProjection +} from "@flywave/flywave.gl"; +import * as THREE from "three"; +import { GUI } from "dat.gui"; + +const CONFIG = { + CANVAS_ELEMENT_ID: "mapCanvas", + DEM_SOURCE_PATH: "dem_terrain/source.json", + INITIAL_COORDINATES: new GeoCoordinates(36.4902, 118.1742, 900), + TILT: 45, + ZOOM_LEVEL: 17, + HEADING: 1.5413763202653008 +}; + +interface MarkerData { + name: string; + lat: number; + lng: number; + height: number; + type: "point" | "line" | "polygon"; + color?: string; +} + +class ComprehensiveMapApp { + private mapView: MapView | null = null; + private canvas: HTMLCanvasElement | null = null; + private gui: GUI | null = null; + private featuresDataSource: FeaturesDataSource | null = null; + private animatedObjects: THREE.Object3D[] = []; + private clock: THREE.Clock; + + constructor() { + this.clock = new THREE.Clock(); + this.initialize(); + } + + private async initialize(): Promise { + try { + this.canvas = this.getMapCanvas(); + + this.mapView = this.initializeMapView(); + + this.initializeMapControls(); + + this.configureDEMTerrainSource(); + + this.featuresDataSource = await this.createFeaturesDataSource(); + + this.addBackgroundDataSource(); + + this.addGlowingObjects(); + + this.addDataMarkers(); + + this.initializeGUI(); + + this.startAnimationLoop(); + + console.log("Comprehensive Map Application initialized successfully"); + } catch (error) { + console.error("Error initializing Comprehensive Map Application:", error); + } + } + + private getMapCanvas(): HTMLCanvasElement { + const canvas = document.getElementById(CONFIG.CANVAS_ELEMENT_ID) as HTMLCanvasElement; + if (!canvas) { + throw new Error(`Map canvas element not found, please ensure there is a canvas element with id '${CONFIG.CANVAS_ELEMENT_ID}' in HTML`); + } + return canvas; + } + + private initializeMapView(): MapView { + const mapView = new MapView({ + projection: sphereProjection, + target: CONFIG.INITIAL_COORDINATES, + zoomLevel: CONFIG.ZOOM_LEVEL, + tilt: CONFIG.TILT, + logarithmicDepthBuffer: false, + heading: CONFIG.HEADING, + canvas: this.canvas!, + theme: { + extends: "resources/tilezen_base_globe.json", + lights: [ + { + type: "ambient", + color: "#ffffff", + intensity: 0.3, + name: "ambient" + }, + ], + celestia: { + atmosphere: true, + sunTime: new Date().setHours(17, 0, 0, 0), + }, + postEffects: { + bloom: { + enabled: true, + luminancePassEnabled: true, + luminancePassThreshold: 0.1, + strength: 2.5, + radius: 1.12, + levels: 3, + }, + hueSaturation: { + enabled: true, + hue: 0, + saturation: 0.21 + }, + brightnessContrast: { + enabled: true, + brightness: -0.15, + contrast: 0.57 + } + } + } + }); + + return mapView; + } + + private initializeMapControls(): void { + if (!this.mapView || !this.canvas) return; + + const controls = new MapControls(this.mapView); + const ui = new MapControlsUI(controls); + this.canvas.parentElement!.appendChild(ui.domElement); + + this.mapView.addEventListener(MapViewEventNames.ThemeLoaded, () => { + if (this.gui) { + new PostProcessingGUIModule(this.mapView!, this.gui).open(); + } + }); + } + + private configureDEMTerrainSource(): void { + if (!this.mapView) return; + + const demTerrain = new DEMTerrainSource({ + source: CONFIG.DEM_SOURCE_PATH, + }); + + this.mapView.setElevationSource(demTerrain); + demTerrain.addWebTileDataSource(new ArcGISTileProvider({ + minDataLevel: 0, + maxDataLevel: 18 + })); + } + + private async createFeaturesDataSource(): Promise { + if (!this.mapView) throw new Error("MapView not initialized"); + + const featuresDataSource = new FeaturesDataSource({ + styleSetName: "comprehensive-markers", + maxDataLevel: 20, + }); + + await this.mapView.addDataSource(featuresDataSource); + + return featuresDataSource; + } + + private addBackgroundDataSource(): void { + if (!this.mapView) return; + this.mapView.addDataSource(new ArcGISWebTileDataSource()); + } + + private createGlowingObject(geometry: THREE.BufferGeometry, color: number, intensity: number = 1.0, opacity: number = 0.7): THREE.Mesh { + const material = new THREE.MeshBasicMaterial({ + color: color, + transparent: true, + opacity: opacity + }); + return new THREE.Mesh(geometry, material); + } + + private createPulsingGlow(geometry: THREE.BufferGeometry, baseColor: number, pulseSpeed: number = 2): THREE.Mesh { + const material = new THREE.MeshBasicMaterial({ + color: baseColor, + transparent: true, + opacity: 0.5 + }); + const mesh = new THREE.Mesh(geometry, material); + + let time = 0; + mesh.userData.update = (delta: number) => { + time += delta * pulseSpeed; + const pulse = Math.sin(time) * 0.3 + 0.7; + material.opacity = 0.3 + pulse * 0.4; + material.color = new THREE.Color(baseColor).multiplyScalar(0.8 + pulse * 0.4); + }; + + return mesh; + } + + private createRotatingGlowGroup(): THREE.Group { + const group = new THREE.Group(); + + const centerSphere = this.createGlowingObject( + new THREE.SphereGeometry(50, 16, 16), + 0xff6b6b, + 1.2, + 0.6 + ); + group.add(centerSphere); + + const ring = this.createGlowingObject( + new THREE.TorusGeometry(80, 15, 16, 32), + 0x4ecdc4, + 0.8, + 0.4 + ); + ring.rotation.x = Math.PI / 2; + if (this.mapView) { + this.mapView.mapRenderingManager.addBloomObject(ring); + } + group.add(ring); + + const smallSpheres: THREE.Mesh[] = []; + const sphereCount = 6; + for (let i = 0; i < sphereCount; i++) { + const angle = (i / sphereCount) * Math.PI * 2; + const sphere = this.createPulsingGlow( + new THREE.SphereGeometry(20, 12, 12), + 0x45b7d1, + 3 + i * 0.5 + ); + sphere.position.set( + Math.cos(angle) * 120, + Math.sin(angle) * 120, + 0 + ); + group.add(sphere); + smallSpheres.push(sphere); + } + + group.userData.update = (delta: number) => { + group.rotation.z += delta * 0.5; + group.rotation.y += delta * 0.3; + + smallSpheres.forEach((sphere) => { + if (sphere.userData.update) { + sphere.userData.update(delta); + } + }); + }; + + return group; + } + + private createBuildingStructure(): THREE.Group { + const structure = new THREE.Group(); + + const base = this.createGlowingObject( + new THREE.CylinderGeometry(60, 80, 40, 8), + 0xffa726, + 1.0, + 0.6 + ); + structure.add(base); + + if (this.mapView) { + this.mapView.mapRenderingManager.addBloomObject(base); + } + + const middle = this.createGlowingObject( + new THREE.CylinderGeometry(40, 60, 60, 8), + 0x66bb6a, + 1.1, + 0.7 + ); + middle.position.y = 50; + structure.add(middle); + if (this.mapView) { + this.mapView.mapRenderingManager.addBloomObject(middle); + } + + const top = this.createGlowingObject( + new THREE.ConeGeometry(30, 80, 8), + 0xab47bc, + 1.3, + 0.8 + ); + top.position.y = 110; + structure.add(top); + + const topSphere = this.createPulsingGlow( + new THREE.SphereGeometry(25, 16, 16), + 0xffeb3b, + 4 + ); + topSphere.position.y = 150; + structure.add(topSphere); + + return structure; + } + + private createFloatingParticles(count: number = 8): THREE.Group { + const particles = new THREE.Group(); + + for (let i = 0; i < count; i++) { + const size = 15 + Math.random() * 20; + const geometry = Math.random() > 0.5 ? + new THREE.SphereGeometry(size, 8, 8) : + new THREE.BoxGeometry(size, size, size); + + const particle = this.createPulsingGlow( + geometry, + new THREE.Color().setHSL(Math.random(), 0.8, 0.6).getHex(), + 2 + Math.random() * 3 + ); + + particle.position.set( + (Math.random() - 0.5) * 300, + (Math.random() - 0.5) * 300, + (Math.random() - 0.5) * 200 + ); + + particle.userData.floatSpeed = 0.5 + Math.random() * 1; + particle.userData.floatRange = 50 + Math.random() * 50; + particle.userData.initialY = particle.position.y; + particle.userData.floatTime = Math.random() * Math.PI * 2; + + particles.add(particle); + if (this.mapView) { + this.mapView.mapRenderingManager.addBloomObject(particle); + } + } + + particles.userData.update = (delta: number) => { + particles.children.forEach((particle: any) => { + particle.userData.floatTime += delta * particle.userData.floatSpeed; + particle.position.y = particle.userData.initialY + + Math.sin(particle.userData.floatTime) * particle.userData.floatRange; + + particle.rotation.x += delta * 0.5; + particle.rotation.y += delta * 0.3; + + if (particle.userData.update) { + particle.userData.update(delta); + } + }); + }; + + return particles; + } + + private addGlowingObjects(): void { + if (!this.mapView) return; + + const mainCoordinates = new GeoCoordinates(36.4902, 118.1742, 500); + + const rotatingGlowGroup = this.createRotatingGlowGroup(); + (rotatingGlowGroup as any).anchor = mainCoordinates; + this.mapView.mapAnchors.add(rotatingGlowGroup); + this.animatedObjects.push(rotatingGlowGroup); + + const structureCoords = new GeoCoordinates(36.491, 118.175, 450); + const glowingStructure = this.createBuildingStructure(); + (glowingStructure as any).anchor = structureCoords; + this.mapView.mapAnchors.add(glowingStructure); + + const floatingParticles = this.createFloatingParticles(12); + (floatingParticles as any).anchor = mainCoordinates; + this.mapView.mapAnchors.add(floatingParticles); + this.animatedObjects.push(floatingParticles); + + const extraObjects: { geometry: THREE.BufferGeometry; color: number; position: [number, number, number] }[] = [ + { geometry: new THREE.ConeGeometry(40, 100, 8), color: 0xe91e63, position: [36.489, 118.173, 480] }, + { geometry: new THREE.CylinderGeometry(35, 35, 120, 6), color: 0x00bcd4, position: [36.492, 118.176, 520] }, + { geometry: new THREE.TorusGeometry(60, 20, 12, 24), color: 0x8bc34a, position: [36.488, 118.177, 460] } + ]; + + extraObjects.forEach((obj, index) => { + const mesh = this.createPulsingGlow(obj.geometry, obj.color, 2 + index); + (mesh as any).anchor = new GeoCoordinates(obj.position[0], obj.position[1], obj.position[2]); + this.mapView!.mapAnchors.add(mesh); + }); + } + + private addDataMarkers(): void { + if (!this.mapView) return; + + const markers: MarkerData[] = [ + { name: "地标A - 商业中心", lat: 36.4902, lng: 118.1742, height: 500, type: "point", color: "#2C7BE5" }, + { name: "地标B - 住宅区", lat: 36.4915, lng: 118.1755, height: 450, type: "point", color: "#E91E63" }, + { name: "地标C - 公园", lat: 36.4895, lng: 118.1730, height: 480, type: "point", color: "#4CAF50" }, + { name: "地标D - 工业区", lat: 36.4920, lng: 118.1720, height: 520, type: "point", color: "#FF9800" } + ]; + + const geojson = { + type: "FeatureCollection" as const, + features: markers.map(marker => ({ + type: "Feature" as const, + properties: { + name: marker.name, + markerColor: marker.color || "#2C7BE5" + }, + geometry: { + type: "Point" as const, + coordinates: [marker.lng, marker.lat, marker.height] + } + })) + }; + + if (this.featuresDataSource) { + this.featuresDataSource.setFromGeojson(geojson); + console.log(`Added ${markers.length} data markers to the map`); + } + } + + private initializeGUI(): void { + this.gui = new GUI({ width: 300 }); + + const mapFolder = this.gui.addFolder("地图控制"); + mapFolder.open(); + + const mapControls = { + zoomIn: () => { + if (this.mapView) { + this.mapView.zoomLevel = Math.min(this.mapView.zoomLevel + 1, 20); + } + }, + zoomOut: () => { + if (this.mapView) { + this.mapView.zoomLevel = Math.max(this.mapView.zoomLevel - 1, 1); + } + }, + resetView: () => { + if (this.mapView) { + this.mapView.lookAt({ + target: CONFIG.INITIAL_COORDINATES, + distance: 900, + tilt: CONFIG.TILT, + heading: CONFIG.HEADING + }); + } + }, + toggleBloom: true, + toggleAtmosphere: true + }; + + mapFolder.add(mapControls, "zoomIn").name("放大 (+)"); + mapFolder.add(mapControls, "zoomOut").name("缩小 (-)"); + mapFolder.add(mapControls, "resetView").name("重置视图"); + + mapFolder.add(mapControls, "toggleBloom").name("Bloom 特效").onChange((value: boolean) => { + if (this.mapView) { + this.mapView.mapRenderingManager.bloom.enabled = value; + } + }); + + mapFolder.add(mapControls, "toggleAtmosphere").name("大气效果").onChange((value: boolean) => { + if (this.mapView && this.mapView.sceneEnvironment.celestia) { + this.mapView.sceneEnvironment.celestia.updateOptions({ + atmosphere: value + }); + } + }); + + const infoFolder = this.gui.addFolder("应用信息"); + infoFolder.add({ + "综合地图应用": "v1.0.0" + }, "综合地图应用").name("版本"); + infoFolder.add({ + "功能": "3D模型、特效、标记" + }, "功能").name("包含功能"); + infoFolder.open(); + } + + private startAnimationLoop(): void { + if (!this.mapView) return; + + this.mapView.addEventListener(MapViewEventNames.Render, () => { + const delta = this.clock.getDelta(); + + this.animatedObjects.forEach(obj => { + if (obj.userData.update) { + obj.userData.update(delta); + } + }); + }); + + this.mapView.beginAnimation(); + } + + public dispose(): void { + if (this.gui) { + this.gui.destroy(); + } + if (this.mapView) { + this.mapView.dispose(); + } + } +} + +const app = new ComprehensiveMapApp(); + +export default app; diff --git a/@flywave/flywave-examples/src/comprehensive-map-app/thumbnail.png b/@flywave/flywave-examples/src/comprehensive-map-app/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..842a09c1d56b811351f42ee44061692802cfdf73 GIT binary patch literal 475474 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 a21bh+zwW|Mhf^Y^Ax;g=F4T|)Pj!_19M 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 K3e0PizzW*YX zYru*(&_zW6;VkPq1{SBXtY-#{JQn??vBV3cN)3qoqTUziB2iO5tsJrQxA`BI|K8Q{ z-=A+JhdlVVhHmSJ8P^8v#Ln*icNFm}Rzgt>_ykOQ4(dD~IH-J!hNTn@sb&YgO@HEB zSTNMzHDCYV7*za(xfM4S>aT}miVi>b={1=3!2=Lxz*xz66Axg_6SsH#ioX8o+={Fv znfKIuh!E066cK=XkCNL3s=J+Tx?Wp<6tv8)*f&y18SLTPB3>*nJhKd$xHUc}eJBc( z{?Ef}yxc~*McmQxYw_^4XDb;<`ICE}Q>qDu(UJbWpovY8`WG`GLbMUXXBxVZ4DmR6 zLXIlQs-Wn7Pzg6opVsEqFwh)stj!-EzY)afJvQESwVW@YgI5>seBxQsYX&Jy#+41O zO?`^n#Q1CY%utf$ZP2FgyBWXVvh0G@YJ1#A8P>Es^P0B{ehv`r^OI|0i zsiJ1Zj+MiTGhK!%oPDm!3J!3zYa+~NPZzBu&&M)KCq2~|J2H&ka^OUQI;`dlz4??K zi43}Ev$@zBD8=vf%d*_C_d-HR2=n0133ZO~nCJy(8u=+yWvuU#sdamq_v|N}_yu(Z zG>cQYDy8Vlav|ek)3l%ss&(Q-O5rqD53Eee#tIK9ixNoAcW*Eb11ln_)KlXrCV#}>?iU}Tj)O5TBIPeA z@14;(MD}ezRAVBslq+cVLM{tXy_(^k5dwT=yaFiw#JfCsmn}Z1xOnq}EDH!%T&#S% zcvJqb+;eZFXt~2$0S|f@=5OR}w8w*Hid=A`O#$sjRVhaxX`}Emh=cAqAAhn2(I-?Z znYW&M!KR_)C;kjgj4MLpXD#;UMA3v@4E2D}Lm;q^LfLr4#Ag;N!KsFmS$B1^Kio{R z&97|=tM%wIPxCqoi(?L>R8=$B24n8LM$Ai?5s`o9e1#%x@;^?YTLIovF5u3!65`W} zv499iPO+8dln7cFuZblc4E4k0{P%07gT8=(pgx^GOjx=>Oogmt0$XbEu)P2I*|&pJ zEzqmKbL@n2$#U{_LHhmjAzGz?rNG8?j+eu0hs&X9Z}wnFKNX8SWUWPJ)XNc z)h;S{QZZ_4ps@Usjb7;Hp|<;oSX~`!GvI;B&yTexzsEYIkAfSpa&hZ3D|*3hi4(Yt zuM}gvC}P;8vlNo*iE7-bX^PDlEJIZ+7ybA)@_U6AqV|Hgz{KT>%Bpmj(`uu<5?)IG zkuq9?Gm(8aO?@TpYYVrP+uah#_&wu2#lllTt>0pa?^@`$Xv#rnlZH%zIiK#@<4Y2Lj2HRar4$0ruA4t0BLSvi_l?(?@Q<{XfIM{4evHI{Vn?CbmK6+zon)3 zHph>*c)<2{qrbLx!OEF_<)&SU$xAl>XkZ2We2#UipMl59aWr#Mz`vWr5}3YK=}N0C z|9-}0)=5?cx`LPc$N0Sc3R*f_!xWh+xiMZDR&TKml2%^OeGAt~=AOMycD5wHvzvyR zd%|TbAxvkT$@mZQ6zlA9so8S=b-DriO|PabVMLEB z3ZK60fv|~oRHomCL=UEc2{AaNE4D!0fmz&^(2c08OR4`{(ZssfbpNk z{n;%?hzG9aesLHaN;1l3_R?9ePF(+OPPK8SWKBq@k1{|aJ+fK;?Q=Gd^T?)78zwN{WA1T;BE?>5Q#Jm-Wq-YALlpi}KA@ zdnuZk5w)HNZ=>o`2G?{_bKw;~%CU5Ytf61Da|}RAago{J%4r?hbLK|{&bBjS{rf!W z)dLDjCV6ZE>^EqZGR+dNx^5evBYEa)l+^@lDIs|X2{vtc$fgc8a(mn2mclQ2)^mi& zv1lQYI(|;+@*zCIYblmm^>87{%Akd&kBM`yjmWLGNZRQ;3zDK?sOKxIrS=g=>z)SR z`}vi=GbA1DFUz%}9y?2)y;Pzjs&X$u!z&Ka81VLXn&k!F;8u_pl?6HppLw&!c$J_) zSJ-`$ba`=6Gd<07#TDEu%vPUNC>NXD$U?rUNqo|xF70wK)+y`0f@a8;h~b7b(O7{6(tFMeipTFK#wLf^=j?up{)jNfeMaeAfc;|AEhcnmOV2}ypl#YayCZclY5Os@;p@! zv~Eb2JTafAj56CW(7T7;H83z=&V}^fQKwj4S%dzZIOIssm#8B~nDEXE(k6rzqYH~^8x$2RzV^MwKA>oNN?6z9how7LG?Ls-i}ao-W_`{*c5w?4a#pPQ)M zbJGDtQD^$kVBw(C#BJi|KzLJou+Nz6QAQbzE43G{>__OI?A{D-SkVajj_kbpDC~Qb zM6eD=C8@&SXS-V>Hl{#wQZ(&m^UI-|!UbjZrIP+`U%fwq)ntM^+<0yN0xk_lsvpcG zuK!>R+bP-ob%R{K-?Eoa#BMD`JpxcF54yna4>-}zJ;|*V$-@qoWu_0LaIAcVg+Vj+ zN;{(ZN7RF9B5$x#H(37ys}+AgoWYx%??e15?&a8_^KV9m&nu_pS=^VEDrXKo-+fv4MmYdVnp*fO+OJus8XLv-Znmn`;z+A_@`kEC3-c}BL zU=C^YD0)d^>+o}rdp;`jxkUjn5&#j6VSEKhvGG?SIM|Nplo%t(%(jgLJ@=pK-t;5AE0Rt&m$FR~mLt7Yuo1-5>0wx}v@3VvgxA{8_KuZB zgA)6U5P2otK~>X+3Jl5nqY0RJP33#cuj(~BowLoxoYX-{3iGZ8n^=^AMeg;IlqM1w;4tO9qb zihLV`$;H@ThR;=~&Z;&mcTI^gT_MCntj~CD-wyExKAgwZ0Y~nF{mUS=^d(xp>puF* zr&V9-8;z1m;u@jlb&M_l*8(J-QyWI6PiY#l766MUNXA6r-7Pr4=`3rfk+-%nZ&$nz zi^ie5<0H-=aQyTTcNEfSllN7yXrNickOA!<;#U)+g4+q_O6`y&$sV7(5(sksCc?kP zC%2~$ZxGuX8;?)pW)!G>U)N3+jC`smup`1nlVHhX7hho>j= z+)AzMwQ|AMkUBVish+V8>3A~NG+2OrhIuBRhx=BCSLGzX$a7pAd^65c#4$09b&q1` zKJ7M;aGV|x16ujg7a$dlR@)#{@sTga8YKP`f4rwum;!NPyswPUt&_u*LnLbW%!5ps z;pL+L&P{?@Ur1i^dscn_OgWT$ST=6++(CdDV1D}L1EcyB?hf~ExytM(Nm8yMxhu|y ze7-47$*}W#MS8{0j^9T8Ms4tvG>_pyxUZben-{UKWlGU(xj=H}#QH`P*-;(q`PwdD zjn?)z z1V^z$H32F4b71s`^a5gmCul^#2eYdk6Y2%%9eDQXXuE;<>lZJI=6A|_<9I{y$9KMX zG$aVIMlR@XIv3CW8};2~t=H{46h(-|TD(0ZhlmC(yx4F(HRNZ$HTI7tx^(!B>pLW| zq;*#9;fvVe7~Sb~kd^oUa(uTY!kv_n6sg z?k~B&?bIns45G0#WobZpBm9nJACk0m{0|N;UOW`<(!-#Nuf+_%dtoMuIbC?NAi`KC z_J%QHq&t)6fTA3y0yS`()6IksR%ngr15xWU^tg}HZ*pU?i{<8FqtQWvxCKQy?pH&M zsj9N!ZldVL(4t?Qw^am{<+>nKOX4&nj`>I>=rE9($Eog)nrLug_c*A|(==D?dLqPa zv4q!xX{ADa(zM4F;Xio5yg)-^j0Ma>x|?Da`IgXtM>^^2j0pF zq30_Nx^Hl5G+j+eQdz_+nOKn z#WN3ut)F*q!&11m&CI4C9|4a~JPauK3DeRu-yv=j^ZW6`yv}upW_ZimE!3n^kw7X&WoP% zRp;3L6b;oIAmt^>&&VK`ub3^z82#=nc@>GfjOa|j7%{ZjAXbD(d?n6ZheNp2c|^_~a;-h~BtoS{M4T))n1#SWp7svkd4Itk02GcfK)*z$ z<#>jLMN;G6I4VQ8e5(f#$t6U=fy9MbEh}0m0hTExEtvugHppi+GX0Kdr)+$$FKf%2 z%VlQd`Fm(hBX?MWxtJ!AiigKI63X_3hwB$llSL@JoABZ!@j1wwG${U5e1|C2F^H7C zzbt|!f&Y!1G&m&TMm0?AB&mPN<|@K7{oF{mrB|!S?PHdQ^R?cEecYb>A^a}> zc63P!7eKWgsK5W0PwPU+s#2>|d$>ZeJD=pPPyCP|R(p*s!D4wct*W35&62vOah8#n zJ~7!cOVD0!8)F<2tYsbnNk1gv9$XN!%!N^|>3bMhzKV1*HTY5GBR3YBR={v~n|gM|VV9D1#1#@OeyFCUcyGM;rBGTTkCaH}m0YWY+|4)?jqwv6aNCtrN~;&mLf z*tZ@i@aLy;;MmX@p1Es=jzKg#m{-0Sd55`N&q~Gu6ijQxP+CJQc}P-Dd!P6Zm49*u zvqfFk;+NTKv!089BiA+1Sv`@_F;xe9f8dM7O&@=cDhR)0V%8%r`7M?hMfNJn5ZwW0 zMYS&8htw6k@wIkhbx%|On5Xiq5bah;mN*dC+^wn<{Vz|S_=}$a?RCQBe<-3{!6A7! zd0<$z1Q**kU?>-u!cjoME-;*2u3*(`W${B~WTaz!aF7?qGj6|`;VlI-R*yi*h9d)ZRU4JVLsfo%ElQgTCB?0_VuEH_oK4;6d+fb&T|=U8u-L}BpyVmf2AC3Ch9!E*g4V%oq({x9r!`Twi<}qV#=hM#Okj3 zF?ds$F|EqUqqq1}hMR%8tT&+Ib=k1TeY~$}Vm6uFuuRhNH2#~K{-fLT(~Gy{&&0a$ zt;^ao2>#Yw_dh}=>6fTq^AkYFJi zA0O4rd<}h#d(%U=_I7n_BO}gXh}v=^D=H4!`}hW{aN|YP;46O0v2CpZeotP7 zi{dcC@QUj(SoKecShhFzC*okpNd{u}uL^D;%velLI9pea?a)c~)?#~4nfpH(qY%sy z+F}1Vd*_WJ4al252FbY@536ys(9j$=hxFNr^>XK$CeL*fQG5GQCM(sEwfj`B6e` zqRrON6YCQ7!RA>*{F5QN#`!6wf?J;CiNDd^H5;0d9~_Xefg)#Z?H=Tq^b(uPB^`6jYktdlhbIg(zC+Vr!&&oWt|o_snmN;3 zXI%wIS{Xk>S1G3L7&dpD3(O9eKAKf@i1%Okbj^I?E^-jt@`*A4Cyl1npAuF(1L+*3 z+bE;5rC%{x>O!EBLsy10hPh6&GJS4roJ1q!jwCDWxnh6Ue?5(Fq`A{|c&(b6%cf&Y zT!h|>VDR{^v8{LIn7;4aA2qzGZ7yFvFtkuRHI?lHfnNj-2vNrHxWH zjxwCFWm7zdqTq^1WNJ_8q!&@J**`)lN>^s3{Y!+v12Q;_yXdAvv(o0hYkuf)la|M< zN)vNy9X<5#zm5;_>$tnF4(w~EoVGq_gx|oj)tzTj&|zY%fjJKH`%YBD@$Upn>w5j4 z^WTsy{&%&L!L-#@9Gw3H{Xhc0`y%TdyNRv`7mfRR4S2}58vDD7wyr{MM|9-H$MD3j zh30D@|zLR51KC(~Z5S>ED zgV&cCp9|-e3t8udt+L5^LuMV=^2~pK&!uEw(-WEZ^-TU`5)+k#)cPo z!WZ2VeMvh9RyN05Y;}Qgtku#dEqf>Vv-1QoiQ&O3?(8>RUNi$cMfuK86My~vcir|K zyv4A@-qlN% zsY_dxn*0)_3m)ibV#c^)MLc%iN^Sd1V$9ee3s;9kBl6#n^_~B`c@SSwAd_o-D`O|~ z7Fye?ZuD+ib{ZN!8B30z%>6{~Oaf#71Z)WODg@guRU@NX$#L7O7InZb*^UHkg+Z|y ziNuy~#m3CF@tG0mCiKLYd`jQ8jP2Ezp6W(|h(8yO*ds6dyVxt~M_%kyieJ3g7F_1@ z!*tT6=EnyRyQ^}@f*66Zr5QEH@D8X9=eIq-ys|4kEF-cL@RZD152SU7qB& z33^v)ZCcbyLD>Wn!0@D<4Q!AQL9am2PT(ago5_B=A!E~`XL45JGZuY2j&0kfs#Z!S zE;3JU-OnsuE(v%BwXwO>TO+GiJ9N<}Mk8b2v)Fd@wCqx0^M$`@64cliyHf{5dDp~J z0m(|SE&ETXLMOpAGC?CI$)rmMF?;Jy{JIO?fTWxEvj9wyA?Z>8HKMrv!;|;14lZ9Q@0^WoUF<5ZQxxrk`)Mvdr$XXJ1Oc`h7`d}7`> zr%rM%HXZ2wx<7bT`dmLX#Lw&}g^m+BU+fK!_2i6v<1@Hywq}#9XhlwMrTw-mHlbD% znu*-_ngctA4d^1XtJK6fwiog;@5^4~4c3Aow!M5>d5P{k=$z!I7`uRP9NCHE#(@pF ziZ8erkQ#i0k3Ou{6W#}Y9Mr+BxUxn?Ij}2lPk;Wr{-6Cm$-meWRj!huu}y7cPub>B zx#@%bcHdch^!X?<1KFD-D>Clvt;y%adSdU}hpJZkp%cY6bKVP@v5mDE+9x(gj=_~% zk-cp@vHswK@}ba)k{E`5Fwe1D=)XX#L|^!txY(BMg~uVrvtK@Rm8SykGWt`-8JVJR?SmeuGGrK?sVed8v*b?Br7azYmw zkU;HJO8;b0A6yzzr@sdH3Vm=8%MN`2eFS;@lEqXp7Q4FZmu-a&f_#RS1)3Y&pq@By zTlNK2tqV#ZB?T{Vr6z8*;SN1VE>8iGi_j^laWPZd&#niC-^~31EH}^ zyjx9-iZ)`EF@hr73%|1&-$>-fmf$lFNv=hQ2FMm|_%kkah|=|^T;X%{C1$ZaK1E(Z zld&UDfxPaD%~gd>8w=~imZ8wUyuatCbq>`h2jKyK% zuCXWc@udG`eLS)CAg6?H6A&fxOx&t^y+PQptI#zvj-Q21)xF|;<>`qXT7DKh1#Mzp zv_*VknHNlewUTHvE>^-?NqmH zF9>~ao2nbv1{dZ-gIv}s1}9(;9UKB@TQEwZ7GnT|t6^Jqpv1Rm0uBW-rY7-Sz}zk5 z>x&V^k3eMEl}gSZZ3b6=)roERE_2da_NE)z>wp70myW5}K=+q@iGw2(SNq?R2|_QE&3&$O)Xth3}&^aLJU5+=Uv>=BvQ z>Q)1>VPN~4_ax^6Wf@%)C1ch0)t?YYdC_06CcG}{1bmHSF3Mn(-gK$!N`xf-%s4nv zCVbhPgDd1Mz_`?zgo7L86G#$j4lTVe-dCmA6#hYQW9dd>?rerTud9|Ekf}{z1FMbh ze8LwP*fg&6iiHGe=2l@*60fAefh{UcH(-s=m<}jG#@TdQ_b7!H) z)`AwcKW#v-Z8d&n%;*qhU`y zHZbu$G$(exA^mKK;fv0Yr%rzmkBL3uwJqD^NU5t8n{Kz;x}9%qJRMsKd(hiy2Ul!H z#5ju}dM3h~vH0aGM&`0Ry0nU=d;n1r&)9j{F$II{(#pXd-Q;29W#COmfHh+?x+13d z!fa9LDw%a;(TNROgDcCi#>S$Tto!58omc;%DQ8}^cq7y*2^}m6@_1;Z5gafjNX$1dt^6t9Wp(2VdOpy1 z+cpl*RwJhwE9%%3fE=0Uf@c1AXuC?09J(r`qUa=U%G@!MHJE#xtkVaJF)B$^FBqYHm!EAqyQ!-OvLY+E1sM~)nB ze@^0HV>}n_6)$WNvfvra1zvTH5KBvTf7bt@&~Ns=c|A!~k^bKA>DlLO(?yAY!^ zlN(hn+jJ-5uX!lw8@YibGoqILS1hdHo0!>F7WcL;2vUQqZiT<9)%2UX$_r;(DX9X9 zQS3hPFOd9tvN0y{A6y#aw_R#vZhJ0dx7Dtyn4|+=<8yK)ayB--EVR%I1+n)6;)>$J zo{fVcW7#~fv7t$f?aQ{v?k-5uCnk)=PG#bN*fdydVy=@HIR&7iI}~{n{8fX6e);wC z?@7+b$IMT;we2@;*lc_p&|YJaGm!;=>ndnkMQvL)K)Z=aaH2#~8HFyqqKw!-X@F-~2fl{3tFU8}eZ^js;4hFK&!NyqcVIF@gUxD!Ec9-~ zy~2y^a&xfktoKbqcObZnZr9FScNd{WO5#uMTNHSs??H~7*ae0-o!EF%NB>Y^=Z%d0Nja@`JY*@mu(gMx_}3$ZB$?iFN94AK&$t-|`Rie$&2X z^R{f`N7KLT{$NfmD}E1jtT|==(@su5$k_)^cS`#9?(RmolC;F_5%1Pal~4= ztTJ-xhcEb8BgR_wVE~A*c}~-{l4w$moLFZ|HR)D9pMZA8z%B3{DP;j zud0hW!-~?~_!d}~wF1rW%rlhRHM&?D&o`XKyvWrnT>8D`_ z2UN*+PyiD6(D)OVJ}{9FQjMR2oR2EJ>4f10GxDLgYhe=Oz@kS_;*~v3!ft$v&#_&M z1!rVNZgs1=RQS@}YVzf)rq1;|y>H;4bw{NO$ zMV4K9k~fJprmy_^Wd|~&-?nV42Cp)^N74I)0FNg$9; zPgIk|Gn6Eb;w0c(hRdpM#UW9W2%o$TO9D=UR$YqY`5!|_K*MM8hyJe1w%`(&IG9Dx z@OnC0n>w#OP8RvZ_UO*0d6M7@NWRo-QdkhUh6UHh_OdCmZEF>L49(Kxo$(eDFk zY-7Vsu_1gJd**UMTwq^#cdLnAWNh&bUrr8%(2GkPB4iudS`a^NFPu`KPn;(8if3ZN zVgHCN=*q%9us8Caj5V+MV{>&QqauM=4mN!@!_^absjJk`6t=x}#*eI-e&IwR{nXW} zF8I7;#TLS$Vx8Jno*Ls{Re^@XF!Hgzcp_h-4TPq;axJ*?8#&koFSNE7zWeG&URQxD zF{HWX=~y{7XveP;LkGMk{bS|2l(FL&+#^bP1^L)w$v#A@Xq|Dg)KQlT%oE9_msfNeGTk{oF4 zuq|QtL{?}f?dZGaYcM8c8Cgh&cH+yx_raV7&Vx%A5WYfQ75;3yc4D3N6J2&K{$jlG z=Z#x>V;d$^w}kw}Y9imZ3Rw&(bQf5rC%z4=+O=ehGLaP!yr~1S)c9+AiEtS=r)*yk z9cjzRvEIe@n%DXEmmECFr*q9Y{1C>zdeNQ41NE}4DlUZhlQ|@uOU{!R-T4XY!5$VL zL%-$`dA8vz@g-x=M9?~Cvp3RaK;64Gz{GIpEuqbdU@Wv|?O9s9HZ7o_3r%&LFDpSE zIAIw$#47dvBy#B7FRy(t03=5|{UzPEiQ&Krv=V8bH{N;5u}{wed<-3m=E36+?+bJeZF+2%4%*k!9o%v6aMw`3tRWMOQPgwwLW^#<0cc`{0d6G@Rta zmB^>eUsWqG(R)H4+=y=4=c0XbSRClWALMRq*4apIY$oAb^8tNqnCQZEAr_hS3nCNO zLJD9xx}qb5g)fZ_@#)fsE`*>BTA_C!&PqA4DT_55?1U!R)D!(_U$QQ}HW)q=T{FzU zfF~Ps_`hBo_km2%%2*)lV%u+uJ(-Kpr=AemUU@OmH|Z;uxnv+4OL)>2bc4Bzy-zM0 zailn0GI!w%J~d>Jn&DVz;{1;FP|EU${IRXrFosh<*VR`{S)` znQ;^?d5gz}#H*h@;6&CyzZ^NO*kNSYrA`cA{HTXdYT~?TY~@d>7ZgoL71~8%6dAE2 zdSZWUF}TYg_DOOe_{%N{F*0$fYQe3=2aSzvQ82<(ks}%xuQZ?mttc<-U3f17$gI!@ ze=>)8pgr+9v|Xj-l_TFqgcUli63bTu(z$eGK99EyE)YwPtj6ALyD_gHYGT$K`TPrR zi$A=v^MpTsr5&)XZNJGbP4eg(zjR0bqJ@V+RTPD2GGPfxOio`g7DiOJB-5R;4M0U* zZ>Zn`QqitrTvm#mwlqlElK@SEUGT-BEVAx`Y$|x$s&3iVoC91I>|D5w1bNFyz39to z0<*n>($EB|TMgJomaZ~|yh~4b>B@|xUVZGE_zwk%c74ME%>*D^AItWd-1_BX`ry-N z3^9`E>(64-2dXZ+>P71p$+oY3bGoVVv#>FCg*R^^(!S(R zz3Fnn_~7@<8=H6zQDciuUNO5iKJu9_|5DqQ3vfXp>^fGMC;lc6t{U-?1Ee3lq8P|0 zxYUxDjEQ`rs8!xX)DbyDgD#es4i1SN21nux9z)gz*VQcI4;6J}OuiC}Ecz3k%*h~b z6M?p6>?)wEBx3{k!P9XrDNioT2lC@f=we{_PjJmz31rin7?gVH$(;U@UxK07+cW?oCqLOG36Wc2IuCbwko$<|%{0Z%;$SETmx&hC@{xP6~ zLV3#HnXC7~zI>7tTlRg^Ex8%p(0AABcTwMV<$rzfgPbV(IY5mJ@zbXHX|IQl7WnkZS=&%#pyO39{&^Gp2R#8XC4c(Dz`WXuz77gZS z*$>{vJK~>M+SV!r=D@Zuo(hvAiHi*#(M(M4_fP%t^AFyHK2=rPw;TT65II*4W!_Kb z_`$lL#KW$2X^fnK-veCmCpwZ3!ADNO#)ga&`_Ncc3MMH-`Le+UGJs84G@(r$lxcA%)=w#V`EOD!!D(~ z<(arx#0*)?ru-TYP2iFfiuAA$#>8QUK5gps8POmXp*lIJQ&+bN`Drh}mcrNA5}Pt+ z8~Zk(CB=@3oU!)J$erj24C*(e?=Hx#;Dij@OIKBsx4ZT{^tc(SMUy!m*ov6d4_%X= zspF#!|Ev{nOIpAHsV5bK?E-213}_Wv;L?N=$+pEue9JgqFR%@f7d{J%4xgzwaydC< z5_YZbWGcz6Q|dJ+H&bm?sM>j@@xRT#r1*5{}jn_4XVnF*)H5lozN{+5nX6?TvSHtj%_GVy^X2{LY50&HqU1bT>L zY@x-Fl|P110R~+eOaBcSxBc$MGTBx(lzqRcu|Z;d@(n&sG$C&QK}xYDb_GITUEoSy zv4a}DiPt0+^pt{`@Lw`)tMIS!D|%B;2(oD&Y#vz7cmt7p)xwa0+zE&h{_2)p`uh6G z{NIs3wez~_mSjf$Al~OoUgp{|oKv<{)#?|2nwiI(FErz z^jt7jPHE{_H1H1&y7ktB%U}N0zl|J>&iEi6(LuO$;O`Td*fqHf=Fs1|SZ9qdt#^S{ z#aCAeQRLP`@vrDK^u^e+4O>7h-pD_Rb86em-drfNk=kA~Ip8Ne(JyKdkFL@O`I@Kh zkK0Y5>ALh5iufocxtw_$@JL=ZTPc!m zE6z95y_Td(5{Q`J0%S>j4wBBe`NjMa0g#z0g;op}#)*4VHWog(=ug%rH8GH#@teLoc1c(98t zxR*@yh%0jjgW#XB0SU92uMUQS3lr4b@|9RuwNlq>VZGsdS^z}{+!?`Rs1#hrA4He! z$cxLe(oYTS;OuU#7!faV*>Hf(_Tn4N2g8fHe{pu5#8OvjYq_&ui6j9`b&E z{akzg#fPyca%t_-v~;pR!XNo3_fwM#5v1fPE$Y=(_+c&ISlg=axy(0%1S1LypuB`$ zt(G_2swx>$f(t-#g@;Cyap)7YyCtB^Upy&gE&7)Zzol3UINNdo3`GI_duI}UvlegcyudXn z`rryB;MY6wGrnL0=Dgp89^0#*^+Do;@3nBfI6%)8rq~XyFous{ru&O*qn7w!BRZNm z92`EO9QMJI0{Qy7Z>SkB;kTT9%P%{~HXABB%Dvd;+ozd0VPn~+K+GzlDwnED8wb#X zPe8}xp+?6HFA1z_C03Rx#QRf7RVi0^f+vJZ+313j*Q`lMF}~OY$(3!swtcL>M2@}W z!sse&6s@?H9DLoqFeL_JEU>W5%WJc~^1JkWYGOk~{~-R0uoWMx8e89%4q5AI{34&p z&mb1po4?`P_Xm8Na(#5fpXyRoDf+TDxvfv)8H_iv#6m(fc)J!!oI~V)P`58O_)CL{ z_}RqOF2+ME?)2lnn=yN!tR<;%UmbEUL`L>^N9vC8HTejaYLAiVzVPRg14DYut z7ju?)1w+@SWdnJp$nmMv@gzpcPk7?nz;67D*34BmI;<1i1N;nd#pr68n4MtAnlNN& z+W0-WNlkc4%?-jOWQNRF_@=ip*XXT^L?p#^`?K=JL&5;pMIHzJ35lG*uE=y1xstvG?M^>mp9k8(fu+gYzUFCmfMvVloHL#BPGSs+Akh;|RW9 zvHr=glA?FOrzIH+2-5GWg*zjLDD`SCa`)oK!i1J>I+K_zVr{h<(;rZ3`{2`asRZQ|iSI}iXHc~fcZIMfM^jZV?*o`YGrHhoR>5Rf zx|+;Q)9qK zA@YK<@kjV6M9HddrGTPuKMvKhFCb7v=;u9y|3yHN?M30A_!_-04h~uB-q8~ur-G%c z)K%!veGpL;&*x9QIEY@fPYNjQMX})|Dkdahf;UO##h~$fE)J^@#` zY^%C-aHGszvK8yP000mGNklB8kx4szt5H=>DR<6KgTa8SEX)<2(_>!EZZ#(X5QtP4U z4X=&w)X7AbjgE?~mYEMv;al|PQ%%N#CoxDpq()zC=s^u2uEE>IC!x%r*p_0`%m1H0 z|I(nQ@<}@nH>U3O>w*tEh3&*6ls@8047y6TRb7&$fq!!mb%4(K#(!ZmHuN4ZKKgd4 z&>^mJtGi{Rh}T@0FWs^OzFzrmZptUI8t{Y_fxKjXgv?y_Q#0IjCD}&DP~tKrb+xLS z-u>Fq_w8};JN!-Nj1lrePa$WU?$p5EWX`s_3*RletKHF+Ps!m=d!%NzP4|uR&<}ns z^f-2H%zfiwHecs||NecAFAmEbz=_S1Ju!CubIJ$i$w zi+Wi&hobX~eU}3}v2HMa=V7|a`e2N0)G0MS=}i2~I^El6&Zo=?N4pBYH>ek;_;&2a zk}cLk!4X{#=DWaxFDK_xA#YpZ33c_-gOT+RY&#|-_-BY5T$~e$xww`L`zNhkD&+0t zMJq4yPt+2uG*cNzcH&R?L$^$6onh?viJkC=Z%~^TI72xHUYw!VvQPaG7+3J&PXw?l zm*m)=iXPr2S-A!_FX}#iU+-TZG_lVf6*7Z82n%v3M!<@mq2P!MUbf7NWY--hNr=k) zgm0oC(x1Lqtg18+T#UtKsH&MOdKqcyi+uKcC_WoI!Tsb640f0mIaxdmURu6@JN9zJ zzvvr#)lDt!OK0MGaZgMgr$33WZB$vd(Py2+BeKyGMEd)RJ0Y#WTqNW~SrkQKlqEQ! z^fQOfrTC*GfYQ(UBtQ~|CE2B{*;cL?zgDtIE)z{*9eldo_Ctm@>#>{7lmB8Ms1l5b zPn??QE}T!HZ`+|pe%}v09^bWZ``R2ywtd@6aZKbeCG%6*2%gAo@Hat>jcXkQdHNnJ z1`|8M;x~Wf!GIO;@gSD(X8batb?`C%ppXw*4m1LWn0yEG0uS3J!h8^lde{? zzNlJe9u5kE7y882YkiY#4e+eZ#C%>+x$M%ZDm6Ye{IPYu^L?=~Z(clyFY+fFJ?oLR z4Tg;zZYzeixp7>4V*b)U|H3~y9UI9#hj7!%BFxDHb%pM#MhA7lL)=b%>3zjc;&vrg z_%-pP&{go;Mh97DF7r1{*;ee?UI*q$9w#<qD}ASO?46u~nUQQmoB6uqq`hF#6DAVUS0R@`)+g8+of)SOi()6SJ$VS5 zVA8rK^FceXKbHRNH=#JSd96A98!k|vlPyPa%G@#E*^#DWkP59zt zmldD4ZIf*^Ikc?{eS#tSyK>{4D&{j+jJrx*5O{1DC6>}+^{w0X%A4?2T(;Fqf35ie zmQdCwKu2u8c>{K?v1IJTW_U05x~a*Hv(AqGi+yskN3u`O)xYJyp=iE|t^|Mdi0fXp zqC3QtV*et4$@i)?@P!X(SyudC@|J>S66Xnzz-%zu2KLAhQ(lz8ARbY$WTFg;t<;zF zk(omL*2}uy*G2AS$@ZctEgl*LOMK1O|3IJ?*#oH~K2YVKx87*C?SM5l1WTmTPb+n` z4&r#QSC0Kybr7BRzqnaS&50Zg>MOq@J=wQo`7*&URr<#@0Ui2Gr62N|m}(Lq zihS%iV}K^+iBbFwP3pjPpoo1Tfnh57%ZG%Ct=#+$4lCQr{>nTjmbyyu(Z&L_Q$OF5 zpZ(B|e@B=0vT%;roVqxyHe`PA>HIsN)VHmb8{AIY;gj%}H!#i^fKaPKrdWS)W<>Tl zcJ}n9W8bk~%C8d&#>ak-PafdnU*?Ruv;#k)Gwnr9rskqI_z!An-w*BEj{O2IoWvL4 ziu{h=14_GdR&E`eTDbC%m6$v^f4->a#B$jqrs;PTI=%edh)FTFE2@bHIiR!z!UiorQUKD{X787M z+l)*w%Wzq$D&okRr3PE(Cpnq1hiH5gV^N#3sB88-GU?k+!(Popr1jw8^7{|&an#pF z9y9*NJ@257w{0U&@B0$trml=H-M9U&QdO&~WT@#!ronWePuL&9LBLXf7x_AQ7)~3x z;#x%q=J3k4BHS46MyZ*O0%-wGASwVVh9UTi{wmtO`5WW6d<${nz+r{q7>#@;yLvg6 z&4h}jJBNL4l*U#z%tkN@J|i$m+AV*fZ$d+H@A}BV}DW%#2sF% zh*@>1x>ePRe+LPDH4f1iA9Qh#bQ?WoO>1Y88EPMb~)a znqZw^8lmO;QzwUD)?vNnuvM<5i#J{tZ~9zI9@!N$+RWRAg}6=;*K^qp24+{`=jO=L z;<2s57v-|VOSadXUCQ;rcX2?(Ugj*Tx|Lk)#486@Q=^V9l%FZ;4xub5bC`12wLKfnG`=!*x;_*mFF z$Y(xX#n%o041U|PAuu#^-?^dw`0+yzK1^gUMRrmV@$JOUBsQ?B!S_9fKW9K!DY^=M zv15lr%1tYufjaoWUE}P<#k)bZ3kh>VqgFII$U-HNq}0*lQ6U&`Jh_ERFC&NGZgM`t4Iy zE7b2_YsRkah{>jf#5FN6(Xn(QW@D8rj9EudXO|5kmF|!13p+{V|zfmz+YdVr`_RprBeYH_Pkv}>6 zD@t6gT+5^j{q!(uTZMrpLAIBYt&6twxw008X+wrTYbnAU1UH=;Bnrh#U-);P?7LfW zZg7GH{Jv##6PRjjU~ef(pct7psdW0r*fG<*ShB)Jj`G-*exz{u(0vT+2RKrHf@p zRMCCm7lDy&6|&)}Zsp1Ux8MIu|N5{0qu+l2mmc4~DSo1vcwgMSPetz}cOx4PJJI(F zPB2gAlJBZ!Z%ueFEn503V72JxAYEX97qYu_7lqRW2wDV(ap)}|&djXiP2-o%EY z0NxcB4x52L_x!E*UP4L!V9i>WZAGVi`?Kl`n~BFjXM;5qeDUQ;y$#lFFi9)^;XSdH zLoGMRNxUNyj7G0*nO3w|*9o?ZnDQbQ>=*QeH}RuO2@INBCfKT4jlZ^WZL$u5jd%E% zQu5jw*o|$=8Yn-hrwJbd%t$-+{9r#Dsgv4xonLFdiyELZ27X08K18OmS1@1bNiAiq zG6#QmsmihqfGH#2RocM0?;HF5P~@X4ayQm+P5eKpze~ALA(Q*i>Z7O7gVv=h-$4BS z+wc1Q$M4*zAM1hRV9y@ZVW{ybScCm!|6Sz4_VTsKUG{PG1y?bD;mZ@>FL-0)!Jhxl zjs3UpKlGiO{ITuosz4)#|PRZ+qx=-4-$g$?_bx0yi~?nx@0 zVEgm0zxWl|OZf)yub+Re2baWF@7$GPr7wi?iGJUAnIC4EB8trOzWUL(J{aN4h3@3v zwwfH+NI^n&B9peNRhe7kqz(Uww`~hOom*ty{PCnb>hs2U`~J4$D3!}BjCw$_WB_2 z6U+n3IOlg{2DO!O<|jU9K6%EKycX`6+@h%J_B;E7g(L$!X#l|bwjKILJw7<=59)6H z?|=t}S(7V{CV3f61g!?(O-=Fdf=Ltp$jn4SxAKhhG(A!R~V5pD}Wi5q~r{8C82&-66Ho+6#sR6b@AVW+<#iB{b2D&cR zCOp+Gp)-roDXPW2LZ_FJw=Z>e2QPUp5=+WWLu4o)vc=7 zZ*{eDfFY$6#2`QhPQ*>9>R@^Wt%Ps*($^BZxmqNGvw||MT z;mdp#{1KIT55}AB&C(0k-#k*G2gap8ennR>XD)5#1~!*%{1^P?=0?72&q2p|>epXpz(d;;IMUBR?$fjx4`L-GV1UDQ}8d7Z59%k$IV&|YXe&Z|F-26l9_xFtR$$jy_|BXGo?YnX%H}UPY_Q**% zhZ?=#I7IW{6Q5!;e1mWQE@F__B*zcVfu#$b7dN!bOO{=-jjp-cecKei2XTv@NiK@@ zo!ae!Uql|?9XXjC4CM^VIXmD@4L$iL!__PA{pLeVFl$m*wpV*`R?<;5Hw*G@Gfz9m zuzVd3eI#~rBKFMPrK&*ksW{YqR+Mp8F3BHl+dINg3!Gd*_(_E ztWxAc$cD!*b+>lnd+dic+RSBdW>icN)wbyX_-=LsjE~Bs#{fPp`ZCYKwo?^53Y=ZD?Zp( zt_eOgum3FY$$jr)zl1O6L@4VRR=*Br?>1(_(BF-zmtm^)&;I+V?P#EqX(XB@TMOJZR6@(7^5R3S-H}W?=Ln(+UUg8 zvT1wiF7ycvNyfD{^|f@J9NPI`!G>PkJjZ)uhv!LBqEFaC4f@bPOrj$RdU1$^E^e&h zOQG5&+e`N#J{J^xwpG;&i+~*+7oWT@WW}cg+j3d=Wfgcg4w8+y9~?Xf2Xp#O5!&$a zik@`SR&>K($l<1D4uBN|X)erT75DgsN6SWY_%$(xOBZoj{(vhnOx|N}qUXxjtQZS# zbxRn{{6u#ZV+8onEZd7@t!p)`B|Z~9q1dvm#4EBNGT7}>u3$Nd&5QiJi1U-&gwj93 z`O#-$R&TiiN55k*Ie-!e+p_*x0=t+PDEB3IAODSK=$lVBt-{v{CE5Vut6~Mioni&5)IAFn>{d=Q_y#p$le< zpZMwU-;}(___91gFF1qsjxS@e#&^yGeHWB=!h?vq3Wf=04sv`ti6`6~yqk=j$=pE3 zwl?Y`KG0noPj>5D*F;+e(|8TiUE& z*h+3ri7xq&J4c1Vwe&Z8fWJ2*Re$RK#gT+PWsGR~wSFJcr@)u0;YqBP6OYq@O zYCC-m(TfpYQw7do zw<8aha4&hwRf;d6kB?Qo<`U~-ea*XMTlW~b^dWkRKfI~Bk=sie2;LwtS$|O+3Cu~GAR$P8CO4-ON1o_7)zwPDH$jSyVjRl2n6pc^7cG2}qJLuh z0#|5|lnK~HtOo}IypXM8hF8{+3FezFa9oOP#*vMW`HCiqJSplcK5|gs>my2p1L(C1 zy+u)^wJqg^se4R^@jrEA9v&uz3I-D_^i*Bii2qK3RF!OUfRU^RlWi3-X~-e5j=za( z9$G^A8;nIfCBAa7fLZWGuDaDwbu;4?^A|VS!A-uZw7(DH*vfqTPVHnf+OaiOoU)#H zqy{GT<4O2Jc^DYPN?g?i-W*OtlL8mMGA*IY_F4;`Cb!|W!z+n36VFikih;~Q;`(L( zo%3LsiD8lruWi{k6?zciH8BrEFhJ2UgGo1^XjvuN_(?xuJMrU5d{P5XVtHa?vKGuA zy-N=@K3MB&J^0l54Qg(nS-bb<$wPDgSV%}i4q3KU;Ipl+J5~ZgYWgCsp#jDdKVQ_~ zN8c9@s7o*N@m=pL>jNB-OFz?h>w8~;Z;iA z<9GIA`h%EEWaZ?DNX1vM#pleAwI+17@~QqCzHR#^^Ap+7M8>w(&6qYd{v^lIaT1r4 zeqws1Ps|g`6C4+Ix*FY^iq=&Udb9q7FFNvveP761QsVl92ZaZFIb(vv>=dr5t7yG2 z9ISW6Ut*1o^G%=l6c~46)7ab#+l-eke7(qJ$c_ah@NE*K_!JuGN?a%@P3mZZKnAyo zAM%2D(X16!u@+|dOg~!J9Q?dwmom1q5|W&sHO4+_?C2g#r_HL1zPJqWf@gp;@tm{^ zA4@LFhGdxTmu=ZMWoA-4Gk`OIB9n)uecOp?3ucN!>k3=!EPe*Oz(M?pBrsN(ff!s>*1;!IkGir}we zV4f&Qwxkg6E*awsGzMZUZl@hM5!sWc+sWF8A{u9GoF)+0Dzvd|T>uYFWbFbPn&17c zcQpYZT6*!xE}y>Fe-g$gt2p!TfB*mVA1MDMe_l7sdxinL8N^;)CPm!$+iSyOX=HF!2<5Msf{a^7Bv-o`BM|3k(a|j&VSRPP{CPf&zli0^c;k#{B zH@v%=Sc|a}Ct~C(p>^HBlhY@KbMb^)-8y&@{l@P(^Y9m$=*yF(ZFF(y6a`KU&*YZF z?!so`L$F~l869@~9BVVB=7MeFcly}~;#xl9N9=^E(Mvq8rT5g*$#}_PZ^^D03`N&x zUaUF#eCL0|zh2a8umS~Fr$Dq?Q9F}(hDNYMm{C>9F1q22MkvC}i5B=exdA@80pwdI zOfqd^IP_v}fMcNh%>F=2a@6=Vn7^=b;n!pxRm!|jAD=$+(FZHd)WBGHBRlU&1)tD6 zz<&1y-?a{i>7A(wB z-B)f7x2|F;vbK3hzH}0+#7p>5Eau^%(YU*5JP;* zwn|!Ue7V3YuKOYLiJq5IPZxQzKX^(T`#Jl*@khDvf5NlQNgfDE3_05ro@J8<(BQMd z2mkV$I3uRaYt09b($(J={9(!jJj;){ps)I}jeH{$KCNpK7gwno&xoDvwZ0a!=JZfP zWBb=y^7SE>c-?EZ>Hp)!IQa~L1bL|lsBM@+?*}4kp`jSzWD0Hk(noz)NoE%@uSys-h^X zCF1a8lf>W5*(J2VV%Fw5P%k#qpb$d8?1ax&VUI@t`--)xiSEeKk&Ql>GEUqRbB1!2 z$}MFXv4vsHfdhOSxjT3wi~t@%;l4i;KQ8i;LtuiZSl^FBO`AOZ`Nx0s#~=S*2Wes= zuI6xPa?r%C$xW!b!HrE7&?blZ#Z8L?hBzetllX@3;H&J^PwWiroy0o!?SLgb)Wv`> zvtGbM-%zkk^4a7d*i4KvzKG)_CP=>d-x~{cwq@UV;@|nMyXw}q@2V;}WGg>!1-Gqb zSj_8vS>;mlA8K^elGEEXXd(l~g%y7X6l}1m3Jb>Gn~>t=MG>3$9I~w@rt46xmcuVL zq{JpYsq=Fk5+5GSVSlRO-QPY<6b@{Q7P0lB3>XIEU~I*AMK3uR@Y%tlb!9CSo$ggYa;+F3rd+Xu##QHm=>Px_07*naRCJ+O@QP1?#rV5gR-*Z!R*wBp<6AHf>^@&7 zbuv}V1;Zc)HahlQA75gBU$K@7ouAm-UVihg-ZpS~`FByv0}3`6urB4H;zgZ&vA=&p zC;j{#&>w&PslUGd(g}ZT3!Sc7{F%#*HTyU>%P;CUGCA7@*l*pjPLKFyE;8AN@h^Tx zSD`QCtOZ+DE9cn-hVTYwA~$(Runpe1@*KOd7u%7=%F6pmUPtO3Ud(a>Kf!+~e1HA? zOHcMww8TbYl|D)lC(aBevKRP+?TjvBK2UU}g@Su0Pg`ON_N4<`(UF`StQGU|H#KIH zFL-0mPJLU+S=T1Jlxv_jeY<7miWt~l{!DD!0E5xK+sqAcGL_Jg*Rjq_oXC{SPk2~Z zwhBBbyZ_O^VKe?}LY+oRt|*R&1*lrW-Fxl*{PNJP_BEW5l9AG|@A` z7)v3+G(!lYPPX5~1oOOODerIkwf^Q~+P0cnXGX!f^hI_V_ej~nteSS; zC6`iHfByL&9t3`_bNj`I-_+1RS7g(lvU0@^9;K_yU+jg6Uxn|J+0e)s{rNWrTrJj` zB`FK&1WVYMa+DHm5-toFCC%ox{pO_znX7JsF_l9(;9_)8j1y&zfhEIcH&l?gCQfHP zG`N}9;%lK=08qw{e6oD-`!Xgk4*T#S%7)vOC-UEZ`*t@!Lqz7HE7af*6?QBu{m538Za%LAY~#>lLa@nY6_l9BaN%$K z4h{Os#eACOBeA%PQ?g6Z9oecz_kqo9Fe`<8@@tOhS#b!qdh^S&t!&81RTpwiJT_Q~ zKZnJOgY7N?-4}LqqkQrpl?S0r#*b|N9e>id@e{ttT^wW=MUxn%fL=UoJ<*w8XH0Td z-3xDWlNeW%d*-7%a<(bpUE3;N>V#NiJ~6QP!53q%@O#UH2l6-sEO^0S|INcBb(W~z z^_chQ3a((4B_{_4zdjd}bVuw`SMei#rRZ%L`%Mk!AdK(9Arwt~h|W+fT4GkBuw@1f z&crM?&Yjxo#BM)S9F~hgFo9$8`|}q!!W`bY$ylY>dcgagZ(n}n_sIwSic$&xhFqoS z|0lVu#0(Y%V{(=Cf;ZGv%on=1)f)5n{+&Uh&lMdXdQw*}9*E}@x^?p*c#q??xKPA< z=9V4&i(SDT4n(onI*7q>;6FHW2z{|Xb7Ky#?RCKC<{I0@IIRgLUD;M@m?5o~4~da- zVZN(0$ln(?^ZZ48&Xu|Hb1nXTKbHL|vtNe3sQWMMe^IOXJBt^2Pb{v~GIH5d6Wzi8 zKFaj<^~J-&&-Fjj`411pfBu#K-0vq3xi1ZzH@bsyB9L7E=Rg0WU=j22CH0>17vDZc z_li}uY=g0W`IH*lh+)>R>?>%3sk?OSyLM`^sjb52swTGaedzorcJMSj2Y$CpB5-Ai z7u`WFsUZektrz;gh({haezNCJzJWqqsh`Ac+jfQTLVvKQwGG}@W238NqfAo8NQAK` zORlV8lDV}{Xk}wR5n!FZxDp@R$oC?;s=T3RV0W#fE3LR}l%p%-5L1iax^>(1;K%Z^ z72DBs;ah6#Z*Z#;cLjOH4+0KL}c?fA;%*o4c#TGm>c%u)@|4TM& zxEzV{?PJ&7mP{63|%gWl|j1rff8Q-$xq|lu_y>jEn&-k4B zi{C;vF`K_+Z=K2Y#OLR`7SgXOrH!tT-}WoYUK|c9s1#6w66UT=#(3w6gf;>;z?6&d zU~~nZ1Vom2sR6vhAC4s5Wto9(6$B<-*cb#BH0mnlP_?W{LZTx<%-YF@{>j&UxvAM! zoO&GJ)(t+t@5_eB!O>l6>}~`zg??~2rCkR$hty{r9#HE7@A8=&TiQfA*uww#_HEfI zaA8t5xC?Z&;!LtU3S)3sRpzTzkZrqp_jnphM(k$K{O=tZ0phil~} z2g-yUdlmn7Z5$er+xG{D)`R#w)c7E-Ngme$3x3J6OSThI<(fD%S-ZeE$ggE3Ry#S0 z&Y5-QKRQgTt6FY~)u>^8#0K)=Io}w=*Tkd2k@etzvO%sK0`NvJ;<8QM1yjgMz3eMj z8*9-&*nAf>G{G^jH9qo@edCFpsz%08DgERnc3<3l&dA13_Ue?1?!Q>Js6dzCGaV@&m*tTLbu}SN)P{ila z$<6Z8g>RXU-XebDn#&#*6YDnxi_pbTi3w~Bt;jMh2GA`N48L-V&aB6eqGKCYNcR;V z>`z@TE38Y)M{?O!>L&LXj$SkVtYr_SpVp3!floI@Q|E!Qdfhzp5Rh*OUhMV3z6hP% zFcRArF*wQ7lfy9&X@ByeAoRzdf9T&l3}g=T#8awnHMEgK$;y>Axs>?LH4wRdyg!uu zuH!iHXJ3@uKdAK|{0botfZNupGMcRQs|6kkfAG8h@WqadU-HV=3C<_Ab^9>XRp{Oc z`T!d@eKx;sxb-G0*Ps@!5H)yG8_(tEQM=liqlk51AmK-@wnzIXQq*OF}NHV=H9eKBXTLi_sa`f&axg zxiWlN?=BU-gi^1;u?RlfYtK#O2Kk5{F$bLW4~S*|XU;BVF8u+<#3+=r$hMkzNB5cY zjrBpyPR{)B$L>IX_zAairHyaV^&8(P!>{Nz0=r2B}DK>4ZyHwrkg3>}o-!2KI;fu^_@goOj9-i{)Fkd@g$s-U> zHu;m2k%_%UXtk}xJ+Zc| zb)m+#ntblaHToi3v`y}+64O$%zGa;`JF*B$s`9E=+h{a1yyAC=A=6CUFB{zCJh91H ze(@lhIu2{v?Ae(?*immZPU4ldi+fJ)YgsDvR5j<_h5b^4iNMJA>IbK|K6!AJHgdb+ z!$n?R)BwzjxA7@)3UA#{rKMcetpG@WVagleCq$N56UJN3O*95mw0V+Ead$OhhUPLt z2a&O8<&lXbVyB2Vcy~ZN_{5!!q^Y$bazlS{LxxokHdwyiPm7Y}c!HIHTs#~MoSNXf zIQ%jf2UD1FD*PkCdmk1PUfXMfeq%F#Id0zzczHy!F6Gt#y*b6O;=nIw${z2@fV~JGhd(B?s=6 ze88&jl`V1#|oe zUFb@iINN45ue2OgBrBM0`q)`<;`3-Ys%ph5d%n75M`o_pw#p?TGx6`1zSnl@iG{2v zIKmUZ7C-ia@deh@b$t7*CGUxWWZ6!GC|P*x?3YUsUk0F5a&D)=36L+ z>MF&*0oIG0WqpDxGMN+6`1Ip@;u8K)^bau0#jC^{+*&p!^T&Shp@;`L_F&>;J8)!s z*%ViB!K&0=>fnp`{`K`-e!RE=ozTzc3%wSCyzX;C@5{DKpGLT%w1PYKnzKJRUesfJ z8SK@8Z*$QE=LM0c09ZPVJQeXCGxh5=nX|3tEV4_I*Gub~n1oiJF7^#iv$w1Im#>NK zMNPBJnR2mjr)>XCI8fb6Eo{`{w(m;YwaM8-_RagYW7w4?5*PmB zx1huz@tD+tWJQMs?u^q(AAfUJUettb?c_4Vk`fCsXB%1k16y-$D?p)hqAL`+egmHzZX?NKJ+`}g zf&IpV!3qpIUu^7?V*60|C-x_6Gdk0c{nZZa4%ujfg7w9X{lZ3M00zF&P9YrJ7#`dt z4k!gt@JC7C*D8Q84&gywgJDNc=U~OsMZB>_PdqTbl;7JAWGpLr3kfXZ zN|S%pt%?CcQ^s!)FJDVrH8My}$+jBb87Y@-!t~~4!nV3fiA$)fv<`gQDx@qWCb1vA z7V_Yqv87xXp`URm4g~j-K|VTdq%7IS4joB(pTzRyEP3(?HQ%bF{$BJiVip|$1BU}S zYP}+#wHLTf>Lfa|Us79t<^u|G>Dtz}BnM|#e3CJPKHG$9D*Taiwd_W3kvr*yzGwbM zg>O$&oB#RGfAo_FgMl2WTn|#o*M+~hi5#!!rNIL4Q(dL|LnF3`L-+?g6CGl01`By0 zTD&90nz(HE=}%(JaN(S597_|?l9A7v(P6JQhFO;wt+&KXxmXX*ub+P@e~+>9jeKtO zhWn0V?gvwYyrjNf`9R3SP+~K|ai&k4qvz(I3s?AWp7}oKFGYXmV|spYr(H2Xj&`CG zk71btp5l+~d(6A#<>$&7eQ|9$H_21>)xF+to?fvIZ*!i+ujD)Y>HlhZc#3R-ZAXLA z>VdT#Cn1~Gp0XSBlQ%`u5Wy5{K4;^0%%}kAe+Emw85}*cxHoq)^h{T+JrZD7l9#I zoj2X@6GusbgdfIH+sfw8(^G8bpkNC3#wvypZ0Ho?I|+#0Pe6+z>MC`&2mpaRwF-w% z-3i!bfGVE2q}q=p7g^TA1>rB{5;w0PabN%)~Cl85Ui@()_`Xb`ozkV zuz#(@MJBpr^SUYa;!8FKP~g5_;fo$w+PV4WE3$9gsCwCv2KomA;kz+$qXE|oTrUoo zlZ~?EQJ1{fmfx~MX;m$~+kP-#92{Uo?uk!N+6zC#Wo!9%9~edaC%^kTp*%=lYpkWO ziTC}-jKP#Sx%9b=J=;nf+o2{u-J3RQW+R8)CHt0`)QBU`c#@akIf?z`(`&-#K37@PdX&BdxfsMz#wc zm%2(-=!T)_uW!D1==}z5+!W*M36A)d^~Odh|NZ+99>BLIU&KpXwy^^z`+Ed5b9p6p z!PxL_k;hIsd9bQ1+lrm|QdK(eq3eywrQnEP2RE|dnw%%uAGZwtk&pC4kq`fO>iD-G zKlJ;L-}HlTcpmYESazX*+Z7xGzmlh%L&lCQ4RUv(|KjWV+)VQc|3W_y1!5iBrkn+N zxH!O>e&Iv>&E7t-5lUYO*(N)4?a$2Fj7jueM`PLR)F*lgo{X+0MvwhaD83xW!I}7N zVeTp&*zGE0i8b0!@O^Bq2LfUr+)w-qh7JCmnyYF_UUH_jOPNb9f+3W-lZVbPZhB8@ zF!Ymt^!@qQUrSa?PhnZhFVaolQ~`LXqr@U{oZv`KnU!S06c-@^AZhWzBNoDwIG@yh zWLbu9$TscGpSgjr6B#S>NG{`_^-mklxz58E=S)V+Phyt7kTrcfI;Ku;?l*A*NB`RA zt38*0@gZ{~bI>5i;#wHM^5Q%k#M(Bsy5kpm;>U-NdDu1KO>37H9uq_2mHGI;=E%M6 zu*vqKLGXZgM$nVsDT@gDCPF`lBn<=<6b>E*T02*w!mD zCmZNVA>KMJWqq=mwfK@x$xm*IvB#ncT@B9Q&VM`q?b~m91Us=@`ron_1s0t*kz~d! ztygSBe+v6rg<&;u+#oBtpyW90maXN>ruZas5&nGI$RTBM@n+YGQzIW*c?DzgmP0V( zChoAVB1`;YKe~b;7?ZEev)>iFA#o+TsNl0 zM}5FWZC`vMq`u)f_HQtmxdHL8%v@d}+X^mo=tt|)flYDQ(QhRuiLveFV=%M4a0GK? zs+uXwwsKfJucy9F_6|yCo-$+!@|(t-Yp+CCZXD~=G@tgmO8dU4(Km>BVua(23u+#wV_0RE!WX)j%Ub5UnFl*B?9}qP$uEX@O?>j2 zZx}4;!9LA?J;1PU$Er(0$chAuCV3D(<{O9~?ECMJW8wLB?Ao!_C@C1bigA;dQ%^o& zpJ4CG+=d=Q;$aDU?2iXDQ#6QoGF7F z)&O4~F0v<*KUQJ$%1L5kTSj+cP^NFG7~83VOGe*=7#!G5eQe!pU97uWX(#=k`CBK> zohM)8i)&6KnWw8Ur^doEu{(&t#dr|5iMSPix;7boL*m2DrF;wW2M+=9Z@MJb(=I*e zV|qNp2TfNaWv8n zVti}V; zuqDUAC$2(QRZ-uK9Q!PKru4yXTb96k@t$_j4_#=R^l9;H;&bxjaDy|xerg^df_eSv zOq5L4L+k8)*KYXj`h_8wBIj~M7Ogqov94~FSStW_mC`cA$W+08kMRUx%Q{8_FvXd* zx#krW`dnEr0=Kb=kNp5lS zbHhB?91UpOOIMPR4flLMIE=LsFUlcftEy#N_XT?FO!SX8F`8=3);4Mn#Cp=bqyz!b~%cs`C1Nq6P*K+ua6=T`RfemAZCeFqGi~0y9F8kK+ z-xnXsm7HDVEquaX+e*KXPi^LgH?bMy+qNlnRd1e&{><&ip`EoAxA$Dvo#TO@#!wTl z?4K_1LDAF9v9w;O1Rh?2)kNC1^5Btg>r#hRr7B~;dB{JMn__H+cM>BJkAW?L^`JI> z=Uc_!*k=#wZSPWee|-O;ADkO&4%?Ya|FP}*zVG_MethivdQfO|q-GPF3rz79*9cMk zn#zswCwX2i4+1%J61NjxaYZJ3YkjET6Jpjg#}Yb>FSX(vnF;1#zsSQ+zP|qK%jnL- zMOTA=$F;d+#g!XPDDt6`7(97EyRe_Sip&J?mHo~)NtqAdU_9W>_@W)~pj3+_Y)G)I zhkzHl@(_@JPvJsG)kc)PXu>N~ceZX>THRM_CAJ5CEgR$|HV3xWJh}!((zi-X^AJGp zgXb4rN=(ER6NC8==IFfMx|c2LWiXCD>BdpSER?w=hc8v7khpBqZ>VG&4FU(+aIBEE ztpEFETTNYTe8^2(-P)*~eLJYjZLL|+GbDI79zv>H%-|n4dKRlQW(KD*B{4VFKBmLm z@{@CG(g%$uaXP7sj4Sxjo4vXEj2Y@CFJHP!U9EMY!?w(zyVktT2x3Xqtt?*TCv}=% zlOg0^HMuSxJPiag*gVW`w7-#8TZ<6y%+l)sowKqi(a z$%IW^y~qsm$@u5bKe#D;-HFd6^Le>S+rDWBQ=>D1dr|D!EFa3Id2wS;A=n7JG_dso z*V-7^jNNSNlVVs{;VX0(iE3ygnW6ME&oY_Px*SiLFr(OC$w9wu8C!)fk=?loJl;3? z2M+?7i@qivg{|vR>4c+}@Vd z68}ptK1rX%-Q;EC5DM97io(#cV%{@1Wm{&{RXm^^+7oN~iC-x76u&O^Lk?9~7plZ5 zgkjmy1yXPqvbMo8m^4rCyZ`_Y07*naRF}dNJw`C~G^v9n!?+9Ivw&Rq_I*=VBbP}S zc%e##k6V{E{N1-+u@IMS)@sdLxxD0qIn?lXwZ!7&mNeo6dwtUGto`6u7T=Cz-SB_^ z@w@&7{r3HLt^eT<4+p>V>w*XMo`;2R`=)REp$GJhJ^KyW-&oHB!#8So-}Z$iamr2k z$=P#aC$SSaZLfWixnSyTQ?uVL;xSjgOjsrlyRX$+R{U*nPU@QI$}Uy4vX-+fc4BWJ zAH8Cwsx+v(^ey^xNy;YHj3;~Xg{lEY7Z~f=5KdJ43+|)&07e9QFi9O(u2{6&g7&!Qwu~(b3>U#4p8SD)F zpXmBU;2H=H))p_APH3*mG_^OEjf=U#Tpo~4&Xo!O;6|$DUSV&_W*}>#Z)P2tiLF|3 zmOi#)Ya~}-!MsdOR+ox+SGO9nOaA<@-qqyr&hyS$XA3(c;)J&}| z$9&scLcA@xDhXNJN}bzQem*kdid^)BqMtCRtH9IjpJ3`WZg6+qemGjd9p31Qt)@md zYQ7r&MH_j&R0oq=7Ma}G9Qg_^H?s$acs9en@9U<1FkZAD7~a)YT1F$wrs-;IO%BPI z{`mKQbLjunBoX2&9HY^4hTz+U1G~2Up@U6W$WBRBrGuyTgN>M*+lL>;$WAuZiBA(g zoQO?qS8d9{w67b`H|^ky{((M~7q75?QV=hm;;$4CTI>S<9l-eC(ba`W$+q$nOc>@h zp`jGdOrjT!f6T>NY?T^c$}L65vLAgV$-FGvs_vUyYut>NTs8JthsRD^j6?5!m6`)* zi|^IS1(dgr__B)uamtPR)J3d=dC-c>whB4Blq+^X-B4I8`2`>BJl&6 z`{0@@?*n`@H~-ocjGx1FP~)+`k&^=NvK1W$2JIvs;hFGFFpF{7+@v>kf#E#|yG(AG z)MPz=Rkg~E7K34Gf=ke(L&JFJ!pD-~vk+4kBffpe{D^M)nXh{DRMxqPaX_I!O)Nsi zd?;~8)2g9!eXB8-?yOk?#{~^~Qs#oiE_Jmswyj_kjqO`@wSvb`Yuli{_w6mCbq!+E z;CXN}-}a5UiK^u(HqWKEP+Uu&72YZ{BXyN_;&*UfWxkpJ(B7qE+ZOF_yUm=DESDaf zZNLBayYdi_K1O)}e(A5Tzx2fo@#Mk#$?wh2+|YoN_Q_d7SB2dNcpscuse%1%{|awn zY%QJ*`xY)xM|OG)u%8+WWt4nmKjsEKsF&cl;3wTIBNKy41k94j{Y9Qmu%5(cpv{Y_ zdhuVMJ%)mM+YE=6w3MmL+tdTRU+mi_zUJG2KY#wz|NQYE{meOlALm+s>IqM7#25II z`-!dvOYh6vkQICaQ)&ec?29?S*CIQZuDuqpk%?gl3&@?&3tLmc6?_J-?KKA*m^llmkMPH~WQ8~VkKT+A>g?P1 z@5;Bz`+mqS>20&Cm!9wmrRL2=F2JAo*=FBu+W0Wh?15q&o-!)vD}o0~_w7&<#J?#* z07S?R_gf=!u^o^Xi3s7*((~Y{dcz^xE2z2go@}J>e8AY24FPi7cYWhYJ!E^`fbwK~ zQH*xUp=#~mTN{lwb4gZoCMmg5CCPzhTPc7IU$$+>pG~>K_e?>vc_SCR%Lm@V-}u+ zn`3}+pyL+-Bzoe9ZFJQgS9Bdba2?>;_FblmCL1R57aJAiH+H}WcXbMJ@QLQq;6O`G z4i4QN+3r@Z$cvzvL9kY}%+CamEj4_h$^agqg}{#0@vo1wyH;*1zK+lx=eQ@Ked zZZ`VRyHgvz?XpYZ50(=Q6QRu6H{TOXYaUyZ&$k=-JdkT*ftvN|Dw!W4vvKY;WW2EN z`6(+kaiROnH&ghM@swnE(!W;yo$w7=l9`VUR1%U)$!T!fR{Z9T*Tk=roBT<8!6P03 zUdpcqem=R0fnmx@&7YhVQ(Wks1S$HWCuHWBTKckvtE&&UVpFmPc^WK4N80Px*zi(g z;$kt_>G7I!S=GJPBOjTI7{`{l26>$5v6F*V6Ss{UUTSVpwK5LIrDO^m*ZR=C>Bu-c4SuWn_JMBm8+%EE(g z+lsxD2b>cuwwDe&F`3llQ-A*XhyLe({=fS7|NJ+79?!Z3%uW0gm+hM$d)2Lms?+i?v~6o_*2IB9GPJGWi2YD<-__iZ$RC)xSPu~!+vq9rP82brn+CZ^EYBRS^o!VS zJoH3Q=2Aa^(ZNGzRVmci2t`*Yb0Mo%4j#m?Yg2q&hbVb^=6hEx2m2uBk>5D91fq-w zF%ef+sllH7nDHQPGdF7TIH<3=a%~yEgzU7qQC&)#aq92M%`GvX=-lup`L(Usp4^NE zI`YYO<%Bxlxq06=zo^@jo9mRh5mLuF|0LN~7kd#r1AQ`eL_d2{ zti`wNp-@5~uEutg(@^pn8%#$KT(!D+vr$F|bxU-jKQ=D>&rNW!5Xxe3$5s)0qkA$r zm+aKQ_t@BvV`0TmRtO;sz*97{oR0B5E;X zSMY;-#tLsT_6IbPFKjXoZq#BaYnKwM$li0j8+n?WIUTF1+s3bZX@cYAf#s=OHhRz* zKS$~Vnv8{QL-F0Vx*E9)EMuv*sjuP#p3MBIlblX`vf;)5$Z1_@2`_WoeyEU%`a)lW zYY^Wh%cS97ROn_c>r81zFLs3PiRZ;SlM2p{?_=qCfrE#xDb_@+2Y$Yk{dsaGP2}Zb z*GeaKkZ)x|$-$Ff2j6@Bsnl}xMfXh2Q#+VdzcD9E!KDc>OtCgGcIo1PiBJxX7f*jD z8)W_Np5N)N|KlEqNtEX)BmY;v7f;iJjUl{_Ap@>3Vq5c9A~1zRnSbPucDSJgNbIa9 z795Y`UiyW!h+ zk_T_}M$aTD1D!dPzw$)IK@ho%z)se}_aOoV6fZlx-RvCLrtMqAqT&>VmonNws_czZKh=#eWmbLH*Kj` z+gca+)7quQgKq_eXKf_pEr(^1>37xA(d5@A2ITZb4aW8)mrTiq6N->+Rkt=U@6^L_ zJd{sQC5t6lT-4qK%Un4n5{$))T{NL^C3j*|jdj51fGsfW$D!QB2J)$=7l)y3=2}~| z8XdM#s?~4iNTx16p&_#3lXh!kix>O~Ns7*p#G0_ZYAHvqknb)t*nmC!$zEhZUd&9=HrJ9{m0 z-mn#F8unNukI^?`q%ndh7qCFZQZS zwiSJ;&FE1su%{m%(#;fXidDtTsBpArXdpvt@Ri2{$jt5C^U7# z>PfEdVJUGH^Cx_RIHtVPe^Ixx1A)fq!&BDZQ|LaSOOYAm^Rv&piaNa3!}6qN5!9gN z71z+`rLV9_kF}u_d`~_>Mwj7;|0m;#y~d|PXX4gfS=C1S*zuX1rHtjiepnxDcT zqx%*4FYaA;yf5N+-f}23xmtck*))6duH$AuR=27fUApTxE( za|3+k>jMtAj6(quhg{>%H2?q*07*naRKgSCZ9DYf#+`%4Mhny!TnEA0puIL#oE4T6 z7#g}jCLn7pN0kz|Bn=g6!0+1*_*(z7jz9kMKl<}O|JIWr41yJr@Km)Ld!h90dg~fE zd{b;hX5psz)80jJZ?Xj11_M+Czq)09Cirf-lTG*3i&(sf#mVpga=1j#lOlR8;t4GW z8k;?F8Wc@rV>|jMnD6npeJ2Q68}MB`B}ZnG93ZHPTjTq-V*6bi1)jM4#lu#<(s>et zEV@L@)B3 zO_#6Kp7;ctRxHU)fh#tH^T}7l%_clJ7;=E3MKN8xWmBP!Z>a{GcBsI&d+2B>e}Go# z+18C2yWqQsC5<98sgWDsK=x#Apf}oq3PV?E-?ybRSX@>y*X*5*nh8Zd`*;weE%VS6 z7iz-0rPh{A>|ZPIjh>A;SkzTZr(FryBHYphWZFjGk%ueVj3bl(bQo?$$JVXJ$LPfB zl1se=Z(<|-7+@RJOKK-I_oTiv&R6zNVtcVhQNlW*0S1WJcsVkc{++!Ne?K;0RACp1 z6}zREeHt5+Iz)-=+qbTg?M0ElRt~Oo$@fN#_w{Yj!W%vr^%F<{V9Yzb%<-PO9K=TO zT)_>_;1ITAH@=>^39)8dl~@zIjfb$R!k1b$)3+qsI`%^ksH^CMCH*dBYw?Tg);+PN zCDX)x-}j{}edRJW$HV-#?Z{d?HXp~X@67$5|N1}rfB&EVm;Uwpzx1!)eqVnuc_1Gi zARs-d;fsgh*BwvrKRFAtFY-X}qCc^oeYa81)h+Wg$?qiIiACD@k1|DP`py8kV619z z)mqDR)+X`;`NTA5U?_80k9_nNae46JrjeISUapm&iJZ8WEIFO%GVu=1Tj#`=vG`$A zHJAYwy)VxC@I)r}w%ABN^^7ly=z(kPw;%Ju?O-7+A9 zWwL$;GA>EQd{rw~Hp-Jv?YY?s<|fdMthjEu99ZXiD9BCY`SsW8=TMFxhOgg&ldX*) z>>L!COK>lWI0-%RH~hq3a=~h-6ni_LgdaTM?D!hYgQwcaU2mDmW}o;*#pO(qCE0n` zec|7PjNS%&S1a)gh7EuAr9Xej5&EGcg}gA=l8>Fl;R5T#PV^)`Rrh-A4i3<)$CtG8 zV-Nj>Jpm^%PT}6VlE z588~g9(@Jo&JCw;9TWXCI--PjzGIoVY%5p0Y_myEZcI<;1*JU|-a=nC%(mq~Yvr2g zjIBXTZo*IWW^Q5wg?htRhB3Y5c%!tHT6pE=Pk!_D+E3~)ZDbGX;PLI7nmk7Llbcf> zkc5(a&3u5lz}sEwYT0i~*q>03mnu}HW;6B{|7v}*%6^OODa*d8+^VvQ@q<_%sX>ct zGG7o!M*O8F2N-1Lh=1yd9qe>*WfJcTZFBWA zXM162{Qi)Q669f0y17y0Fq>czUqptl8axHT8Xt^Sfw!x)_^HpyIQu)bd-8CZet6gZ zB!`Jx{Kx}m_VtUK_$%j9i2i^_T&`9x-%69j+E!u5vIgVmUwU|uTYG?fgipEPP4nc? zkN%7NFP^pM5(h1v;fV}0OLtc(4>`*Q`eMh%zJ<-9T9{fJer|7U$+5Vs#O0UdeirhZnLh9&B(x zu2TH1Zn2E{U>LMRxdw5KCOcRM{)R5uUR1;_F>B)1RWd>|ifQB1h2Izc34W%Qe8HD9 zBduMlhQpin?1#uFenO_YWo+2dj7Nb-%))=+L-Z%+C$Sya$z19o>xqBvH5Wca_kx9d zp({Q&x)%jI`@6||RjX;6H5;4goYafbVmCSr=A|zKI^n00@yoV~c0*tItotW6Z7&Cc zOXhNmPu zN?J={4tW$;6nCkifI>Np0TY_H9fA-Y*L7)P(6$o%1UVENO)wuEz6Xb3?1V2#d2$F0 z4uH%x0d}=S0JBbK={reO^iAwoC4(va!ICy4u8Hjl&jo)r6;o>Tb&^&syA+wCUv=v# z`oR|88v6}z=8E<7Gru2)9^BL);NSO$a)Uo;_x<2t*wx5YwF;TooD0WXo9xBL3ikMz zwG{HU@A^=6>-O(l{K1$a*@;sqx|5rWyhTqoYINCFBipsfE=eR6vMoDQcdPWRU|ZyS zUR-34NYgO{b~o{XOke2W`(74eT?|=c{vx)?*^`5Q@U2I+!4U;yEjJE6(rx7W0Dsy- zM!BMfxRB6{&?jZBiQUGgNb53da~%eQnn+De^7*02+E#wV*JO%LB=TCSIh!uxbaBA0 zG3zl=*)h2@&GXKDgVh?4%36&w#~vxudI)jjbF= z-KCBEE*-3~B=N8iywS03`+6`a_$;d|6>rfwu@#>}FAnC^@{@;~C;faCA1qmOx;C*v@-Eqd>UwFH;L666d{*7Fm z$^&ESW|9xdGP-jUNgZ9}Vj!QrIEmM~xifc>tJG8Gx=Lv;=7B>DZd}pT_)#k!R&++! zGNW7+>>3P(r@@srx(50Y)3G0X+W)45IB&#g!XF*M@sn@&{^Hl2q4b~0Wt9$c`JG?S z=0Azduh5!3mv{~8<4NoX{usWK{45_CN3Se3HgX0Q>%tkklzvs?<5aCV2fUJxlYAzR zp-je3A?pylnM*U*o;g>%CzH6Lg@eV|NI&sO4AX}NyBiIXFo(y+?jk8oFfY3d;9B}3 zn;J;_u~Xg3*=l@9y>{a9#y5#U^oYx$ywOf_J%|fkaI_46`na*0_}J)8JIH%zf|DTe znu|X&u@@40Gqz0^a-nBJVk}izU9CoE;-A(o<#J&^9cV60-l*YS6}x7lmSe44 zlVnGIlw>^xo=q__kfi{@K;$|`DX;`-+fj(Fu;q}8OcFf_Nc4T=;&@10Cr^?oqy#K; z(Kk`>q(Jj;^5-ubZyq)zMLGz&h@|bPgRIB}i?{~Ge}#Cm`}+B(z9{nGi2bhChwN-T z1X##iY+fWIG*_TlTQ*9GO%kzf+meqgOR`Ii|NDOE*dN+xn>fl+Vm0u4fOpbPbjHWQ z_yS*idhrS5$xY?Op>tt-;I~j5U#c1a(gp7qpGw!?S->B;=y7a==VKEwif1VL7h#hy zNi5iAP3XE5`REjjmhW}lmu=ahQtU@}J_YALJ6VUqx9@8+#K$V)C!>Y!18!ccKd^gp z5|A#ax`UIYcBlU6ot>R)x^UF=bE2LK$ZrWLpi)B{U&~0 z#3*aj)OxCKb zu9Co-9K%j59_!!zco46~&wbyt?}^W*Ade~CuS z5S_$;IYt-x&UukNopb48KLJN#Ep7O#THAhr<4_YP+p@jt|HV!0Bv#?=D(0ocGkUYH zqWj5y9K;_Ht&3O`emsr?fA_VA{`&dH`Xsy_O4hzSmAW*1(S2d#nFn9+N@i^+*FAH*OzNK9Y&z5dx> z&cnM_TPJcq!Tu+6|Niq&{qfhI%CEtS_~jde-+%j;@=r)V*bm#bYY>Mg=jzG6DQ|oT znfgNhiSFnc?19K8=DC>@S=rXQXa;p^TNSEO#)(;CGSMA=t&7SdPP{X+TvomLbAFAr zc60l^Ca&m+&a~mL+7fDTUaaOdZ=2Yf=#Ub_sjYYI@A?h)r2}7BUJrp8i)$c9gTAq9 zX)+$<`SxMLZZ-9`?Yny0WP@E&Vv%!Tt^H%(E>?qKfOD=sNtOAD3=?Yf8NNyEFvl{y z^s~OPwxO@8C2akgW4?%&xMuuFi*WoH?3c8*Rf*l6B6(AcHHqH&^!nf{-Sk5b4*qZ7 zepB}@S78fUZNO^C%gl-rNm=HU)Ltdia+tpE)}s!E9@th8Ha}&LI3=l;wyQK zZ^6BM!@qp;i#>7KiP@wEP7aUz>w3G^O(FPT`SmJzagD0}Zz4zkxlnQ^S_Erjfq%{j)gvQoyeIb_SR z4~}!b=ljFwkGSsZx}UGt^YK{E%6{ox)A}W+%RJw|hup^Oe_4PTpPTvq?@w;@m{iKo zkCq`7pE=Qwz1~`0WQ7zCHx-7=L*{fQoO{`z_0V;PznUALd(1Qf8OPx=w|y~KOv$mG zaxp}b3n#<(St+c0t9-}$aDeu2NA$>(^v9g*7dJv+FI@So1_$yvV+Rnz^nzDL0UYwf zs)v7hN$XRl6{1jyd$;NtkAsva=OYv3GczAyIneJgS!Y-02LT@t!9;>8y=(QV^4TpV zW(=xJ*Fa+{E?4Ref^FW&?!%Rh6g@?E+tjs?ygwabp^H=)BBC~wL+}O4!32xCSPR!9 zk5{D_i`K79`bGtO){W0MZmW7$3qtCmUhU6|9(&fMdAB=k?OtG>t`q}~!( zdGkTIZgtY*ot3h!7Tj0H_L@^2RGCFx-52V4_xqiVW}O2wJu$jkn-1&|CzJ?E{r6Ce zGj=KCSq@ldJ#^sgNXH_%6R4?hYYK8{=T@)zp9vBxMPgKEgbrX_Y=vPlBF{3Jj2-I2 zJE@7HFs)I_`BUmO&)g{{$3aGB)21o@7L7KS0!tkmmtDJFnyzOLKGCY#=5*eW(c{;8 zs9KpgpZb7{Imlc8w*G}`+rkqo1#vp1vfFP?X6ivYC-ijDPo2&C>#D6T_kiYH&wRW@ z=ja{R{yS>KnaP^`Yqe}mqnqxvXEF(uxYP5kkN2^sEj24e$C4tRO1G9q%yKXXm&y9I zV`RK@ZVNhTM5puD( z?XQFlo3E)yCIqTSW~Zy1D#hll2(tohKO0xb(IZ=eHQtFm%rHrJhegDutLV^Wh?S=h zKX~Fo@Y!<5NCQ_MPQ|$C?;~a%{K&?6c_|0V-_P#pVRKtbTb@mH!r|`b?qt4ojT*?k zT{)VLE^u4vN%Z}@J_r`gu|3Sq6z}&!0V8H)_WW6FM|Lu&nSkT|D7#fv(_xFE-3Mm_ z>Y^^Sq&E%6*Z{(LS(+s)RDUaDh}LKOCj|8vp&hEXSTC^=XYAM+!v$vT=`D|Gy{9j1 zWA{S)W#v$(HqP$&x5xgO1?GD0#76n9{Jq^SYuPeQ#e$s1Iyf@50H>;9-EYoDQs^` zg&ZB~T5LycJv!7GX@^W|Yf3Na)LP((mW&d&Wz-6sEgZOTDLxcqOWfN z9@r^3JYgO)HVd`AbQkT*<|Q!e_wzkSOyyw8V%~Rfg?+3x75e1jW!PNkyG#$63+vtQ zy6A@uq05NC*@KJfzU;7)m5Hm%K?j-IK#XsahdtX$Ci0;I9Qv-)kBNuI$N_ZorC5W- zR7@40^jnA)09RdO$Ny%?SSbP& z4WLxrfC_u8zQg_(6~}p%O4vp9_>Eny^-LnvFaOoUj_AW!ng9sb$E*&grK9py`bb@1N5=GP&SY#Eq}AgV1LaXy zR_#<0?J{tF$6PiY@x2#6BO&W7>hXbrIHH>}SFB>}UBRQ3^G^5g!mzY=_xr#@=#`+Y zNd9H!Yr9-zBC%ife7d;$_q7c+mohA>u%_p8F6b2BS0fT~w7(2++POhl?lAS6)8fq} zF3r=xqRBt~ZYR%teN}Z@&Wu5re;B)Lj5feO&U#8(7mI8ua{vpDbvL`BlL)wD`k+sn z&jg?OHF}B$fxyZ#r9L}5-MI4uYrZHltzuaOkWaG`H-xBD*rWG-}Gl0Z_`* z;|d6S_j5Oj@3qgTTt74R$z!U1(&86RZu^;%r~Z2Cp@jpE(ub07sOdG|7Y*l=!lYj> z-`iH=OV8fCryEIfG;b}O$HLvGL9Y#cISp8fhLVi6oA&imSrBkPTCsuBAK;xUUAqea zlJ^2ruoW||$EDqy%+@hTLTO4c<^O_b!6ee@gEr?YkxMy z1TnqGs#{xBj7YkANo{sfXb2kR0Bz{1Z@SL^H2dDhVr{EmJ>oKt@bKhmAn<%;UU#rR zF#T>u~Va@oi~?t(jN%C ziKgkUmYDK?sVQrRCej2!wvSz7R86~rUCWmUKMzvH=%jDq+r3!PdCl(sl=cVe=y3f} zLOjZ>qtB%5VY(p?vcnV4I zjn3-{zq6hEaoo6?!bGHHa#v8F&9blKs5+zN;elIQ8uu$}L#zw@b`A=|KRvX6M7_-G zd(P*3b)$j=>$`jQl%|(y>3(3r4Ls$nkztto9}2{{j)aF0ZcwVP_4vso&QXnc+j$Rj z{yXy_+(f(2$U`Ae}`-|yKZP{DJNSBJi8B? zRwdPB+fwPg$l}ERIr0a?dC!~v3F$wdlxtA(jmMZL zqpSG!52HHZGX( zNRy>5c(=eJ?w(>YI_TKG26=}3HFx^^^UvK0PAGn(bX62K1YMh~XJ|D!oOB3H)TdFJ}j_v5=nKxfU( zu}@<=My}PFh+T(;E1H}|0fg1l84Kox>a<#-*?DhSa+?(@Z#<_(uWAx@Lc7;9_Sn5^ z=?3*JDtz;JgzG1uC2D=-et5O__><`*6~p5GnL%wYZ7(V!h0DL1I;qTr1gDda;PWND z53>Ttp3aiua;eUnd475`6YX3#l1AXVqCzWo5H0RG53@f;O9ECXK4~9OXeeJy-p|9^ z&dqsYpPv=hQhfRF(f*sN%nhp?&L`>R=2kaZo(>uzZYlQOMpw=RDz?~d4(ZRpA4F`D zIn{P{0ZPG1;&st!#maP|N*k2jnedD_A;!ee?SBz`L7kh>KT@&h!h604+y~g(^E!>J zg&{CIrtA|Z?22wJtsNWJGnPO#=pH%~ohaBF!uHfKwSvKG7f(zEeEje ztuHs%$*IWxVpPcoxSC*CI??}H5PK?YW>j519n7&?`_g@n`2}6!4n=csXnFKMt(l+4 zjT^CjRPl)}RhT*YzEZoK3v3ico$dSWVfMnU+L(;n$c$R8CU5KLFEePwJeI)gS2RE( z_)XVHc?DlWcCje+L5MWclk*7d%I0gK8?19m287HQV^v#2mqqcjhNy>YiKvaV&jS|j zrk-ge0W!;(3h&sEni8k>dvWJhTVFua-KE!t6Rtnva(|q+OxQzhG%fqs+upeid&cee zeG;v~&sHWStjmZej1B^hI~;)W#qV)geE~z$w70viqjH|)V6c&(>qz7Dlt-$>LtK_w zm8%d_qO*Nx^ubCuz7OAGHn$E^XU*YS9 zeh}Ia_trct$FR9g>u_dWa?{#_{l{DK8Ru8VL!vG@fk5{!^)a_?tT=uhO5-RXrfqef zz-wygw$B47BwTVmv*qawzs#1m)FbNKb=m+}cMdUR_yBp0AYh1;`FjVK?*$?;nq11v zLpZPcsOG8}X?7sOk^b4C^!h8|tNys8sRR(n=@pkIVb_{ijFv}l-hzHLch?-fUgr_> z#IWNeO_o;zze+o4+6^WN221;s7I|{-H^O>1%p7#9AaDOf{bGXgG&JF#mLzA-^}HbH zo>0)z{MRk{+1o5Kt2=Bt8Lci_7p8B2NZMVp*?GT8$gV6mONo|rQutYTtmbNk;#V?i zR-$KN4DPZwKU?HR|IlihnjGN8*Sz1*>=0=aw~`iw>fq^gi;!hyClfy}zixO${sms1 zSO*-@qTo2?g7qEV{<8aDw>&%1z98|IuUlnogK>&#x!KyRJse>XYujO;;_$Cy2)8G7 zK-u`;eSS7??{|0K{#Amzr+q*FuEGDZ0GnyKPvZeJ>N8Qxj)sj{PoP)T&@AjXHlz&y z(MJaD)$!gZ1lt@LKu1$!P2BjwDz3yvfaxzB5QxdTt(ak~_d&tLp{y-c<%h`pBRtK; z;+v|BnX9{JiTCIIOP79enonf<2vVSR6iolJL<{`}&kw8P=VxgsbxANo-{6E}y|t@v z<<=Z#-ECf-*D@NUoazF{0bFzGZIY`qSL-h5f+cYgu%yixJ9Z>W%9NWqz$_9eHam9j zc5>m}McK~UAc5wBzw-{ap5k&Z0EZT`m?y}U#ttmn%KOV{zIBLuawoNcg=IE-2$NG} z&vzSRF^C`iQHIf*Xf|x{yhYH^88~L-cQ1$V?MBh(;sdh4Eplu03oDE8Bh zLr)nOZg2khk+H`iYMf(9-@zmFVci3Y6F;4ZAjF|}Dm$=%Hl!`fz2JS!HtB7&ZCBW^ zWNII|fd1mrsyS6PX|o~d92#>m_$?BeTv2z%^)uDKb2GL;Zz59KIfHMK$!PG_?OWI9 zdk=h>^6wb~nt0|b)7wnnii<40Bo36h(S!soGuddLQZh z96$9w(M2Q?Fa^7ys7dP+YmP$DiQPXKcL_$qLl)b#Wd9N*-M_xddlr_t{zhyD^?v-5 zW_IhO#o14%d;=*HNUCgdSL=G|_lbg;^8HrA(E45@T*d;mra{tS1T9Y*p73Xr*oI}W z*VOqg#X+HqNuhip=;nq4u|~f&{WAvy=k;z4lG)0nTc5fYP_K)TbX;W*9}^M~wH~q7 z7PY)1FqUj)LvlhcYUY~$CSB^=2}r_60w1f?Ve$7*AnAxo0KOwdnUy9N#|4eHwd1b_ z1S`wr2d^2EP005o`z2POBt4nL=#@Cu=fi(ks=2rD$X|k4Y*Eu}CgUOzhNf*R#NmqIEuQ)x0yi&1`0mPHMoC zKOcM1Zon}*TisLt&&PFd7@YyANL)xE5S`Hd_ggP5^$lkjl^~3 zT&Y9tU%pe8mHq$G%}yRR%_a4wbvFAg7BM}thE?qi_OAthna3<-IzJPh$b)IL`?{Fc zX2Wl?mi7X;=1Jhl@Z7D2xP_0R2RqDvx9{lw=@%Q<1@Jv9KLylCK z;>{RZG|2+PBhl1%8*KI@-dCLH&~V$F(U!#AUvz(~=62dneym9U@BJ)!zN2c)hz{v$ zVv@n3)Ln2u>*SUnqZDsX)VWzSIz-8z+j$>W{iH%j2~xaE{%<~Jfpykb30fhCgVd%l zu5I~!`E}w_VM^Kr5D1P$Ihq^d^mOLyyGP+>=Kh~Ysm`X7mRBY>?}CFAP|ryMns5rd zG2%W(|K(9S8FhTWI;`dhqdRYi7Wr{!p65>*#v0oneu@OoV;53V(b|Fb_C+68C0|PK zhWx2v!2?k{u@$_ytQ9G=eIdJlb>p$-ZIx}8~ixC9>7aFB)ssP|CEmli|s-g^~p78>O* zbP(1{jvbIzIaFaQ)?4x4ERw25gqor^0p3CGH-1kIJtr_-O&or6MgBUpBNnN|+^Bb7 z+G-s_#j$KivbwmnpIzU~K41$sHo{;0N|~0Cz5=!4c{jJSO`ap#yss!<_(kB4T4VAI zao}p|kmN92{L{a0*jn{Idb^;m+k4!2c6uB1|1efJ$NJmVBaGD)DG40Q!v20dZ*@!)-TTpq*EJR}6w;2{#P=0T9xwKNcl^P%M^t3^mkm`p4Sr3-<(N7b!b&wR#8c@A;>GlT>zdS)RK6qWVEn3tIS@^+E5`P%uFwSL2juN^6+Qi4Bt+d>7?;Ed^c&&oxLRhuT=QS?Zm?Cb=31E=Vx~3s5i<}A;Y|8Xf z;tt(kvyO^h^Npx9u3B2izgXhRqvoc$2&4Oo`hx1W#u*wM)1S!;oX|Ul^%25!8<%mM z+hG>IsUvN_GNYmjmj}I4+q8Vgd<2Y}9L;wNGi~lcphba|+fvWLfm;s9Z*i7XpYGv9 zEr6HOZN=p!NMWVmLm@fJmeHqbFOM{i`*i-1E&sL`Mqs{p2=v#PLgdUMay-a^@w)4R z0fq7|X%y}w9x!KUDG~GL+HRR{CvB$f=H?qhvfIBSJ?sGyZythoCpI6+ehw|39Z*+d z<}L(LuEvsOTI95$*VgR0DQ5O-x>}itymZ8ndcw2CIDU=a&(sVS-3JFN|F!xq5m`2O z^M2AKQGRH+P~(hZFx(ICfml8RNc!HOiQJZU(bs2)Ll%S@pTTy$+~Xf8iC^B{1wWLY z5@|?KP6=|HsYIgrl7<$`%8l097a{&+S_Lx*|NJfY?qRFgIA!8G(>Y0VZd?L(S^r(9 zMgM_5mtM_S>A_#_6{_mEIFTqrkdwN1#l+%|DJi_vnGVu>+!UB7Yky4JGoHhDc++yz z-{a+xi->*X<(M1(YbMZ}%S@>YEA#U2T>`*eb1!Lra07pFJg(eGwWo|A>R&vs4i)vM z`lolIM#xuyM)J-~#VB@nd@lg_YrF0znfQI$RM`X_gP|{TbuH`0mt0Qz!R{=VuDK7H zQSf)OX%(n;SF6JFvFGC4d0XN>`fjsP_XlQZt1IVUsBSxrHPP8I#{2`ASlggJvU3c$ ze_xqB$YJ#?P^07b;1RlpM?tzlnKPDPU|z(cTE+Ps=xQS(&U#(M9fNvZJ$aqn2$J$C z5U!WasefL9ZT&Tj%JOqzSqsZ|k6(ML6Ve++UtHa;+g-BNK58~q1v`c%g|r*sY|M{+ zZ$NH@FKcIKvZZN9@-*fBCUX#v*B8b{h}Pat7K@1`jjmxeUT5_PY;RRLd+7| zq(Rva0+c7{u}N$jew z{PeTO_0%vgUp^{X6(7C_CM%4K#|qG8r{0VESS|_;J@|@_35G_5L;K$)?+y+u#fakL zUpAl@->+8yQ*o4e*vJH`S)&s)>n(D6x8t9aigdgU&<$1dIu_u&K7(#(I&@FW3daSU zwHfL*uB4^c+-QuRS3|6whuxCO|MuG_oerk>Ru^LR5Li20&!5E;G{iK&HH+5HxomMR zy8HNr12;b<7^YkK8=?3+&T~AD#r+3d6|Z(}A?eF7u1gmKkg-Nb=UH=b-8bfpi4#QB zT{{qlN;QlAR#zDH{z2to@BK8+^DvCI%@eP zl5#vZnjHNz<{EIJ%bDCrnq{o}$>*8L3Li`3=`o;_+SoiJF|~imb9erBiyvymX2JF* z#g=c}X$RJlDlex1dcV5%=%BfQwSohD&V~5q8A%fjgCBC_7uK)`;*t>iWy@R9i|E*Y zijYuKTpf0wY(FiUBn&+A(bG}`##(NrUhuV6D$zyI8#XKC?o9iKR%EqCxRNR`F0eW5 z2tU)JRNd@JsUWUteaLvbX~KQSW*lh1Yi}sk0T9>ZV7;*33Vfw&!l3?@{a;7l*eKs$ z?axH;Sg$S@*^yWVi zo1i1@RX<=143@dO=vG+Td)q<$VcpRpB-X z%Vy|};u{tJ9Ku2M?g4jJ-1(15H$%rZ-9rf(2Y{!*{Lxmkhl`j6bP0-&6(OLve>T-? z=u9%&(zNN2Cpu~G49cAu+-<)UCmEG9{5y+S7%n2i-%RhWuy zzb=GC<^@MDqV@s?TocCR?YuxdnEI#h@HA=nuFH*d@)f#d&(ZKrZ)R6{)62?zWmf7I=60jD;?KdQNk0-|G$C zCx0F8Lvwol?Pc174@hr?S#(|C2Yn@MK^I5l;7$E#f#PttD6RqV5GLZc>#j|`OY*P@ zfNqv_S~0 z(5cY^3O+^E*V8JZyE4jy7hfC)RlAIs#wnLG44UK1QdKG4ssDip{oqe(X`vtovF8w_ z_4zQ6pEMIS$2%#245{zJ2dZX)VGUOqeq_pbpRPQKCBUc|bG0kFnUq|{N4Lkhl~Xf# zt7VxNHI;W)_jf*T_kGH{bx8<$^1?@_1L9v_nIoHUthy}YN8Yr~dyEOF8^~fq{R5AE z?rVN^*4ZZh2I#NlrVJnyi?X)mquwitNH#BZkY>A7F=IPf=>C3<1y$e5S>$AIztx_@ zzqP|BG^PTY=cUix$wPKX41?W}UE+l`F@Z2D&E7N-7^;OMz7~&7FXlxe_?aK&(X z_4F8cmClYpuSYUv>5aghGUlwo-=yk9#;ETrK)mlR`O@f(58wR<#|d!7Kn!|+&c&t# zuZH*vE8RB!z*^^SN*y#yG6y$Mhj9HW8@#EyLH{0u5)1xaEnObdUBRgcxUjRsrrW9P~HTVFEV%9N3O0-0g0>&wrBI$|;&p>bPTdvfcNVq%#D7 zi1$*?*35a?noN`_tmrl~a&cK}c|<*rU)K;?P_WXmv(0ghA^6ijBN9KY<*v^(vmF&N z%n_qviwc=%SH#X0f0#=P8j$G#-+kzU37Y?0r>LMF*>w-8bvU(t`t;NKySi?+*?hcc zM%)duzvYiO2UMlGt--n0{(T57Q+nE9yUvGWXr%Y&QzMc#t+`5Y`8i$L#Gjum1T_K@ zw)d!n_ERWr+9@>Bn2YQeH}{*vYt~jBWrFBYe%+x6VQzv+1#l7Sf(ip?i%{;7oxA77 zaGTPL*b#UWE}BZ!)1zmp+Z;~Tkqim_dbVp@cE?iE?Sv|jU+lr*`S8IGE|!Ai5jk`DC1^#pT$2yl9#PZ_h1A7aZCOkjkakKc zg<5vMwYt3-_c!q;NonS=W?a^Et_vVp`3LP@-emNsoVINhEo054f|NNaLz_Zo_l=a>*3g7%}P(D9KEkkTk|7&g7hTZuu@>o zyChy)6PpQZ%7oIp7h55(#&yR&0#4hXcup+;u+)j;P^p6W(^_IhcjOR{H`v=v#}`iX zD67;5fAij>MkManwRWe-{lFVTS2dIh`F5=@!*nd7P^_VswkwHER_ zaB@40vdrz`KMe$vaCVN(%!~fzA73=$)Ha3?(FkVeMm1;W{yU;5VJbusve$2mP{(}$t}OWL33Jre=$9D z6>gwXHK32A+AEpSV`@8}&z@ntI35cY835+l;R! zqpG9x4dYxL%FW--%%q-11DGJfh7E|r{hoB{Ak*f|sNV^>YTBd`^24KGC+j8wtE}O+ zAgI9M7wV?1J(8B~?lv1<3f5;~I0QMI`>8rj9vML|3Ers7meZ*2YdPHP0{@{WCf^c( zK)vc&^9G&Po|8^(T=jf>ZK~XzCNLwUa2$e}hCRaAwDu1qImliX@jY8!|1+lWExU({ z1lY&-%}j2GT%B2VLwoJFdyu+$J=Po!5%E6n^p(qc`{oK=S&y{KD-11F{!3)B{#aiA z8YAQW6J0 zY(_VzAVxl*F}k$t40{<|ZcceT5y+G57e(Y%CZ%ct$?Rg#vs6`jkSlb(-fW@twaUc=j%5TZC0 z-JO(lv6u+j+Zh{st&A~<+p+^yV|$~u29jyz>s3MS)6IekKf8i2c4;TkINt;pu%n3lU{hI?VDc z$9+ceW|4VR>)XCYL+|lED{o2HY0YK=W7zh17_<0Q7V`VwlUEgLMBe7Ic04Q@nSFSG zj~L~?Aj&F4AC$gMhg;B+`ds1qZs)LCgH=5t;B{E`lhA2s*D-9%hRHGK?7@TCjM=Xs z=K`qS{S~%WdKk^|2@az-Kf)l}ci+^)yhG?Z@bi^dx!LAg!B$1T|Kd#=oLjoU4I5)ctKt8M`G(k{MPU%996#)1PZxh5=VbnwN&?{L4_TN0#Q*%9O#s= z?3x%KvrpVb~wI72$~=(e~aAMogY-S1!$c{9tFXk6|}Y8#KHi1H~5PA$tAL5QG^QC#3H7a)}*t#*gEJjon_rSAZ3Ze|Sy`3okD z!5(LGxR!oCRVpz zxa|ea(!22hW2(>({r)73ff+qlM@M=5k<-c96O>ZEcF5cB`_3?b$T+=O8bb#A?l!6x zQ!L@~%orKpF=a!$evwzNu9b8!DSITf>d|djhbU)kE9(bhI}*)tz`d{;fykdZOX)6s z1LYL+PnGv|e1`DvFa|5E#(R`-)9mY?aS96Ef$sNoA9wk=w?Ov*0S&~L@1@wt9vs7A z7JCWQIn;<1O{+EihiFydHWMV;{z6dbN*MBycm6*dDp1T(3E^hi?+UH^X7ibTB2W)Z zKL(sf!Q2xUrDNAQ#b=8LF7$evao?_o!lsZic&iosoGt(n#JCA?Z>rj=j2`b_-}ngI zSym3gN}bk}RiNaXG`OX|Tel(KU9h|@-+7n3NyN_(U(XcKkNw=4?m1ZbN$WQ%lJ6_# z!e8ilrf>xCPQitr^HzUp5XojQYJ1|1WOA5)@3kqtd93gs{f)FNUEfii<_g0y9W7Bi zXSq;6m-XYXIMe~);?73srh+c1s=#_7cbQT&P({xb-b=D*yLpM=?*>oMI}&(H;J1&x`lFk+({@hS*G|zo{k)9gaA7m1ikuL>OqL%n zAb0(vh5cTXLoyy6Gthu`t^HU7AhL;-BN2U~8fh+4GA{ORs=L#Md2*64;HMmJYuw|w z18y8FF}*u>v^*_}=&T-tj2L$uZbDR_wB4Q0ks1uAl>BL`=USX^M#b~F)9t^g+Xrwn z;?Q{Lkms5C!&4~{_d8Z>Q#iw^!TXQ?#?Tj>z_lp*CS;%3AeaKm6PUv2i{G{dJeg%R zyU}!7*b;oG@yOb6eVgwInGKoF1DhPpTBfTG?8zrN@LO#-BGaddT1fP$Cbc*QSo zJz)?f_QLObozUWCpCc|?bw}ZQ?y-U0p@1S{CEG>d<(UW|1kgGZfY0n@TyD||-qo&J z!P~^SX*;u?F4w$p5OsO+*#*JXiF=>io2QGTY`l)Ug}+gXm28r3uj=-!PxF^Yhc9e6 z|1Jjk&$F#(no=)Ca6h>%dci0|S+N@Eam!zG5ClqNSzH}ge~C9u$pFmEm|-SSsX|bz zg|AAbqb>56MNYPEMPLzObgd#xIGCnd%D#a^`6b==46~1mHgqLu?ReGh^+#tH1%m0T z!&YNvbD%)JlS0|qq7dS9qEFbrek^Sj2W#BYTh)21TgEK^@ zdx6(+L=wnxAV*#>@1iDJ0&Hp+S0zH$RRAk*-*W479m`)xBpwbZU;Mb_wDJgDqNV{r zSg#XZ*3o>9&>UFXs4f$IkOEgx#i4SFjL14-XQ4@AiH&#*m_T_}##sb1aA_^xP`3&E zz`9SRJI9Oo``S#nMAR|wUx!49ojkozi`+%~Va#>g=L2UiQ9D*BkYlPU+012buX*RS zF?}am3pqFs&l&|?t*>_nUysdPgkY;&rbe%xC|wuP*gqJP%Rt&$L=#9bDg*xz$(QRB7Ml3hJ=dt zm+iw(w^&<%%1T(C^U)-!V|&-+cJzFVHP9+8LiR6vn%9H*7%l*NS8d-Tmwr2u`Y_7J zcH3%JMaOC{e=jpiHTbEwzH)`mJC8%K}LMcdqOLe)4S(qE|_1N<-EW*p%0H z#F!r4S={2_=V9yuu+-3SM>KO|^zL1(&=H&a@odjFqqC4$R9be4pvN>DXaRH#AsseADosdbznpuNU?l#&^tyM@Cpv=`8RH;#Ms zciV)xgnZHqg@bzrof8(AfccY8Flmiws?3~EW@jC}$VBUBA*cBju6Wyk>|{NG|yvqQ{meUIOXycYLg z8y{7LNx*hCkBcp%j_Bw3`=d9jrpsM7bmxBY$iWDz`XA-0erzq{q}ZyvA0@t@4y~F{ zj-tFoNi{yHBBxdrPy*QVGA6N&<&M2Kz&pcF?kdg#)kyrLm7AXeDEW_!*>g9e2p0)NJpyew zY@w(TBQ!@1=fB$UdVek5(9DK0Z#jzYhqbCR$DIMFOZ4c;27*GZ0m|VXB$}*p-ps-sevb z&*95Wn3{~|jpg!|f9L$|>&r92-Etj2g~ zu>R}TNX}|P=UzK5rDLp3fm9=Fwpn7n6bY%Lv}&t8|B1N&80b0@df!OS-!}XEe@g!$ z$SY`7(;nCx$JQ*1FPOOj!5h_E6jy!znzz1H&Fr;Dn7pesR!a__1J0Ap=u7oH#4&at zn8|!N9HBQ1IOQIC6urF#(QIllX`nixF^Rr8&Gc38V~@c6FIrx5mf8s-uMD+$Ha{)* zWrZ0}`?^QTJFSZVuxI9-koDJJ0k|TN%Lb`9V*kqTe(9q7z3xE(~DQkEMg%vKdB{Z?-sOG|}qV?BLY9p&{ z2ML$Gv>VcLlE=Q~@1@RGURR?#si;E|q)qJ3LDr{)m1gnz1%5&qDJl<`F%*ybaRbFqzl;=OmDjjKYr5N( zG>`IscnN+lBYmj%V3w7gM`*Enese@%oSLHy2|!+}6TS&XQX(EzyxZUUMMC`ld0nzK zFK`TUH(%)tvdwIa&>fmjz6`c=Vj=WiY3570-@ludDqHL3kt2k1Tm!+PuOs5ocV?%D zMvI0l>4up`Hu+i~zWy+O@^n97M31oQw?81vkd!br3^-Pj}{Nm~cX!A9J z98o?^{g^saxaGl`6S=aKIm+?RUF^WCpE62bEYbz^O62+OwkIL$pKi-_XA@bKtlgWd zK=cC4yYh$^Mc}I}F0kHe^F(M_MmL4Kx~ON|a`*3b0!(4@N9L6b_oOOQ7`XtQGnXqP z68HLHLlrh2Mjog!atKj!+lve@sODNiX;=(7?K~2%)AA=Vs)Kmw+f{(dA8bB2?Qc`qm4nEcorcfP(V~$ zttmOXIlfOP$ku723}BLipyupe#b{eAbW$Ro?{qbP(>+bWWIks_Xdx>`OU}Gw`C)wh$yhM zUdbDgPxA5lah>Jr-ai~piQnSJ(6lblZ=HupdSt1$=R$_uaL9+w&HaIkXXy8L*B)%u z<)3B~mtwDmDf$@9fkB@mXubV@UPemTE?@4+SH?0k9+=mv`ui_wMvlKZas4yOXeRV> z>Ch>vb|`!#pIOh&V6jMSX!O?Ih4+|q8$QJ&p*y*<8F>no%v8;BG2Q?rIeXA?!O5EW z$z#|ov^H)O$<)Ir7t=#cQAAYW)(j~E*LO2!ztgw)a`BttdeyuLxK)%7X)Huqq6Z&d zM#Mz}J7(GiUCOY>U#%=yjNT3~XJOW+LzPc>oi3O&fok2vAOzxC4<^d&of^9A*lOnS zJ<jyBkV&SlFj&NLCB=qh zn=qK306V*bLlz0BKE+*R;`POaY;ectZt9@j{oVA0hp#l=hR4zlCbrQ0jbP!b{@2MY zuZr^U>SE5-9SdFGPB!cGyD@BrxuM{C2N`*HshTWbeVGaNrR;q%oxQKFiwhnabT1(} z2PBxO%VF29cOpZVi@K%5_)>wZG+q>MB_WxqE#Ivu3UN zha4@ptXDJ_=LMpg9L-8fS&zloVG|)&k;~6_!x2n1r1!C^;cv`i;_)UD_l%$g%&+nN z*FZ@fDe5YxFljZZ7AAff{-yrQIsR|os5C&=RmpMtX^>L9=Nt~k6~z_nvV1w=EkRhx z{wOF2SJ1rkMsfch>%$UGWSv^Cyl02oTZX{DD$r@a24@c^Sz%2k{1}YowRRnIw&5tk zUuZMU#V&XdYb&AdV1Am$0NC+ITEp4?0_i&n;_1Gx0KA$3gwD^YEwQ;InvmU~^W!e+ z#HT4`*If4Os=8-=*Y}`a`Uxv96uX{PpZ$VUMt~qHW#p}1jN@q42*@cz@O;evj=JkR zg7ppe2Pwc4kcQU1q&?l3OMvyUQB>i_e(nHJ3SfI z3ay*fl$7VH@J5BXk0Vv0j4E%DJTu9wp?X_ZI-Or`jUmx7Duy)%@t!15>usRg!4fy9 zky1^o8pAXeS;A|Hmi40+TdvS?ixU?z_Sgbibr}<3HHZU1Kk^0dT*$GFq=tCauk;ou zto?-*WGmUh8rl*^GM@7IxdnUK3cJ6kc12WGo-V@>Xjp66;P0oRJ`P_=K30+W?WY|k zs*)Y09&DVOWnmp^r33Uvt3nQRkex79Y&ZyEom}G_LnWH>x3Mt;i4}5ryEd-=+|S1( z5+bV$l3aO;d=^9{>etK78Lja!fNp0Grof!PKlp-TEwLp-OZoINOqYOE3MsqF(Is%> zI~ejY12C1<+cot^_w=UjnqKhzO&-3*-L7R>oUAGlWgLaPZTzrB6{87+#B72gP%~Wy42%UK4GOeB|CNEde;FE>N4w&W=SSe}PROsIP@1 zG^QKBkInf;TfhK}pmY9`y?3~G&helCj@$f0Og7V|gB;cI`5`Y$s%gi_0C5gw)VaS@ zmYV7X=O%}!EtQo+c9iZ}d!i{e!Agb$>Te6UeMD-NWZ`+RF0r3X4RFba-no=*x_E8U z_i1uxNVUfkv7j(!T$uxh8)Z3>-env-JdO%AhM ze{`BCw|%ZOzx6{0zjJm!QzsT8t*d1tm!eo7t$GsgRyl9Pz&)yVdm@M-9l-3L<`(3L z8+;f~`TXQFwf9e)8muHwYO*Hdo+~dP0{yzsq^X1jEndb$dAL=LY_Z=FX=xBLp=4*p;sL9 zv^)L?VpashkX;=3`vU`8jhZUUywiZ-$E<~LjlVtKj+PcrCPK$C^b$qzi)tfdod-_w zQWT+a>8Zmw#!m8so__MY5rD@ko2==5?g63fj_z~?R5hpQ4~c>HEEAOPXhJB77S55s zpxeN0&&SI%$|AzviHYePVY^~KtioSs!u*0e>%3=B^(+1i?Rzs3kN-a7teG`$TD{Qo z^r2E~UaI=hlv$@~p}if$m~_9lfd2vI5XTMXZc7w6k6(E;h(~~#o6S#ei@x|FnIN;J zP#y>^-~& zD+kU{MrmE%wN{HiS%iIt9!2}Ani#+W88_F}(Fx#zEvSsg;AgmBebb?=L{o&UHw!uo z;Y9CaXz*}Z8-_Vg20CFLRHLKge)UKfeO;j+lDe=$zsRaT7&Y_!&W)NHOt1Qt%iHmE zAQHOqG^;V9c3WB^f*3~vQaA)XS5{gF=aAMTG8hIRQYuxq?eX&CVYl{*t;^((+;`=s zw)!NLTpgxKlRDwQ!rKaa0-I&Cczei@BUHUqz#FhRSyryH!Oq(wC(A)!Yh=p3kWxZl z`y*R&;M;Vp{r|E6oWrqI@eXD_YA`fBy`|0Evg*+^HcaU9O*JlUH3QPRtHPx?an+r- z|48hy0LcF<)fvFM^|P~q+gxQ|0=%Vu(#O=lt}t@;$&ub{~??Dcx~nv>i)lh2RcK=ca+u*otfm=-XHDXqRES_+nCW zpHIYbk4Q^h@RkBROx^z8^$8m{q=}1%`z^F(*mQiRMZRjVnv&=MI#~}x8?rM$?M8)XlGh%b$F7lwlN-~1l{5JB(0?qcnZeK2MACcE&V zbRG}&yB;s%xyg^qvbc~p_OpJ#(}fIs+F1qQ0#kH{Hnwe6T%ti()7mE8TSXf^Im3*e z+&4dYsQmBv%W&sK@e%D)sT>=bw579}BS+x!4V*ADtCID-K|+x&ct5L|g_~ znK|JSU{{{PAi635mEmQuDBK)83+J){pMcz>vlKqtXn<&oK!@xi$(N?^=gH`)fLiF- z$nH2a?G|Dx?Ag(G>#@IDfb!ZQutYWwE1Q0TvIs!*4xu}9S(_q3MnX??L)EQnh`wF2 zS$h)$UiY{O{Bay}6KFO?Gw$&V8Nm}mjz*+|cn&&RM$^SQg%}*RRo!o0hmsWej(65a zNS;4(%`i#*((M>i+<#i(=be5i{D&D$s?9 z;^meG&t~$$VGsKjbPJKqTPXG} zYWfqu@?SxGa^n%2AKZw#{N{oa{}i%h<_p}i1-zRiFp1ye?!TOAmln#e5V89Fd=6jy z2xUDn%w|LlH=l3%;5X;oAQo|dz3X-%yBUW!wzB8OHiNG{7nuh!N}F7U2bds|Ds}0a zzGMl?y0|7!_>?yGHhq>^F<9{#xu!M?fV^1BoMqpX`K+5*Ff}q{LPkSg(HCEy?C;LuggSj7EBEo5#HkE|c;^{z&yBoxF}<~QpM zWm{b}H#=pHv9K?$D$hS2^a;-33pI0%zQ~G+g1;CicU_!ujBQqV3F3uq4~0Lv7jGGvmj3azi`S#5m*FYp^`t4*|K6haP+| z39pU4=%fu^SIx~PdGBsk#6!|jKCNbu|EeQA`FkBde*Msk_y+e+;_*qGlb;<%^u@Ml zH~4MyVe>WTkzJ~WuoVYcR#nS3ZK=8y8)-#$w+Eji7agHs zw{P9Gv&10nqF~}^ri8FvvPn43-$1Rd(kN%{`W>K)q+fTkB;5u|_q7G9P{iw=O93SL zDZ&e97KQv}H@d4^5_SogeFGKOCVAnFd;-2v{6!gO(|&S*|KiE#$DjYw&-`mj92j2* z<&GVEM3rnSLC)q*iz!?rG2y{Zibh4)Azim8QCP|A|{K1*kK^3SNwa^ z9yx5p7;;9LT{0BD3)#_ueA*Z73)%E9aJ{&R#m8)Z+w;(H9&FzC0Tq3t9Xo^HlF=Qz zx7-p_ioabwd9+Kp64&SrhQ+1`#GCI>!E2KbeA?jHY5xl?HW~!h1?COUZO6B)7{R~5 z6KicE}8>r=`%MJWS%@!EpmWi#cnvGe`5#u!#^zmQ${E12Vtn6EBOZScIn^Qk--z#`*+K}R;W4YY;s3meybO5W(TJ%`PC z9{S+7+jYPoWgA>CIHmZw!SzCSa`EKbh>H&iRi%P=*7#jCZR+}y*jq;KAjX2H>9=eX6G2-q z@PzNj&z}_TQ` zB(YxIYIu^1g9m;ad29oW*H)L=i>>o~DE2pT8^7^uu@_?JCuhnfHud02{#jWa;i*VWa; z@daJnT%S`z@vo0V-PnPw+m?yJgNLsN4+6oJ*dAaj6mERK@NwY_0nlO`8)K8Z?$_GC z|NKw=$r&7e+tlmlfq+zQ6byl3jRI)@GNX?{EiuyF}YRUs_NlM%$r!* z9vzaks9~EHJCPOF_<;-xkS!%1B1Va8FxaJh+K%2e#w=GMDP=!~HhO1b-Zt-6c-P=t z^2})3>Q;2k9D1gofw<6bH&C|9R)fFb(feXbnm3_;4WDgzOSxh%=kz8v!pBB$_GM}& zc?z-*^7rlIyAuD%M1NONJBJSHxQWI59e^-^NB3py7UU6JV<74z>%KP5vdGvt2m#Fg zTGfDzG20ScxBgp4#^SPzcbr3)ZP`|2hD;(LW|ixfzk`r|Y^PnwZk)eqE4UJrNhpWU z#wpt>9JOzI`^_(|D(pZumdeVwDe`ROQ2Ln@MY4#){6#5>Hid9;Grq8KaWK7@`^*z9 z4;!C+ZT{q^kMKk$pQtbR7Ir%Y(b&XZbPg5{#)U468SsALU+CTVx3C)>xq)A=OXkmU zK6E}FYKkU0Vm}AYg&m-x$wQlB&0KWaR_v!Z&f~#>bxP=3=zk#>d$#4Tc$j_&yazEk zkZJ4{>xhXZ&1K2?!-Q?+vMn2e*LJ3~@y+7T-^Q7nMds6{LdYV#;t+c&*plNbu^7iT zoao3qdIk%Ew#C%VL7Wr&2gQG!r@AUj5ImBS2f{*&4LVOgo#qo{K2Zt{(Rn@|+QdFN z%_q#PEo9}A>QEma#Qz)gp&S@N^+mE3+Co1!{$LMnY@uF+LGdXu&&^LV7<=ZP)KPeC z=BSnPd?>N6>Oh-=@xs5zr5>=P2f6uxFa2_94gqcsO|Bw4^VleKf?jDynFQ|%9Wrv^ zw>Bh zxe}AegioxwBCENKo^-+^OU2qvJ^ce;Pi)%3AN?1h-ioi?jR^DP(@~NY@TA|>>Z;KZ z-AuD8*;z#<*ytuFiP_jh--CD`*b^7a#N$Lqa`>W;@8}GFVv-LZXd(_vPaX*946c%g z_d%_N&hs2Bwq--;CIT|8_$|2$e)Q7JoO$=GY4jxq4YsNlOIkQH@nsM<7IkA=ww1i4 zrc>KFJD6p@&;yMQ(81SL+$@s!L(RPH@l#yUotPo0(3JPsTsrx-;Gf_BssHgG{})T8 zi<^9KC1x*bBnOFS&Z*em$OKdLipx;?wnqk0 zi8og(wl@AVoVD;qK4WnqqKr58ZylZ4x#`=b?C~NN8y(lzSt-xFZQ0gFcI;3=Tbg%f z)m1|So@^!BN|)ZXG#js#WlZlHeGeVrE@j zYb}5;#mVrXj9Dvxve_HH%vVLvo7h|l%mMHQQ`YQ~jTA(O*WLHbgB3krG7k>_Z{Po+ zZ~TsxPejN0P_rHkU;IdeYb!y*B{1P1ofKFK?UPS~Pj2ejv>E57vU0Pg@HU08sQ5*| zQxMtY;Ym^*ywHv1p+}zVp_5I4dTr#_n>G`q4%>z#+bUvdXPi_@O!D$jC0ndnV8#B6 zVtjJbi0uWITNjHdKQN|O)jEjdah&LGrsDIZ!Hs-mgFl!ya(1bz^cz31i)?ob(+Xyk z(65QtIU9;`btA6#2@=_F?1Df*lF1&_GK z2QW%jbqV$8-#!Q2=RaH!b0DE-q7y38j)OP+etzb>et;jBN0h^9d>%Tgl^O*Gs3e;nSn@4RzO@p1H)l@Tmej20Yi!dGJ{n#dImu;Jmx|Ul zb2o`=5$Duh+A4C7jr2b`JO1RGi6`~7nH#^6?FJWo_FD(-tivM<8?jT$T=Jhbbg`cn zb!l5CwfT*6??3+eKd8H7WV)IfIP@Zq7ra8*LZ^)`>8^d|GZ%ffRmfDgWMOa3xsVtp zFE>xYgM9Ri?t&+@`QNgA zs?ky1va@DIuB+9|&&DJf2b6Kv#I;Fe3ONPvMf)9OmU-Q}B--fWAZu_I_KJRP2q!lN zN+T@FwJEk7)`&=8p*#rD(t7K)1U4)2&APZ^JBLm1xIBI*76-P1*DiGI`TFjQ53$i< zSt!?{0HR#*`WXNK5CBO;K~zVKn>c*QiYsf`IFY?5?2JCsbl-cT5>>|Kx!^tc;S>*cSkO}2CWVz5)97;=14yL8j#Yy-?>GmO$ zU)8DY7E{CbgKv8N-+%o}|N8S!zS4YYv9O`_TmJ>$r7O8$&bAU;VJmeon^?K5CQg!- zc^Y0;aN8dF;I!j^NvwuY2|qI6jC?*}2W;rU$=89^BZn_Q_4x!y;s=xM`jr zYVwkYiWjjCUwloTgBPnDSWCHLFZRQeZ?OK3Gwu{RZL7*rPmWU;OOazBP(qqZnrNYIL65WWIm<&>#7G5|4*6ZkP|&1s2gS_)I5Lrmz2U1#vjj z?mWss#Dp4nQ5UJluouGVXYNmaQu#Mu)Bhq@@ngYz>*w7ScC1Nu#y900?P}$Uj(m%d zJWU@viB%zMTPJ72w{PFn#K5*9J9UXawzXhh*o=H~oZ48_U~<2RuWe;5w&>Eo>tiFI zvn+E}rLN}ZEh~L}T`Wennl+aSo=|tm@XQ)Kye8*Wv9&bgDr{{nuq<$tTTM=*{bBy2UZX;~g!s70?;3+IyfFIoY}T;_9_W^)8wz;u;t z1DK+kL@$(sX21)@1sNXNYIV2l8lLD+!U9(4=;P4IX2~b?2RHlUe7yNR{INd=8-@AF zZ)Z=QRx=mcIJ8Mb`U|{^{szOwVdWY~jF`*NHYP3JZqk3fY|C%oY{8b~i_3Dgg6-f& zP!s@@immvOmcb-r2glnU=4UPiv4~}Oj9_9o8y|o3aMKipZEbii;cCUFJ#a}M!e3O1(5&oR22 zVzR-FX!Kt>bIR>jUblk+Urcy_f--C>IX!Y&vGEXMC}yI*~RH0!#VipC4RaEd2a@ z>L)k-9F~9n_)|ZA{NTp_IdQqj+r_7}3;P#0g4B3!m@oPl4;sPdDzG0aY}s#2vRq)2 zlsbWm~D;&Vy=l z7W)tjylV7(&c3>NZ8JxFiT#EW&tRTfO6{}0_Xg8eF1iZt7e8TT+}KDf#gmd~kN!|& zKYLvx4}Oxch?lq=ZLyWHnPA*q`XB~frLNX3w`r`#MwO>Ott3mbJyf(i`T|Z;Vrbgn zT(L_|7{Xgv60|wbE;?JeF&#(p#9HLHgBypVi!d!Wd2U! z&p6nF<04m$TtVHX^C-SKIP`IzH*xd-fbt3YL3cMEkemNce!9Hr7r)j2n!MiYctji&JyqanRa)}Eic;(U`tx7& z|4vAJ^Eb~oxQ3|NAMBTly$}rI3Qt$l)A*8@f8F%&_8K3;_d+iEBcHSAMcja)P-B0S z&+NC29ow@1BE7HZ0nV(+QgspUhazuVxr#P%uuGXS@4*|MMP0`Jh3$-4iio-n*;Fse zZL6x4T8ZCdQ<`-<+5~^ABt>s{E_@3iE*Ld36Xz{U=<~>QA>~9`61tjw*o`gU^UnGf zm+|X_s1^7qYJ|8y6Qk5BDipc&VP*}F@ogReZsTa-m41N5@!Me2L>y-c^u^bcNyPBr z#1tCK0pju$Uv3DY=*oI1PTN-aCRoM+kYw#5xGy$Ql6*grKPkW$LAk)Y$G+j+DOe)5 zp~wYeDDqdZ;B3}lMW)8qW^hG6hvUW9t~u1gV{}maJT=0Q7mP^`LSr*LOes8JUA$#3 zK1E;jOg}b>OL!yS)%v15?Pg92dQ?RR{E5wzpBLhD3OGK9D;xdfQ_{gfW8xG2FAnIz zO|oMDiz1VF1&d@wCWpm&K6J-d#BV_twUCx#z!}@(_4aYe68z?U!wVmAyg1Nfa}#eC zWP5n3ioSl!(wn}xcKrH^GwolpLdI_@Rdl(SL>m2b`>s=_ zZ#LSNslzMcL&?V?*THrXr&s8AO)Uw$DX6m5g|BbwZdJFKo)||q{yvl2;K$bhjK5EO z_|ltp5!V+yE_5D;4k$VP#~=StzFtj@Mb5Sgd$wiTg0Hyo9tZV+FLp_ms#{fug6Uv= zV>^fJ3ty7+=m_J+Ph+!e#H?J^O=H<5+r;zYX7N*Z4KIA#N^J7`a`ZjP>nHxi-?4+g zzqru|XCKsQ4*&QkFl60mkAK0CwP4)DH2GcBf8;O=7j_umb5bydx=N8ZZFIia^9%Xv z9=w>9thsF8F`%|YKl#|;psQSAn>mDRtE$z+^dc9DmtZh&g{?;aEA#joOqm-TF1g@> zU{zH^CSIQk-_gbNQrkMw{eRGT&Vx{N6}&LZ4wjO@MHG~JGx`fkYsX&6lISY)p)cK4 z>>~Uu_~B6a#1;I%_^|bh{qg6|ANq41a-ZO&u30zyk?n3JzP8oGuBz40Xa3$3F=%Qn z|256Oc__$(!NgQzAH9Y$KJly2H*sX`Kt6d&OeW^w+vDHXi@LOHa6F0c6FaGg;I7X6 zHFX&I$e>P!U$Shdic-J_YjiB?dP{0>R@UDXTo>nF+TgIQhNpv#T1$UF`GF2H(P7};-XV%-@~{8z#0shlU^Kf0eO+! z0ECe>L52#Vm6=AKz-&N@%f*_^iZg*FJwXsr~gk{io>y+1V@Q&**9gp z6HJOFeWrh}6@!Dxe0_F+-?6gj>1i!0;M1{=~GcBei_ z_y=FHJ@~|A^j+YO-E5XcKYZP-0&hZfQRG<@{>ScdK4cf#^IEd4s@B0KJ=oxltZnk3 z@h$qZNx%HqDBa+>pWa{a+&L4M_4S7VuPUqi)U6Yngnc8Q+>SnKFXN5AP3#|hC3V4(Z57qVw;-n`F5rJ*Blc0F0KOQ9Z?o1_!xtUVyRfr3P&XLG zl^B1J?+0`c>#o-DlCwhLP!(QBb^Jz%S9&gxL=SvSsb~%F6TfmUX1&~M@{lz&@Y?7y z_&*e%96@HXK7{QrS-Yu)`S#-&bt=yzvqdGv_-T;yrdk`=I-mGH#3llY(b zc#K@5uN2+JMlqLIoajX|VN_R-)@H7Y+Cg9P`XopBB%cT6PaX;~7k^Vfi$dEWBp=v& zoDZFk2X>0OyhiVf9Hcg$JWRaUE3m2n5~7*@_s2H{)1p2W@yJ^Ez6j(Z`uEV%_wWDI z2WMRq>+nCxfeQ|5fPla&ZFC7AA{09_KOGdjCl|It8#x;*tlQRL0r!GZUl;j_eC$;< z-97#VZ{#lYNLGV~#kbkm38t;^-SZn@Z<46hQ<$U291P)0j6V66G4W-Amyy4?X@TyWrkg;-sYXj(uinRtnRVhYf6#nL0qc;wxpw%x_Ufrthdu{ww zf}`9ZE($wOy7|w0o@|m7&2NA3i@c0%H9B0QBNi;9Brg=gMCdXg&U+|>FMl^14TH=x zJM0^2tMTz<<7M-SEB1f#)E-PXGn2e*D}LD6+~V4dn+^M+gUxGOi$eaw9=kBfwhFSX zT$vAF{7bvZSLQ-Dz9?Vm-m>5;mo(zHU*QeenKVmK6?RI7HMMA8aKR)THGiuH8nzS z_Q4_^8(R1n8_H$DyO4R#SN}PDqPwc+tJ?$l3QqVIn4%+eQ3p&ZYh9&WncpP6sf!N| z&hr4T-~xbc^>N6>Sh2pbd+Ehtls)t0)6Xw{4vTzlE@^W(6M6ha#-*x5n{M`V*785{ znF9iwHW+M5Bsmee-_R1KWqT<2Uff_As=;`4-ShbMiv#@!b(XJnfBfX9ke~ksrS#xn zesF^|`XigYeT@$5@!Lmi?F(C573D}?#7E4;W_*z)+bUvZTd|#WVf#3W@d2h9p3I-b z{YboI{%G{tmTmf_#5Vh+sz+ya{a&+6xiz=o1jn|W{*6s#8y zKrqT>6=V}v-PfXiHkf0($w$RLSY4&+9{MDfp-2?-68e=Z+1Q{;|1VnPFL?|tbYl+8 zr9PUt+|=M`^dFgnigEZ7t7uB!wrsOsUf9?=sK2V3Hs?uVCQE`RpV0Flmv3#7`=5M! z^NafX1@@dbKk0uVjotBYY(~LGMJd?<>^p(3!P(V=iKVe)fec+VBj+rH(6wnddd5cj&36kq#ql_^*x>1JoY(|1 zYqnJ#U>tPxV{P=k=bD6OY%JaOx2g^>l6ar*{yF3G_>j<%V2(_c3>7#G>3!Ly1BXLB z^CnOr0++aKtQAkd^qFOCDY!2Vu_rh8PYON-kr=Q7tPSz{l1J|A61&S~>TKbV@s z>VOif13ZPzEN>EoHre2SGG5pon-qm%3U6W)swU1%22T#6@CqzRbZ|%B_UJu*;=2E|q| zF6`tc^}@fj8E2zs{lU%T!HwgkLn3z@Ohaf3GpS7Pe$4xhMr zF1`3PcwqzA6^gBk4lixPO%5*PFXD{_!nonv(_&J#ryqNt{B)2u7^pOL@eV#16bxwN zfI5b8Xf$<7H=mm8ZaX59bpKUAaU5D~d!XD=V4snsFykkEPH%~s*F;r9E z-K8RSycm~0sEH4JNK8YySq0O=+0drFz!v$)*_P|}H**)57WmVbCEE}-T*_4#I?oeZ zt*TO2&V#K5w&<26+v;E=ukkUtU^?M~HhEflf#FHq=Mx?MV5mZ;(Mc>4kJM?fhcB(T zFwZ;jz@C09joPg(YJhw(nkDmIU@0(mmD1YGLMV}a_rpU^w~a+^FZT3{@dD@bcR%ra z@j#QCtZjTelr!}L|BJYNl9yl9{!hNa$-l$!Zeo)hJbvRTt@bYUO{qwL~S)>nH` z1Th9CIB$Kt>%NdjNAx9#&5f|x7}c$+hCk~?pCaVI&@NpZ;wh9*o;aTrUF<9(HBRH; zi?1c8013dJc_|no^Gxv~_v6RE`CaSZ$|sjk#!qhQS$m={PqY92_kSv%=wEE!1TYB; zUgL9vZ7|Z$#;`3xwv|7@vEQ}}p75qX(}vPNzI4#qM*UXoEU*VNGs-n{98_sHzHR&w z{8hvUS;3gN2X~S=>zPE@wDq=M@H6$cvC7U%R|M&moJRQuLuN z5B@!Nq(vJ_u9LG+^nQH%hw>@Z@NWzUPk27bW$bO4QZ%35U;075@2~yMLA02Aj_t@G z3g6aFF6qUOu2OPdw9&6%puR8i7AjlatsLy#r8ZRWF*2x;c-zD$C{hOp56=w`mhfq1 z6}4NzaIwkLF4{XsFRgrX#_q*_%crocg=cutesN&Dz#LycImmxe^YQ%!|HXVhv3>Ft zV`LNiJMUYs@#6x2fgjxXk(=wuo=nXK_X76@p>kPZ*^0gkn;T4pAK|r4Jg>I!) zAsN{VJ3>eNKG1FQae*`Y?*iii-+AN##aP*@DkV-g&rjlS^wrE4_KZA0=3m&`$QQPi zIbj7%n*P=;|2Yq_3%v0K4&_QtBbHcZ9AAPZEy<8gw$Qclf6*@DSl|kE&MW#kUtZXs zb$B)un;V6pPipN#F7p}7l94;khYtK*(am}=&APbY$(WwPuUzOg^S0%(3X*9dUUaSC z3;v6`Nk2Lg`?MzZX}jJrL?~XCgYyc>K~ zEgLWC^RD2xOPR0Y3_^ciHmgw}S}@x;j~#>_xkh*VIjBjOm45uNitY#lZ_Bof?nQ7G z7;VqG?O7Ao;v7#rH$0M+%Pw`bni_)jmSJHNo5eoa=-TiveA&d*wi--Tt@xF-4eyhO zunkYyZs|I{vfu*4N(U$jR{9E4cQYhy4%pL5gvHBWE3 zQD*J}^aAuPf9WD|>FUL>IWeDLMQ3dM;;W{gzy4JE&-t|R z8Yl2TLT+0)aw!i2!7wd2o;-x)aQeyDlb;-d!4g_v%0>*X@rSn!WjyN%Bmr)c(j>mY zWD*4nuPxgu>{ivgUut+yiZ_&gRl}3{R_A~p9RMXI8~uwI4i0c$Z^}H&Qv{0`WE_bU z--D;zk8gkIWRqm>;^vt6gd)F)xn$WPdSGj89>=NpAg=I)YSs>!mg%<)a*VSU%9^vd z1BbT(Ce57lZrRq?m0Tuo)4q9UEj*B`W%P%ljapW2P`@}7lOwzE?V-d3pD|qHa`UVR%-V(iJd}h#K9}o#p7Bi>SYQNasqv$_ z^@2a=k8S1-^>M1YC$>-O`~~Lt8an`Dep8>ZClzOebmK`}heuclUh2^{tJ2`8n)aaW zy8YPr_QL*!jZox++xWV{y3x~B%6^6?o6#3W7ZZZNy7u2Rl{qK(}= zP+j;buGq=^1`9(~-Lam&OTl*$58J8`I>J-kfiYBFnBDVG_@zg(77z5X2RhkS;@jxg z*xEGYO>i)d91Xsn^55nVQ{v%v>|oC#S!s5^-{bZ_Q)0W>qrF<9)EP-aroX*Y9`t&4yyiYX+R0|#BYufRwz zvnHqn**A>^_-})#`ddGG7GSRZqWhBAz*SpE0f_lcfd^0m^T|WSCr>laxzRt_AQv*& zjU9sIZdKnT#wbHW-Zd?p)5cz~q(!|%kZf?f6dgINKJxnqUxy}OMRKcK%|UgXr#gM8 zx>d1bPumpt$sretTxfXV=_+{OgO``ErnvyM3Ghl>iSI>H^ECU4j}%1unlRj@_=($9XE(lZWTcobB7TZ~MWazhA89C%?oX`MTGMEj$jf?y`bs zV#K%^=in*qg>o6Eb=aRTVYx;H&xv53>*19?E=j=4jh7wYBku;XFj9X2oLk zo{xu86DR(}X5wOl62Gt9SZTY97#(A;0B0K#= zoHdbK@3iRpzb5R^by?1YeQuy?n<=DKS7h3y@@Nh&QG zwc{^1l9(?F&yM0y3`*FrY|~3P*+B0#+vsiu=W(8DY*+PPyyzbvDV!@wLtl78Rdw@? zE=|9XO>9%(zxehfG6mnsZ$FJs!FA#H!iSCSjP-S)C*#bEex_|>kzSP2w=B_$CJUL? zTukuNEa0PZ%>=5p7P-H`p9AlchrGo9H?C@!qY1)pe9H#5Z+R4;aG`mV=Ot9>CmZf3 z4*=)m``ieV(}h0^O=AaJYg_IQ9UuRYs+CX1skKe+R&o{|XcLQUMvNd02Hp(?pRu~o zn@#)Vp)IbK{@@el&26*VR za!}_t+Ny?^hwimyTayE7$05du^V;Cuv_kiSuXM{T=Dy~Io~2+c^i4}CDo zygliMHu24PallP~Y+Gs)Nh3njlp=u5u33l4bSvFj>0(G4!d zlswPhvB0MnHMPlUY9~28iAPr}*t-g!t;|QRD*Zzzb`rPDc`R+BWN=@MG&qIDiY|*;_I~L+|n3Y;N*f z`HJ!9uTTBp5YBInx$#>B5vIu8fR{Ew+8C$9%Kft8gcQnD*3*XKG=KtX$OM4-=t$tw zrW7-qe(by`@E49Rf(koo=N*%a&HK_O08HxU-_zPw6ObBP;g|BBae+as+g4X8d|mIt z0PCIvzI~(U^RlhT4ljk0He=hU`WvC!M%Q~@vgUg01s%f;jfaCZxCLMIRkdv59R4A2 zNHf>iHM$WRzf<7RH*v&n^ekeOI1V3rkPJI6z=>JQOofWJm={;ZmTmE-T$tA4EjkgC zW{EdCGk&*O58p+OesP%p;J5x42Y(UIV>Yt&g(y_;UD( zDzlBQf?7>{BU_#56c;~O>f($_bQ!I!u^j)RyTU_SWN|3TY|j`$@@E~}~}1``?HVqaXrX?x^@B{IPm z+Ux^Z#&+aG2eD~lalZ4gc=$GYZI5rMi6>`5>hk&ipcA=A9tO^b;-@_l^iQy!*gj=P ze#IPQRrgTvZDJjN3P0}g(r7@&rU!{@gSW^r-N8Z#CD!23?+abQ^F^b#3oM5uFhmHM z=vwGYJWwWAgY_{S_RVKoRi#`Dy<#kvl9M6U8a$0`c+8rsWd4NzMZHX%h*!s7)>s0; zf=CkYS+}tVmgFoei~geas#}eI+w6f)WpCxb4vLQVKLm6siCh%p24D(*QlA z*;E}Oz*!Uef+03i6p8ECMzjmLLpOh`3PMlpNkor0tl#*=ddXGF6`i(`Z}od~*`9+b z8$9;xtRITLO)m4d*7G%0FxW<4%jml^ATb!)*rp?WwYKb=q>^N6n~Wv4Lz#hGGF0fa z{^Hq^7JS**pWL9*@8h8dU*}eV0o}p7xETa%69c11vgV2ch?gj$`Iq;8@KeE}m^VC6 zZZ!Eh;V0h+{G$J)R`UR`5H?s6_a~bres5$Jb~dpUwC5n&>MG@sDNJ^if+5CkKFRh_ zu@;OTd{QCM1%EXgokI!ik;|Tmo$w#$p{6E?7<(t5o~*7`?6pg|EUU0_z&C^*OIqY@ zfiwLRJ>ePM90DxM&WaKiIe)4~PxxjGQ`+EgnUT1GUy5Iijro*EoADSVI4yU|IOE$Q4tl+vDq| zPC|?J#d;T?s%1WKEX7H?!Y(_SG%~Sg?0oz9KJ$q?3VBf-_-vd0*SUiDEjou^YQkoM zmoN}rU-AguKAw+h<6Glr6EC!A1QeP2|zfJx&`TFv!u;10HZgu5G4i03(v+>a` z8H$cgZNAv=^U%XS`J|o`1Ix;5zx8hH3fb;r4?VbfKlA|OiH*l`kh=%9c&P9zGWllb zkMI9bbmhjdv6HnEnLHeP@F0&}>de27fG zsfn$`a>Q9{uyr-Ehw`)2MQ&gD84RCTCXbh1e5zgiMDY6ohK0t5)M&oRNSg<#;IYlB zWP2#OGrx&V@NM+2Ay5P2p1b>YslYNVxb8l>s+0>Z!aMJ>qraw2P8q_&T6AMemKq&| zhOXsm*#(crClsl=bsVSat$%@M4+n2_Y|DNVJalK=$Tjy7p?s4IxM$urx)*23YbZPi zA4aM=ESTKCDQl9o$$99`5qnAZRW5W~d?Us;=zMEf=#~Ld1t54fPVN8z^rCQwa6YS5 zrJH)%$T>3b3w~a*nF%qs0g<9uUwSC^&0LbTVczH^9&-L*Kj5O@X2vMaEBqt>(x%OH zu^uwQi@8N{ZEz=Wg|6s{sIZatOXq@TZ2q2aH36>#5?w%s{j0OlBwDCr%$6R3AK*X9HIE@Lwc28z6`4C!czre45KO#Pn!8esBo{$+U_q(d7a7+j?x zX5;T2S9HHwGM+;PzZUi$+*}^qG`?&E>qgg$C;tWRo*bZ)fMtHMwwPb!D-RLh4kkhS9KbFPdRYtHTe&=&EHW29pnz&fd~OnRW~ML{ zG9nAzi-(gwImya=_Fz}5!5um| z5XF@kr=BnDT;wc%H`p4ClnOWgOA8xzNnk2STtrSTE4r!^hb`f3aL7axObeeT)+2AG znI~3xS(_K3HcY#ZSYx-nq-<5r3ka zHnHF6j!Z~sv#mU|=0B%g;Et{fo}bihZl<;syN$@_d8#O-iD59rGH}Y8|UR8)Lbwc zLwk6a3O)AB1UC9!tV%^(*3_S-egw#7E_OP4%PN;PJWXDTxu~%%XC9vsQLd^|Bb#;; zgUDqbVZ}ytW=+=U{LKqfYC7>JQc7*67J_AgKNQ)GE!%Jl6_(%jGv9@WtSxwA>&65R z^WsWgXk;_@roxwcuNz&lX~tjmoVCmseD*CD9m!J_lU;`j5{oeqAZcYW-|7T|q}Yy} zHpvUPMZu(HV&=0P4za#*U{6Z{(7zoC+s<25Pb=1Th{Q~Q2vp|6Kf1!jdd59iTZN(A z{KJP5}0hBuMLm{MMn}giQ@@1ZT#AQ!=6~|U;u>06&sK; z2+^4#Z?V`Ldhf3U|PhDg90B?D@km&D z7JFeM7yf(AYHW2CZH+Dz@LKr(!k;JfV!Y9$H;d3+iFh$l_315g=F`W1u-0W@tg@wMA%d$QAHp7G3czk@^ zbBw!-e*7wOeX6UK%XXTf219N}$I;~a=lx&?o+me+?1{hfwq^d1I_xcovBfYom%g() zu{qCkaI*;JYw{8s@iDpF)MAX2BJ_y$i*{#9w#h>=xtU)>;tI~h^+0#}LixoxaItR} z`ZmgPlT2SO^pvVv*|+h*_KXt)Ru!^MOiE2VHG+=R_$&3!r}#NjIAfkX%x-e{ah}Tm zWGTKRCtWqTi*~TF?>=~_`^GnOwn4aOoi2DRmt;vz4TPe{wsaiMQf)1YR77i$;sqJghe-LzKIDi>)D)^sDgktHe_ zLRPtk|F5|%mythaUa~IkBRTH_rmOGsk3n$U`M(%#Siy-g+p^QY>xYqYEqoT7w%>Ni zA9K-R!v*PmRh2>+vhvoaIg4M^UFJiLpCKR*f4srOR=~yJn&J#AfaIGA<+k3^8bQq@t@lpt;zvk(g zSyW8#3s-Cp9}6ZfL-f%$he0+#coL5bpBH4K3El!LA&_n5AhO9T{VyG|2+4h*EC$E< z4ZeEYXOX$cFKQ(%3qaY5&#_g2FXYijEiY-NdJhb#&f%R~UxE zGZbTk)2i;@6gvm?l{!0VVUdk*+@v1ogKr!j90G^BdfKA3q`R)*4GT-10oVU%v_tmwl&4^UaFsv9$H`a4Q7*wwN@h73bQwv6n-fnBU^ zCO2#8Ctg*hvei}icOQxwhnQAm&v#sB|B^o&P)bPRK}a(4k%{h*xK3;~v9W_^PpwMy z$@>OxG@WHwlkeZgMM|luAfvmKQuxs+NJ%M3$B-6AHw+Mv93ddxAR^5GM|Vs2=$bG} zHij@lc=o*bzun9GICkIHb$-w9=W`(5l|-Vv%@UCQPQX$7SSv4Vv4PFt9XX=+} z;8XB9lH_7Uxm%?xS>eYBauV(-4)II}d(z7l0a*Gc(68X!^i{9a_@}!(M61g&*#13h zl^y2;?kieAJBCx9J25A-)s)RheWik5!F7Lj{ZN(V>`ppn4|%tEX)CkQ9@(^6mLP$dpP*ZvlQ4ZBzoTzkG9(UoS+IHZ z<9!7GIps1`R91X;(i#s3rdZ;>PEU@Lq!wK$?y8*I{7)8^dgF#(Nq2d_e%(<~k`C*y znrRu{;^}JUQM2UP1&W=1brI{F?QV@e>n!Gnd(~beb4rgc1XOenq{SXDktwGqkk+MWx@nvm=%h#vS{yNpiJn4*~{%iH9EUH#5aMVoni!X}; zHm_ml-1wU-Wg7Sw2RVCU3>sf%e(>)*O30CN;}wMAxouxYIC(xQ+GO@L@z+*Yu>JiG zng3LpW^6sPi0=rq@ZntM`!wy%P6q>j4`fN535;@i|SmaGabi+-g z{K~H$I>=J9E>#_R?O87K9w=) z`q#Ay4M`_rvm`kTx2%6-5lvf94w+t?tJF5{X~7nd)0$hPR9Eai3StdMT6_07tSzDx zbzA09Eik5o=l#_T%#HC9;syQAk5i8_6mZAl8*hW>F-C%FO$qT4Vsj<@VM~Z76cRPj zWF5Lxm61AO{FnaY{+Plq48avrUlOtB>@WamI~5UnihVQKn%}9B};nBZAd5OLH!=(wX zns0)KYWo$OBdenI+q<55i4%71&6q;l1tB9p;;z!_TF@TPNdMXY8y=6jNrM`&i2w!Y z!L|}CSw9c(PL^Inq-D8vy;By=Cc2-MGoi?srLUIk+j6 z$cRa}ox4a81@aKNRCd4OZ2R_M4bdKThcCpsm) zZchYv-9x_8@+_L|Nb6Icl5ZaMl?H20PdI3;`C=)b5e&NT(mqT&iVQn*VE&tKYv#d| zxH7g`*c^8|mSHz|yY2A)P+rY)`p)mmToDHo2*qY8U%WomF~b zXqb$Zlht#JknxhPgZs6siGS~q;xEbs4=v*h*6BFsA$se;CM`7CDP?H-e~|R|PkuGf zwk>_`x!oBm(63{K1Yac7p0FSfWP8YXJh&Auc~vBQ=5TBM*&kIFRYIQ3>ayI^)5ov_ zd`w0czrLWnK?lD(A~8af*qr6X0z6VMG$5jhF{7szJOux?!?sdQWAhGp5=kzchu;{) z-HH`FlGuq%9{#Klw3|x#^y>1ESFERRqZWi`8pKV^f&9hc%FutX0lOF-qYt$_wLl+J z)MSzWlM*YM9Z9FG8Cw464`IHn)mHm5x4XJeNBW#xg*5eS zt#WHWrYfw&B{0p!{tb|A93id3X3HZaJnE_g9$4kdWk&RioCdrc;a3u>Y-@xuGlmbr z$?jC{@=HhyTre}{2=$Oz1$1@mtbx(Uqf$v2e-7i~5GskXZL@^z%N{el8d0H?-%>TS zn|k%jZ2<<$oLv2`^7!Ih+JM^&s1JB z=qfq--ozl&Eih0&C*|_{R_XN#lPt!r$n$UlV?XbdQLNcg7l2X3*TsBpLnwV3dje8& zwmw+AUSZF_$9mLt!`(Tw^ZshjqiLfvc<00KYotKX8Nqpt;j8jC!j=j>(ZnTOXNgRI z|KRR-)+d6yM8+)3LQ&4=mCa+wyc`wXiV4E?qO#CrTX>WSOQ%A55=?@*#zaF*89KxR}l@FDlBs`so#Y2hy?FM*{E8YX6TXy7ORKh z)k$Jyxqr}>b z>J=u1%6hd^0-ostTlYkD;;}*h2Ko?$toq(Pv4KllsU*TJ50XZm#32xXooKLU9Wqs8 zc{j@UbX>=qD_^SW?(bgL8GcS4;(;BPbhe2099X3BHR87oIC63NFL>oc>M`cka(~6# zT$o*lKii|@kqCRAQFw)>fmpEWEXg61kgY3YuORXEFP2o|_F5lbZ$8Dd+*94k-xeWs z6K7lxdIvkd;o5o(*PKqBj=puuW7)z&h0k6Kg^bIy8AgJw>8^FD3h%1LXG?2=~BjgryXh#u8h)sUg7=tuOjp%JBEo!~^+c>eO7 zW18I$nEre{J$dm!Zg0ci4Iyem^iTn^x;1SfIU;;k$YU7CSI0j4>E#cQ!i%Jav5aXPe-t9LKXTUqrkVe9~UtRlx9H5FPWLxSG5VH{wt6uw!}_n@jja&D)^ zB+dX6yF()Z+MTRP`dMytfV%(2=tH})9{GKty+&hZD9!@4m==6q16lFOcN!#Zgys1Y zVR-?1jG@=vB<;UtCUwt;cpU~*azE>=U>|)!M0Qn_=RiuD{6BTs3tkHbovT#4o#(my zJ~#@!N>(=bu0EL#n@42@ym;+L>w=_PF*HaHua43^sYJ1EYBRnWA7CAI0xuY&pm z^*Oie$AgaESoq0bGndtyPm2`vBVoZH%F4L!af6*H=A znB>Kk4zGxI+v*=kJ;7e;7jWIFyt5?wxOMg`f=IE6sMbxXR-4sY$-lUVMvjRjKoT+h z-UMHG;rkU~UHPYO`@WZR8yc}y&Uxk&+% z;{^8qf65*!Xzw=|+v^U>Ez^0S^9SPAKDU#a<4VQ(a*#+oT1+B>>FR>TToibO znMLX3DoEiA{*zKf3ejb)b8B(O&vh02zw7)6%QG%4tn{&JxPtT6R9HWy3eO2XH-eYNKGzE;#VVasUXR+W zW!vNA`~$8ga`DI7t4}GoIr`OD7blg4DzQMN7cullkt=7@K(JeOq1+{o(4M9!*#I zJLaX#2R^o3$dmRxl2ARFz3C>wt4qzOjlI-=660kd2e;jWcy>78933HtmDCk$kDNKm zo7?nYir_T{S8Y!s8PqYn|8^u{6AYc^{cP79Z!67611rrKTaF_8N8I=9f{vEP3WZxM zHdQ9KDU2JlG%55R8>mS5_W$+^J@mJUA5YLakUE8v2JMu&u(PfEfcnXTBjq|4MF13H zUgzU2KhmJt8m^IH6?!fHQ_t6eahbXTj0&Paxgr$-T4!KD(#`#q#j63+I;zJxo7D%? z0V$+yjUq{qfn5*T^+Y&Pv%v17z)o_g27wBE{@#9EeU7wE%KNm<-A5*|yd*V6pI(qK zc2?+}fhpYXks?xcPYWQC+2`4-^ZJuNp z%;S8io{pqcrFBy`)67Dxhe5bYB+nfOJ?P&gPUnmGjnYYaT}xW+o~JUI%gsFsN#k#< z`SA|DN@F%%tz}(Pz!qEwhBY}$czec;#lwXbJehqw=C0WOAE`q0U20~>?YR{Zp|6vA z>t%^D;p@A<48eCk2P|RvIah048(A%D1QK5wIb~k6^nm$fV^<)Q6TDlg+LsAAcN_m6 zXV&!R^lBvzh{=L$X#Ox`b^pb=LF(a*R6E#G;7-s#V8L<-pVSd@+V620ZpYc$UoW~y zc!f5!+qo>wk;{ZJG@Mu7g!}tcX27`OHT?t!uJ3Fapnk) zNnuxxBJFCIH6zoNirB4?#rY1u{sXw5brrWEsaOi*7Z;U83ClAFf$7v^_FmBt$P#&!wM)aJdTo}NJz9vc)8BH`e=r*Jtk^7_A++@k$X_I>rG>pU?$fU$|7udlB}JyGm&d5RjqmY~Qa#q*bx24f51N;AhWY3xpFmzrK-TCs zBQHoQL6`_H%OrtZgs5U3B(yHY7Koh}puXJ$B9xMZ)YyQ)nl1coy7{6Yq zFZ2|W9J@6<&arN6pYS*C!?$}3B}L3T@jZO(te)%yZa&W4A_cFx6v^9Wbv;$pm87iG zH#{j&8B77;?z{V`8}iv!8u{OTQ}5Qwy1Uz$_}~4~E(qzgADumaG?4mfo$+KHK~LIb zy@L20{*f3E=x*fo@&xy`njsvxl00s|j$ZcDB3n)V5O=f6Q16>+!V!rA^*{5}qSy#Y z61_-InZ69l)38#!c3UusceAEko*Dx`^parBv&srsrGN`bLb#nQd7r;18~JVyb^c1EUmQSPY!jxL*(9n`)4b7 zlhkSBKpG@p=f6;Nrw9%j@ILGD0rBSzYh=l^>@xn?%vV@6Kr@Yh~7Q>`*z=;BiV3Wv6cEE3-x-;&N?eo$esYb(Nz#g~3}@O;7X18KMgk zF6?mo-g@9&S+0qNkBI21HWI=pf{ih=XlUIJSKnr3Qy&?V6Ct?iHaG)@uu8;-@Z;mi zo6q0l|2hpuAu(dY&nHnmmx#8ymJxQ653l0*v6Oj5;G~XXU>vaivfE=o;(#xBVWOT$ zH_c#P+PG^hIx*gnS=PY-m9Vk5^KxTG-7woij~i~dSQ$O}=t7f}CzDut$c{dl#IxBF ztF7ig6zUxVk4e_CcXjwC1*!+o9@51hzgA;dnBq{7e=-C))(&NfmiK21*=%A~Nw??^ zc$Zw%2Bz`+GTD`{I1_HGUH5#RUP<>N%YG?&F;i^UJu# z`_r1^+~-*~znEg&HnSYCb$`E+zi4-1H&uc_$IF?ua#v>D&bX~E0Gh!j?0EV z4Llj*A@N;^M~_%mI68<3FF$yrVbIKQ}75V02WY+q8 zU)zv`lX8B`k2eTZjP&g|VKU*xad$6)dVRHDgKQrfvRk)XxhzceTczF?N16`SO`(b_ z)CjMPad5tG+mkgc{x+plaot-&XDiv9;BQkK6er5d(&^HhwjN-WPJb9 zCAEa*E)UR&qbYK?{dcj4?*o!<=S;dRVef1I-gc z_lNx7#l442bPU@T)t`<{&S(3@bi166@@^%y0iJ=f(DE1+9=ARA0`4<(f1$XdroZFgMR6 zQsw4XbelL-%w7;k(Z50xz+p5%v8?I_CW9DMn%5V3SOEmRH+#=jELIFzZrvQceK;fJ ztHyl>@Gd?DopI2KLQFLo3%Jhzc{5oE;YF)JBu)N3*N50QI&N0un4-G8T77CaWJ&>| z6)osKH?zd$M5TU(>&ZAY0uw`2`)MZ+Q=4&Z-a#b+c!OR7m_ z!j9xQK#%ZTet9=lU_|>1g(A1XCc=@u6af|S3h*e&54M#EfZ(H+1O>xy7e`PNPKst( z&sCcBKZZsfo<0ws%VXbi++s1AKkH!tyCTsLJ7&MrSo7_}=Szdxbv_?=nq27P$K}ur zW%Bs;(KJxcsi;!b)h6OgFY_MeFuNU~@R#s|C#zKSV>1=4*c}hq-7rb{)G*ZhAg5=kJI2>%&SoNloJ@B;aVp-WbrDi8TP0vJXbe6Cg0P|4%K9E{`^JNuUY zTEJpq^|%4-r?;~K(AjNEsuP;?O>!OcpJL|;lp^R9T2Yt&rT|T z1o~vQ{z9yR`DMkkdNZJ=9g@_i$L?2EADn!X7kPhXhNLD}7>a#j{*I7La|3!!e7j>i z$9Xc9MFDS9aq_s}=7D+`4|#Bo{MBm#-;dw~*2Q=g(aV>VDn) z2Qevu{+mY5Qk}y;niWCUdF)rMa4hA1u>($ditz_61Ubu3jM0-+iIF>fu%vde0B!V|bb-Jyu(5V;GQioAYa&w%3=kjFAdt8UZ&Nq*FM#~MMOLoLBnl!% zSWRJRO#AakZ|@5XkKUm`Bjk~^%pj!CRv*3|fKFt2h6j+)Jrk6L(O=4in6Al1hP-_+ zqK116H2t*rGiz-a*n1Y{U28c)irtSOU&XExuaii8k|)+m1PZ^=wag4TNHtbGWOFcC zk$ogTa?Bh3OQk(l)a(6zlEN+W?ex!E4;-4RH z-;2GqYK_aiH$@KHrL_vI75-UgJVcH-$?aB)i}@`tsoZ9qidMOslNM+Ep(^nx_(B@& zvVhgdy)3I>ozs&4n0NGWM-yBH`>A?|N}ZpVw!h0gi?-&x@_gWSmbGECLL$r-%&sy~ zBzX40dv|0X2rv49(Y*Xk^AmQ-<(rIc8w~jc_k2672U$i7C^mAa86-e#Dy;}Mqn|#{ zV%LQ=%n|}yic*uG9VCV!bIcl%F;p@~y@k;x&;47;WCrMlo2y8`*caC`)CDIu3Tcp- zC{om~wXyptoGSs3{%ozp63+z4#$Yp-jfLCxx4q6>c*N?FOqcQ4I=Ls&mXvblWJiul zep@!Y>%AvO8mj?^aS-Jdd__x5^9nHrHN4u4H^)_&O(z@_{ypF7k0z9}P@#|u=&5?6 z=Llf2N~n6Im0zC`a!SC?N+Wbin-jYu$yyKl0`0sPWy5>Qin`1UeTFU*33;JVKG5$m z<@a-0@u@IN8OxqB0G)*GPh!;59Gbp>prc#K+FDI zwjA9MTU!}(X9ddL@mg?sH@V*>8C2qs>O5U9-vffUs{`IBP1-ZBd##l4`cJQmxCKsJ zD%{;OXy474@ZDwFp z%Lwo%STrJkFW!#OU{+IVzFAZ^kLaqfGj{UH`*K*`Uq>XsajU0Uyv0I_AI-C;>6g6o zDe~b~eCwM8$TXuCx4Sogu(710Pv{(-opJM%7Em(cQlxS^HW z7?Tje)KzREaP-C%sP3lCO4*3EVGs&A|a zkR*Sc8%Rc$B2T2qiHs~K%9WzhX&6gu4Dt7;VAywE$YfWXzo!*1JOQ%f#nvM0@Bd$? zN=*g2fo3_u(bbBhkfSFW7aFDgp+S9hO!uN2Kn? zyY^xoBV8=t{W1CA3xqCfg0SXhy6i^eoI^0sQRh25|R5QvP!E!m(Yl>u-Hs5;8qs(gqd)T!pyzR13 zU75B0b>>IG^QWgn$zsw5Yf7e!EqOQ8?JhnUy%*_3rE{ypTR{e5T9o=FoA#q}N*@2Y zxxdRM68Os7%tT?d-tGRrHfp6_bMMl>r<^A&!Dd!8aeBx0T^OM}P(1mur2(^3_(ORB z5l|zU#;ky8SIQe3nl`Ge&;@_+2WqXkWlr-B!W8=KD;WQ-D<)(WMuBLSh^f+keV|d; z(cJ;L%RqlVH9{`xZkZXS77%91O!I2UU=;odhVpf$oIFF}azbr#qAI2q z{WZ9bgFo9$I373t&&KO)WO=j123F`s$JBmJYy#}J%-APP*$0o(#JXq@v|qY;_H?i@ zzv^#NM9d1~JRXNOZEK$9^$omWLT+1)r|cc*CG)SujqwVDeD|&Lyx3G0Da~{b_@vha zIlW$97U$P6T|H^$*c%BttQPh7PFqkAy1yg4_bA7FyC6YAC?QmqNnR>`-Py%+13Wiq z*uou9Y>pI{Cco-w%|&Sy1b8x9j9da+JEtyl8GdPE_Np{-y4HP-z6;UI%dt=lG1wYk zb}$q-w`2aS;-5d~WgG71FZqrQEGD05dGqkNW>z0lS^0D!VFQEtJT$F#qikhuMl1m4 zx}~h1reCVjLxvLyBJ85OP^DuH^5k8>)8ZCW)rp!h8WX0pEK-0c)r9VXG^w?F`YX4r zn&hN{BqLY$LK^~!f08;rFjwrylkC53!&oGM7uZ>6jH<7<%mPZYBISaeFdQfF=rZ&n zC46Xt2SjdRBO^i6TYbQ?^2%kKvOoYG9Z$Iu@0Q;?^ocUjgEQynr0M=V{&b7%dA-5V zp``mPMCw0CYzGo1D3=(q(Ip|Kmz}XR4db?rJi(LX+rZGAC%U(;`>DV%-HC2({95-X z%A}d89(NnzknSh8{bg=A>ON9o(JqxtD!ty@dW`c{L>FL9ON4FkMH`smD0Ex;M*S zITkZT2m(9XavgCH)E+o`(-{g~m^K`=@~lC3ok0@}I%{D%V!8LecXk zAzjzJpbriux$Vij?ui!DHT~VA1E}tsMqI^ zll!=DQ$o6!)IBql04yS+_rP$s-q9=dc!RByu>A%q{Nh&&!K_z<;L0{hw=TOymB|8k z0jkS*5r^B{l$?yl2fIjun{qSYHoicRMnsZ2LTF|)ICr6W#q%hZ({OR&Hl#-5RBPOH@Br{@ z{8;}IC4tEwqjTC*a}&w{WMP;w(z=w_()b+=rq-GDHQ}x-S$3erUkN)Rj* zC+cYy&KU&emer>hFQxB$9V2@3(bj{=!);=Z$NCKlSCaVE>Ibenv%?%f`jsjAA{%xu zJIeBvc!^eV|3g=LH{^ZaXP0ke;c1-}b`VNISvO;pi>HK7l&)L8A8Y5)3HpN$JT%M^ z_v*e~ROBt81+RyS!!EqYWI)cD31ThL9)=2jvIrC=0OcxF4dPfjhsmYdzQSBYS`Zl^ zY(a~~aB^M_kE$eHFlOmIp{(h|!v?Pqf>31W~LnE;EUqvpo78|Id1|^TG@mSU!qg z`c5lxvL@TFkF8SKc19WCwZNIJ>_+g0_w|Cml``m})f!cK-WuSHoEAjxeXPMbHl$36 zQh^@WhJ6t?NeQov%S&)`W_wBW=ch?8a(pjWhP(hS-svDG=tkXXyu=6Tj zA)xzi%&05$t~B)SI+W_>?_$^G)vYkgt%Au>!C3*#KCm@kvUTu$ba@QOcw#-h9;;Pc z$&j9r2#yvg8Tc#^uz}4QKLVK73rpPj& z{gA7r+V!34P4*5$ek$(1_B!>6=;__fobE!wd(HaJ?qK@}lCW{K+=MOkV{((k!fxN=FUv>G=Z-{M)D+q0(JZ z3op3-bO*5Dl5gM~1q!n|xyjJC9O@mbHm7~kE>;~*v##p2BtJ)(sh1Wm06P^a76?2P z?HP>61mHw#Ujm;1jUPG2mc$dj0FISR-(6$x8F?bibhh-eJw7mu3<=5vNe%~USlr|zC#8Wpg8zvkn~xL zl%<$gaV?KRX-zg$Ue)wNIl$;qWrQ4UelF;ehfR2~p5{k}meanKcJ|MaOZ%9p1r%A* zF{~@b27iAmC3cO}Hz`B={KYw#`H42-77kD~DaSyX)12swjwafGb|14BKPso^->e|a zQ#B`o7M%KW+INdCq(TqTfXRr^#zK`E%!<%c>Ce*bdH3c|OXPCJs4-i{h6xKoAe7BA3$Fr_gIty_1MM3Ti+*v1CLva58j4cCn zLVi)rghMOea}^)z&={}9abZ(6XWzz!$$UhU3DJHm@o)H%gDKYaG>jv^`Nhb~|pY*nTg|`r+ERAlcIh;2qi0g$9IBxws?y!>}*+&6CEJ1M_ z@0^BYGRsEC3kiu&g9o-x*!<5nvYE3A5gh&Q$tMHZF=Cn!s@RuNueLV$%Ss+BNd$yV z_N3_E76qgC&xVo|(jqEa-w)WUO%9Y*3R|9^%53%LT3I<9-g~ zim9Hcc;>I(ZMt74*G^N}%CsghUJHT!$<5Tnc{-+Yq`tSr;P(NtDYKWa!dbtPnfWdd zX`YR@x29#sx+yVKd@euG^W*RIevEJJx2&8MN1pE_DfmCUr0eXz85uP_;QrLYd0I zj`%OpuRtQW6Q1aW+lGEOsT1uW99#Z&Uc6U0;V{NPbC@M*Q&MS?s&AnZ`eRFUNBc(M zvhc5zFhcVq{3)Ryh1oRqEhm86)_z?~I0nDBEQ&>oL%Oq+XM1 zc;=p8l-QM7>_@9zL`6Di2c_cz!OUEy1^16`=Ur%)@8Ou`k|3$klX9QhUv{f(H#FR+BHm->?U&VD?K(}o0iz4+u^yxIS<0EBuMW(}2ae4o?= zPP3}Lq4l3{aoc9Frw|xo+^t&XqK?*R62Q(S+m*UFNnFCUNoRwEYiGWgEzPN5L zGFu#GHDs?aEj+Q^<*9Totn&$gYCMC^;yG^Jiynj7s3#n&UPRP(dSho9bNlO$ zF_+Y#3R1>MJRZLjt}3Owb_-FIrK8ZNfBb=Psb#SoaR9E?~Pix;!dPm9Y7EhMqu8kZME zh^Z3E#Xb#*absj;O@ZS3Q;2AorM#Bxn1r+hB$mLYL;|Zq(PMIm~QF*6TG-8TuD zq#P7x*-;3jHacYpo^FFVFur69{$zsQ(ykUjW-qI+Q&020ETg5BvK%J0&+|vvwZ~p| z3cPEo7qeRU2*Rzz|OJ zv%Xi)zz-MiuhwcWgcq=hIn2?ij7yZRJDZGWPK?XNyTvj-EnDxt5=|YpVi_Q3yG)lO z0V#loQiP{n#J8Y3>|JHo-M`R}w_eLrw9a(FP=^s~rYTxJRa+M_gjEB~GWQ3o5H>7OKk(n193$ zsqWoTa@9#>dZ36y*-0~DjvBfPe9o!BPtXKUd%_;-8~flVMxvAK7g(&DX9L1<%r#ZBou^z8NI`rp@e66_irR*)IcI|{wH{2 zcFcf4{JpkQ_IwbGjgE4)4WKi-ZJA_#7W^4A*XQ9g0W&+d>K?`XVJLs~fnV^wxd{uxc zdI^5YdBu2U*7uTN*m6;i>QGmn`@3#<9Y<=ez->>I)Ybc!!q*G1$o~}U=7VSHR_x6Q ziz8Py0pjLyT+-WZqxA_ZW~*t+-!1B^pHGsIxs}K~l&ULG=5Tj^OXR>Ad$&XZ<#Ko_ zJ`x`?E#4>)NG9xdvE;oUk<<~PUvgfPk2(O*;Ac@{hC9*F`XccN$c_j`R0xa+F!(0> z_<=l@6o9fhHH@3s9N-Hv`U$S1;_=koHPe=*6pRivDmQ^5Zjq^q^31YJiWcJ$XK$B* z!qfpU_0D%M3T#i&(0G@(66y<$l1WJ>O~aoT;jMA)EYc(U$6l4)v2d?p4|R*~kZK>l z9*|?gi6%`N1Bmn5*`=^;aB*mdeT+gK*ZZx)0Ks>qN?TQtlkwflR=V>A2=Q;bvi*ki zt)4D<==Kl~RgnWOk+iwS>C_@&&M)GQH-PJ?cukvdg_f&`-Y6+#i!> zn~0ESrx(eqV9%E}17zWw z4phQG#I?wwp72JmQul{c7yQTR5y*4*wf?y&b!u=y+tvnOqo&a0hCyWLfIMc&@%QqW z1g2_^cxS+)Cv z!tyHL83JzN@`^LYn!2EY9ihSVMMk3r?`l;9@QQC9$(1+I&Z9n+V2Fo3F|T70&qkI} z69b?3K$Fv%QVff97Arfog~7$BT$q>3k>{==^dDMiVUS`QY7s|;7oux3m3JVFF%tKL z_Zcndc`^^SbK=VCbqwg@KP8w7b$n>1c6}}KGEm8uB2X0C7bF^2v^leZeEZY=oa5!Q znX{Jw(X<$N;IpQ^l+8ap}&__GSqM zvHOMHx>R8i@{%Kv=eK53h!XO>ZX*7H&}s1&GQN%O!b3@bSiq_-v{g_4Oxi_l-hZ?c!9ImN<`clbncX%Hc(VP#xFPnN+%AJ@sFj zZ*H|Q5&rsW_zl$uuZ^xElwamx9M7Wc!914Y?{9QgW7$K2n32UyVqHtw3G5e|_3BOO z===4>rHLFeIRLqwWkSJ~H#!#Sp9L;AtJBSCJ#x?R0N~CFJaq{#;yu-HrQS*PNWCMK z?>|uj85LcVjK;T^)sHvNfx9CzMletiKFN>2MD`0g)je&U<~A)7_K%V@#qScK%Q7arv!%lGUmLpI?h1z;fEvgXFC&Sh0I8dpPsnT1KwQC50*Yq5 zdmzMYZi(kRG1wc7Us57<##)Br;p$b-m-4SHkX}1x-ac#oIrM>i0z!>16FU(A;a(Ai zHx0JeBqm+icGqHSOxqbXIH}Gx(kqm*U*^%wafYp0B8AfE)cGjDkOCyU@FE0+%kPtw zYB^ORR_HaKo_9KU{o{@0>qF%I)kxMb-VO`t34I=4frGW;H%bTuO971XNj#Vkmb@Nb zybACRMJH$&QJ+wsExbC;BmHZEPGY)>*~*H3LLvb;hq|SwEFyQH8QBgKFHo^Aujz7D9DdC1as(Y^U49^xEwsX1Hy)rRPYMpp;o%rV38$qAKOSv8A` zzP8P zKbmR3P442$MZ1897+31u)Qfrj?{mt4;Z$V=QYv!VRF?lDKV2gS zcnY{&qV=b*M_wg|!-BEfMpXY4@QSOw%eN&vQTjbbDh}IU`9$1HM+n-bsu)^FIp`sQ z9bcnEJ(Ihz!@Lm(GrXkl50nw{-*LRA*0Nv586c6-__HBeskB$&@`G|u!BtF0f3kGY z&|~wz#}4k7X|KRU#Wwc>Mrv7~#jcf8Zg)wdgcj_RKH28v&@htcj+;M@y&$NJsf_!n zGBn;)>}d{n~)ZdYTSotgFo zBeVLmxkJx51fO4Igu%3iJK6b-HQEctjyP3 zHNw~~p@7S%PPiS&R~J6(6+j?wY+XlG<<)J!4w|=mU@(-7p`wZRSGH%`5^l8=d4>pa zIn5Pj)dkRECg2%LAD&0NRVbKfJ9%V4JQdGAYAhUj*y`w%KBB zM!7O1F1m@SWye=S|H}fdF%LI-^WDZ-j!FP5*{pM;p;*Sq3nmlrlKlyDU^lSf^$OB& z$06`LS*X$ERSOyA4D*Gxn|wgC!cYGvGa>7OMpDX()RfrAODR*~x{TvgXZtGUX4 z)c_BXl_h>I$y^~$$23SQg7GVH5RK9% z35`g@VWQBFX^TGmsiB%l=sr+R7t|Me==O}Be)Nf)#J3j$%jwylwVqTx z6pvP8duT=-^T>IPbUo}S|8vw{hTy~d5+m?pw@(p(QRH& zEgqnNmVX1E)anB2&0O*~wT-Esp*^dSFAU59q6z_KIt4LUP$fA{;~x&+Pb!tq!+N_i zl8E$$48&w9$HDCbgKa!&ui3w(6#Mka(UmUYCaqrJ;3FSyG{?4RM0`gG&WxBVI$d7d zb2h|C?Le|`FR`ru{$6xlGT=0WbDgLdc1|MX0eegwvBHO5EC4yl&(<~{{6^`Y=UAtD z**|wRudn_yLn{1AAq3f#`}eI;ESF>I=wO-JZ8zS0IWjspS)kCh6FRZgnwEY&K=>O9 z98Nf)-a)xqzM%3xM`;O=w?3|~jtn)aJv+_@5#$c_EIC`CenI;=0LAoy3lUqxF4m7t zCS~iU{_;;^*erV<2O*ZvwjRoQ87JP6TL59McrLJI@c(E!&v3TizYW{b8d00rv(#vnC?&LtmMT9jt(vu4iM_>4?M>05W~;5e zYVW;?DzSrg)awHFaacdE6l^>T$$rTU%j6V%5{Wc#cxj>s-*ILrQ%F{F!s5oyF? zEsEQt#d=PjM%sRh_N@zMRisbB>%ELu^2>|GP=w1m@5LQL#L#;$8d76UBD;};Lpz}K zgOb0|+*W|})%FHf5pvCn2Zo(kkSKA2+-nnzn$dO-A7bISBl9Oxm4ydH+v0=DtWk%f z+5ZGK+I+?Sa5YJHxsaH40FrDviFgE;dxy`C^lbEbbX8f0lDK5J-R#xOgQo`kG+VgB zUkwR@zbh)UYa~|7uWrq9KMToLg?j(f*X1I+7k&-#TF#=rKxM~ z)E?hS3AUPw79^slQs2yWM}b1Q&gk8|8FXPd`5`re3UFAF)WVmD`+sSwGTzVL9UkhytcKEPhB;;~q`+hvV!w3MA4re=J=$qX>vH6HXLpGuq8)+4~Y^Hf?vvqfpo zm%n?yOdrzS2SQiuHO>_CdJHxCC$jB(9Y1rqyrpSDGO??~|6S|VZMDC+=qKkotY>sd zzGA>ScHGfFv|;DEB+>FKp!uTvwHo1r-NgjcagPp1U`-CwG>X91A;|Z)doTp5rt(UG z^8u~34m!9{QgIYfQxPEyj}^}!82ReQkOd3*bCi6z+C*62o#+$fPyIywF}Kx9VOX}O z(o|A@s`RgiztdG%^2&}eG#DS@{YMDCUx?)d%NEDRx24n2@rK-2F{^TuIIKk%YRf6v zntQSQiZ<$VLJQ0h{+)<6VXaUrcDgOxPF5z;@J9WfzWzYN6r+(+26FpCH?#mGM$5y3m0@SZ0IRnoc_>e*Otv)LqOvnaE3MV?_uC!`jQy<2mqHyYcq zru4~m^h9%(!LdKTGTZBBgK_j(Yi6!~V&`o(7SCyZyNp0cuDhHnSh#PMLW>${w!BI# z;5KKfEXz=OI}mUdGoEl+5uZhSm}T)=VDV|jfDCuD-tP(=bWe`_(*E$^vsb-#=9U$H z43iN~sk@l_DyX4FQ@B9qPD)ul8B7_Nk5RR|uU6s6Uz<1ooX5@}pabsd8mVz!R93xf zwiRR$k$gmMDV$Apf8q%MozpaNe3~lu+HfKyAALYK6MpIw$6wW}hh*`FQgP&WGfiUC zd9&@mTFw}s_i=vT;SzTVI--9{7QJ)~r8*~eM*fv1;Hla4n6<3oQ#BO>%sjv9@0Gak zf103*I*Z!cz4b50|46Svk}yW?yD6T7DR4<=TvQbVGH(Nw=&Dw8)d==>dD*BHqT_n(PZ57oL1g5Wn?zy^K)aoODVZ_zn*;u}o z2~3T(w27R-lCBLBHgtZ^gf}AQpJ0gQp{fOmfh%YWt&BcKl&Y6wbu?)nEqlY z19E};sNM$Td}{hyJE4WVR~|kqX9J$d3lI%w_l6fj6eg?}0i+4#YvmiXAsgM#_6W^u zmTG)p4=XY`#Qms|!Fr=!ZyEls@Y!LJE&Q>d5dFMq9pvcf_Jt zU!H42qJX(D?MD7vqHY6rem|m?n>)~d@+{mk;Xy>5K?!;BpOgwjRjI``ADz3_R z_(T(DQt_~pQPRe|ju{Od2v5OocgQckTmR{nM?QLj&mggDLW7pF_tlEHV53X0c>SKO zA$624nT9KP1aK3!&xd=IsL$Vx*93=gi`BgVO(nqYPSx)v%b&dPbiGK@?+CRhUo2E3 zFyx>A^xb~mi4@d)O3e!94ElJKtF$yD!p#G(JZ;P{`T8)QNqmk0?4j*Ac+kxQp?j$B zPAM&7n-ikl>GvH)ORZjyIXZDmEd>=wpR*lkhuDf<5DW6COr>NM3w8a~)owl=_nT$P zowik0ul(JY=Km4>{J3+n(x0=rGLzvFJ08*;kcTXg_*O%f3)XL)&T|Fuv|CW^HE;h$ z1_{NLKCRR%S>0GQ9o&*WwS=l(^!o*MeoNk8g65s z{~m9Fb;uFFSeL$IjvdrI)(z2z|0Dh&woXX`xw*SzT$$`CBdRO#-9hQ96Zcjtw3TYjBrOuL@a{tvvm{Vf$^P^!k0CH=KD`2@RvDH6JvSB(0G_X=X?y?B_eagyM6Z{(-j7&-wU>aJkpcwib$I(N z^V-n&XG)%tpFa~)?uMwL)I!NVBW%JFTfR@_uyyEcp`~<8!*5HJt9tc6 zG>gXMbCXov-r0JbD<}G7b;OW9rYsp@ow#(>H#|g}Pb|+$Hrvp|P!B&5xNbc|oZ}0* zB@$PuY|XM(EQCAg$~Sc$Z^`cig)%-D>M;Geu4{7p)gTy?S~tw9UDMtF&490=Mwj`V z3FZD@Y0#cUIqbxqAbv}>iC|;Sz+a>>lu?#ZGu`DgORvEN_6n2V;p>-nrganIjn9ES zVq#ik_3`sqEiI)SIcPr&VT}pZZ8bclp?o;!VRuBa*`ze8ni>J!N*)E z(_>YzrD{t?lQAG1@sFue*DX<=`~*z2n4g#HlXNx*1w)O1g1uQj&-Nw#dQNPa*d6Wb zIy3^_JmW_RHG_}4`l5HFQ;zRSCO061zL$lWZn(U>MM8C$cs1S)p|nF9Unvt#+Fkka z7u~8QZr<~=%R{rHf@$>9NA?G_Rk;tl)@N-sTxTuZ0TNt%FFB+#sxXvYs*6_pRP`8zV zs4{w&-F5RahSfm;4$0ACPn#d?ULz<0UWRqTR|%bXd7%yi=ASsF!ykpmW;y*TA3KBM z$bp7x*t&27s;xlwxKEHRzW6=+H=wIld{W})-0hTs1NDCeJfR*Pa`1$zZiY8rqochO z*^lVk#Z#{M6=kE=aSv*^lCD8O93J0U7LEA~M1+2{IAlS~tSDb{*deQ<>Uunuo)^nU zW@#&LQ1G>xsrz_PNcbQAplNakS6_3bP}i}0Lmt()Hs*g*h*Bgc0ck%a86vX`KQpK| z;BV!WaA?Tfl0E;G(`=cxAsaT1m(tT*V4;dQq4Qrq&?K<3)L;E_@OBbbZT2aCUsQ~i z6Cz#vcSF$9tsTkZpq1k}%6NOPB$*e7A;>nSjQ1X=M_gUxhaN|T64b9w3HkYff~sbQ z8;hCNfG^y4Hopqz$OKjk^@=`?(nyI85wNHcKRiU^2j%o)g4-Os-Au;k#*Ka-(_yk@>1vUjSam5#CS4zT$w&VXTAN2s7a;nx+_ zB1-yEffVeBmDq2E)@IOvk-Jj4h&P5~WDcTH$UY?xD+%2WWA4xr#E=kN1(l8rOJ@<~ z^@MD~#)09E5MU}Buq8ncX!_qQpa<|{>Oa??@y#47dtW1AqwkpebgkkDifzN&)i zCj{3B;ALwThUkn^{EZE{?v&#mW%6mREBNX~wxh~jIZj5qDY1`bZa=f+ZHu7p2q=x< zy|Uf-6u8l^3K0*j5nS0&%eco7A`%{&I5D;1bv}?>KH9yY+zII(!)YH3Y>n{?J~I8N zySd&w&XGeshg&q=dt}Y_3wNW{*|&!7%v^a`PvrnFdj3fo&nxiY3-23>QFPHn-8Zg4 zu!>+uX=o?Yt?S_F29#pZh-f^)B7r^17cg0=d+y^0Qx6*plWwoc}i&N{7B`)fw~ zy-_4S^mzFzBP9*SQS0l-`>&)-nz_=BnJBi};JTcDz7E@quWBxu8!}zK7Ms|=Cf2q< zP)@0tma%J;N`c44lWde}IXaf*}}@Td}EWH$NZDE5#uO) z&zZqcF)+W}IwU!dxG8+u??@Q_MliIx9&)&OrVYI(mOcn=xX6ic@iyg9=hA*b2%K2+ zE9GrdJNJr#%#VR`y15htLRh9TOQ$LLS@uxRYmdJo5>e1nPL^^NzOyeWI}+FOD&F!B+ zy?34;dZllZdgVVcs1O9J03*PTj%3#d$$4r8X`|gzfu0oohHP4!E|81|#wNE&Uj$fB z-3ujy8e3n4OTRFe$oxAS0HNE%YW0X%26-rDEmU`| z>w6C#9Gj#v`<7kTpm_79GyIW+WT#M@@gXn074G`t$$sd)6AZ~#-R+fKXr$O;>CUz; z=Zb*=3k$(`BCGtR=IURVFqowSnYfT96R*7)>fJputR6HnqoxSgIYBE5r&B$a&U-4L%=aF4&*UO*0)>QpV&$Ls> zdsaF7FI1uKq^})4PMi4Ah%B{OhzG;GvQ_?`q`xgi%585+mn@Xhc$C z8|ieyt#1-Z6ZGs?MN6VA*cg(gyBXrKxZ4%(;VHS-kinmzLUwS8<}CeT)AISTYjhMgaj(VBE6iu2k?D+Xo#CQqJhDRGibPryVtg;} zlQz!P{xFotY%L&iMI`1%j|_D3y*E6@^sfzXG6Hw%hqko$ODgFk8JVCDvhI93&Vjwvu<@^5l?)8WxI|XRZceU;^P?@=Q>m2v`+4dwt zB?LHu8qgsc=7|W-Q>~V3E32~X&QS(ee|pZGI+^!a#=0D@{Y-@GbL9BOz2D`Cs7(6Xz9%kBnqww^)~;E1f!}pCALrc~Z!3stQ?Nol=tT0gGxB_u z3%j_kSDk!C9uxUtd0t9_p_&`lulp*pW)mph4L){+_4lZf~f# zg6u^7E-Xfx3BwEzozD)4p?|tHc2!Dn%6V=lRPu_bB@}O11eX`kY2aX`!9skoV2Jj_ z)(`&3iqhF-hyRIf;oHB*IRRxghWI_dttk|BoWz52T_86Sie`9i)@+>hHE z)j1xVn4zkTnk|1@r^`Gm75YMIK|;4Ti*F+frfv9gv`2p8)A+(2TUX5~phGa*#*>6Z z$VFB%*RC_@tyCayYm!(9eH%IRwFs)*=9yt|yZ;K^p-`9jUDuin7M0YeE-DNwE93Th z<3fG6PWFP1&gdFolW`B^R?HGkPy4awok#J#$}47?k3zkJ*XfJ;6c$W5ML;6Q+K0xs zlgXOdSX~elBtUSVIUKu@&OP`Q+xCW*)~zhNKTLxhj1$Y{iQ#%2-lnU=X#s zvsPP3+w~qCFOWB-Gwr2&_v4k{+~b4^oVgjcG&7>N6Z7WRqI-*GkaM>~>z(wo8{>}l z;|YH||238S9T_Psl2!AT_s09-Qu(--aXf|acgg{GBQq?xYuH25CqHWm(E=+6e7|Fu zwTBG^oVSZLa?ZaDwdw(;w3Cz4wS;Ps6^dT;qLbQk%ntkV;K@~Z>+#W+A#o9Ho+!5% z_%O&=pCNQm;GYOl;4?P|r15 z`da3#z!(>>TJ62pP2H;~4K?54z6Cz`R>1e|yFkPBmTDE3Fl1jY9*tvrVA9Cy@{23b zBGdAafiq-FGk(9nm$lBB6{#1yI7Tk-#%>Ku_7MfV*If2=b%`nyUd+X%0?pdYBCWV? zX-_!^8SNYg^S2EqgkM8G8Ph$D_~C9gm*e;VcRb9?ye}6O`4e;07h>Z1>z%!H%k7#~ zPu#WUJ_=rIIT$>?4Hl_kW8OFxWqPcj|4hX1#YRr| z<9xLxE(pr80&?8V5CL;o&YwEmR#Y?WFkK;91#FlTCsvwJf_|Z$^lAa0LJp1L_@KSM zI()!J=s@_Ln0a)O#vx*GnbvK9OX&mGEy9SNG>nSC&xr^fB(k45iY{RFVkKn3&Cl)rd>Aq<7LL!;X~# z;5gV3VB>j|U+R@)GjYA&zn5z@{hQ?30#<%@qgz=~uqy!aVn(`jOB-sH@;!Nsy5ScS z)VrV5-}oV?JyLq!^i3VoW6b0Cp?jd__radlTb+Pl~?W)=&5+M=(=msYBX5n}Ncj zTa+x(d(-1~f1EZ}ZST+|?-xc|Vd?LsMl|-y&QHJsbL{VYj_eyWb3eu|7hHQx+40}@ zhJMc&f$0+_p#jC0ot4w0N9a`H_V@^oXDmMd+qS|Bdv^5ORqNuFb%srJC0K@ja%N zxvdI~j`^gl(wBS<4q2rPt$;IVIO{78wZw5M=q&vr^5@W?_KK&_H^Y5&OQ~MN0hcB= zK6*W3ZW8?Gjx z9Xe>eG$2ph(iYmi99DJ;-y0?mn*0f&<16F_=~B7=j$93`FZ&Sc-RI=!6%vAX&URy6 zJLni+Fw%T!-|>cC22(5#4^NOkA!xf6-9J9=j&|L+r7*n9jWT{&7K=wiRZ76md@`Ue z3*Hxbh&lv)%HSI`ot!Tf*X~ijmM2tG`k3qdTj=&r!kZ<`4EQ8)7Oy6VLC;WIN6{IU zL)T+F;@6- zxqmmV_J(r)iAny)PVv*soc3dm8Y1l%@V1s*LnWbJ9F&_dlnLwCxiR`whCatgv#*){ zPlZG~ z%JCvt4Yaz|%0170%b37X}(5 zllh)&)fLk>{d`gx-uS*--abz({h_w~L?_iZ*Y^`Xz)Yr+Uu$u_8fL>= z@ICGhb*Cq7RzY%z8R?+!~rQu+~cM77JYH425y<>I%5` zz`Wr5|7HP7Ek}kQsFuGLQ&q&tyjZN2m1;ob zY`Uh);mde6-Ty73d>Lo_5|s0uKWNy;%l`x7hSU=F%9tR3m>cq+-<_*j7f`aeo!y|} zF$^Nk!(p=IU!#@oYV;_>_sG>=`QGSBU-Ey$#_(&q?H}s#mt;s0}9C17H^n}*UMm(zaT3m z1>qba)lO-5zY4Rpj|V~uF1tzRc>K47kV0jvQKanb=?_WZ_xMYHhtJ_-8fRc^Iv0YV z-u%Gnysb~7V|C<+zMBCD{%$BG%m-#1YX zpD4dKmA}seI5r<8p6rTb>f@F3hpK+K6(;j)S+6;zA8nWY#z>qUY#1R7NlA0u8={Th zKVe6YB!Xl}x+FD$nIRQVg9@esHw-H12SPsYzcU=Us#8+;2a zwIA4YHD9Yq%yaR~`Ns;Qj(=TKG2LobyOkMkdvE0Qw%&iUzopGM*{K#N<9fhE?uSPr znl1O;oj(C;DSClUl`^Ef@u0UzH-Cg+YXVmb7jWeGLEb%arc@LL1a(Ib!}rE zw}2fkdIS_$r#>YhI+(&z+Az8!f1bnzL#B7duckS zc@tx0T~Fc?7v~}^v9&b8n)MYP|Dj>dX;z;VMo|s5oZ4=HTd@#uX-)5|`o!J=S0B66 zY{PH{i@5FXwH(`Va`WmJ0AS>vDDP}k{4ETb#JKYTFELpY{KD(8AbGJ1hdz(ziWpqY znh}sVrTWse&lcqI&d(IY``?t-s?}sB*|ck}gG2+zJhoO=Zu}J{R!KPa;Vu4HJ9eu@ zBkDCu4brL?cPf{vY$rS}v}To%4^d5Nnd|0!=djuy;<9!Fi~A)N0((bMwj-@{Udn5( zWK8>4Xh3s-D@Q$t6rZ);#y1|G(aT4qxAFR~b@(?MkqvI|sVO%rtk!^ZL;h&N#%IM% zhVw}W6c~&V*0?OIObNfxb$R&UH=@zj-UlyT#l4o%(%L%q62}JR4AuN{Umfg&2r|Kf zwlyBr1EN6nL+>5erlwcL*!aKbq>Taj^{0CpXO{i~_a1(4+4ldTEpgJDzH)+%mj&%k zY1fro3?rrsJeZ`LX3Y0o30%PG$Z>VN{JJI>f2cX4DubPK;kUgDm%9Zl-a}{(m{f>Z zBU@i-y^+nfHB=08w4u%a-Rrg)_O--!;^>7HGs*wbk4E6EA)GIcvlSUyoh%5?nVsS2 zG3v9j?&_x|dYvo?l(R;rjh;Q4Y@`Xjy38V79$bCxB#|0Pj=9#of84wdyPocUSvl;< z(;!V$ZRNFvRn7&zY_vV{D&o!_!k+*ZZyIuZnOa&0auC(ifm^VITX-A$V-8m`cZS{Kw^-l$=_r7!P8pub< z5Y_R5oc7m4)uwPLI={&>w`{9%a6PK&RDS|N5aF$qf^cjcjDo3X3ydhQv7@^=7~WF6 zFM05Eoz2~(tW=0Y>{gPzYrK%H^W7*Rud*TJRemMyYLPn?$ZYYQcRu?C9G3ftz`+7P z9k4*zJrDuegbz4gPd#J)qVORKV8J8&#Z1UbvFC2ns%v-QKXZjIVo44r&caYQ3T@K{X4Ewr5xO36Q-W` zK#T3zfGCBHCvcwEK?GGE4>=4Jf@(&XRJCZ`>Y~Qddojv@?p5+_7BDk%{O>GOhmZ%4 z7)NY~O_V=pwn>Cp?Y+v61g8Dj2`?g#!c`OC$Nerh?wb@-FCeG3M@`Mvd2ep=NM>;X zM&-@Q(8-3%_0UmP|50$Ug;>mlLSVD`_2C9iCAQC85P-sJEOja-$@_8b9`8KC*jDaG zS!7%|0ogZ8tMnL)bU3dxea=S4t;rn&z$20ds5JB!!%ILO{1BdGXejVKtLPRBPkS~@ zspSA5*^>q>Qw{l@AiIg?wKxo#%I7PwG(2Kwiy)6whG<(=ME#eb%d=WTm$anKN;4{%*}A`CQ|xj6y5UO&^k<4bAWIC z@!>3xx%Xntj|qjPbNiLmEnboaYhRQAT>M!bh)z+kF4rQSVH_}bL+~t#?T<|xJt6$L z2H^pZ+bsx{@hch`v)!HzTO%AWYs&%MD#gU{!{bx;|02EaNDZd+CEjgWQ@#` zws3h?A`QHEV2K|nI&vbQ`_sLrVGo-sa$nWzBx>t4Cp4ePJ2)|B)neQmv@^$gGOa`mp)H?P5&)qjeyM&QgRhZ_ z*bIxYZs-@!Medt-tgzq16%~@}FA1GT*TN02pDCuaX-oj3C$Cirb*h6B?YB~yMZ02b>(qbh&GynqY^}qC$1~4t#|R=(^2}k908=o`-By z4lM5H|xg_>QsU^|^v*88@E`tLa76=F^HHXIb3J)9&sJ-IxY+~k}qeCURZu5wx$A)n5ERn>_QhADSb zN!h`NUZlwqjnL`z^u3(>nOhi{n*I;XiR4l1kOLouI@ekn!!X#0@ar8hW}kYMjJ)TO ze8ywynR!ocR^`sub1fI5`egLP;D+*5Y}FKCzg@uK>G$qImsziqK=1zy$p8?TPGbdA zNc+jZ0pHoTcLnKKTZe|%+v*bYqmzza5S!CPCsHwDPS$%E8OAG}XNsWvr`jzsG?(C* zspGO_QYs=(^=^F|QSEH=He`Olaa3-8kCp%qS*_*>c`j*E@s7ZKKrmPWt*|BvG?IUD z&2J1*iPi86XF*?NaA+3-=@BAkVX!;D{o;-5S^52XCWwDfMbYMDeh88ECp7tU3Ae3b z&jcrs^p#=oIgN+aFPZMDmv#e+r=S}hiS1)8uhsFd@Ne)&^8_D6N;*4I8GG6gtJSp( zr0o!q9M;}!y1Axrg8Ve43|VyxX-ssdnL271m9$1elM{kZ3#`15@s8-z(UD{{&^Or$ z>rgxO8Q>NtN9#Pt$1131-+GhEz6JLm{=Zrz&24Vkc=(^^U6MKXftN&|fJ4_Dz?D`g zk)S0BQrxw9J7DY$vr=v7cqO_LAO_VoBo$Qc8bOfWcq4~jUt&bb1_HFv{rT_Ve~quV zm(2`UII~0JI2m5us5Y4@l};b_Is^%B1PwGe_(KB=s2se_ho>cU=-%xJhnOe@7F4VG zN*zU+qPT7NLRh~z<8}oKPw5hqW8dDeJ_dyk=>WAN-2`0ACqZtKQI8r5t*JqQgx({v z5yHC6oQ$st-J|J4(JR&?)JhtevL5MN<)}6Td22ht4djL&e-tNR zyk`T?2A{rd7;JRxRCr;ptkxhZvbg&0gHDpTd(oW+ax=$F5a~M$(s=sU>w8{uw5s>u ziLIgf&jMYk@5m2l{oOgeV8Fo$Z^13KI!A0=Qf1%k(sQO3ovZLGKc)t?4)hW>C83qc z@))#uz^$DdsI<6KI_$CGrWDxaF)T;x*L&&yI^d0n>7sN&*_w*IIcJ{MqUO61htGS> zUnN+8HeCe#2tuHI;h!eigys)bW6i(M}Wj=-Q-A{KeD*Mw941 zHA0tTg|aH$O|eD!pl>~7DcvTDCcmlH^e8+zE3b`P9e)<@rP%OjcNi(WxX}0M6{io# zJjEn%*s z`xx5WRF@(Podbc-bHky)M?MLI+kVNxiKcv_ubJ`+{K7QBx4oN;irLNm)`&m&My{>M zIC@Jwh_~_e?zTWvSE3{t0rYyaMO{(AZ!*JE*XiXLQXjtBK!|Z0eN#mJTJ91n!Ac~w zPO4-4A5D7u>&#`s;GGP^@@+*vWZ>Y}f3fQp-YDIUW$2aCN>LC^M;axMBJzK95q0riS()#l&>nmaq z>E=z4iuD81Tqp_H5l76*E*e9q=daY=s5{H>508JvB}Z2T37EWsONPq3+jc^CgkEgh z_XfM){>-lY7WpKfY(Or?X|#7({cDt7B? z>?sgDe++Ax=%eDR@Lp`X{(p%(zj0G}HDr6krzOwoJH<)ROgt-rr_}4&d{?Z=R~-rWf+GyuI)3`f zA5%!Q^Y;0TTkI3jwYYz$WR^~|5QQ73=J;G3ZPh1h3z8a$)o}lhE2kM|Vq>3kwEbd3 z|CsMMn7nnKYQ9y$5XzmvyeFB2VV>!G&hcsFMNRl8H~!B`q7#51>8o)Bpwp9xM(Fyu z%qA~9*63LRcYMpVa|r`%9pl6S_eVCU4+pWAg~@_lgVE2RVwpYGeCU?o9w|B2sJ$75 zd>vz8v2wtJd`szd|E+?l8|DnH!>bfd+x?JuX7O2DrZYtvQgRV@bBagZ#Xc)bQAtD5!|8kuvUxKBHLm_ zZ*)1Y6}o%Lw!oCfoFxgwucb$f3m#%9Ny9ncQbs}}jxj8W@^!vu8bXon!*4OHz3I`* z=A^1n(zFI#U4D;rMwSy*N-{C=4 zMPI7V*n9(77tJlaNU-i|mG|K~%A9I2t4r+IA#cn|Ghyc<2QN74IqtVX)y|Yq@;NTV zm@8jGs$|rG;h&i~N-{?D^H#9tt+7C*+_Is5IZq~(P>tjvcV%VE9G3uc&o<;c-a}GH zNLBvin5#qmOf^t6hdb%W$g1srV5AkYC}-kd_T9?$pEuNzPM~K;;|xADZr+x2Sr8Rb zDr;+vAHTnm*|2ZA`uSM$guL*#Ey}NSB)>PSolbG_G{u)!=cp!x8sx3-KFM2g#}KwLM<%$^17q7dWXu*>}%%HU^4bpI$DHSQUW92~u9KG8HO zt1(|L{Y&O*d2Mf|f2Bk|q>LfA))+O zV@jikkwUi`6XJ8oHM<6YylSxW9y}QtKQSKe^Iy3X39|)P`w)HA4I)WAv2NoVqkCib z$mDe2Yo;$h9v)izX0wwerUT&iHvoIJ6-wf=KD+vXSYIZ#hC|HXp)wJ=CD$3P=l0DIUn6G8-Bm5YfDI=$lZd4h{8#W-t(6dFR4VfonCvanooNwkAAgq?_ngFZzbM!)!|6VNW#0=y|kOq7*(vkt4TfsOMa>n7{$(Lp0$6dT|`g$R3s#;PBtd>&a6RNO3 z<^{L#y{`xkx@3Gt^|I=#D<$`}1*Iloatnqkm813vY_G(0T3Lm`zJld_zaDeh>(ju% z7m=<(*w{O@@!6m&>?z8+~(Y$FOu#yGrB%kHnfuHAlRhl zz7H{)1VWZW-Ax}I1VCQp&x90)-(vnXKahOiwWxP_Np@Jlw5`sjy@hr}W zoygk;d+Pj=xmahsZl4$UM2>1LwraS_N>-Kpq%kwYp~od54_8!_hyQTcXmtJ|(?;!Q zA1zfhx)trm!q^z>2MpmCysHouP#$aT@K$WQ=AQ0~2oPnV>1{9PuRUs^;QOvCifh?h zZ*iEC{Ef&}3TP*nL0eefQ#IjWg@d>h4d)*jNsJq z{kh(U*&Oish5lI~Q%U9w=q=KO)@UMmLO_-lT3Y^26i+8}*REDw{G)iS56svm7fqou zoYKB@R=yDoG|G3v8k@Db-bJjkYnM>Dttvi7jO+`fUp%GbMvU=d!pW1LFOgT{n~-z9 zBsg1&#`*;YrVh?t*C<#t^}q2_;Cep0Y22&YX95jph&By^<<*87?Jc(}>jn17yP(ME z(^LSDhvbQ-rvSEP&MO_kp6h((M?TI1XZu@3CUu^8t9V21!An1``GF5hUUHt&ntZi` zLoz(3K+Dt-=@hJkhRp9HLm9G*5GxHW49+~D@{c7vL5$Gemceh@iDA4e=^yLf<`86D zYUJEH<#*_X_tAv+KT|-~IMG9L+5u`FBRvidOjhA5!$qp(NwUY*z<56O3@X@}Q9(yL z9@I}||GW^&0v^udCs{TZ2*diDXH$)v?7{*ckXdpQ_k(5wn~0m-8HOavZ``4r`kJi z0jcUL*P)t+4(_jXN55=LF8mXo0hl}Z34sr7Enw`Ajm+1ER~$L)K{k)t#X|#7{Sy+E z_Hwl}B}rE^x&k8_gaNsrgKnZwenYhEVGNVoL<9ghFbq0QB!^R?20P9~XVMSIN)drA zO(-!uv5m%lJT8zyUaFg;ttY12SYei{&)sJ8d~ z8(!*;Wb(FhGYUnZWte@%)qJS=d*92a%$nu%TFW2K3&*#f;|rF1`AEaWBGtGTmT_aP zjTN*W|6P^GOpkRuk&nOC2oiD1ic<@FAa^2Hf$SV&BQm$+4~$-??_$KyVl9Y_kib3X zno@HWE;ox|IfGvLMMi@O&MmNf)tDQ9EHAlOpk8hATRomfH?{vxT56(}Cz7gn-$I=(G=@S=^(mD<<@%PrLUDohF&Y zDu?8}WB;aZn<~E7#ttxj>Oi)rAnbEj=p^-z_3S?W^`j@7)Q3k!{ABjv5z8@VCbLA% z{Pi-^&conil?}ev5tT2G$|My$yTq;)2SqpC6^JpA%3qRSAJN!mD*yufo2u=I>L`DW3E<^W&SgL;T6y3g&xc7KXLC0n=liqBT7D3g z{FE#s@ZtLB!{YLzjJ=~Mxy{)ui>9S!@jqIwsJAS>V7<9{)#X_m1n?in&)6#?a7x51lx_59Nr2vArFAi zW1Z^}P@TJthg#A<*Ot*kCD3Z@lV^|Q0cGA~`Ur#_Jo2?QSymwo?rteBAo{&^86tDd zf_WLB^xrZnqgF1w@$zzCA447aN@#WNy}*n+257m6#V#nw4wasFciSw=$$AI`S&Lw696kiNe|LiKFayLRS<{kkvL zdIXkhiWPfmRy5Lr2YC{leRWKQ&HDmulrMxg`q+0+86Rpa-yO09Zsu?syTl%36Xf8p z*ao#Nt?6Uv&r&uyALevi7TWR&RxUg~F#l7=9V zf2I}&dv`ZzKOJ~2ARtE28lHW1Q5CuyN+ya4ULKux;@NWgs)vGR90U^tyzM(3`IckP zYz`#Miibw@&^a%kSP zQ2Cr0KE_Qa-eCaY3RtKj;LtgZy`YOBa(;}VU4`=oF3X10 zuI@sZt^IXr=Nun8piaRDrI@PJ_=ASuGcL1Jc!Rjf3hg!V2iq{fwc{{Lz4#TJ#ToG7 z7d>qM|7HOxZGN~7nM`t`Sox8hPJ9(XTX3U(LuYun{pCCE(NI3w@0#6<@awLes&G4C z`}XPRsljwl*8BWm=}XXr3^@MA8D2Pqq9>UM; z30lp5!&Yz1(iFS`098y0es17s#rHc}s1=l%5OWFaD{aBiodtu35+yDxNu8{f%*2BU z;n5P|zo;Jc)b;!8bF@XD*X*n;Ymtv`FFCaZ7{#kVS%*^Wh*zdE;8*fkh zrU>`%`J*KaK_;1NT*dJQ`D(O>Y2NMclwATwyBP!{YDI5U8?%wG(}d2Pp*lLauamjL zE*{(Q)Y4$ifQ7z#?P9@pdMJ*;`tLalcc*53@HfglexBQv#*%)0PFZ_FUO@i5LS?n7 zAmTf5H%s-l8n&-Y`xsjESmBFE$8D=Jyb-c-N|`2LA|jzIdt!=G=M4{p$O6xH{5!iY z)D|P#QuLcnFf4ntp=i?W;%3lM+$^frx+Aq3YmO1QOh2N-|5!Wn|9&09Qp3g{->V)> zVWL&#I*$*3RrB-vq^AGMVZ$H#sZ~UdpPip5TUx=q&z!2ujjQMnp!%6;m}mVrx-^6) zafOh92TeiX@fLsnY^|@!zb4kW^1q<`Xpw;HWh`UNcp$gu=s0N!RwuPz+R(jJK>S?G zc*wx57xpX%j&TqI&gEYb#}5ueYol(7k%Q|6mCWxPCt^k*s|p(U#ug4Zm&+aF2$9$R zUn-4ze^uo^F!FrYl+X#rcO0^5P+3=H6&YF?b@<;ICa$-c{V1C=OS^Zz{}K*D?-cGT-&0?apOdk?LX=$=rn(p1d%PbdIYOWNx^ZRs2s6yK+A2--(2xqeIAV*-7 zI&zZ%|IQ0B^uBo-*113pm2de8Rmkv{gow|L6*>)p_UpYm)@0Qm&$lGbpLN5a;TO)` zk{X{5xLb-NeZ%7-L7biqCfIMqRa{{%oKI?>7WTUf0aM_f^c870>uiFg9t=!zx_ZR3 zaRJ`3a_g=rf`X%@0(qR+Uy2AiQE4%&QzXOYGn?*FOHjC4JeIf@rr+6EEv+zelcf`U z?N!%T6hr8B$@n}Ecmmn5*#M=mCD6spk8J^ezoKs!Zqg*INwLOh%cbExC)NRh4-6@3 z6p}0>CBu>|{*R{ferNlA+c-+KRTL$N+M{YyQM;ums#dMqLA4~Py_M9aYHx}Utu01s zZ;{xFioH@>C00X&C*L2QtwL-`e)bGY2l;bK+kuf^+ok6h6V)2ZSdM8?2eU%*E{X)4Paqa5gVZY z#CwF)t+4sq^`Cxdq6a?cX~WZ~6xS|K880^ke(g-P5kplvT9o?6;=Ti2*TnM%K7Pnf zTcXL){eq7NB!_l=HL-uZ=I3N76A_k}nG=FL&~SOO*Ni{@)r1W7hMvrq^6Jw%ih6`k zxS{NuowTh>HN(7c|0ONs1Z@G)#-8n|Fii0ZWJ0eh{>e%s{swU8gDv^%lD8sClU`0- zJk+^XruMVEQ`}&Y;2&eISW&ci$GP;Y{JR8!zelx|>5JH>?%>#jRd~azNEJOXD?&Ry z%sy2&Wozh3A;imID;1M^L-H!-t)=F8lyI{iowR-dc#F19P@R!@;f7*SA+tU-|Ng`q z>dByp9)8Q&;^Gf?;u9)y+W41|6)((JO4_gtMAw+k^CE&j#*QVrEj)90c|?5o24amp z04uXdvwneFoYsr!qUKLh1kJXG&jFXo`kWEt#Q2cFz2cjL&yJbp=;w}K`-lWqhWvHd z_yznmIk242nV3kL0TEqJ#eM74dDc4rHh*BJnGoy`smVWIJ)u+fmnRYk>hvnfelz(p zxDqDLNw6QhW`~($kD*ZfD6QGOT@&OasGYsgloQn%esUhT-Y0WaXDdF2J+1gQ`bJQqSsFjE zyg@WL+g`9?<{DXRyUbvzkL3&U_L%!N;UIGLsdFuMd9CkHR6&40MPyG!T>OR$xZ+QN z-9~pn!IKZKjCz@iAjF{L(p!HgcPYLozE~s{>?B=({TRBvYV0OYturLYPL?o_{A#fg z)TilAMtRi{Kq~{Vh!TOh=R9~r=3R3aMkA>YuzOJqs=Jx;an<-qVi!aFQa48MSu8ZU zc{M6CcLRDswz1vRLxFxKi#K!SD|D2=My{;srldv(uj>><4EI9(XUV9aL`pe;OzsFE zglM*BKRTWO?2gXG!C&Uj9_0QfraKZJZ5$VazP~-NE^!C@^(z+yhqMLS@FU*gnYSy5 zUBUNPSm8CY22N}sOcP$}L?ZzJJVW2)Wb}{eGmAVyC8U8XD(!);Cxp0;$w;dUZas)Q zD!8u!Wq3gjzSU`9zO4&Qr1EZu4i3QxSF6?kU`nskDZ6@EkGEfP^vEf+>aYPFA&Y@Z z`(GR3swxxo)<*kUPMg4mc&ks*-@kT>Lp}(fKz<4VuZ9%7KCWRio?J8|5PhV7q{HimzoFjx21*BH#o|u>z`?!iRh7QqT!Be_1B%;`poEnqOg%$<#b^uQeE zoOeM4fT4Dsr_C4cB{3!Hy>uDDFb`s~t;~@~4s7d1s?e~c+exkai%ZQdOWh~?{mT`d z|9sJ8y;i_37LUOPa~dN+TeJ1MUuM~0wrr`#w4C-e$_Q9jJ>W>PY?IN{)5G8}iP*~2 zHGV90`evyDTPB)xGx4&@eyn?&G|tQVmfTgj*W%zVqEhw?d>lJU>gcI>Gef)AQ5zBe z1u74MW;iE(28-+N(8wzQ(t$?Js%x6;Nvsqt8OGP{aTfa8KGJ_L(Od) zeP8tK*pv~a*I#p9o63EC7o&16B)Z|8>qDWXDI2`KBF|k9`uGkp_)RVI9l)o{92n)P z4GLX-2YQ7AG!EF;TNKi&z}=8Vha>h{I(`lj?LM_Z{>2XV4t%N7pYAf##TWQbN(B@A zXjd{4+y6T)h6Zj}>FpOCod0)qg-yO8ymDeCZ#Mz^ZczA&^e7%cYKTsnEPbus9v%)2 zENSbZmVPzrSm>Z-=8w}=t1;tZZW|^UEe~0 zA6z|m76!K^z;P;5T34Tg66qD2M%6`6W#zSPKC&587p+LUuIIW#{XgjDLx>E}4dYGQ z)x!2^+h7-)X|$R?aU{D5HT+q{QK_@3f;?E~m3{#Oy^5V5nX@hF(6djDBi%Rl7FICaWg2d77oUM2ZMnVKmr7x> zafgH2A=2Xe@P3^J_&E1z-9&cI$_d*_cl<4HzEt+h)rHiP$#ioo=89j0dVi^4Qe_R! z?8s`(6nLLiUAEN-Zw{9yZ#au!As+lGu#;)jR zse6G(Z*$cAjcyg%5(^>%p2t6}u$-yBd1Uv*9Cw`FsPsYsNRtE2d-Xy5_F6?o@;ElX z@g&N8sYK>>;m1yZ>`@TK#UY`Zp9yq3;NTq^rNez2Rh*0)Rf}B#Fe55;&kVSiGoc=< z!(b2CCp`#XTgeUeoo8wc5K{(yzsj8E3HX{eK9-%-d*}aL0v8NQz>0 zd=cU8kcNPV47T({mC1ki?5@2p`_h(!H+xGmU~^(H2__rR4l0_+j#j@K4pA#iR>k@u&TZf-;}GfK|t%NrunB+oANzYi?PGp~-{H!TujH z^V?jno4WANvj4{rM+k_mx;59On0J1m~ZcML>XwqqdM zUnxcGKC-n^Lbw%d%nhb{2<%+auL?0_tjeIvBPQkAX)IFy@b(qLog91?(jD{aIQS zF0!k<1y7~8hPFt50&-1LX)0Jfdy*tZfY{I$QU8!4h4)>!z4MVx3)xD!=-T9AE=*p1 zMEcev#y@`2FKB!0AV|Xg+CCO^7|-ZfV#eiwivL(bQci<(_uaV-yIyRQ+%F_qFhE*4 zaLO$GEALT?;Ge{5EELS0F_OwOdAI#IV;Lkh^YI<>vgjoRrXFVAAiE3~wx9so&5sUUh~^ccl@H55bkDKjmfH^a#y) zf<}Dj1Vx-&iyoKzM*{Qu$0GLfk8iC^?qKA^FTNPPp;#oHH@RDt&^c6DX6d2L<3?`4 z-07~sFycQl7L@Ukr-ZaS3?~4Om9Vo!nCSIZIuY-SDU{}Be0chJp=A%6^cP4~e4Xlp z;>jeceq$|sY*?V=HtV~O7$Dcs^WaqFBsCZ-;9n5{Rfp-w#ZLPtd$Bz_%T6|Pn@{K%#F zQ`7g1pUQjmahMMc<|C8LF31qwVFgL=B;Opkh%UOuYby@===m)%z!5LqCl-YBkvL zPq&C8NSbG1DBb~CQH52Z-;O^;;3E~*SHC7-txM`b>jr8%WxAhEfbY z&-dPC8G7>X0ben{i00gM0|kzKw_@L<)%CE9C|;!wE8f)Xs_osn(N@%JHhK8SsUtyt zA5&oU*!4YuP$#zHISHREx~|EUAF<$M?{L|~m2;6AtT;!!cGdM|5%kKhXDXuVGH=On zW&Z$hJ@T}%9@zlXrIr{lGKeO=+P0fkYCjGa+*;iFcSunuTj@7x8 zwm2~jd~NA?fa?*>ewRwvE|ZQ5m=CYgjUy7cyON5==7dInlml%eKm@rbKk08@XJtY? zuRp%&am&PhO?0nMT28kr5<%|EygjoIrfzt!tSRQ>{fcg*z_>E{4!T0oQp`m6x7QSeM zdCLs76Xj`d*N5Tp_0%PfK`+v9(uQQkLWC5h%&Th_Br}&&z^+k?(?Fpt=^ohO?D?vf zCANTyT0$5oZ;5<0uc+`61=RIF^!0qL$)eD%xPFpf1rdhsEVJ4Uy$w_edm-9Bu745y zbF_$_{kfQ1)_hJ_cXYrx7MMqPQPUPfos50!-TfA5EC9G+)!-5Ho^%bSyzd*sLwk;* z4%&BeQ%7ulDGavri^M!+>Y@~MGk-_N27|3hzHaPu1(oINy8sm>elhjm|c@wK`+Jq6cK0nHz?r_-(T^{`208VHlJWf>rM;fHV zUGwXc)9m_~o>!Tq6nCZ7cb}H6F8I+wl7hjA20BV{aWE>_vB1`XemiUrMda2>7))^f z45_S0m+q`f4rX{R{_uku+V)eFlArzLO&JgVO`;F#O;B$S=AxWS`@Q$wgAZeUNCg*J=#{&gj~wSp)%^DD+A0OFsOdBJ z(QoxXaprXd@B|oLx12dR1>fVNL;kvvj|#2JJo@*K2zY+(b9lU=zCj&^Fl^da2U^hp zZG#Pnr^nxpuJ4?mABO2&4%ISZf<*A#LJuBf4i@U!j>veiX6Ka#*cVc(9EW&@z83;a zp#DSJ7HGwTDtfCRkR|zTH-U_mlmEB^w_(S})GKyMswyb6v**9I3X}$IA6|{0AC>nr z+XA%^PQf1E5EXCGAG~Uqi74z{y}JMcfYQJ8iQGdU$C6{aSL{{RiPZ^^l<;))jOml3 z#Ytj_z!qXs-peL2H1pFt&&Qo;!wXr2uCMT3b)4_5kkVC}q&S<_CUe}%r)0k)hsWq< zLV9 zQ}tvh0gkGXp|k2eV3}@i#yd5X9AWCX2Elqa78rtg0VGd0MODz>^iHOGX6TK7y$vUq zeyJm^AOb_`Iv5DszwZkfMqrJ=JG??8;ZUC@%>spk;u_7*aO@hm(*`Rlt2sTgW!cGV zS=!H9!P@nE`O9+ATVIv0j$sho+|iH*@4?xR?aiW-&Avj7i}a-kBN0(;CnNStBm zt|_OfbLe*8f*j{U407xjuPso~>->2qYDo~0{EbeoeL8z~E>|%0zC_*Fjd1G4DrL@h zlQdWNKECcZU7D741G~Z&q}!vq{Tw_U8bIj1 z+Hp<_K6)le|BvVlQw_jvsqzr9H?#`K(NGh#cxhHHbgl>|s_?0s+bVH`)oItQU2=T~Ja@3BeeGG1pznHF zJotf{Z2IN=#(5DJ(M|XSYZ)PQDcX<9i-op`q63fPR-fOFqGaX(E6rvI8b)gkZb!Wv zizGAqRQ4}KUGzeI5i%Ub`;^h_ohQ6EoYkTIQ7q)51w8luE>)kPI~gOAd&y~-crr=5{mRxufKH&`thf^-y&t^IA|g&y*>XLP-p52&+g@f z-8mbG7=Ih1|Buk1e~BdvP~s9j5^5DFLCvY0mgTcX=%M5~b2Aat3JoaMaV0Dn{byMz zD;PAnL4$(?og`Z(xWCx=RDO@M&eaQJC*r_2_-&jfLgRaB|8x~_;Y}4fo;J-NY4ho8 zNf5ao*D+z$2p-iMfAOX6gChVzH}|%kO*#e?y#E5Hqb#M$$|r~NX$qvnP~@(;e(%Y= z(ZXI3BlbZJ-{c?*C6J9=PGm6lwf>EDmA77OY+xRh~y#;*cL_}lvtr>bkPPU>LBS0YXy0K;#Ff) zo!9S?ub*FglUSlTa|%rIdCm>bsTBgr*zv`1*G1MhHvko$*YubBdPo0Nor4ymJvj8o ztt^r3k9CSA(?ErTMcF5x^NnBr(?1D8rHs)-&M>U}R$P{f{Er zx;})&|AnN!UkFR!6N-<|{nPsx>RE@LLy!7wy(~zJ*z{X#hDy)1`c37>EC=>#&jyl2G`|Tz?AuLvhoj`mMb@W{aYa>CHG!&pQ~do zrs9pye?K(8d}ZmDu6u9GzwHyU(>v)`Pu{g1ok?knvP#{T$j^+OC6X_`_4IWt=Tl7s zwNvuwW>5e539Ho{E5c=+9d9^Rkutg_)hY|+4ti>q)(;g0TvUOwyON>s_zUvh{>GGLXTb{TAP_4_n}{11$fZWS|3=DAifc2ge~P zvdgXCk7Qf!%$Wv<9Ic*=@oxp~_d#B3E|Iw6$d1UB4eEgKTg!y9 z2d_-fh~@{3(j(6tS6z_F+Lzb?+{Q+^AmaPWJc4MjPV(}*-L~m!=UE(B=GPS3oS=yW z-J7JcL>lFDn9Cw2c_m`s3l%Kr7UdrEx}KqRw~z5fyBUsiWf7mCMO-D@r0TkLI>6PU z07l1xPl#Cx8R~EtZjFAECo4Z&4;r6;YYo#)t8!gvO!!|JJFp|z9D_U6dz$TAt8-0rcDYqnu|e za**q?OFKp@s0Z&awG{MW{iMBUwD|~Qw)s2MJ{u&ZPkWftY%`P>f_LpBk+QSX`>rYm zk%iIk#ws!KA!g;Vl@<%JQ!`lmd?I!8Uq55VkIpKqH6hyM1@vtxD64wa4L!IocnfA-2O&`XT4{FuFG32=)>p!% zn2;5~&bz#8D)2ep^3#o{cW-$xR{Glc?jK8^C-npHy+RX-F ztb4zzz{;<2^Ujs%bhQ#DE>er;I+oNJe8RUx2=gxgB7tmuLwk5)DQvMg`Rq9t7uT`s zF}myE8b)Oi;#kn`9ipUq@|8>R<658t(-)VRj8{@2D{w{JH6{UA?9^3b*Jc`t&q|5w!mMd{pT z7HM7AUmHeu`JE4&OqK%IjAtf|EUOYzcGz3a2KFP()*cq$StVo=_lDy;*r)<%gYAmly0ctWMXSEfc_!+9#R;QJ#+ePzXF+Xv%P5#OSyEhu~jmJ=vITT(iXPMLJ_cF>I;&nLvmn&f%B|{^`QxA_YvZMUQU_{X zU0f6yUmR|p%MQoOdOs_-tvaRo=URu!ps7!1Y|pKY{ackg67o)lGCX$RsbyRv6mma} zz4w*m{U$xGdcJbuss02_%Qsa!``HpUHeSA;Y=T|!>r^0Dfq;f;OrtIc(d{Amndj1? zH|Z6)#?2?D1s$pYQUX=HDe82EWpZN`;25pXF4!b`V&pR+5}Js;=m{OQf$Sp9_E~(N zKZALP-yDf=Qh06y*m?;bxA*{;ppz29Iwb#-m5wKJ%x?n|W>%5T*V=@H60T$>n$)Xrg>sk&;NM0+TX-(mjn*lK1lZvq`MpjTMuE;@q&Y z_lK_oXeAtY?#|&|WiLVo87wmdkbGR0faa;1e$obB<=EjOhNso!{6;-s3@y}7`G6TI z>6@Zo*h2-SSeYhopO};TYD`1>Fq|d?$?KI|r?h|kFJ%JY?jW(9O8sVAbWxvfsWw~m zaY?n5X=z0L(?Aw2P++A(za_H|g+lM*#)5!)F2A1>jrCMS%oc5lp@<(BkJ_4aenmt9VGurRBY%or_K#-(6B z!YI$u?qR?iJGz>Q0Xe$()1sKCGd;Hb27yY2c9&Uw3SJg?i-g3a6zFd)zariEcE%s0 zF}f?Ru}b~=7llGn$fc=EU1wtoVhf8m1i(irHO3U9W`Xf--qi%<(o zRGS5R)?s_hmyFi?B_|wVq&MLdfJFZ1sytP8zRjHt#`yX_hXJHf&j^xyFT3qm0G5v@Ab$xFvy7cg-n zJo-NV+-vp9S2A_*5Xhgk#ISXF2TPzOT5N`m+VWR_DhzH>X&(38NdGw|K6rB#TmvY? zEyIP4#5+RnhpK@vqYs{Q59?p&9k*Tah%(Kp>gE>n`332=Xx)oJqk?C<~T@)G_IZ2rXUhdTZB!5 zHTWDeb573$7j#;1r@YSc`YPvVQsbotHpSvctZxWO5@;RH+@_0Fs}P)(f<)0)up+(h zmF$t$A#&mH*Vd_jSl_Lw(XXfP?m+~2Q_`-L?HMV?sQd@DKjOL5139oLrE*ADBjbf+ML)hIRE+1pBI zjx_{-Pxp#`nKp=T4?bfeeE|ZUxf36s7E-w<^EBI8jJR&@ABU3Z2PbrqJZ|%`MHR6- zJ$;4pHx4)OuVq6+zIRWcyfZ7~xM$ooM( z%Lbd*It(n`PIU&@JJ7RLTHWZ|R_UI_z(cl|esv9ojd_7~O#G!6HcIfkR_J0VznvH9A`GtxE2mLgS zKO2gVT^VhVP`=qzuSw2-PcSJgSD|~qm71RbxFH92Fc!i+jTv?L+{j?=&vA~HIDGFo z?6g`YL?kd$Owmfu3hj>TBBX`DGgw$bjpilr22@8Ge?&D-9BC>U zHg$N~xYFr<9a&3}8-g>nKx|my`Eu4Y%36QNag12KkG{w5)k5xI%*Ad;vPB32s&#_5 z9|{D|j|SK@8g^`vwfC^~vP|(Mc%<`l?4@CcK^$B+BWUu~vAnHv67t$~U4N9yR9ghX zUXTixID==Z>B@kW!{$5!jMAn36U5G|p7Wzsr=xRX5q&3~xL4bCGHZLyO6p<#;8+oK zl9Fl%Tp4j9x^H??f0OksL}~p+*G87*vsj6{I zx}42ZpKX>S-afxeUNtEol@p(Q@B9trrN8_qzX37M=>WO20A#v=tc8XrN`D>l< zVLOCwI{VMnjNU{3TWp4)EM6HUETnjiF)gd|&5}SHZ}qDGKOSDSwjk7Abv*wKukq2h zU-lYZ>!sufLbmZdB3GPBF`RY_*vMKvSl@i8Iwc8^YS@RIF#w^7u94n695vtjV z4^5A-_i*M6_9kI9yetbB4Xnz1fLqA{b?2Pe@)G@;V&flwP+uV>RN8*|2-)Mz8$od4 z=iYCXTI!4t6;(B5bT!~<^%$K;+oX|=xt?(aufLMQ5tX)8rwCr*wzyC*?crIoqJkO5+@9UllpSpHEoW$-w54J1Kr?xI+-f^ zz>^{ATZdN8KTA-EE^isHzBu?lv7x&16~Lp%eav{Mjf%}sU?_w0FH11%^@|RPdf5KY zw{FW`_p{Y;v0_Ayf>{z|9m4g-K`<*vmO#rWE&WJvD+pz$20bItiuQm43JLT(;AR2MmbGN$4idgE!nd%eR0Zc}f z{)}inmHYErGtcU3i{JV`V}M# z;F)f0Y>QPXClNmq7}>%Ls#p0DcpBY}gk%e}5s zl5JEsS-a8Vetv9J0coH>WUA&ZU`C4;wV%rt`#0j3c5?w750pXA_y4=j{ZeTv+iHhg zhTA_GVAC{qb09n1r%gSb- z+3Anri9Rg0Cb4wVrcC;<7GR4)Jiom4NMZ<*i-a7^#b5RG5bH5N=>+Pgc}njkKu=d) zn6LI7xDd}#n=GM_`CnE_0o?$!kUrNhKoEE{p`M$D8 z0%qWaHw4x^6<^=(K{_8oe6z!#$@WGn(a{=H+WzVBncPb8bJKcCdn4g8>un7)j4Hoa zoprES7+w}9=$@QD;KbHO;w2><`=*3}qBQ5zpx}pm!059biA}GE^&DS&3h{~Keu^OR zvv<2xVMsWfTfpt%ft;!YGn)>_^)tLMHHAyA0P|0eloDRLg%h55Pvmk=2&*9w)1>!r{& zl4K#`o2r!yy4bl9L$jZ4`Ky=WT1T(F$M*s~UW7Z*(pEhx??Z&(;5E6I=O1(28K>wr zD-s%3C+q#=Kw?69AC)=Pa7m=hJ5~iEr7=l^*|LEvIkXd3fbRyCX8^Vi@27e9~se3vVkDA zY{XZ_6O|OzcDD8i2FM0yfWL?GSxT)?%lWE0R!&*<1Y7DdhU%r3e;K+DWRluf)aoH6 zv_v$0xqf<0dhGq{9>b>N?Gg?XYaV8_=#myeG4&QSBxQT$bCfz{K%QFRba5V=d(p8d@&a=V~rpt}2= zKE$2+asTdUUI+Y!knGc`^e+@9rqL0G|DysZ>Cikt6u8ovqh4%(&~1<#pe-Dxn=2v z+K)oo>cu6)Me*C>@Ko4&s=J){`odg7!ouVkN6H%DNeLL4GIi4d<%<~X&5>eP0^0U;|}jMRcUT$Qt(CQe(vOu|w{USyRvpKBhidx1*o#N79?Zp0_kNB>yZtGH%WOOo#nV!hvJR0PT7`U-Q`&y znAo=I5AlXumSTSn7Ugh|vIbI2NPOvbm(O!0o;@Pv2DpI5w?SMT4__nKQ|nv~1!s0X z?CGd$lfns>CfX2UzPf106@Z5kMxa2vRA*KRP25=S*#ocOeay>(D3Cnn_~`S8Y=2r% zrU|G@PTTa3&WD5!%xxim1^J59LR^aFB3T&83*l%P32FGYZ@x&dl!bXJCw+rNGK{;Rn6Zy$&GlgwSn4aHq(ICB8?8DjY(xU(}H4FjG_;-3Ta>PPoPlELGcRYs}9(6 z*+$ltlgC(BwmOe-wp%%l>+7}Qol`^hUoAEccKx@q$J~w?T5*3an6@Yja@ac$E{GO8 z9Sl=?3>0y^6-;v(uSDs`iH$xwz;$hL@eILKPR{o-JD=#Uv;-AC*l5tP7E7gWdu{C% z`uiN$BX_5$5r#HNsZPT}!q;+$?Wljb;+tzf--=2nCnBrM^sdZ2#&vgON&m*N4>)M& zCO-}vHNLD1Iyu99ilyaYBI(s{-DLx6w}w{I}P2#V80OrSLblnN>yvDgP&XihAaC_D~vdq`T9 zPh+y!eI4t0UMi6sYa9Q_{J-PuQzft@F3o~?*F!wh zkh-$BrB)^f9jABC5i;vMCedL1pCCB?(!k%HgZn;`QYp0hZz&)kKH**+{6LlXa)nP~ zs1q8e(7daxvPVV-I-3ZxEzJAm4E%wN`>tMEl~l#FVO$?4KU$zLeWHtqM3*ypjaxmw zlrjDNK0ZQD;MbS#cmC=Q4t&mR%VP>3S>O_k@XiIAkTDtmp7!L?NCortse1azYr!ty z^x4kb+a<30zCQMF%97>CPS%PF_{vOR?ZB>P*9(^#TJbvk7qmJl?3yECPv zm5_?+^iqP;6-Xk7I(PI*ki0|UKI{zURh-;JdMZV*1JN40yBU$LILJ0{RDW7v3`s*S zllwhF915WSo$BeRVI#@2aQ!S@<*FWmbPs0>(|{5*gD76o5$!o=~=*R^l9e+0cAabQvi^YJt!A&(gDl-?PQ+HY7<@Ugz zURzFz^IF!U+ZS84g+r?5$$*Fkl&UOELFOk>0;=uG zs;Y8Aw1e}lh+?+}ZBN3!&yl5DnGEyn->DZ8Z66d1USxtWBCHnT4!ivk|SGTQR9Z=BD>0cr9n+$0nq&i$bCMUCkFLle@TmL zF+=GwNilKB1~9*)jFz-sY5Q!ZxrqT*6Yc3kx#~U;cIM~8`d!9tyHRs&5lY$?-|sD0 zbG~C7y&Y-`OAcsEw0YJ!NYT41{@uxwN&zWbDv2>kJ;uCnlk){#Ej#9ZDDm3=X)-jH z!=q0#KcXQuA>*7Vdc+VRjYxhFG~Km@16zB0)4Y^p8a z6f+;#l()`QJ!p%nmAn4@qk_%dql#cvgM}L^A)LZ%v zahnr=*3P46AHDe6;}y1+bARe{f(0(JQ}rM`_K1k`D&x!u9&`4Qnajk5TM|cdX9OHW zLh*ms>l(`Rj&_xEZApXCoOza`b8KzAWeFXZB{%Pie&mx6rINXCiH9@s-Fd-1lz-Lh zyl%PTIk%-GDMq_&H()y!ZQ$`5{Jpm${VY#rExX}{Bzky&`aeR)WR60TKR5M+{Z(kq`aNKBdUH3;sn!Ofba=e;&FF04b)--P+BeDC$Qjell#-=YR zm-W?0axRaHFcHkta0XYG3lOv@e0;k;Nwyz~lO!iEpyIKpd3)Qj&!V`?eaN4vwS}3> zQIU9T5n~I9QhIT0ggXqo{&D0-xh51~3&|j+X4tkf2o=R^qz8g%u0DiU5*Aa<+csx! zt6p6U67dT%wrszr9!cD^Sk-4aKi+@=U=#F_vr1oEIbkc1Dlu?|09WtPs+iz{O6O0v z%vPO%5~9C~2GUTt)XJ{S{CnydgyBZdQ>4aeHI+s_Ws&y#=T7LAm)sn2N% z!Mao6W=tHm253+@K2j``anh{#HVcDzI8}zbDh5r#Rq<=O-|)ky-J7`rrMawAbP^Z9 z+}7c-V$Po^O_kU1+X(huw4Ryv5#)*CBWY4oS4|4E*(mtsGDZo|Xzq+}S&=o$*s^gm z*}S_X`$2rUd6s}uu>A2^)5aL=%G1WfI1tFt*z~8l^-eCFOXaMNAt2Dj(|s0YiT#n0$S z-p8H$rzIC--?F1ZZYjpv@28B5q$wFoJpG`(eTQ#y;=ah)?q?B)Y>@>_*mry?X7uU0 z1x5#IIeB|7LG69?w(#$Rz9?g?BH}ykOyfTUzHKb)3q7s)ub0sk%r+3gPP-RMic&Iu zfWn-=c9yA%ApjBIeWSrw#F9z;VUDv;HAJ^cCooKjmNQ6^V@f&#_`!_Seo*aV^XG! z?GVd&GY<45Nx2+!6H=-DI-)Vr=Y4hjQx>{XA^IqT)I|#d%KTSb9?M_c?WfZzPPw~s z13RW5Ate{R^QEz93fVl{ZB<=;_rG2yu7(7H#n zqP-KTnc+$89HhM@>IqTj4~~nYCrimCm8Q;_PFgBM;6h^kdO(idx>|G}Yk!l1vtBn* z3>YH${3<>&xB0~_Mpm9@874~(B^8m)>$3<^;jVA`eTx+srPaoG>g7_2qkBO;vhw}Q zW4%0ua~$$k;vP{#aTZm0Lz2C0dPZ+_7}yGDs;|Bo?^ue_MAqxYSi0M`4)5p=G+Rrn zvc*-$1C$qz)iUHrt-M`&HK{+Qi&l=D^|a*VX&?L}C<{;NB&;q?ppsWK{-LT5@tEnv zNP7>ND2QiD6Z1So2iR{Sje(6LmIYLneZM90)UYA47QDNE7e^=F<^M~Q@SY}HFcS{P zL35R6zB~-V#w5byGm*hMcRSY{7Er9f$bv+h^j134sK#!tHjC6`Z8vrIx!sHqk3W{a zYpxEt=!Dy)A@A}*8*{4iSvC6~P9hEtL{8VVIGIR-s?m6RCs()W5Ipe*da6f-b&`QH zhAXv>paf+*|n4gY8hTV!+d>GfVo$I?FPzfR&)!qvm9k1%WG|G*eD z(Vk9NeX9c9@;id#(G20eY-k)_PFDVwgpUuO*~K3|=Mt`3OodwucMwNuT>c*;pOrwp z+`OM*xb9%%DbQJQR%TN+-w_CI6o&sYVnIO5pAO8W27KRz3)(BQ{l6A)zDf?sRJcx` z#9%x_-^mfU@?_M#K%OLa97)-&SCdjgL((|-u0VTPCV5T|Z=f)rgIBU(O%+bguSfoZ zIp_8;=IDTZ1KR+c`eB2J$~t{&iRDt@y}vSBXLd>f!gT@wPA-9CrUx7!pd2+j1*e8_ z!2;KzKa7FdC`N6PQ2cygB1Ge_{0b>jZX@Zmk6n+>gMVS=#56MU%#x04ht^AP*2}o>>9$UQszFr*oAkXb84^ zLwWzsbmGWcN2m3b{wDzRjK5_|TiWdjOU^1Ytl_5oqXqT)hd}F?z9!EAHylgV zvTMYm|FA36A8w!q2+Tt6{VKi$$DlR%O3vvB<`RnyoNmoiC00 z8a9xoamt_henHcZ7D^F<-_i5mbMtSv-w>kz^43Ag{EKy>N&M4k)TfFZxmk&j2&c6L zL_L|59GvFEQoH7$&Y#q(-0dw!Dmp*$G?;VpLVrp#OYXz=dyFe)NA+kuR+C8gsl~0- zqiUvXjaMM}Tn6oJ4t}|_gs6PQ$(7FcJoa;MPeKlM7BcK3i&YUlbwz}WGh;E>&N-pz z)k5O0fAx^57U2UuvsH>diUq2x>9sqZA&zXOI5Bpb!k(vIN6Lb%wAUfsqL3c&!Hj_< zvp*+C0{!O9Sye3|UaVD`I(pFgap{27y9-WLnrNDp+Tf%A?KuPMkU6K)7o_tXd7XH5 zufC_rp8?Y-N8+1sW+vZ2vaSLl3mfjK@jt2#zN5-CS;)ofKX=I0q@N=}nOCClY?Yte zq8gzke%L%7f@AXVXLmhSDN(FPMb#k&UTvId6yd%U3gru2ubc9HZXWKBv^ev92vQF^ zN`*5hdM0o4yjQ_pl0KRs1=uB6XS-Po}1pk*QiWJ%{%p~8k5UWKWlQ?ZN9fM|D#y| zI1lZIcyih1HhIHYdWQ*MB?(fU<;>8L3R6HnrZzQ+!TU{G|%F zo`5$nJo_1WFH_ca3G|@2=SuMU^~q>fGX2{wjfemKVmd*Gut!S?2}_A zBwotx{nL!Csg)A0p)mb(Ia@!{B;sK%W5^Ut$C&`3;KHSPgk)a2O|BMi6(t_%iQG@8 zY-lF=A$gAwnTajQsk#)6cMFok_ljL#7va8AY6N15+^+gG5^HXfw)_rK?7s@4U6)M( z(UH*Gtueok_W<-K5*^*i(ZsInONq4oxl?fJtR94(^IoLrXwQQ@bl8Qj zU>6)B5FP2p;~L~hP0h+u_|95DBe&@&!=5R_yNq+ddJKTfo9;&WIO;xPmu|xHUZB!fg@+SWDju&iZP>R>n#l8d z@G|fgm*ITCk6YiRzN~bDU$%(EJ!u5Quvk7%@@C;;cbM;~ZnSdo-87SVAV=G2Sa&3Q z@43rgsAD!h<_C^xRm>(k`5}D_PsPH^fvQPmaI0IQp?LcFWw1W(?w%;p=Lo!07wwe_ z3(`fj)n)H$mGT|iC=D{#7vIYnfxgI5Xg)$4o5rUcRByGt4f$*g6+wMYQYPFGb*4Dm z0&8|p$|^`d_z1d+T(WHB4EdC_BowycVcJLbO;t~sNRbm(?Z!8xu-~PcJpw6liWj$V?L~Z5(YzOGH>0m7 zk;|BX4jzr8!7fa1hgQ>}V`RMlCVl82wvbIIp)6eRw2BzwetwM8$@ zrfQN|c=R7+rfRB%-pru4MZsdOHYrWP6O_M(PEV*RBY*6~iZy;N_=hLc#WUw+S6jo5 z#I)(Eg1lI_&05P6+teqsDtOzSM8lBkzU&uG&jQ*aPeco9?ga1adeZMFZwL!=5vg?! zMpH#a1lutsug+471tOYy#;5Fb^F5aAN)(nyatkh&*V}5%SO5L`nI`$p?L56;JJPvi zf%;e=-{}>Winh}pphq85J=tvxZ0&eq|9ThvtW@+A1fbw48~Pv{Yg)(7{)JswXT$h& zRj^N$eUSCdL&4yJs$Og2sh1W2HE$!DGN!#XobYRSYVeKVTqyNm65WJvK(@_GJjPI?D=YKUj*y-HJl9 z=_=V=5%)^HIGqD7=?n2ELyJBS1rcix>zi)c1C-giF@8Xt45XLK`@3#^O*Ne`Xx*R( zgybnuAz?l};skOLn2ZLLIxK3Kw-}~TcwKiDe^TZZj&1y$N;D)+sMP@r{Gy_!+EkTx zVzwQYJ~>nXU(scfTimwdjQEWaRJ6Ceam_y_HHyef&Q~rr8{4V5Iu1#YKMekP2i)X% z*wC(3!T%-v77D`(EvR7Y+^Dpq(+G*&5~xtUvfWAZU^4}OUqc$u1a`EQ$F7S zo=%4`wG%w+oo%IB_3P&-e)D!au8hXRSaRogTw>tA3u*1c0DO!@ zRCX+5A?fK~=1WfN>HPbDGNOe9*TR1#{bf|iN)-11lxQWEY&EYhVIr2xR)vB#rvjTH zNg>-k9p7L|8CqX4pQh|Go(5%h5-SqZTxaQ~Qk+${xVU@09nh9I(CqSvWRI>zz(|7L zGIwV~%;E+u3pviV{Cgzb`z>eU;F!tiMQ={-99yz zVoG7&hp?!O^kLk-OCtW6)yUbp`5?*Eg%?_uz0f1YM<)((0*$Xf^r9L?sa@*ZgWn01$z@7FGg*Ge0-~0k zqJMb{oay`<8rXTKH$AxhAp3HNa?|*&o8X^?j>mE9sXtg&|`fQ zNa|@Mj21!!7EXa|mqYNuD}v*d4Qk0Ff`tvy^ptgRF zHM%ywJHx_$Ok?6&PGXdZxkc}m?3=io%jN7BSYZr!(W18OjC_uDV`E9*lzn_I2QdiS0WSVM2STXlQQxlVnl%d*#>BRg7h<9)MGimSh`)L3elWD;HA71 zdMF=ATc1$#!rd;9Mb&Q4o|SjXm6z4kVwmY}gdz-nZK&S92D?I@>;n>HJDM`T4mBTa z@5ey*I&cb8a@TjrF0kObYVNgp=1zu7-3u}$)+{3IVXdF608R5hgx zf0GELeLLr_z*w0s!10w%^844vveOqUF9T^E#N8_z6CNTNzGQIgkW%v>gOvhqgevgd zdkxjHi#sKoTWMSjI>KHCeIxAz*vPkj&X|6<9g{iKO7_RnrRwb8RG&xucAm#66dRbe05*IMmb zTx=D&TJ`*^N76sJ{;o;HD!CUb5a(wvz}km@cTHC)Q`$3KgDR9nA)xyCax>ltC%auU zslyNi2mOB?Vb(NC{ekc5rvK345V`H!N5Vbpwf!nRcip62*xKSt zMm@tKey`77Npk9_HD1+Dd1#Ru?(o7@|aG`I?)<-(j!)LJ)Q0E`V zL`%A+>eZ-&mVR33(xv#QA&=l-!K@t<66rI5v84-~y`A80;2bQ--h(ZPs>cEZ1}XM^LEMPUlu z`G2{tA8&#g6NYhiC{0G#GR;7(8}7!U**34D8ZTYLSAB=wcp2}bbz-z8;{UUNB}+rn zgyyDF6!3Uwtm6xUj{oT+zS_Hgr4ef;)b{JK;OOr-mBXyW2;ZL!w9vCww{w;E;oLuk zZk-k}&i=3|T*qL9M%!vFhz1a)&~I;h#TU%bkbvq|hx%+huLL#UT%M*!Pc2>seZHw_P?)GgdqcY>;=bG&9AA7pe_kyz z{V(Fx+J8G>)@l^*FBZTqGbAR1zQOKpcKjk$7?=B27VWKQTNaj|;PUFDFikgGX=^_- zd*eCERrMoBr|!oL4RQgQOR~=Qa&*y2ZX`bw#f^^VBd@S;4z!*HkoHe)V;sqZ;08`t zA^^oAweUL>#*MIh6%*-7V5LG2Uc93+5WLnCd|Ech7Zu>eYenooj{lR!G+22(ONb{W z13FYT1c-bJ*^x6T-bfu;xW1xZH0R(UH>ehbpJAMx@1K>9`ZZ{!Qq{7mjL+3)oPKJu4o-Qp8sPtHQquzz|=fG49+7)_2HqIY&h`U5Tg)aOI7)E{c^z z(0;t4`#Uo}9eBIg>{d#l$G3+sZQbQq+^xny3``7%1 z<9QgaG9n4j_FC8)><1Y+GP`ZTbP@!3yzcr*x>nU%N#WlsL( z&Dg)A4gq%uSHp)#-iu=2&lhAyjc%`$l?KC*R&v`S-ikrnFhna`=)U1@nfW)mk8~>E z`RP8^Ry5rWSV-yo@VZOton&FV`a?@6bO}Q14Wk??SB5t;_^s!IjR*Qb{NM0Ak5pIt zH!6Fv6lu3kia*?Mtt{M~dNqZ)=U(XVR4F)?2mLm9S_IG(ge@1ClBRcPcFsWC65$d4 z3tgB2!h}$1p_-mSnt*1THu2;84y47)hu-5Vtj1RfeVQR*#Ps6RoFm~BLQZa;2`|0Nv{M~eYqe)iK%zahQ;kenjg!8bV_Mxn6BW>7m+=<8nDGlce7IjD zS9nida$tp#9nP=%}ps@{E3U zVG&k*2*<)a*-|QJ+e|JB$!ZdB>D%DD|CpC|=1;=T%2T&+BAx4%PXy^x46S$ElXE1U zN+QsVz=xGJ+Q}{1Z-&u?Qw0*7avwg*#}BGHBJ+_J?xe$2;&(%%AC^EPgblPEdOBl$dPZ z2%(5XwmZm>ewXBN5>>AyFrzFdN#doY5VUE}XjqJ(1yA(1VRx9bziZrSil7c$bH_H( zaW|^`9PD@RGV`leU}o3*6dh?yr(x=W8Kmk@{k;;AicXos&zRaWxatX3HaiO9uC2n& z`Za^XZ||ed83u!cZf&hEbbg>;(k70HxX6DOL*<&=EQOWJ9DYH2Q2X$#2ndvHrsFwQ zuvjpYibkw&%F;?|8S}fmEUc=10{b%!Cv>eiH6%5aXXLiXO-?lswYNl77jqCI8YT;) zF%QTFNnXs4!ojh&b{?=8An6F1GChdMag9hS6y3`Xl~t&9lDw7US$L}DeOTz2;@Xwx zk!uX~T6&njTe;DF`i1&h^{D+@KGh44WD|vKjS%xHV5%dTp|@t@2=|mE@Lx804p90W8Z46 zlCE4`zn(1_1ob||y6mLnpkkec7AlA|3(j1_y9_{C&6@HEA|1~hIe+nb+n8gbjocbSz`ut>9TkV7( z-BfZ(=16ayi`^E<&*M_>$yO4=4{l?G6nG1f-G4u8(L-AT0(~%e6Aa%}J9KlpC&{O= z+tY=uA+tSG`gNGbT(xFc)3h8o1qSJ|mUbkNE(&rR;xA4#_52~b+5PSo($jg{>T}7w zO{uT1ZpPi-zzW#HsrVfWZ?$e)QRwwMgfq*ZdfPiWqNI3T?AD!P>dIcfxRKY#*2m2k zlXoxs&t}L?hc464pJ(hv@7;|V$n{ff!6V-xUCs+yCBMlC{P$_6@a^^q&yq2(jzJ&U zUC{ckLy#hTy$jbI56vCK=pO6!H^@kSH_B#Ea==Uy!3^~`rZtjN(q&`Z2#pS}SO(e{ z_gz`z#Jae$xbG!Rb3iQrESGGC+v^>9W`M3fC)f>1VMpR zp+o@FzcL+8P_T5DJ0uAiTfoJ}=G(Y!#l3_}-oWy&VN4my1}}s?N;SLKwpy`wz*3br zqP+^Qg>wr0e(STVXV+_O+k4nX&waj`HA~-N{d$&B_Rt_BZ^=62E%&E9GM#g9M>$Nw zV}4Z6t=6#B?QWp#wwwY4CLkPoyJm#_nccuOr{B9DR#B{Uf^;P~CAp)(;*dXug>Jc* zgD(^HNyMHJE{*_%r-I^!*a9=<35RW=9U_ojCH$sDoXQI!jpwhvuE*q#lMl=1QQRwB z>Pf|oK2^`}4Xl6GJZ;{U48N>9hAR((*~8#PJOx6V+HX_IBkI#6IQaSacv%*K-K;_p^C0$*1B@S5U1$NodL zy#Y*>;Do=9YCXrk$Q~?J62FYwyKXCK4a$Nj#!7G;S6r<_B5>CZVoIMBY7o5eamEm< z7|I&CB^+Kkx1B~aXmc(lw2f}5!#{Nm%Se|7ZzrYh6idXH(crpoxm&W4Q!!fnbtI6iO)#Vu zd3bNjg{Cy(CNEATb2RF?bnjn)Tdb-!SHR>4opAcQw6v|>oXT1K;5D!a6K$<6O0XM8 zwPxnEF(^v-vDQIPYVlXb50}bN4bW&eXDF#C{#P5s?AQ2Oc8!4naF6N|#C^YhtmaPg z^bh0-OnV-u^2Nj1OrpeOin(C?SSFK;S0vlIfHpcKjwb6WuY;omx>Pwx9(M1k=ZFpT zS_hp1>A^dC=O&|1tzWPznuy$6NsMs5PUL(f=T_(?9-z)3OTRDjiU0pu7@7jk-A3aSS)VOc$ zw_)X3Gb>-e>2ks_wssZD0JQt|~sp+igbSo7iM@y`*zQOej$z zf-6EI&W!00afzIdf)4N8KsYef{gy_xWET}1mkkkNo4cxED2C|a)y88!No3@_iu-X= zr{U=5kHh?+aMbwA?R$qO8BfR@>|yt&NMPvs=$A-vK?vl^fG2B*M#PSA#y?w@;#vY~ zjlZo(v&S0|&`a@7n>7F;OmDOS+>VZ;e~c9tmy!P2R?P6eoEVYIXa~C?vXUrXdulq-OXHb(p7N{r2>sw6<*Sz|#N-iEqCK>WSkWk?Lw})c`UXEVmKll*8*PQ3{m*9Sgl7re-N1!U3 z`oU0{pXb-9anPFfCpw}KcpwyAN66{|IG@8w@eVC4SvX}Ed}*BCT=^6cUgQpXgq9P! z&R?4}O04yV#@pTsdo&yu|*JWz<^@?@%w&kjMAdU@sgI4LZ;r*HsM~PPrha zq-#MlVkt+OX1TnRo}f9swY*<`Z-X3BFOST;wFzPoeaW!e>};3W*FmZ+XJPU9^Fz70Sk&!G9q7&q-lzpMsJBk%_U##LiQ6O(&U@Z zNi|Z6W9{BNvTiv|vK8wTqe!E|AjBbv4KV+UxgY&?%CFxx#U6V!1kzcPNpK*{T=LU+ zvFT$K!X4WppSn!Uw^o+T=}Mix+5iThm7xH>TcIK%&)+=xPH$(E3nxGoTJzzIz;+fY zPPJA}5>>R<_re&Ca(;)iOp7vgrd3v}$It1iwzFt0Zz)Z~hr5FK7*Lk>HGe=BW3QUXIUBwzG{!e>XyhrE|MQ@p^F-hC zI=nrN?Mnq;iP9o_te>evFnGXnTSP@~2`drE+&y>=F5Rkin8{&tPPE4qY92BqPyPBk zIwULz$AgRzoodrw3b!e&0$H`b9dJjAa>7Ja}|H?qp7 zZOS|eCH)$Kx`Ki#G407ujrlUv<#prCl@#Hk+DiGY5_uzbG6lrPv7iRX_YG(IUSy1s zU0JFF*!a5Jwdfo~>`C#FQ|C-{j1FL;BAVQAuMoa*&FEVl4WRV*6Du3FUx_6$9i&vf zjX)RgII*oDeU*zLSJjT`;lzSTcANYBnu7@Z2$V0PrLU+ppZDyZbt6)IjSC3sV*Xk7 zPWvtlEdf;Tdbw=*jZ!1f*Ves6K{f%8Wh$o0J4n_`J!mY&R(V+!r7~ zSJ-}TBAygb{plSe#(tOG?l37$>};XJ&}7BFuE%WxBW@+FEG#H{E+4OJtaDf_nWs$&P)Pd`$rckxwd1P`4x`Vn{l>V^V%0dS z9r?km3~sWynMP1{pAEMs|Guk&Vt{&GDU$YW$^4#ZTdiT8PRWoIl4M#Bo z{E%4BV+le##tPXyOP^yRAbb^_HJlUa75lTJyYJKWz@(6UQ5u^HE})O+)i04&5zgYV zmHQh*pTAO!Q|~cb4*;OVzr@VNr({mbc((=N*s_9W% zxknEhdmuA>W&wkgjdwjORPyzVi`f_mEq;Mm(=XNP5HFFvZMe%DJ#;Gw>z1$4Rn5c2 zURZ`J)XMMv2Rpo8Y)UxVYegWx_$itW=vaD82p{~xKL3Q9{d^KS-lmVC30i-Vn84a+Vv)gXg}N< zNvPf$?m5rA)gAjxLe-+Ohk)pT(i-y7_m;JQ7$_*`DZ_t77}NCp&lIPl+$~aS-Kbp6 zvcjXfnJBO74HaV6fvc|x8KAhDjAEyV_+m}B-T+pYSflLv#17lmUk~OD`U@dpDHJ?B z4+Jvxk`Zey*SZf!)d9RJBr4fh8=D)U-P9U2(RLqh5>{xF7$zQPX3`82V@ijJC@TY0 z2aav|$!m;J1fIGj1K#^!5Q^-R;~WYWWMGhPgqltu#ni~$co|qcRD_*ZD1n`iD*EuL zd*}`3TqJ<<0>n2osoMO6958-{0x8zE%!yQVp^zs{&4~0_eMEQd3X1QzzGX z_^#iHl79r3hSu1jEuHVJJ<}xKUA4bMGETF{Ui)nsZ7#Jn%b~tPT&)&z=4w&OZdm?0 zr5VHpyoO1#4{$KMa-P0fU)#nU@?_qiMsl9Q5ywVA(-;rcL;bXlrlU!~i+_tcI0R)Q zjiZH>TSeP!^5l9}iripW%z&YDw%XK}jMv=jta8{>+Vq@iy;15k=n*>VyRXi=-gO&7%I{hf&3hE;Bx`+Y~S zUFHnFqN@~J64xJI#UwLjAM1LuE$_w+H?7|97wih1U~mnBEQu`-em^UYkWx`Sv=$Ov zX}=*ri;(DDv8Aj{0K|2+7~X1HbKRD?Z%%bwI*KbY73|KUONpzF)D5 z{f{QkgmNhaTe4ppCqbC36q$!@x^#EEkQ>kz6%woYWwNW*Q|EcFkZV$;TB$X0p3~zd{x~jtThe6F)Ps_S33F}kXTbl`lG5qkW>-V9u-*0{{)8}VC6f^4#N?NR3SrL9Y}?qWMm^t7mB;a z3$jRDPxxndb4-z-?jQ1LZ}3(jGIB%pbCR^?2e-gPx~61SO?)RJ+CNq-g7eD%?V)grk`p3`DM0(>*!D$nZ)LQ1sWYNNHYJ>Ho)4ITxZ-XbW z%f2hnTRsgNw!LDj4ORy~ebtr`Uo?+y1E5{3G1i#g={zUd;pWSfKq2#=Y)a6=X_-tg zLAYU2kXW9jY|9}iR>(~&Lu^t7tFr&l3ggOA38)mWuU(qAuk313@m9Mi_a*i0wLqoa z0_lfTP2|QCZd4{bjQD|qcZ z*Uu;DA+m0hvgVo0xQYq8^()V%N3Vwhefx0Pu{S|q)QUF-8fDL!QyEs-1x(NhI>9Ik z#itCCeKF5WD8lcP)@2F6-MHM>H-Zo=_0NcU-54`RO_Do;WyY`-nTM=FrzSe#?bcev z;JST#QTH7Q89jM}i=?b>!m}wo~c6H}o-_Wx2oSzV#qy;pw2vSXwk>SsPw7$-64-zFg2x z1jh_{kk?@QM}py!-zUY9Mok|0k4!qQw)FR|>mTxeClZAP7o-aD0iS$$f9?30@H^(W z?GP03TEsy|`;l9!(V6S0hD?P$@|CQAcXn?3-yxY&K{&E*vgoVXL-PSMSRlO5>>*Ty z?d`m~cF+7!9OcCbfW>xG2_K@oC409K#eea~l0$R*Q;jRATIh|d50meR;y;8DFPQJ^ z{jCfzlND@OLY<-JEnq*C>r{Tuwh%vo($(g69#h#OE=WCAF!kQ{6%s7w*B@DWB(UW5 z+pO&28=0B-HL8T&5B%q#$HtRkUZZnlLK-#%TikLOkN$-Zs~H(^ciN{Kt`p>icZVSb zfD6G3Az=vLfU^-4(-Iye-q(r{G)7X=+NQkjZxUhw!4SDPC4oYU5AEzaT)@)}6NgTB z?dB()n%4APoK(w*Z^J=tetFcA9yT%7$|H%!OI~i+f zj?0mqfCf4IVA;2i`*epsC;MdWX?=E;IwChuqn-{v{ZZ2)1^o|Y`;WWFqxNGl-_24X z-cGrK92bcYQKq^<(^oauO^~`TBg!y)MOGBV_+!>+=?R-hYWcFyOwgJX0Bn zOXX&j5LqPXc>|#E_z1r2xpS>V^Mga}QtGO7_y(2aT3%FScbGfu&ViDg{RqT{tl^g0 z{N$sIKQ)Dc?KHfdzTP+8#aM1iZXz=l!7BBSqj*Iz*)G0Z2xVPk%6G8T#UOu>h@K-kXLH1tPHA_pZvu{AI%fD4=s+Zhw zm%b*70RKvtGx&9fBjBcAG3DJ0xud?2pVADOJqGu$>)s4j9N=EW+!bhwF<9bb21ccK zC;ye@CE&T%HxjkOF+bNXuWl`AaqnCAYmVBB`VKt`o1wqb(TV=Oi7WfW#ikI2`!N_H zkR({+Q_l9KRV5^|(7oBG&jE8E#cPg5+;k&gPg`Xn`UoxgaRj9k z=t*GAmmiG{w%b&}yZvSzLNyD|eAw0!HmmwLF5G`;zMm>m8V-SMB#o2p$c#%H^srmY zHebmv7n<}uQ0M$^ItlY?q;(4LYJ@`cBDbT8YEGX#{==xf97_X|o7Ywod; zxTPJkv4nmCSgM@O8u>OO1K{;P>97bC1iuQ-XOZ z4hX5;y^pu~c4wi$ehY>k@y6cxJCXSAv#V|E(1CbyESXR*rll7u-(`y7E+tPM)+*L) zR_t5^`B%GDf)}a9R(`^r>w@OWdyO66%=E%uR$RyUR{ZTMcau~!z+H0$kM(EL5#HYxvahSr{Wxgy7fk*tC@V6)|0DbW$1>LK>PES9joJt(zClZz8sI1^`zBroq51oG?1U`eF##LPq-JWqgl zn(7uydx9opS&%Vo!?eHWY-%zn>M_iZw(6DWSu-mmdmm|%M~Bgb=b|Lw}7D3hKK z?gwv#eXTwOp$Sg5SUG^tXzSb0icPy8pk(^J(5{Z|^oYX_tLFVvc*m8D(`QGXt3UyO z8M~m$-SMPeo&qp$Eg-6rScXnF>7^?b<2rmhCeS4v2&!Ly`807(1xzklv-ZX-W8G-zL1xXg9f?yCi~EyBvSqM6u2=pGJ?_&bT3s{AF!>!+W{)JVU4HX= z=`o(p`@uQ!QRo&g^`bx~Yg}dL6p{I?b>JPeIAB^T(rUZz`TQ`}l5DS2Q&tdbCFe52 zq2?k*_;(tx-xEtms89vRWNE;8b$D15>lNJht>eTr2e?N>Cy#;YKWp>J)042MMs(DF zo*pn4ot7CRc7(|L{V?T{%1siOh>kq$T(+jsMf4Ik}Eh7xNl1kTI#@#Qkl zIC)u>#V(LwnrV(Pqf!-#BpuPlXPUP0mEf6jj=56DG_O*94F2?(#ZH_nelp|WOP7?x6D69fu1SLIu=t;y;Zd_~wB zu4KAhiEG%Q^+7``uEypQ{7=!9EiO)MR=+bJsbCZ(04nowCQIvo?=0mYXmhmEOiPRf z4pQ#hAwQ1}Nz+j5$?^UIYg>XTub9euafRwksajzQzJ*0On{732wmAt8moNglSE`)U zKI$**XqF}81%(rk`ur0&BOTM;yD)M#t?bZ!aH2=gpm)kl@`&rN;2zo_w524q3NYH9XD_UO7CcSwYR(l|*q&_m@BAGI4 zLOF+nqnJ5Ral+h)iV9V+#US=}OiLZ;1@lW0cue(q&d2qmz)Hb| zOSs*TDLCEXdo@cg6t*~$akR997$0y))~j$c&tA!V5tM;P20xfxa=sKIb_!y7D2!?f z_cIU58o?q#M=HSfhEub5O2XO+zM|y(>*&$ipj}(t?*ywcff4elo6$gcGO=GA$TY~_ z&D3nzvm9V{w)0{A?_CZJ1Y?i#d4Nj9&s(DxF_Y>!i9X<~&BDwH4~HVoz*q9cnuBdn zmJHG9Y1A-(6xg$bcRC$VVqVla4Nz{U6-=f;p9s{_q-P_Gpn$0_6XU2bp=MX!3z~V6 zP>6z~n?llrrN7nNgq`Ogg`k(k&M6lBAl?2)3zY-j)|U4p@#v!=VKw+;^Cu;UztHT#)(F?qxJ#sUZIxxn5yF<{jKdL ztbP|Oq*5_Bz4`Le$&6gLYGQAw-ZV_(Wpm5foA7=z&*@{@yF4V(e^ix!W5q?}vlz_J z+%TvjH{@nuUdnzslXJe>v59=8g7Z@1Lmn-LvhY9hO&>!R7!Q*F=9I47>F^ttdod!r z9VXJbLA&Ih1`~~2qj6Wy#Ukd2(KDnuV@$U2*$j?<9 z@f@O{@ha28sTv%0o6J_XI8R%LPHGs~yNNA4;rn*WmW(zSq9~)P^t7}`DQ#%Ij}!ZD zEv*;(W4}Cd{f$VuA;XPmcdt_j#gJBSIRqfWRRxq*6GLN1HofEUI|-oKQ~SG&M%@R zak2`K4^X3wNUtAm@-7}GPp0DTA^UW%+k{8$lKfGWM!}!@I7>r*Y~3z^Il=#Bs;Qh> z?nBOfY!Uexy6; z7gfUId@if^OBX_DcbH8~hC1fSYV19gMoo_knzaNE0oJ{H(>9&re?qZMj2x~<$0wpP zv5EeKY0NK=r^=JK{{oyTAG}y7xb5Kaz;)}|iW&p0`tlv|P1W0pvd7ZAqbQoIfvWeml&9zL`hF}YS!8711bhR$zZHqX)vDh$O zngutOmtQZ{<80S-H8D1zF#pf^)n$h0pz->Hx6siu3IdIzr+&i>vTh1opM%18-xtlf zO}HN!BdZb@-u%8|(LzxN#cG_i0{^8KsQ|V(=^DKI89LYIA!Dub_EAmEaI}cI+mLra z@t0qc$P1@y)S(U(X?AWmBfK|Xkk8JYr{$I~w7={}u3v&9)KX4!K+iw}S&&z>NnmN89_c^wTiR0!vpdKj|@F2!J(b4p^yN`}j$)Japewz>m*Z z_+x&04JF0p#7|6^i5y{lnJ9DoZ0ZB-EAO2k4NZY2#z~sGGp$|)?ow1R;wt_xKb^ql zNCzD-0Cml2s-zMt?>IjESHj~$Vme+k$i=0iEwd1b%*K>^`^}rQIzMPyMJ^4}IQ|Wo zdwWSGYX_7Cued}WUvPj#Yf+(VYYfGbqu8enRjX8Oy~C$i5eflhriC-U(a zD;J8H{TlSO5^(*6Dv#dk4F&O_O+TTGBG0!pj$w<8a{ta+<3w|zpN;J6%Av^x+VG#r z2h>FyZvBp;8=KzN&Px_!g9>-UGGC8~K6TW5*-LyIf#_m%lSw`$mknu0UqtkjP$$$k zPT^-V?ri=L3#UZ*#DExBAOYAsl1f){ye~yvq)!%q09u zK?Q^3(Htmj$kO>Xc(#t3Cw{K;e^_iM3;QW=c#$7|`*?la)m>=`tFD;wNB0FH7ND_k z=YYZ5Mza)>J+BL-A3(1?Ze)0hjq1sFVyQf6a%W=IY4T?yB?l`tlw*b;oek)}1jRpL zioq&cyGUqul6__eX8-%Wgg~0rSsPrJ^ev^~^^uo($MQhe>IKjH*1}{FsgPVk4C8voN^bKAP00J4Tct6h_bs z^DC>lp6_!t`NC)3H@%CQ`JwNQW>IxPE!voxSq&(NM7;5@(9bQg@t$wBn0cIW&REAx zD9|9Z`;rgZau}W4ZZGodY&UNwW)!xd0uM#8)ya0q+!eX)(5)Tj*j)%IPa~qEk=JWm zls$#Pf5d)FV7f&7wp=YZG2wM(ee4S)TlkQ8amrJJyB`w-i-{BM@0x{ZpqMKzsi7vr z){2kqvrOm=r{x?xP^0Ce{g2-hl)+dTQPBbS|IY$U7{bjWk${H%9c)3fvpHMpM{%7j z2_l>z6^Lv?%wF|CAjqj1+Zhg<-z}=@OE)r)ukt4XZ&Jp` z0K&Ja0I4Z%j11IM|4FO4KQ~N^cd%p^M-IIj4b#|l*CZecCz-5kOotnz|j9WBia74WX=KpOqe#ZtJG+=K9qsCN9~;N{i`lo zDuww?Bn|^hVu0XRIz}RG=*5E53$T48-mZPbg?P^zt+4JoWD5J;+U2Nor5sJ*u#sO&y*cUe7Q{t=rJi*-oE~!X4L)dp;O8{V@Dstw4<)YEs)ib#x%9WdZ$GuHuLJxL? zNl6dC`TVDgT(^k7VHO1adBOg_8`mZD4Q` z9BlievOb3~XZOL~-~dmHZz)4|0SffI`n;W)2x-?BAqED?A9nZB!Ai_@>EBfp5p6GD z8Yk<%a#0Px{}BJf=~F%4g-Qfb_F9rIhZ#H9i5amRonN?!d;Lo~7_EE6s0VD7&v)gg zBLE8g&k*W260j5{uCz_$wE?4b!b1b7^}2A{p9RV>khb!jLxk|7PkqNzkz5)X%ybFy zgi%0XQM>ho#o6nH?4}gh5^JuciuyR#q>xudxOdh>77ZO|m>eQv(8E2;j9F?DEZoyU=CxJ-Jq~`XVE|pe9*frsV3x=C&W0(J;TCTV#TFQ<8g_(0ez0l&EQ( zqX^+i4wOBF`RBw3Xxm|o@2N9Z3i6Hy--QIV&oTK*;xh|9d%bVO$^!DtAj40>cuV`! z4o3ZzbWErE(@#KGr)7Ze>Q~Q}OVkbz<@0>HkP>erDa3Lxj_b&}-4kq zqgrA?&)N}MJK6RDQB6-epU<~e`S|sW;^J4_4}A9hf7y@eH*|dawqI4%-zJWfum+r3OHI^ch6jt-nAA@1Bo@5L#$8Q>TA(;G%dL-Oeu$yJw#bTDQ>Z;ZvJEk! z{%??S>-yU_qJ1Yv&DM$!xX21&G$qai!FeX0u`BlAnxx@I1AZ6>dv>*1mT7tv{zb9& zgczagIyz-yUQ?L3Y_6mInA>1Vh&#f*vL(=rolW_UoCRCfgZrDY_kg?-Pak*>nQ{bx zEGuj!E6P)+N+!dl3Vqo20X^XG=t*J20G>`8(ozb-2J2QPja8`ZS1EsSq$KddRrZ3s zD-~Big)y6|6r_f_x@?&sFLdQPqLv4ShbYy1xM&_%oTviDu88NQXHIb;?;e+k?i;*- zbaBBwW2WVl;Sv}b%6E?&+i<*s1H%sAleGv(qiu48bMqpwLs!@b|2ntg4-^6@b~-ZjxOc-UHNa55?O!6&Pc@AIy<^D+N--XtJK= zMQpZ+h%AN57Pl6m&4TDIXbR8B((vIp6Dz>d$Zlx9fTm2Ak-W1`yY1gw#;A8{Rn$O` zi-b00?f(J|Ci2soWDcD?T&&ydkqe!~zR5)d zE11x2aD~!0JWOWz5FOL9E&I^O;p<%oWBe`fAfaHXYN2pQDQ1mq#eXP=>t@X@ux#`| zicl;GHLT!^h7KOkob7ob4;G~$ zRPd{4+&7cBCZ{eJe~7qMJO^WZ6L8KQ`SICTPd5I zT<`V4xsr1*da=C$LL?EB^Mj5}tBBRbK6t3Q)tsB}Ij@G#T0GBzlI_tSTfdFT{A6B? zE!(0y^ANv>e&!c;GwK`0Qyv_28_?czj-*%S@qSGkYNQ#XP>-7*(VD zxW7edbWMJu8`;n``T5G!fkcY`s>J?KqdRf96kFV=4AoG46PV^-0{jo7S^OkeQ!J#B zr4}@SmX!8QnUnz%@BqpNLg9#ra_ba{>24(fSi<+x+3@#5t&(jX{%ig~?!^nh0!x#; zVl0q`Fm5Bq2F(Jy@LMG2iCiA^2|9h-V=q3R&kr7aABr8@)DX3GN>|NzSC3BQhFl0R z;XEKOVq4H=VQzrz)bKOe|NQ6w8vO?t=4)^2jm#(CV0`f@C+!X1qmN0M*ooV%X2RlE z;i0pzc@b0oJJXf;naKGs3#b!Y##^h-AFDn;f{(+<^)z3q|}1#|pv=5kvUj|?UlLz1LtY-ECy zye;Zb_|Zq{$m-}OfAMQ@W^Ug7O8*w#JPbB##`KfJ_kO@5`|6qlIO}AQ6WfZ+lfCiG zOCjsaMw2V@?>K@bw1N@6=!OQIDA8e0Mkac;Rc>{)vNuA(O&CZaL7e;B)}^eS%um+s zi-UfFe>&slJRp8_X#B@z8Eo9K=_-w%so~f0|NQviocN(9u{3z9;k(d0 zdQF_eAH8Ga0k5!0=44|lI-D8x|6}W16y&&ZB^v=$m1KK7cmMw<_wI}zQgb6|1_(@WOD`cIr$?pzc=pvtaQD4-V!4U%Y*fje=RUP+vMz0_TqQGwtjye_Lgt|4dZNTu z%!OnaT&Zl!E*X;24vCUFMDuys>6fZQtscL3b@xc@XDnIg?|fkT_V-_UQsR=NcGM+KpxY@HvU*ntPkqy~aRj8(> zE9uB*e3KVk$~NPXfeaNy-PQWSo9~T{NwON8Hzq#*b1=V=;EjREiE*P7>#;4$>rl4C zMKb=7Pwb0_rICMNGx`yU-AvjWFBW+y&_H^VvrC(NT2^v-tD*(}Y2yaY!oVgs3&OQT zUz8jO@5n8D&s^}}G>bNKxyjSV^J}}b5l5{Qx$0KtwW^gknz*Z54c(rY(+*V^I+kMq zvP~aZbZ)GpP&Svx<39SLB)(vxIhUgi#>{<4=?`hj;Z0K;xdrw`PUhgB17)9F5$k3Q zA=w58*uXb9UGP|i=x<1rs@9Dclp9#nuH+UyhA^?Tkc;fX$9nn;_VD7-wyImn6*sQ< zu*Q+70gefr>J-DHwVw7iHfJ23ZDn4%N>!E(DJ4c0HXypUuE}E+zL0|j&NcC;ZKF41 zXWX``TScsl=vA;vj9Uu~i7D$Zbz+N*ZN}G(PhURxuyuRRYwAzC1QOlY+nEDNc5Li< z5xDqNH0zCLIpdL&MJzYn$p7aW17~a|7or4Lo|nk)M2VlpI#1ge@H1A1(v!)FT{49F zTzhoZ#Io=oTe0y;tef!n6L)My(RM0{%GeuUq9du|*QLT=KXY>D`Fe1GroKO8YMz&> zR^n;uuIRi7KDrri>K7Fnykefw!1Z{W4huMaQwg&bP%>_uy_ieMs#lEuh0wr#FF)t_QiU-SZ9TtWhI}Y7+E`TVo}EsDynWa^e?*I z`6S4M2Ven8=0RoE2lRIq*0*neD~C}&ImW>RPSOe>c9Lt^kkEUAj?+cZpb1ySc>Vyd zu)o3Z!KdZO*j9MeJvBGwlT>69d>-uRo{8bmz~|P&EI}r*9K0V-S}gvJ|1Bb<#x%aI zl#R~~?_%SbMNERu!nF*hj(->OQtn-?E;b|T`|Y7G9R5W+w(>wf9(UQ+x9{Kd=bwMf zCoTazx#=pUjz7tYUhoU~tnu+d~h&TE0IQkbo~)4W|2pxgpnf$@bXo zY8GlUUJ}BKJZxgWBi~ipY~l+_opDXvm+}ITg@BUGPw-(<_L;ZHC3iNX*eR&7d4q!O z#u~Zt0+hO|(Zjz*?ICVl&$d#ZvFcLfyIWNy%rk#W$;AS9XoFWN#J&>~m=goda6bt) zEF@?w2ytMipGc`0jj)Y>5mz20c!?E3IDTSaEc#g&tS7{WAB>4F)Z{($Xg$lw<70HF zVLKL4PFz*3M(300n|Q|tGA^X4Q9<*0(GRvf3t1D1IsJ^Q zUwq$KN2!Cy_&*v($&>fV_2~|0##6BX01yC4L_t)K+vgSEpOoA^V~(GL@zSVbw>t42 zD*Co%|Dc!A*h|~C5RhaAL--eK_no~Uo8snB$t>EIZH-Orrmk+KL?@X~9ZWA0I1_7; zgX9|nu#zOJuw@^cmV|fQEXEi4xU^>tF6u)U{ouOTzgCET)|x0b+W3lpx^uyr`iGxV zcPaC5XK%gV*|(UJJVW_Msvh%9w+fk__0sBURe7)$2JM$0Ui9!cxZ$}hyJS-klDZuXoVrk)!em$3y7BnXhF`nAgwnx@3Rre=#azw5&Z#VYjA?EHDV&7|ILsc!iB@G zvsvRv$hH=HM%wu`MP^I#=loQ+j6K`3t=NyuO8!HW*YJz+Qk*7piKh||RD;Q6YHP7x z^Q<0v=ZyMWfAcLwWzojg)G>pXmy?T!Z)H$s1Y+#9AuYhu9lqlzVJ~sIF2D{>S~nA$OO6n1}tH7mLNBLPNGy$SDO3o1jCmRot2c^{v%aBZ~>lfC$-O z6Mh()vB=MXb-z!7QAd0YE+KF612g_y*3`xVK3A|$4JtN2p(*4;lQZ-q|MlxvHH-P3 z$)2y~i6s*r3ePS@PL$M{sO0j4c=Mn8<~ zCl4k2^pp2H>w7kO^qcX~ugE~GGaExM(rIt%xL({qb2brjG6zs<)=RJ^G$9*xrO>d+ z2YQi>jBQo7Zmgqb9aOg(3Jx)rd|lYP@@!&TQ!H_XY|B2R6pMcHHZ!6Wi=UmA$dQLM z<;etS`~YjXwq=+6ALP*sPn6_8`$3+ak6;7iVokm5M9$<K{OqID z1u-u-4w=l+)Ep|eC-28xVG$hhw~6ogWOcwJy~4T*KbhBRY(DKZb<>Z%`{Tg}J1F}K z`(V~X#zwCjee|kiAB+>vGv}JZoR7aBb$k=3oFDXpEo8$1k4+7|o}I?e@!R9Cs%1xJ z94NXcuf#^23^HKodEwtOoe=Yr7Wx(3(A4w=MS@`^j^u0TIiL0!wM!nHg(y5OL3XLY zcJg;qlgAs+P$=zk%Z?!Pg68qTKEj%twUPC~y3N|nx4`)@deL8uKT#`(et|j9d0{KI z>*+Ifx%gGonh)7;oF(7+PEo7#1tMh1HNV%ZZbj~| zzy9KPJKx7d@|nYb6JM1T`=PFqL$*>ru=@@%Wy%ARTsQWN&c@kdEE5*{AN-0YFAQ(I zQLf||85^9L;C$=B3rMVf{rZc3{q;A+A4nB{X_pQ5eGV3K9{<%vKET9S`kQ$;M1b(B zT9Jv3*unr8Xo+k62c3stF(2V?up^~~z4SxF3x8;7O+MGL$NI_m_;}6(2xjca#o8GS z&WQNjri;m`1<$rbolBnu9{l*&!A)KlIou&Ij&+QDj)xaH#@CY%m|SDg6?;Yd|V@o)<8DMJhMC4qHqNDqhODmMs72{ zkz0^4WOIjp$VNHz6W@v?a0{}E7=(^ptdW*k3pRZE87tx%3*lAC_7JYM$lckrE^@}< zsFX8qpE{hO^szN{6zoI$E?}#7vo&47Ni}@jU2+vd`AArEif>v@JARQgBk3A zRJ1;cF~hg`p|0ttjeV3I8#Isok9onqcz)ssHu3EzzH8bW`Ayz4hN)DC;2nOl1`9dv zvaP{J4u7tjd}oibB+rj1o46K!797d;Q@7RKniqfezWe>5FJFGqm&aG=i*D?}m(8ZeCi3wE?S+;4RgIut$ z#EJa=?5~;Ii}}tukov+-_T?dDV>^03*Pk-P=fqvD)I+waZfbJkYT58fY2Uy1JQk;MqU>Bb{-*{X3uJ^ZZ+9c2jRc?F|#}Km89s6H6 zbnhIxS)?`~ljNC@E!&fj21_vDBJm0-+1BepNHEv+j^B4oUrH&r<_#Jj&0>rG#_k7i zJV|6|5$nh%fl%79wZUNHg*wR!eK5iKRY&4Z%vG^}SL*0RN3tGyqlO~;fByB~`s2@k zD~Eo3T}&iab-NwCdioT;WGRyqKOf{P_H0iKjj!}$V=)JjbyYH{O-wd&JC1ta-QKGF`MsGazUaYMLQvXMc5(;uM`M~eRNqNHSu2JS=~Yl8zRO&NZ;l5Lq7?2_cU^jR$X zbjA%$+wcn4*<`Q??hOq#Fd!mXl#D^(UC;5w91YQr_l5k$vvD!U7y0Ikd_1vT z)M+pD_EQFnQh*HU6xw)|jE%_AFY;SpfF;|k8P*HWrzj_{89A-$Rt;tbpI1ghfa1bC z`P)NB$DYxVwk*-l2$E0vt%dwWj`Q;SL7i{F(qFVuK&769z78e+{~&B&5OE)j$Zc|} z6nxqqes@h>#1ZOx^?Uf6ysXy??#uymi|viAkK~yTQ`u`is4w~#7&8{%Q{%_@*0Y$} zwzz0X&(%*Y<+-&@U268UCciGvm?iku^xe18{M$V8Q@=QiLL$g`5P0vY-#WD~ZZtkDP54lpylg>c9Q=5BOScYsG;lnuBXTCa)kY8ea+oh!+kl_yz}ojWFnFZ`COAQyvNjHll$ewPuH z7T-q1$4-LK+a$p@RyP}GHc#Sb%(fQeC&mvY_O!P=2l(y&P*tz45Yf;~-|b z=Xd`9{^Q@u|1oOe<09!@r7!#*|8cu12Xf&9#qljl^fon&+{qJi$QF8=g%C0$cFFd{ z>$J;iu*82CV-jW;cPWTZ}=Pi@N6(a3hBf)wtgCqTrqA(w$uf6si;Gy zj!g7o`_P5!gUB|+p=4^ywz3|Np2516wUlo`vLC(kVxMoqV((?&)iQpDOwOR>BEAw! z@@Da4sH~LDEiK!MolsYe@9t7{PrK5FpM%!em^`tT7kN#NQ*Zk3A8&jE_)Xb!u9=?? zO^w`<38IY!$@bW-EDB{p2i!@G#6>$gpr=At2@{38l`J@$P4?z@*@S3|8B+9R+RH%;tHP=yQoO zSO;T1%suxp9PQYLlCk7Fdc#AfH+}3ZBz%GCEA&W0fB)eD70AMcInQc_l2*O9(?k>-3W|B>ki$Z!iJ_` zl)9@p`~V-DOisXvvay?qc+Un2pH!%jweg<}06sE{1AH^S@r{}?TxD!FiN$Ue?9Eql zS=>*bGZBqFtE-T^Lk}4}+gjL5JR2XP*p^&MG4kPOe1Wl9)Hh-*=kULHxZluUYGO_N zk^S?}KlRt&e}Q@{e{sLTdc)3dzx<~Bfsbu%d~WO|fUeekY~nK*EG71NNnotN85v4Z5^Ye-$<14;*%_{V*cAuEhSpFvfvl_R`3daU+E3l+Cl6Bh6FYdhm=-H>R5xSIdbxd4&w8pE z?>c(1v?u=;x>BQeyR*)yi}}M4I|YgW01Kl@L_t)Gj8HlE2|_MIN56b(Aq7{bAeV*( z_fU|B!f`L=v%KOB@5o$$*=U)0U=FYqecZ^lx?0V1GBkOq;cxsc)@1C2Bs`N3D%n<5tI2uD zE__I9;>E{PZ%^(Q&jssBme8}UPhI?0CGKJfdvl5JHeI-k_=N*z3P z>gtwhXZ|c~g6lIE5*)ZL*4v)7JY(b~>oV=U7$oN#J^eq$!^z#Y><}zuU-G64TN7Jw z47P@QVp)@)^TB5P@my_qn|#Ga>P0&kF2)vPBw_Ti0OmzbKeY1vK*2ro%vtmo^$<4F zAH@KI?3!n$XYRlR?%0o?`856heLg&09K8u~cNAHtKW5p*J zFV3}KAB^x$zKo5Z<}C9<{2Td=jBPdZTiwW&5;vekM@OG;H;DT^FP}U=i6eT^xn4ow5mdldJ@IIOo2=&B`FZrD8Ig%^)~jJp#d*M$tEM2ryr5KHj zh}TB%XJXKXN6solE~;B;+eSCI6RD=y@P2eLxwV>Em~ zSr;>okLbT-(vEIbE9BUM!XG{KC-*S0IJpo1VlC#`O-@rU<|q`|P}*nX;eg<|-A_A& zi6!yOT*{^rnaGD}TZy~D(macU$0ghN#XF!kYd54R9(e?aS5q=$B2ZLd*OPa=21C~K z%r&+o%eLYt{z7TnR!VZVh%>Q9_vIwRw#RqXnWsv>JoaqH5(6~PHEY7i*=PJyr_l{x zR>}s`_#{`0d|rIw{9uz#o)&93d4I`8Hf`JBj~&ZCl=!3nvy5$}9NsIJsTbm84d00` zKBBvLF5-9mgW+QDIv6gc{lQ_8@e8?Nj&Aal10`dz5nu7@nHvlK-EIuY^g5n^}I4ZbfS)eD1 zU8-ty^Kx>NU6O^2WE(2TIx;U?B^Twp+P*1D0mRTt27rOD0 zb^^4m=ywr^zzDt@crs5f+g8eERI>d^dKNgc(D%WyB?a^A0gwF~c$+-LKf?;nMIMBv z@g4jj+lqY1wq7MR)3(hxWPG7#TQ>byTNGkQ4mOLH-sgC1h72=f$vsU8hI7*?(ajvq z1B0#gnNKr=TUl!#JalJ#jgpOp|4G<%S@GG`YT^%7wW^^i*^Ha|*@mI`&)i7IW-->0 zM^4YO!G+-TkWyFjk=C%dC1W9)T>gm)pT<_~R<#OUo7hHtPmHm@iF;y4H$y+Ugo8zN zY%4O6wfLdWT~v^xmtanm7@ZE9IvCy5p;A?=c@{!j*2Qy}JtcG{2C$$d zyJYMec~?m?nD>d5I1`J;Uq;A+Ejv^iJ(r~DoP)xa3Og}xTTKkrExTk}@ln;P4%P5t zAE!z^Ibxrj+;AAAJ_qlcQZKMa=Fst(Hp*Ov_K*RLm?iL>BuUIcR3zy3%*FGAOIo^n>?Z@<2O|C?`yzaK*9 zjTeZ>ePC~oFO1{MHo3mogFp1f{O3g>XHDorc5=5R3rxf*@u#WFZe**uz`HL!SBqbCNkC*cAqeKb9a( z$s$Qy*5XT1AQzhSgKp{)}JhnJ`;#%Y={u5s? zZ1AKG#trr&&yfex#1}warRZl-L@wjE{9Y+`8N(Z5M8E(3DTT{mVQfw~Ti8pld2`=*)sY1R#^+t=SKxcAzkj|Z3aJ}d$NyPw$21}Kixy{R6 z>e#joHV;2C67wWnpvIKz*o(i-2DlV_;Tbu^rZ3vIm9kMX{n)N9Y(p+Ngg|r`YrwQ^ z%i$Y;(W9T-*~5?-D=^#ik)I1(q)O*GdZT`uKZwoRpK(NOtGao%?wSoL?V0=16l_c_ zpNiTBC%&qBa?wxu@NG|=@7d&eMnC3RV-F*a#XM}i>^#j;EkGvL5ZzCSNE$y~@z*M9 z+pvBWlA>}W)AGpGjN7GxQp?fvsC?e=o%ROX3SJI^Y}yyNGk@!U)>+d~92&c^ zU99Wa$XtD}2fy>xdiJe_y&YL>ryfc>KB3VkhXolMwq=LFp8k`ne#Fq3A3hv*a!xyA z8|Mq07oV0>4^6%q!4F1dY=q7W`v)s%tGd Date: Mon, 27 Apr 2026 18:28:12 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9C=AC=E8=BD=AE?= =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @flywave/flywave-draco/src/draco-format.d.ts | 12 + @flywave/flywave-draco/src/draco-format.js | 14 + @flywave/flywave-draco/src/draco-loader.d.ts | 65 + @flywave/flywave-draco/src/draco-loader.js | 69 + @flywave/flywave-draco/src/draco-writer.d.ts | 46 + @flywave/flywave-draco/src/draco-writer.js | 56 + .../src/draco3d/draco3d-types.d.ts | 294 ++ .../src/draco3d/draco3d-types.js | 47 + @flywave/flywave-draco/src/index.d.ts | 6 + @flywave/flywave-draco/src/index.js | 6 + .../flywave-draco/src/libs/draco_encoder.d.ts | 5 + .../src/libs/draco_wasm_wrapper.d.ts | 5 + .../src/loader/draco-builder.d.ts | 93 + .../flywave-draco/src/loader/draco-builder.js | 352 ++ .../src/loader/draco-module-loader.d.ts | 18 + .../src/loader/draco-module-loader.js | 106 + .../src/loader/draco-parser.d.ts | 137 + .../flywave-draco/src/loader/draco-parser.js | 471 +++ .../flywave-draco/src/loader/draco-types.d.ts | 70 + .../flywave-draco/src/loader/draco-types.js | 3 + .../src/loader/utils/get-draco-schema.d.ts | 11 + .../src/loader/utils/get-draco-schema.js | 38 + .../src/loader/utils/version.d.ts | 1 + .../flywave-draco/src/loader/utils/version.js | 6 + @flywave/flywave-examples/codebrowser.d.ts | 1 + @flywave/flywave-examples/codebrowser.js.map | 1 + .../flywave-examples/decoder/decoder.d.ts | 1 + .../flywave-examples/decoder/decoder.js.map | 1 + .../flywave-examples/example-browser.d.ts | 11 + .../flywave-examples/example-browser.js.map | 1 + .../scripts/cesium-3dtile-downloader.d.ts | 1 + .../scripts/generate-example-index.d.ts | 1 + .../3dtiles-animation/PropertiesTable.d.ts | 6 + .../3dtiles-animation/PropertiesTable.js.map | 1 + .../src/3dtiles-animation/config.d.ts | 10 + .../src/3dtiles-animation/config.js.map | 1 + .../src/3dtiles-animation/index.d.ts | 1 + .../src/3dtiles-animation/index.js.map | 1 + .../3dtiles-gaussian-splatting/config.d.ts | 10 + .../3dtiles-gaussian-splatting/config.js.map | 1 + .../src/3dtiles-gaussian-splatting/index.d.ts | 1 + .../3dtiles-gaussian-splatting/index.js.map | 1 + .../src/3dtiles-terrain-overlay/config.d.ts | 10 + .../src/3dtiles-terrain-overlay/config.js.map | 1 + .../src/3dtiles-terrain-overlay/index.d.ts | 1 + .../src/3dtiles-terrain-overlay/index.js.map | 1 + .../src/comprehensive-map-app/config.d.ts | 11 + .../src/comprehensive-map-app/config.js.map | 1 + .../src/comprehensive-map-app/index.d.ts | 28 + .../src/comprehensive-map-app/index.js.map | 1 + .../src/depth-reading-pass/config.d.ts | 10 + .../src/depth-reading-pass/config.js.map | 1 + .../src/depth-reading-pass/index.d.ts | 1 + .../src/depth-reading-pass/index.js.map | 1 + .../src/example-categories.d.ts | 6 + .../src/example-categories.js.map | 1 + .../src/features-text-icons/config.d.ts | 10 + .../src/features-text-icons/config.js.map | 1 + .../src/features-text-icons/index.d.ts | 1 + .../src/features-text-icons/index.js.map | 1 + .../src/getting-started-3dtiles/config.d.ts | 10 + .../src/getting-started-3dtiles/config.js.map | 1 + .../src/getting-started-3dtiles/index.d.ts | 1 + .../src/getting-started-3dtiles/index.js.map | 1 + .../getting-started-basic-config/config.d.ts | 10 + .../config.js.map | 1 + .../getting-started-basic-config/index.d.ts | 1 + .../getting-started-basic-config/index.js.map | 1 + .../config.d.ts | 10 + .../config.js.map | 1 + .../index.d.ts | 1 + .../index.js.map | 1 + .../getting-started-dem-terrain/config.d.ts | 10 + .../getting-started-dem-terrain/config.js.map | 1 + .../getting-started-dem-terrain/index.d.ts | 1 + .../getting-started-dem-terrain/index.js.map | 1 + .../getting-started-planar-map/config.d.ts | 10 + .../getting-started-planar-map/config.js.map | 1 + .../src/getting-started-planar-map/index.d.ts | 1 + .../getting-started-planar-map/index.js.map | 1 + .../config.d.ts | 10 + .../config.js.map | 1 + .../index.d.ts | 1 + .../index.js.map | 1 + .../src/gltf-splat/index.d.ts | 1 + .../src/gltf-splat/index.js.map | 1 + .../src/post-processing-effects/config.d.ts | 10 + .../src/post-processing-effects/config.js.map | 1 + .../src/post-processing-effects/index.d.ts | 1 + .../src/post-processing-effects/index.js.map | 1 + .../src/real-world-country-garden/config.d.ts | 10 + .../real-world-country-garden/config.js.map | 1 + .../src/real-world-country-garden/index.d.ts | 1 + .../real-world-country-garden/index.js.map | 1 + .../PolygonMesh.d.ts | 15 + .../PolygonMesh.js.map | 1 + .../real-world-ecological-farming/config.d.ts | 10 + .../config.js.map | 1 + .../real-world-ecological-farming/index.d.ts | 1 + .../index.js.map | 1 + .../real-world-ecological-farming/water.d.ts | 39 + .../water.js.map | 1 + .../src/real-world-pipeline/config.d.ts | 10 + .../src/real-world-pipeline/config.js.map | 1 + .../src/real-world-pipeline/index.d.ts | 1 + .../src/real-world-pipeline/index.js.map | 1 + .../src/real-world-power/config.d.ts | 10 + .../src/real-world-power/config.js.map | 1 + .../src/real-world-power/index.d.ts | 1 + .../src/real-world-power/index.js.map | 1 + .../src/real-world-railway/config.d.ts | 10 + .../src/real-world-railway/config.js.map | 1 + .../src/real-world-railway/index.d.ts | 1 + .../src/real-world-railway/index.js.map | 1 + .../config.d.ts | 10 + .../config.js.map | 1 + .../terrain-elevation-modification/index.d.ts | 1 + .../index.js.map | 1 + .../src/test-frustum-geobox/index.d.ts | 1 + .../src/test-frustum-geobox/index.js.map | 1 + .../src/test-frustum-geobox/simple-test.d.ts | 37 + .../src/text-styling-dynamic/config.d.ts | 10 + .../src/text-styling-dynamic/config.js.map | 1 + .../src/text-styling-dynamic/index.d.ts | 6 + .../src/text-styling-dynamic/index.js.map | 1 + .../src/threejs-lighting/config.d.ts | 10 + .../src/threejs-lighting/config.js.map | 1 + .../src/threejs-lighting/index.d.ts | 1 + .../src/threejs-lighting/index.js.map | 1 + .../src/threejs-model-animation/config.d.ts | 10 + .../src/threejs-model-animation/config.js.map | 1 + .../src/threejs-model-animation/index.d.ts | 1 + .../src/threejs-model-animation/index.js.map | 1 + .../src/threejs-particle-system/config.d.ts | 10 + .../src/threejs-particle-system/config.js.map | 1 + .../src/threejs-particle-system/index.d.ts | 1 + .../src/threejs-particle-system/index.js.map | 1 + .../flywave-examples/src/token-config.d.ts | 5 + .../flywave-examples/src/token-config.js.map | 1 + @flywave/flywave-examples/webpack.config.d.ts | 3 + .../flywave-examples/webpack.config.js.map | 1 + @flywave/flywave-examples/webpack.config.ts | 241 +- @flywave/flywave-gltf/src/glb-loader.d.ts | 36 + @flywave/flywave-gltf/src/glb-writer.d.ts | 24 + @flywave/flywave-gltf/src/gltf-loader.d.ts | 48 + @flywave/flywave-gltf/src/gltf-writer.d.ts | 26 + .../src/gltf/api/gltf-extensions.d.ts | 33 + .../src/gltf/api/gltf-scenegraph.d.ts | 173 + .../flywave-gltf/src/gltf/api/gltf-three.d.ts | 13 + .../src/gltf/api/normalize-gltf-v1.d.ts | 1 + .../src/gltf/api/post-process-gltf.d.ts | 4 + .../src/gltf/encoders/encode-glb.d.ts | 15 + .../src/gltf/encoders/encode-gltf.d.ts | 21 + .../extensions/EXT_gaussian_splatting.d.ts | 7 + .../gltf/extensions/EXT_mesh_features.d.ts | 22 + .../extensions/EXT_mesh_gpu_instancing.d.ts | 27 + .../extensions/EXT_meshopt_compression.d.ts | 6 + .../extensions/EXT_structural_metadata.d.ts | 25 + .../src/gltf/extensions/EXT_texture_webp.d.ts | 11 + .../extensions/FLYWAVE_bim4d_metadata.d.ts | 86 + .../src/gltf/extensions/KHR_binary_gltf.d.ts | 6 + .../KHR_draco_mesh_compression.d.ts | 11 + .../extensions/KHR_mesh_quantization.d.ts | 6 + .../gltf/extensions/KHR_texture_basisu.d.ts | 11 + .../extensions/KHR_texture_transform.d.ts | 9 + .../deprecated/EXT_feature_metadata.d.ts | 6 + .../deprecated/KHR_lights_punctual.d.ts | 6 + .../deprecated/KHR_materials_unlit.d.ts | 6 + .../deprecated/KHR_techniques_webgl.d.ts | 6 + .../gltf/extensions/utils/3d-tiles-utils.d.ts | 73 + .../extensions/utils/spz-compression.d.ts | 101 + .../src/gltf/gltf-utils/get-typed-array.d.ts | 12 + .../gltf/gltf-utils/gltf-attribute-utils.d.ts | 10 + .../src/gltf/gltf-utils/gltf-constants.d.ts | 20 + .../src/gltf/gltf-utils/gltf-utils.d.ts | 16 + .../src/gltf/gltf-utils/resolve-url.d.ts | 1 + .../src/gltf/parsers/image-loader.d.ts | 27 + .../src/gltf/parsers/parse-glb.d.ts | 19 + .../src/gltf/parsers/parse-gltf.d.ts | 16 + .../src/gltf/types/glb-types.d.ts | 16 + .../gltf-ext-feature-metadata-schema.d.ts | 400 ++ .../types/gltf-ext-mesh-features-schema.d.ts | 44 + .../gltf-ext-structural-metadata-schema.d.ts | 316 ++ .../src/gltf/types/gltf-json-schema.d.ts | 740 ++++ .../gltf/types/gltf-postprocessed-schema.d.ts | 647 ++++ .../src/gltf/types/gltf-types.d.ts | 29 + .../flywave-gltf/src/gltf/utils/assert.d.ts | 1 + .../flywave-gltf/src/gltf/utils/version.d.ts | 1 + @flywave/flywave-gltf/src/index.d.ts | 20 + .../src/meshopt/meshopt-decoder.d.ts | 5 + @flywave/flywave-gltf/src/webp/webp.d.ts | 6 + @flywave/flywave-react/src/MapCanvas.d.ts | 19 + @flywave/flywave-react/src/MapCanvas.js | 143 + @flywave/flywave-react/src/MapCanvas.js.map | 1 + @flywave/flywave-react/src/MapContainer.d.ts | 21 + @flywave/flywave-react/src/MapContainer.js | 31 + .../flywave-react/src/MapContainer.js.map | 1 + @flywave/flywave-react/src/MapProvider.d.ts | 36 + @flywave/flywave-react/src/MapProvider.js | 168 + @flywave/flywave-react/src/MapProvider.js.map | 1 + .../flywave-react/src/hooks/advanced.d.ts | 53 + @flywave/flywave-react/src/hooks/advanced.js | 195 + .../flywave-react/src/hooks/advanced.js.map | 1 + @flywave/flywave-react/src/hooks/useMap.d.ts | 29 + @flywave/flywave-react/src/hooks/useMap.js | 34 + .../flywave-react/src/hooks/useMap.js.map | 1 + .../flywave-react/src/hooks/useMapEffect.d.ts | 33 + .../flywave-react/src/hooks/useMapEffect.js | 71 + .../src/hooks/useMapEffect.js.map | 1 + @flywave/flywave-react/src/index.d.ts | 5 + @flywave/flywave-react/src/index.js | 9 + @flywave/flywave-react/src/index.js.map | 1 + @flywave/flywave-react/src/types.d.ts | 107 + @flywave/flywave-react/src/types.js | 3 + @flywave/flywave-react/src/types.js.map | 1 + .../flywave-splats/src/SplatGeometry.d.ts | 4 + .../flywave-splats/src/SplatMaterial.d.ts | 20 + @flywave/flywave-splats/src/SplatMesh.d.ts | 182 + @flywave/flywave-splats/src/SplatShaders.d.ts | 3 + @flywave/flywave-splats/src/SplatSorter.d.ts | 18 + @flywave/flywave-splats/src/SplatTree.d.ts | 73 + @flywave/flywave-splats/src/Util.d.ts | 1 + @flywave/flywave-splats/src/index.d.ts | 4 + .../src/Constants.d.ts | 61 + .../src/ExclusionManager.d.ts | 62 + .../src/InnerElevationProvider.d.ts | 29 + .../src/ProjectionSwitchController.d.ts | 83 + .../src/ResourceProvider.d.ts | 165 + .../src/ResourceTileLoader.d.ts | 93 + .../src/TerrainDecoderWorker.d.ts | 95 + .../src/TerrainSource.d.ts | 284 ++ .../src/TileResourceManager.d.ts | 264 ++ .../src/WebImageryTileProvider.d.ts | 132 + .../src/dem-terrain/DEMTerrainSource.d.ts | 71 + .../src/dem-terrain/DEMTileMeshMaterial.d.ts | 130 + .../src/dem-terrain/DEMTileProvider.d.ts | 333 ++ .../src/dem-terrain/DEMTileTerrainMesh.d.ts | 130 + .../src/dem-terrain/ElevationProvider.d.ts | 144 + .../src/dem-terrain/ElevationRangeSource.d.ts | 89 + .../src/dem-terrain/Shader.d.ts | 1 + .../src/dem-terrain/TerrainTileLoader.d.ts | 52 + .../src/dem-terrain/TileFactory.d.ts | 30 + .../src/dem-terrain/TileWorkerDecoder.d.ts | 96 + .../src/dem-terrain/dem/DemData.d.ts | 147 + .../src/dem-terrain/dem/DemTree.d.ts | 28 + .../GroundModificationManager.d.ts | 449 +++ .../GroundModificationPolygon.d.ts | 167 + .../GroundPolygonSubdivisionModifier.d.ts | 50 + .../ground-modification-manager/index.d.ts | 2 + .../GroundOverlayTexture.d.ts | 109 + .../TileWorkerDecoder.d.ts | 21 + .../src/ground-overlay-provider/index.d.ts | 296 ++ .../flywave-terrain-datasource/src/index.d.ts | 4 + .../BaseQuantizedTerrainSource.d.ts | 163 + .../CesiumWorldTerrainSource.d.ts | 79 + .../quantized-terrain/ElevationProvider.d.ts | 125 + .../ElevationRangeSource.d.ts | 75 + .../QuantizedStratumSource.d.ts | 48 + .../QuantizedTerrainProvider.d.ts | 171 + .../QuantizedTerrainSource.d.ts | 70 + .../QuantizedTileResource.d.ts | 143 + .../quantized-terrain/TerrainTileLoader.d.ts | 80 + .../src/quantized-terrain/TileFactory.d.ts | 57 + .../quantized-terrain/TileWorkerDecoder.d.ts | 112 + .../src/quantized-terrain/index.d.ts | 3 + .../layer-strategy/LayerStrategy.d.ts | 441 +++ .../quantized-mesh/GeometryClipper.d.ts | 64 + .../quantized-mesh/QuantizedMesh.d.ts | 168 + .../quantized-mesh/QuantizedMeshCSG.d.ts | 9 + .../quantized-mesh/QuantizedMeshClipper.d.ts | 31 + .../quantized-mesh/QuantizedMeshLoader.d.ts | 42 + .../QuantizedMeshLoaderBase.d.ts | 45 + .../quantized-mesh/QuantizedTerrainMesh.d.ts | 67 + .../quantized-mesh/Shader.d.ts | 9 + .../quantized-mesh/index.d.ts | 34 + .../QuantizedStratumMesh.d.ts | 51 + .../QuantizedStratumResource.d.ts | 56 + .../decoder/Extensions.d.ts | 13 + .../decoder/Stratum.d.ts | 18 + .../decoder/Version.d.ts | 1 + .../quantized-stratum-mesh/decoder/index.d.ts | 2 + .../quantized-stratum-mesh/decoder/types.d.ts | 248 ++ .../quantized-stratum-mesh/index.d.ts | 5 + .../stratum-tile/Borehole.d.ts | 75 + .../stratum-tile/BspObject.d.ts | 23 + .../stratum-tile/CollapsePillar.d.ts | 123 + .../stratum-tile/CrossSectionUtils.d.ts | 86 + .../stratum-tile/FaultProfile.d.ts | 76 + .../stratum-tile/SectionLine.d.ts | 56 + .../stratum-tile/StratumCrossSections.d.ts | 43 + .../stratum-tile/StratumLayer.d.ts | 24 + .../stratum-tile/StratumMaterial.d.ts | 153 + .../stratum-tile/StratumTileCliper.d.ts | 52 + .../stratum-tile/StratumTileData.d.ts | 245 ++ .../stratum-tile/StratumVoxel.d.ts | 22 + .../stratum-tile/Texture.d.ts | 13 + .../stratum-tile/index.d.ts | 6 + .../src/terrain-processor/constants.d.ts | 32 + .../core/RenderEnvironment.d.ts | 25 + .../src/terrain-processor/core/types.d.ts | 33 + .../src/terrain-processor/index.d.ts | 4 + .../GroundModificationProcessor.d.ts | 162 + .../processors/GroundOverlayProcessor.d.ts | 75 + .../processors/HeightMapProcessor.d.ts | 59 + .../GroundModificationHeightShader.d.ts | 7 + .../shaders/HeightMapShader.d.ts | 10 + .../shaders/MaskedDistanceShader.d.ts | 4 + .../utils/coordinate-utils.d.ts | 21 + .../utils/geometry-utils.d.ts | 24 + .../utils/texture-utils.d.ts | 92 + .../test/stratum.d.ts | 1 + .../test/tin-terrain.d.ts | 1 + .../src/bspline/akima-curve3d.d.ts | 33 + .../src/bspline/bezier-curve-base.d.ts | 51 + .../bspline/bezier-curve3d-homogeneous.d.ts | 37 + .../src/bspline/bezier-curve3d.d.ts | 30 + .../flywave-topo/src/bspline/bezier1d-nd.d.ts | 34 + .../src/bspline/bspline-curve-ops.d.ts | 35 + .../src/bspline/bspline-curve.d.ts | 97 + .../bspline/bspline-curve3d-homogeneous.d.ts | 54 + .../src/bspline/bspline-surface.d.ts | 128 + .../src/bspline/bspline1d-nd.d.ts | 31 + .../src/bspline/interpolation-curve3d.d.ts | 75 + .../flywave-topo/src/bspline/knot-vector.d.ts | 48 + .../src/bspline/surface-location-detail.d.ts | 18 + .../alternating-convex-clip-tree.d.ts | 72 + .../src/clipping/boolean-clip-factory.d.ts | 11 + .../src/clipping/boolean-clip-node.d.ts | 51 + .../flywave-topo/src/clipping/clip-plane.d.ts | 76 + .../src/clipping/clip-primitive.d.ts | 101 + .../flywave-topo/src/clipping/clip-utils.d.ts | 78 + .../src/clipping/clip-vector.d.ts | 55 + .../src/clipping/convex-clip-plane-set.d.ts | 60 + .../line-string-offset-clipper-context.d.ts | 14 + .../union-of-convex-clip-plane-sets.d.ts | 45 + .../src/common/analysis-style.d.ts | 131 + .../src/common/base64-encoded-string.d.ts | 29 + .../src/common/color-by-name.d.ts | 158 + .../flywave-topo/src/common/color-def.d.ts | 258 ++ @flywave/flywave-topo/src/common/frustum.d.ts | 111 + .../src/common/geometry-class.d.ts | 6 + .../src/common/geometry/area-pattern.d.ts | 55 + .../src/common/geometry/bounding-sphere.d.ts | 9 + .../flywave-topo/src/common/gradient.d.ts | 136 + .../src/common/graphic-params.d.ts | 55 + .../flywave-topo/src/common/hidden-line.d.ts | 94 + .../flywave-topo/src/common/hsl-color.d.ts | 17 + .../flywave-topo/src/common/hsv-color.d.ts | 19 + @flywave/flywave-topo/src/common/image.d.ts | 83 + @flywave/flywave-topo/src/common/index.d.ts | 23 + .../flywave-topo/src/common/line-pixels.d.ts | 31 + .../src/common/oct-encoded-normal.d.ts | 31 + @flywave/flywave-topo/src/common/qpoint.d.ts | 494 +++ .../src/common/render-material.d.ts | 55 + .../src/common/render-texture.d.ts | 68 + @flywave/flywave-topo/src/common/render.d.ts | 78 + .../src/common/render/animation-node-id.d.ts | 3 + .../src/common/render/material-params.d.ts | 26 + .../render/primitives/aux-channel-table.d.ts | 53 + .../render/primitives/display-params.d.ts | 56 + .../common/render/primitives/edge-params.d.ts | 36 + .../common/render/primitives/mesh-params.d.ts | 11 + .../render/primitives/mesh-primitive.d.ts | 12 + .../primitives/point-string-params.d.ts | 7 + .../render/primitives/polyline-params.d.ts | 16 + .../render/primitives/surface-params.d.ts | 33 + .../render/primitives/vertex-indices.d.ts | 11 + .../primitives/vertex-table-splitter.d.ts | 43 + .../render/primitives/vertex-table.d.ts | 18 + .../src/common/render/texture-params.d.ts | 7 + .../flywave-topo/src/common/rgb-color.d.ts | 44 + .../src/common/texture-mapping.d.ts | 148 + .../src/common/texture-props.d.ts | 61 + .../src/common/thematic-display.d.ts | 227 ++ @flywave/flywave-topo/src/constant.d.ts | 22 + @flywave/flywave-topo/src/core-geometry.d.ts | 133 + @flywave/flywave-topo/src/curve/arc3d.d.ts | 481 +++ .../curve/construct-curve-between-curves.d.ts | 45 + .../src/curve/coordinate-xyz.d.ts | 50 + .../curve-chain-with-distance-index.d.ts | 324 ++ .../src/curve/curve-collection.d.ts | 241 ++ .../flywave-topo/src/curve/curve-curve.d.ts | 73 + .../src/curve/curve-extend-mode.d.ts | 46 + .../flywave-topo/src/curve/curve-factory.d.ts | 198 + .../src/curve/curve-location-detail.d.ts | 230 ++ .../flywave-topo/src/curve/curve-ops.d.ts | 76 + .../src/curve/curve-primitive.d.ts | 457 +++ .../src/curve/curve-processor.d.ts | 72 + .../flywave-topo/src/curve/curve-types.d.ts | 15 + .../src/curve/curve-wire-moments-xyz.d.ts | 24 + .../src/curve/geometry-query.d.ts | 95 + ...end-plane-intersection-stroke-handler.d.ts | 51 + .../internal/chain-collector-context.d.ts | 64 + .../curve/internal/clone-curves-context.d.ts | 19 + .../clone-with-expanded-line-strings.d.ts | 12 + .../closest-point-stroke-handler.d.ts | 39 + .../count-linear-parts-search-context.d.ts | 14 + .../curve-curve-close-approach-xy.d.ts | 223 ++ .../internal/curve-curve-intersect-xy.d.ts | 149 + .../internal/curve-curve-intersect-xyz.d.ts | 100 + .../curve/internal/curve-length-context.d.ts | 29 + .../internal/curve-offset-xy-handler.d.ts | 32 + .../curve/internal/gap-search-context.d.ts | 13 + .../curve/internal/multi-chain-collector.d.ts | 102 + .../newton-r-to-r-stroke-handler.d.ts | 17 + .../plane-altitude-range-context.d.ts | 63 + .../internal/polygon-offset-context.d.ts | 65 + .../curve/internal/sum-lengths-context.d.ts | 13 + .../internal/transform-in-place-context.d.ts | 15 + .../src/curve/line-segment3d.d.ts | 200 + .../flywave-topo/src/curve/line-string3d.d.ts | 458 +++ @flywave/flywave-topo/src/curve/loop.d.ts | 79 + .../src/curve/offset-options.d.ts | 93 + .../flywave-topo/src/curve/parity-region.d.ts | 55 + @flywave/flywave-topo/src/curve/path.d.ts | 42 + .../src/curve/point-string3d.d.ts | 74 + .../flywave-topo/src/curve/proxy-curve.d.ts | 63 + ...nsolidate-adjacent-primitives-context.d.ts | 22 + .../src/curve/query/curve-split-context.d.ts | 16 + .../src/curve/query/cylindrical-range.d.ts | 42 + .../src/curve/query/in-out-tests.d.ts | 31 + .../src/curve/query/planar-subdivision.d.ts | 34 + .../src/curve/query/stroke-count-chain.d.ts | 182 + .../src/curve/query/stroke-count-map.d.ts | 91 + .../src/curve/region-moments-xy.d.ts | 57 + .../region-ops-classification-sweeps.d.ts | 263 ++ .../flywave-topo/src/curve/region-ops.d.ts | 398 ++ .../australian-rail-corp-xy-evaluator.d.ts | 40 + .../src/curve/spiral/clothoid-series.d.ts | 65 + .../src/curve/spiral/cubic-evaluator.d.ts | 39 + .../curve/spiral/czech-spiral-evaluator.d.ts | 107 + .../direct-half-cosine-spiral-evaluator.d.ts | 38 + .../src/curve/spiral/direct-spiral3d.d.ts | 257 ++ .../src/curve/spiral/integrated-spiral3d.d.ts | 147 + .../mx-cubic-along-arc-spiral-evaluator.d.ts | 37 + .../curve/spiral/normalized-transition.d.ts | 135 + .../spiral/polish-cubic-spiral-evaluator.d.ts | 49 + .../transition-conditional-properties.d.ts | 52 + .../src/curve/spiral/transition-spiral3d.d.ts | 128 + .../src/curve/spiral/xy-curve-evaluator.d.ts | 79 + .../src/curve/stroke-options.d.ts | 116 + .../flywave-topo/src/curve/union-region.d.ts | 46 + @flywave/flywave-topo/src/geometry.d.ts | 702 ++++ .../src/geometry3d/angle-sweep.d.ts | 232 ++ .../flywave-topo/src/geometry3d/angle.d.ts | 258 ++ .../src/geometry3d/barycentric-triangle.d.ts | 284 ++ .../src/geometry3d/bilinear-patch.d.ts | 98 + .../geometry3d/coincident-geometry-ops.d.ts | 72 + .../src/geometry3d/ellipsoid.d.ts | 384 ++ .../src/geometry3d/frame-builder.d.ts | 111 + .../src/geometry3d/frustum-animation.d.ts | 58 + .../src/geometry3d/geometry-handler.d.ts | 329 ++ .../geometry3d/growable-blocked-array.d.ts | 96 + .../geometry3d/growable-float64-array.d.ts | 144 + .../src/geometry3d/growable-xy-array.d.ts | 248 ++ .../src/geometry3d/growable-xyz-array.d.ts | 329 ++ .../indexed-collection-interval.d.ts | 59 + .../src/geometry3d/indexed-xy-collection.d.ts | 80 + .../geometry3d/indexed-xyz-collection.d.ts | 202 + .../longitude-latitude-altitude.d.ts | 59 + .../flywave-topo/src/geometry3d/matrix3d.d.ts | 1215 ++++++ .../geometry3d/ordered-rotation-angles.d.ts | 115 + .../plane3d-by-origin-and-unit-normal.d.ts | 160 + .../plane3d-by-origin-and-vectors.d.ts | 173 + .../flywave-topo/src/geometry3d/plane3d.d.ts | 131 + .../src/geometry3d/point-helpers.d.ts | 282 ++ .../src/geometry3d/point-streaming.d.ts | 83 + .../src/geometry3d/point2d-array-carrier.d.ts | 79 + .../src/geometry3d/point2d-vector2d.d.ts | 269 ++ .../src/geometry3d/point3d-array-carrier.d.ts | 138 + .../src/geometry3d/point3d-vector3d.d.ts | 785 ++++ .../src/geometry3d/polygon-ops.d.ts | 433 +++ .../polyline-compression-by-edge-offset.d.ts | 80 + .../src/geometry3d/polyline-ops.d.ts | 84 + .../flywave-topo/src/geometry3d/range.d.ts | 646 ++++ .../flywave-topo/src/geometry3d/ray2d.d.ts | 68 + .../flywave-topo/src/geometry3d/ray3d.d.ts | 196 + .../src/geometry3d/reusable-object-cache.d.ts | 52 + .../src/geometry3d/segment1d.d.ts | 109 + .../src/geometry3d/sortable-polygon.d.ts | 46 + .../src/geometry3d/transform.d.ts | 383 ++ .../src/geometry3d/uv-surface-ops.d.ts | 39 + .../src/geometry3d/xyz-props.d.ts | 150 + .../src/geometry3d/yaw-pitch-roll-angles.d.ts | 130 + .../flywave-topo/src/geometry4d/map4d.d.ts | 75 + .../flywave-topo/src/geometry4d/matrix4d.d.ts | 280 ++ .../src/geometry4d/moment-data.d.ts | 179 + .../plane-by-origin-and-vectors4d.d.ts | 39 + .../flywave-topo/src/geometry4d/point4d.d.ts | 277 ++ .../src/numerics/banded-system.d.ts | 38 + .../src/numerics/bezier-polynomials.d.ts | 460 +++ .../src/numerics/clusterable-array.d.ts | 188 + .../flywave-topo/src/numerics/complex.d.ts | 59 + .../src/numerics/convex-polygon2d.d.ts | 43 + .../flywave-topo/src/numerics/newton.d.ts | 242 ++ .../src/numerics/pascal-coefficients.d.ts | 28 + .../flywave-topo/src/numerics/polar-data.d.ts | 41 + .../src/numerics/polynomials.d.ts | 664 ++++ .../flywave-topo/src/numerics/quadrature.d.ts | 87 + .../src/numerics/range1d-array.d.ts | 79 + .../src/numerics/tri-diagonal-system.d.ts | 50 + .../flywave-topo/src/numerics/union-find.d.ts | 48 + .../flywave-topo/src/numerics/usage-sums.d.ts | 85 + .../flywave-topo/src/polyface/aux-data.d.ts | 108 + .../src/polyface/box-topology.d.ts | 34 + .../src/polyface/facet-face-data.d.ts | 40 + .../src/polyface/facet-location-detail.d.ts | 262 ++ .../src/polyface/facet-orientation.d.ts | 38 + ...dy-triangulation-between-line-strings.d.ts | 57 + .../src/polyface/indexed-edge-matcher.d.ts | 83 + .../polyface/indexed-polyface-visitor.d.ts | 105 + .../build-average-normals-context.d.ts | 25 + ...dded-ragged-range2d-set-with-overflow.d.ts | 53 + .../multiclip/gridded-ragged-range2d-set.d.ts | 85 + .../linear-search-range2d-array.d.ts | 39 + .../multiclip/offset-mesh-context.d.ts | 198 + .../src/polyface/multiclip/range-search.d.ts | 23 + .../multiclip/range2d-search-interface.d.ts | 31 + .../sweep-line-string-to-facet-context.d.ts | 59 + .../polyface/multiclip/xy-point-buckets.d.ts | 69 + .../src/polyface/polyface-builder.d.ts | 474 +++ .../src/polyface/polyface-clip.d.ts | 180 + .../src/polyface/polyface-data.d.ts | 171 + .../src/polyface/polyface-query.d.ts | 572 +++ .../flywave-topo/src/polyface/polyface.d.ts | 255 ++ .../src/polyface/range-length-data.d.ts | 27 + .../src/polyface/tagged-numeric-data.d.ts | 91 + .../src/polyface/triangle-candidate.d.ts | 60 + .../src/primitives/color-map.d.ts | 12 + .../src/primitives/edge-params.d.ts | 3 + .../geometry/geometry-accumulator.d.ts | 59 + .../geometry/geometry-list-builder.d.ts | 40 + .../primitives/geometry/geometry-list.d.ts | 15 + .../geometry/geometry-primitives.d.ts | 65 + .../geometry/prepared-geometry.d.ts | 26 + .../src/primitives/mesh/mesh-builder-map.d.ts | 44 + .../src/primitives/mesh/mesh-builder.d.ts | 79 + .../src/primitives/mesh/mesh-primitives.d.ts | 94 + .../src/primitives/point-string-params.d.ts | 3 + .../flywave-topo/src/primitives/polyface.d.ts | 17 + .../src/primitives/polyline-params.d.ts | 8 + .../src/primitives/primitives.d.ts | 62 + .../flywave-topo/src/primitives/strokes.d.ts | 22 + .../src/primitives/vertex-key.d.ts | 26 + .../src/primitives/vertex-table-builder.d.ts | 23 + .../src/render/attribute-buffers.d.ts | 21 + .../flywave-topo/src/render/color-info.d.ts | 19 + .../src/render/create-texture-args.d.ts | 19 + .../src/render/edge-geometry.d.ts | 81 + .../flywave-topo/src/render/float-rgba.d.ts | 42 + .../src/render/graphic-builder.d.ts | 86 + .../src/render/graphic-primitive.d.ts | 59 + @flywave/flywave-topo/src/render/index.d.ts | 12 + .../src/render/indexed-edge-geometry.d.ts | 63 + .../flywave-topo/src/render/line-code.d.ts | 15 + .../flywave-topo/src/render/material.d.ts | 15 + .../flywave-topo/src/render/mesh-args.d.ts | 50 + .../flywave-topo/src/render/mesh-data.d.ts | 34 + .../src/render/mesh-geometry.d.ts | 108 + .../src/render/mesh-render-geometry.d.ts | 62 + .../flywave-topo/src/render/point-string.d.ts | 4 + .../src/render/pointstring-geometry.d.ts | 42 + .../src/render/polyline-args.d.ts | 25 + .../src/render/polyline-geometry.d.ts | 40 + .../src/render/render-geometry.d.ts | 8 + .../src/render/surface-geometry.d.ts | 31 + @flywave/flywave-topo/src/render/texture.d.ts | 27 + .../flywave-topo/src/render/vertex-lut.d.ts | 34 + .../src/serialization/bgfb-accessors.d.ts | 3422 +++++++++++++++++ .../src/serialization/bgfb-reader.d.ts | 117 + .../src/serialization/bgfb-writer.d.ts | 65 + .../src/serialization/deep-compare.d.ts | 36 + .../serialization/geometry-flat-buffer.d.ts | 19 + .../src/serialization/geometry-samples.d.ts | 670 ++++ .../src/serialization/json-schema.d.ts | 674 ++++ @flywave/flywave-topo/src/solid/box.d.ts | 118 + @flywave/flywave-topo/src/solid/cone.d.ts | 118 + .../flywave-topo/src/solid/linear-sweep.d.ts | 78 + .../src/solid/rotational-sweep.d.ts | 68 + .../flywave-topo/src/solid/ruled-sweep.d.ts | 76 + .../src/solid/solid-primitive.d.ts | 59 + @flywave/flywave-topo/src/solid/sphere.d.ts | 119 + .../flywave-topo/src/solid/sweep-contour.d.ts | 92 + .../flywave-topo/src/solid/torus-pipe.d.ts | 123 + .../src/topology/chain-merge.d.ts | 115 + @flywave/flywave-topo/src/topology/graph.d.ts | 740 ++++ ...edge-graph-from-indexed-loops-context.d.ts | 34 + .../src/topology/half-edge-graph-search.d.ts | 122 + .../half-edge-graph-spine-context.d.ts | 97 + .../topology/half-edge-graph-validation.d.ts | 48 + .../src/topology/half-edge-mark-set.d.ts | 228 ++ .../src/topology/half-edge-node-xyz-uv.d.ts | 49 + .../half-edge-point-in-graph-search.d.ts | 33 + .../topology/half-edge-position-detail.d.ts | 106 + .../topology/half-edge-priority-queue.d.ts | 30 + .../insert-and-retriangulate-context.d.ts | 34 + .../src/topology/mask-manager.d.ts | 29 + .../flywave-topo/src/topology/merging.d.ts | 151 + .../src/topology/regularize-face.d.ts | 102 + .../src/topology/signed-data-summary.d.ts | 33 + .../src/topology/space-triangulation.d.ts | 43 + .../src/topology/triangulation.d.ts | 235 ++ .../topology/xy-parity-search-context.d.ts | 50 + @flywave/flywave-topo/src/utils/assert.d.ts | 1 + @flywave/flywave-topo/src/utils/compare.d.ts | 10 + .../flywave-topo/src/utils/dictionary.d.ts | 122 + .../flywave-topo/src/utils/disposable.d.ts | 62 + .../flywave-topo/src/utils/id-string.d.ts | 282 ++ .../flywave-topo/src/utils/index-map.d.ts | 62 + @flywave/flywave-topo/src/utils/index.d.ts | 11 + .../flywave-topo/src/utils/json-utils.d.ts | 75 + .../src/utils/priority-queue.d.ts | 67 + .../flywave-topo/src/utils/sorted-array.d.ts | 233 ++ .../src/utils/typed-array-builder.d.ts | 152 + .../flywave-topo/src/utils/utility-types.d.ts | 119 + @flywave/flywave.gl/src/index.d.ts | 22 + docs/docusaurus.config.d.ts | 3 + docs/docusaurus.config.js | 179 + docs/docusaurus.config.js.map | 1 + docs/preview-build.d.ts | 2 + docs/scripts/doc-manager.d.ts | 2 + docs/sidebars.d.ts | 3 + docs/sidebars.js | 70 + docs/sidebars.js.map | 1 + docs/src/components/FlywaveGlobe.d.ts | 2 + docs/src/components/FlywaveGlobe.js | 148 + docs/src/components/FlywaveGlobe.js.map | 1 + docs/src/examples/index.d.ts | 2 + docs/src/examples/index.js | 88 + docs/src/examples/index.js.map | 1 + docs/src/pages/example-detail.d.ts | 13 + docs/src/pages/example-detail.js | 534 +++ docs/src/pages/example-detail.js.map | 1 + docs/src/pages/examples.d.ts | 2 + docs/src/pages/examples.js | 133 + docs/src/pages/examples.js.map | 1 + docs/src/pages/index.d.ts | 26 + docs/src/pages/index.js | 144 + docs/src/pages/index.js.map | 1 + docs/test-server.d.ts | 1 + karma.conf.d.ts | 2 + scripts/apidocs.d.ts | 1 + scripts/apidocs.js | 133 + scripts/apidocs.js.map | 1 + scripts/checkLicenses.d.ts | 13 + scripts/checkLicenses.js | 101 + scripts/checkLicenses.js.map | 1 + scripts/manage-devdeps.d.ts | 2 + scripts/prepare_doc_deploy.d.ts | 1 + scripts/prepare_doc_deploy.js | 55 + scripts/prepare_doc_deploy.js.map | 1 + test/ImportTest.d.ts | 1 + test/ImportTest.js | 186 + test/ImportTest.js.map | 1 + test/LicenseHeaderTest.d.ts | 1 + test/LicenseHeaderTest.js | 26 + test/LicenseHeaderTest.js.map | 1 + test/performance/LinesPerformanceTest.d.ts | 1 + test/performance/LinesPerformanceTest.js | 43 + test/performance/LinesPerformanceTest.js.map | 1 + .../OmvDecoderPerformanceTest.d.ts | 33 + test/performance/OmvDecoderPerformanceTest.js | 165 + .../OmvDecoderPerformanceTest.js.map | 1 + test/rendering/ClipPlanesRenderingTest.d.ts | 1 + test/rendering/ClipPlanesRenderingTest.js | 216 ++ test/rendering/ClipPlanesRenderingTest.js.map | 1 + test/rendering/GeoJsonDataRendering.d.ts | 1 + test/rendering/GeoJsonDataRendering.js | 928 +++++ test/rendering/GeoJsonDataRendering.js.map | 1 + test/rendering/GeoJsonFeaturesRendering.d.ts | 1 + test/rendering/GeoJsonFeaturesRendering.js | 290 ++ .../rendering/GeoJsonFeaturesRendering.js.map | 1 + test/rendering/ScreenSpaceRenderingTests.d.ts | 1 + test/rendering/ScreenSpaceRenderingTests.js | 373 ++ .../ScreenSpaceRenderingTests.js.map | 1 + test/rendering/StylingTest.d.ts | 1 + test/rendering/StylingTest.js | 948 +++++ test/rendering/StylingTest.js.map | 1 + test/rendering/WebTileDataRendering.d.ts | 1 + test/rendering/WebTileDataRendering.js | 288 ++ test/rendering/WebTileDataRendering.js.map | 1 + test/rendering/utils/GeoJsonStore.d.ts | 34 + test/rendering/utils/GeoJsonStore.js | 44 + test/rendering/utils/GeoJsonStore.js.map | 1 + test/rendering/utils/GeoJsonTest.d.ts | 28 + test/rendering/utils/GeoJsonTest.js | 75 + test/rendering/utils/GeoJsonTest.js.map | 1 + test/rendering/utils/ThemeBuilder.d.ts | 45 + test/rendering/utils/ThemeBuilder.js | 142 + test/rendering/utils/ThemeBuilder.js.map | 1 + 690 files changed, 57844 insertions(+), 46 deletions(-) create mode 100644 @flywave/flywave-draco/src/draco-format.d.ts create mode 100644 @flywave/flywave-draco/src/draco-format.js create mode 100644 @flywave/flywave-draco/src/draco-loader.d.ts create mode 100644 @flywave/flywave-draco/src/draco-loader.js create mode 100644 @flywave/flywave-draco/src/draco-writer.d.ts create mode 100644 @flywave/flywave-draco/src/draco-writer.js create mode 100644 @flywave/flywave-draco/src/draco3d/draco3d-types.d.ts create mode 100644 @flywave/flywave-draco/src/draco3d/draco3d-types.js create mode 100644 @flywave/flywave-draco/src/index.d.ts create mode 100644 @flywave/flywave-draco/src/index.js create mode 100644 @flywave/flywave-draco/src/libs/draco_encoder.d.ts create mode 100644 @flywave/flywave-draco/src/libs/draco_wasm_wrapper.d.ts create mode 100644 @flywave/flywave-draco/src/loader/draco-builder.d.ts create mode 100644 @flywave/flywave-draco/src/loader/draco-builder.js create mode 100644 @flywave/flywave-draco/src/loader/draco-module-loader.d.ts create mode 100644 @flywave/flywave-draco/src/loader/draco-module-loader.js create mode 100644 @flywave/flywave-draco/src/loader/draco-parser.d.ts create mode 100644 @flywave/flywave-draco/src/loader/draco-parser.js create mode 100644 @flywave/flywave-draco/src/loader/draco-types.d.ts create mode 100644 @flywave/flywave-draco/src/loader/draco-types.js create mode 100644 @flywave/flywave-draco/src/loader/utils/get-draco-schema.d.ts create mode 100644 @flywave/flywave-draco/src/loader/utils/get-draco-schema.js create mode 100644 @flywave/flywave-draco/src/loader/utils/version.d.ts create mode 100644 @flywave/flywave-draco/src/loader/utils/version.js create mode 100644 @flywave/flywave-examples/codebrowser.d.ts create mode 100644 @flywave/flywave-examples/codebrowser.js.map create mode 100644 @flywave/flywave-examples/decoder/decoder.d.ts create mode 100644 @flywave/flywave-examples/decoder/decoder.js.map create mode 100644 @flywave/flywave-examples/example-browser.d.ts create mode 100644 @flywave/flywave-examples/example-browser.js.map create mode 100644 @flywave/flywave-examples/scripts/cesium-3dtile-downloader.d.ts create mode 100644 @flywave/flywave-examples/scripts/generate-example-index.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-animation/PropertiesTable.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-animation/PropertiesTable.js.map create mode 100644 @flywave/flywave-examples/src/3dtiles-animation/config.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-animation/config.js.map create mode 100644 @flywave/flywave-examples/src/3dtiles-animation/index.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-animation/index.js.map create mode 100644 @flywave/flywave-examples/src/3dtiles-gaussian-splatting/config.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-gaussian-splatting/config.js.map create mode 100644 @flywave/flywave-examples/src/3dtiles-gaussian-splatting/index.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-gaussian-splatting/index.js.map create mode 100644 @flywave/flywave-examples/src/3dtiles-terrain-overlay/config.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-terrain-overlay/config.js.map create mode 100644 @flywave/flywave-examples/src/3dtiles-terrain-overlay/index.d.ts create mode 100644 @flywave/flywave-examples/src/3dtiles-terrain-overlay/index.js.map create mode 100644 @flywave/flywave-examples/src/comprehensive-map-app/config.d.ts create mode 100644 @flywave/flywave-examples/src/comprehensive-map-app/config.js.map create mode 100644 @flywave/flywave-examples/src/comprehensive-map-app/index.d.ts create mode 100644 @flywave/flywave-examples/src/comprehensive-map-app/index.js.map create mode 100644 @flywave/flywave-examples/src/depth-reading-pass/config.d.ts create mode 100644 @flywave/flywave-examples/src/depth-reading-pass/config.js.map create mode 100644 @flywave/flywave-examples/src/depth-reading-pass/index.d.ts create mode 100644 @flywave/flywave-examples/src/depth-reading-pass/index.js.map create mode 100644 @flywave/flywave-examples/src/example-categories.d.ts create mode 100644 @flywave/flywave-examples/src/example-categories.js.map create mode 100644 @flywave/flywave-examples/src/features-text-icons/config.d.ts create mode 100644 @flywave/flywave-examples/src/features-text-icons/config.js.map create mode 100644 @flywave/flywave-examples/src/features-text-icons/index.d.ts create mode 100644 @flywave/flywave-examples/src/features-text-icons/index.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-3dtiles/config.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-3dtiles/config.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-3dtiles/index.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-3dtiles/index.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-basic-config/config.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-basic-config/config.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-basic-config/index.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-basic-config/index.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-camera-animation/config.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-camera-animation/config.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-camera-animation/index.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-camera-animation/index.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-dem-terrain/config.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-dem-terrain/config.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-dem-terrain/index.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-dem-terrain/index.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-planar-map/config.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-planar-map/config.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-planar-map/index.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-planar-map/index.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-quantized-terrain/config.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-quantized-terrain/config.js.map create mode 100644 @flywave/flywave-examples/src/getting-started-quantized-terrain/index.d.ts create mode 100644 @flywave/flywave-examples/src/getting-started-quantized-terrain/index.js.map create mode 100644 @flywave/flywave-examples/src/gltf-splat/index.d.ts create mode 100644 @flywave/flywave-examples/src/gltf-splat/index.js.map create mode 100644 @flywave/flywave-examples/src/post-processing-effects/config.d.ts create mode 100644 @flywave/flywave-examples/src/post-processing-effects/config.js.map create mode 100644 @flywave/flywave-examples/src/post-processing-effects/index.d.ts create mode 100644 @flywave/flywave-examples/src/post-processing-effects/index.js.map create mode 100644 @flywave/flywave-examples/src/real-world-country-garden/config.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-country-garden/config.js.map create mode 100644 @flywave/flywave-examples/src/real-world-country-garden/index.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-country-garden/index.js.map create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/PolygonMesh.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/PolygonMesh.js.map create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/config.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/config.js.map create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/index.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/index.js.map create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/water.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-ecological-farming/water.js.map create mode 100644 @flywave/flywave-examples/src/real-world-pipeline/config.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-pipeline/config.js.map create mode 100644 @flywave/flywave-examples/src/real-world-pipeline/index.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-pipeline/index.js.map create mode 100644 @flywave/flywave-examples/src/real-world-power/config.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-power/config.js.map create mode 100644 @flywave/flywave-examples/src/real-world-power/index.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-power/index.js.map create mode 100644 @flywave/flywave-examples/src/real-world-railway/config.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-railway/config.js.map create mode 100644 @flywave/flywave-examples/src/real-world-railway/index.d.ts create mode 100644 @flywave/flywave-examples/src/real-world-railway/index.js.map create mode 100644 @flywave/flywave-examples/src/terrain-elevation-modification/config.d.ts create mode 100644 @flywave/flywave-examples/src/terrain-elevation-modification/config.js.map create mode 100644 @flywave/flywave-examples/src/terrain-elevation-modification/index.d.ts create mode 100644 @flywave/flywave-examples/src/terrain-elevation-modification/index.js.map create mode 100644 @flywave/flywave-examples/src/test-frustum-geobox/index.d.ts create mode 100644 @flywave/flywave-examples/src/test-frustum-geobox/index.js.map create mode 100644 @flywave/flywave-examples/src/test-frustum-geobox/simple-test.d.ts create mode 100644 @flywave/flywave-examples/src/text-styling-dynamic/config.d.ts create mode 100644 @flywave/flywave-examples/src/text-styling-dynamic/config.js.map create mode 100644 @flywave/flywave-examples/src/text-styling-dynamic/index.d.ts create mode 100644 @flywave/flywave-examples/src/text-styling-dynamic/index.js.map create mode 100644 @flywave/flywave-examples/src/threejs-lighting/config.d.ts create mode 100644 @flywave/flywave-examples/src/threejs-lighting/config.js.map create mode 100644 @flywave/flywave-examples/src/threejs-lighting/index.d.ts create mode 100644 @flywave/flywave-examples/src/threejs-lighting/index.js.map create mode 100644 @flywave/flywave-examples/src/threejs-model-animation/config.d.ts create mode 100644 @flywave/flywave-examples/src/threejs-model-animation/config.js.map create mode 100644 @flywave/flywave-examples/src/threejs-model-animation/index.d.ts create mode 100644 @flywave/flywave-examples/src/threejs-model-animation/index.js.map create mode 100644 @flywave/flywave-examples/src/threejs-particle-system/config.d.ts create mode 100644 @flywave/flywave-examples/src/threejs-particle-system/config.js.map create mode 100644 @flywave/flywave-examples/src/threejs-particle-system/index.d.ts create mode 100644 @flywave/flywave-examples/src/threejs-particle-system/index.js.map create mode 100644 @flywave/flywave-examples/src/token-config.d.ts create mode 100644 @flywave/flywave-examples/src/token-config.js.map create mode 100644 @flywave/flywave-examples/webpack.config.d.ts create mode 100644 @flywave/flywave-examples/webpack.config.js.map create mode 100644 @flywave/flywave-gltf/src/glb-loader.d.ts create mode 100644 @flywave/flywave-gltf/src/glb-writer.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf-loader.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf-writer.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/api/gltf-extensions.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/api/gltf-scenegraph.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/api/gltf-three.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/api/normalize-gltf-v1.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/api/post-process-gltf.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/encoders/encode-glb.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/encoders/encode-gltf.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/EXT_gaussian_splatting.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/EXT_mesh_features.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/EXT_mesh_gpu_instancing.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/EXT_meshopt_compression.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/EXT_structural_metadata.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/EXT_texture_webp.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/FLYWAVE_bim4d_metadata.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/KHR_binary_gltf.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/KHR_draco_mesh_compression.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/KHR_mesh_quantization.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/KHR_texture_basisu.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/KHR_texture_transform.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/deprecated/EXT_feature_metadata.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/deprecated/KHR_lights_punctual.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/deprecated/KHR_materials_unlit.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/deprecated/KHR_techniques_webgl.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/utils/3d-tiles-utils.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/extensions/utils/spz-compression.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/gltf-utils/get-typed-array.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/gltf-utils/gltf-attribute-utils.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/gltf-utils/gltf-constants.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/gltf-utils/gltf-utils.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/gltf-utils/resolve-url.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/parsers/image-loader.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/parsers/parse-glb.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/parsers/parse-gltf.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/types/glb-types.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/types/gltf-ext-feature-metadata-schema.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/types/gltf-ext-mesh-features-schema.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/types/gltf-ext-structural-metadata-schema.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/types/gltf-json-schema.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/types/gltf-postprocessed-schema.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/types/gltf-types.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/utils/assert.d.ts create mode 100644 @flywave/flywave-gltf/src/gltf/utils/version.d.ts create mode 100644 @flywave/flywave-gltf/src/index.d.ts create mode 100644 @flywave/flywave-gltf/src/meshopt/meshopt-decoder.d.ts create mode 100644 @flywave/flywave-gltf/src/webp/webp.d.ts create mode 100644 @flywave/flywave-react/src/MapCanvas.d.ts create mode 100644 @flywave/flywave-react/src/MapCanvas.js create mode 100644 @flywave/flywave-react/src/MapCanvas.js.map create mode 100644 @flywave/flywave-react/src/MapContainer.d.ts create mode 100644 @flywave/flywave-react/src/MapContainer.js create mode 100644 @flywave/flywave-react/src/MapContainer.js.map create mode 100644 @flywave/flywave-react/src/MapProvider.d.ts create mode 100644 @flywave/flywave-react/src/MapProvider.js create mode 100644 @flywave/flywave-react/src/MapProvider.js.map create mode 100644 @flywave/flywave-react/src/hooks/advanced.d.ts create mode 100644 @flywave/flywave-react/src/hooks/advanced.js create mode 100644 @flywave/flywave-react/src/hooks/advanced.js.map create mode 100644 @flywave/flywave-react/src/hooks/useMap.d.ts create mode 100644 @flywave/flywave-react/src/hooks/useMap.js create mode 100644 @flywave/flywave-react/src/hooks/useMap.js.map create mode 100644 @flywave/flywave-react/src/hooks/useMapEffect.d.ts create mode 100644 @flywave/flywave-react/src/hooks/useMapEffect.js create mode 100644 @flywave/flywave-react/src/hooks/useMapEffect.js.map create mode 100644 @flywave/flywave-react/src/index.d.ts create mode 100644 @flywave/flywave-react/src/index.js create mode 100644 @flywave/flywave-react/src/index.js.map create mode 100644 @flywave/flywave-react/src/types.d.ts create mode 100644 @flywave/flywave-react/src/types.js create mode 100644 @flywave/flywave-react/src/types.js.map create mode 100644 @flywave/flywave-splats/src/SplatGeometry.d.ts create mode 100644 @flywave/flywave-splats/src/SplatMaterial.d.ts create mode 100644 @flywave/flywave-splats/src/SplatMesh.d.ts create mode 100644 @flywave/flywave-splats/src/SplatShaders.d.ts create mode 100644 @flywave/flywave-splats/src/SplatSorter.d.ts create mode 100644 @flywave/flywave-splats/src/SplatTree.d.ts create mode 100644 @flywave/flywave-splats/src/Util.d.ts create mode 100644 @flywave/flywave-splats/src/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/Constants.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ExclusionManager.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/InnerElevationProvider.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ProjectionSwitchController.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ResourceProvider.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ResourceTileLoader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/TerrainDecoderWorker.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/TerrainSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/TileResourceManager.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/WebImageryTileProvider.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/DEMTerrainSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/DEMTileMeshMaterial.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/DEMTileProvider.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/DEMTileTerrainMesh.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/ElevationProvider.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/ElevationRangeSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/Shader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/TerrainTileLoader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/TileFactory.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/TileWorkerDecoder.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/dem/DemData.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/dem-terrain/dem/DemTree.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ground-modification-manager/GroundModificationManager.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ground-modification-manager/GroundModificationPolygon.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ground-modification-manager/GroundPolygonSubdivisionModifier.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ground-modification-manager/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ground-overlay-provider/GroundOverlayTexture.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ground-overlay-provider/TileWorkerDecoder.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/ground-overlay-provider/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/BaseQuantizedTerrainSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/CesiumWorldTerrainSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/ElevationProvider.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/ElevationRangeSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/QuantizedStratumSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/QuantizedTerrainProvider.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/QuantizedTerrainSource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/QuantizedTileResource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/TerrainTileLoader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/TileFactory.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/TileWorkerDecoder.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/layer-strategy/LayerStrategy.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/GeometryClipper.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/QuantizedMesh.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/QuantizedMeshCSG.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/QuantizedMeshClipper.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/QuantizedMeshLoader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/QuantizedMeshLoaderBase.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/QuantizedTerrainMesh.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/Shader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-mesh/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/QuantizedStratumMesh.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/QuantizedStratumResource.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/decoder/Extensions.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/decoder/Stratum.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/decoder/Version.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/decoder/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/decoder/types.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/Borehole.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/BspObject.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/CollapsePillar.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/CrossSectionUtils.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/FaultProfile.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/SectionLine.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/StratumCrossSections.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/StratumLayer.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/StratumMaterial.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/StratumTileCliper.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/StratumTileData.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/StratumVoxel.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/Texture.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/quantized-terrain/quantized-stratum-mesh/stratum-tile/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/constants.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/core/RenderEnvironment.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/core/types.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/index.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/processors/GroundModificationProcessor.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/processors/GroundOverlayProcessor.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/processors/HeightMapProcessor.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/shaders/GroundModificationHeightShader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/shaders/HeightMapShader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/shaders/MaskedDistanceShader.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/utils/coordinate-utils.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/utils/geometry-utils.d.ts create mode 100644 @flywave/flywave-terrain-datasource/src/terrain-processor/utils/texture-utils.d.ts create mode 100644 @flywave/flywave-terrain-datasource/test/stratum.d.ts create mode 100644 @flywave/flywave-terrain-datasource/test/tin-terrain.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/akima-curve3d.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bezier-curve-base.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bezier-curve3d-homogeneous.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bezier-curve3d.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bezier1d-nd.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bspline-curve-ops.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bspline-curve.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bspline-curve3d-homogeneous.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bspline-surface.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/bspline1d-nd.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/interpolation-curve3d.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/knot-vector.d.ts create mode 100644 @flywave/flywave-topo/src/bspline/surface-location-detail.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/alternating-convex-clip-tree.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/boolean-clip-factory.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/boolean-clip-node.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/clip-plane.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/clip-primitive.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/clip-utils.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/clip-vector.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/convex-clip-plane-set.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/internal/line-string-offset-clipper-context.d.ts create mode 100644 @flywave/flywave-topo/src/clipping/union-of-convex-clip-plane-sets.d.ts create mode 100644 @flywave/flywave-topo/src/common/analysis-style.d.ts create mode 100644 @flywave/flywave-topo/src/common/base64-encoded-string.d.ts create mode 100644 @flywave/flywave-topo/src/common/color-by-name.d.ts create mode 100644 @flywave/flywave-topo/src/common/color-def.d.ts create mode 100644 @flywave/flywave-topo/src/common/frustum.d.ts create mode 100644 @flywave/flywave-topo/src/common/geometry-class.d.ts create mode 100644 @flywave/flywave-topo/src/common/geometry/area-pattern.d.ts create mode 100644 @flywave/flywave-topo/src/common/geometry/bounding-sphere.d.ts create mode 100644 @flywave/flywave-topo/src/common/gradient.d.ts create mode 100644 @flywave/flywave-topo/src/common/graphic-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/hidden-line.d.ts create mode 100644 @flywave/flywave-topo/src/common/hsl-color.d.ts create mode 100644 @flywave/flywave-topo/src/common/hsv-color.d.ts create mode 100644 @flywave/flywave-topo/src/common/image.d.ts create mode 100644 @flywave/flywave-topo/src/common/index.d.ts create mode 100644 @flywave/flywave-topo/src/common/line-pixels.d.ts create mode 100644 @flywave/flywave-topo/src/common/oct-encoded-normal.d.ts create mode 100644 @flywave/flywave-topo/src/common/qpoint.d.ts create mode 100644 @flywave/flywave-topo/src/common/render-material.d.ts create mode 100644 @flywave/flywave-topo/src/common/render-texture.d.ts create mode 100644 @flywave/flywave-topo/src/common/render.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/animation-node-id.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/material-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/aux-channel-table.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/display-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/edge-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/mesh-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/mesh-primitive.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/point-string-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/polyline-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/surface-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/vertex-indices.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/vertex-table-splitter.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/primitives/vertex-table.d.ts create mode 100644 @flywave/flywave-topo/src/common/render/texture-params.d.ts create mode 100644 @flywave/flywave-topo/src/common/rgb-color.d.ts create mode 100644 @flywave/flywave-topo/src/common/texture-mapping.d.ts create mode 100644 @flywave/flywave-topo/src/common/texture-props.d.ts create mode 100644 @flywave/flywave-topo/src/common/thematic-display.d.ts create mode 100644 @flywave/flywave-topo/src/constant.d.ts create mode 100644 @flywave/flywave-topo/src/core-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/curve/arc3d.d.ts create mode 100644 @flywave/flywave-topo/src/curve/construct-curve-between-curves.d.ts create mode 100644 @flywave/flywave-topo/src/curve/coordinate-xyz.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-chain-with-distance-index.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-collection.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-curve.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-extend-mode.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-factory.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-location-detail.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-ops.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-primitive.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-processor.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-types.d.ts create mode 100644 @flywave/flywave-topo/src/curve/curve-wire-moments-xyz.d.ts create mode 100644 @flywave/flywave-topo/src/curve/geometry-query.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/append-plane-intersection-stroke-handler.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/chain-collector-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/clone-curves-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/clone-with-expanded-line-strings.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/closest-point-stroke-handler.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/count-linear-parts-search-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/curve-curve-close-approach-xy.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/curve-curve-intersect-xy.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/curve-curve-intersect-xyz.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/curve-length-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/curve-offset-xy-handler.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/gap-search-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/multi-chain-collector.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/newton-r-to-r-stroke-handler.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/plane-altitude-range-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/polygon-offset-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/sum-lengths-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/internal/transform-in-place-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/line-segment3d.d.ts create mode 100644 @flywave/flywave-topo/src/curve/line-string3d.d.ts create mode 100644 @flywave/flywave-topo/src/curve/loop.d.ts create mode 100644 @flywave/flywave-topo/src/curve/offset-options.d.ts create mode 100644 @flywave/flywave-topo/src/curve/parity-region.d.ts create mode 100644 @flywave/flywave-topo/src/curve/path.d.ts create mode 100644 @flywave/flywave-topo/src/curve/point-string3d.d.ts create mode 100644 @flywave/flywave-topo/src/curve/proxy-curve.d.ts create mode 100644 @flywave/flywave-topo/src/curve/query/consolidate-adjacent-primitives-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/query/curve-split-context.d.ts create mode 100644 @flywave/flywave-topo/src/curve/query/cylindrical-range.d.ts create mode 100644 @flywave/flywave-topo/src/curve/query/in-out-tests.d.ts create mode 100644 @flywave/flywave-topo/src/curve/query/planar-subdivision.d.ts create mode 100644 @flywave/flywave-topo/src/curve/query/stroke-count-chain.d.ts create mode 100644 @flywave/flywave-topo/src/curve/query/stroke-count-map.d.ts create mode 100644 @flywave/flywave-topo/src/curve/region-moments-xy.d.ts create mode 100644 @flywave/flywave-topo/src/curve/region-ops-classification-sweeps.d.ts create mode 100644 @flywave/flywave-topo/src/curve/region-ops.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/australian-rail-corp-xy-evaluator.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/clothoid-series.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/cubic-evaluator.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/czech-spiral-evaluator.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/direct-half-cosine-spiral-evaluator.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/direct-spiral3d.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/integrated-spiral3d.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/mx-cubic-along-arc-spiral-evaluator.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/normalized-transition.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/polish-cubic-spiral-evaluator.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/transition-conditional-properties.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/transition-spiral3d.d.ts create mode 100644 @flywave/flywave-topo/src/curve/spiral/xy-curve-evaluator.d.ts create mode 100644 @flywave/flywave-topo/src/curve/stroke-options.d.ts create mode 100644 @flywave/flywave-topo/src/curve/union-region.d.ts create mode 100644 @flywave/flywave-topo/src/geometry.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/angle-sweep.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/angle.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/barycentric-triangle.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/bilinear-patch.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/coincident-geometry-ops.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/ellipsoid.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/frame-builder.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/frustum-animation.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/geometry-handler.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/growable-blocked-array.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/growable-float64-array.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/growable-xy-array.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/growable-xyz-array.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/indexed-collection-interval.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/indexed-xy-collection.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/indexed-xyz-collection.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/longitude-latitude-altitude.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/matrix3d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/ordered-rotation-angles.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/plane3d-by-origin-and-unit-normal.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/plane3d-by-origin-and-vectors.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/plane3d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/point-helpers.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/point-streaming.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/point2d-array-carrier.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/point2d-vector2d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/point3d-array-carrier.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/point3d-vector3d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/polygon-ops.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/polyline-compression-by-edge-offset.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/polyline-ops.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/range.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/ray2d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/ray3d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/reusable-object-cache.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/segment1d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/sortable-polygon.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/transform.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/uv-surface-ops.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/xyz-props.d.ts create mode 100644 @flywave/flywave-topo/src/geometry3d/yaw-pitch-roll-angles.d.ts create mode 100644 @flywave/flywave-topo/src/geometry4d/map4d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry4d/matrix4d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry4d/moment-data.d.ts create mode 100644 @flywave/flywave-topo/src/geometry4d/plane-by-origin-and-vectors4d.d.ts create mode 100644 @flywave/flywave-topo/src/geometry4d/point4d.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/banded-system.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/bezier-polynomials.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/clusterable-array.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/complex.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/convex-polygon2d.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/newton.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/pascal-coefficients.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/polar-data.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/polynomials.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/quadrature.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/range1d-array.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/tri-diagonal-system.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/union-find.d.ts create mode 100644 @flywave/flywave-topo/src/numerics/usage-sums.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/aux-data.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/box-topology.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/facet-face-data.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/facet-location-detail.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/facet-orientation.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/greedy-triangulation-between-line-strings.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/indexed-edge-matcher.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/indexed-polyface-visitor.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/build-average-normals-context.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/gridded-ragged-range2d-set-with-overflow.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/gridded-ragged-range2d-set.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/linear-search-range2d-array.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/offset-mesh-context.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/range-search.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/range2d-search-interface.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/sweep-line-string-to-facet-context.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/multiclip/xy-point-buckets.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/polyface-builder.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/polyface-clip.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/polyface-data.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/polyface-query.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/polyface.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/range-length-data.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/tagged-numeric-data.d.ts create mode 100644 @flywave/flywave-topo/src/polyface/triangle-candidate.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/color-map.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/edge-params.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/geometry/geometry-accumulator.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/geometry/geometry-list-builder.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/geometry/geometry-list.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/geometry/geometry-primitives.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/geometry/prepared-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/mesh/mesh-builder-map.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/mesh/mesh-builder.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/mesh/mesh-primitives.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/point-string-params.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/polyface.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/polyline-params.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/primitives.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/strokes.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/vertex-key.d.ts create mode 100644 @flywave/flywave-topo/src/primitives/vertex-table-builder.d.ts create mode 100644 @flywave/flywave-topo/src/render/attribute-buffers.d.ts create mode 100644 @flywave/flywave-topo/src/render/color-info.d.ts create mode 100644 @flywave/flywave-topo/src/render/create-texture-args.d.ts create mode 100644 @flywave/flywave-topo/src/render/edge-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/float-rgba.d.ts create mode 100644 @flywave/flywave-topo/src/render/graphic-builder.d.ts create mode 100644 @flywave/flywave-topo/src/render/graphic-primitive.d.ts create mode 100644 @flywave/flywave-topo/src/render/index.d.ts create mode 100644 @flywave/flywave-topo/src/render/indexed-edge-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/line-code.d.ts create mode 100644 @flywave/flywave-topo/src/render/material.d.ts create mode 100644 @flywave/flywave-topo/src/render/mesh-args.d.ts create mode 100644 @flywave/flywave-topo/src/render/mesh-data.d.ts create mode 100644 @flywave/flywave-topo/src/render/mesh-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/mesh-render-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/point-string.d.ts create mode 100644 @flywave/flywave-topo/src/render/pointstring-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/polyline-args.d.ts create mode 100644 @flywave/flywave-topo/src/render/polyline-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/render-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/surface-geometry.d.ts create mode 100644 @flywave/flywave-topo/src/render/texture.d.ts create mode 100644 @flywave/flywave-topo/src/render/vertex-lut.d.ts create mode 100644 @flywave/flywave-topo/src/serialization/bgfb-accessors.d.ts create mode 100644 @flywave/flywave-topo/src/serialization/bgfb-reader.d.ts create mode 100644 @flywave/flywave-topo/src/serialization/bgfb-writer.d.ts create mode 100644 @flywave/flywave-topo/src/serialization/deep-compare.d.ts create mode 100644 @flywave/flywave-topo/src/serialization/geometry-flat-buffer.d.ts create mode 100644 @flywave/flywave-topo/src/serialization/geometry-samples.d.ts create mode 100644 @flywave/flywave-topo/src/serialization/json-schema.d.ts create mode 100644 @flywave/flywave-topo/src/solid/box.d.ts create mode 100644 @flywave/flywave-topo/src/solid/cone.d.ts create mode 100644 @flywave/flywave-topo/src/solid/linear-sweep.d.ts create mode 100644 @flywave/flywave-topo/src/solid/rotational-sweep.d.ts create mode 100644 @flywave/flywave-topo/src/solid/ruled-sweep.d.ts create mode 100644 @flywave/flywave-topo/src/solid/solid-primitive.d.ts create mode 100644 @flywave/flywave-topo/src/solid/sphere.d.ts create mode 100644 @flywave/flywave-topo/src/solid/sweep-contour.d.ts create mode 100644 @flywave/flywave-topo/src/solid/torus-pipe.d.ts create mode 100644 @flywave/flywave-topo/src/topology/chain-merge.d.ts create mode 100644 @flywave/flywave-topo/src/topology/graph.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-graph-from-indexed-loops-context.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-graph-search.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-graph-spine-context.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-graph-validation.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-mark-set.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-node-xyz-uv.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-point-in-graph-search.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-position-detail.d.ts create mode 100644 @flywave/flywave-topo/src/topology/half-edge-priority-queue.d.ts create mode 100644 @flywave/flywave-topo/src/topology/insert-and-retriangulate-context.d.ts create mode 100644 @flywave/flywave-topo/src/topology/mask-manager.d.ts create mode 100644 @flywave/flywave-topo/src/topology/merging.d.ts create mode 100644 @flywave/flywave-topo/src/topology/regularize-face.d.ts create mode 100644 @flywave/flywave-topo/src/topology/signed-data-summary.d.ts create mode 100644 @flywave/flywave-topo/src/topology/space-triangulation.d.ts create mode 100644 @flywave/flywave-topo/src/topology/triangulation.d.ts create mode 100644 @flywave/flywave-topo/src/topology/xy-parity-search-context.d.ts create mode 100644 @flywave/flywave-topo/src/utils/assert.d.ts create mode 100644 @flywave/flywave-topo/src/utils/compare.d.ts create mode 100644 @flywave/flywave-topo/src/utils/dictionary.d.ts create mode 100644 @flywave/flywave-topo/src/utils/disposable.d.ts create mode 100644 @flywave/flywave-topo/src/utils/id-string.d.ts create mode 100644 @flywave/flywave-topo/src/utils/index-map.d.ts create mode 100644 @flywave/flywave-topo/src/utils/index.d.ts create mode 100644 @flywave/flywave-topo/src/utils/json-utils.d.ts create mode 100644 @flywave/flywave-topo/src/utils/priority-queue.d.ts create mode 100644 @flywave/flywave-topo/src/utils/sorted-array.d.ts create mode 100644 @flywave/flywave-topo/src/utils/typed-array-builder.d.ts create mode 100644 @flywave/flywave-topo/src/utils/utility-types.d.ts create mode 100644 @flywave/flywave.gl/src/index.d.ts create mode 100644 docs/docusaurus.config.d.ts create mode 100644 docs/docusaurus.config.js create mode 100644 docs/docusaurus.config.js.map create mode 100644 docs/preview-build.d.ts create mode 100644 docs/scripts/doc-manager.d.ts create mode 100644 docs/sidebars.d.ts create mode 100644 docs/sidebars.js create mode 100644 docs/sidebars.js.map create mode 100644 docs/src/components/FlywaveGlobe.d.ts create mode 100644 docs/src/components/FlywaveGlobe.js create mode 100644 docs/src/components/FlywaveGlobe.js.map create mode 100644 docs/src/examples/index.d.ts create mode 100644 docs/src/examples/index.js create mode 100644 docs/src/examples/index.js.map create mode 100644 docs/src/pages/example-detail.d.ts create mode 100644 docs/src/pages/example-detail.js create mode 100644 docs/src/pages/example-detail.js.map create mode 100644 docs/src/pages/examples.d.ts create mode 100644 docs/src/pages/examples.js create mode 100644 docs/src/pages/examples.js.map create mode 100644 docs/src/pages/index.d.ts create mode 100644 docs/src/pages/index.js create mode 100644 docs/src/pages/index.js.map create mode 100644 docs/test-server.d.ts create mode 100644 karma.conf.d.ts create mode 100644 scripts/apidocs.d.ts create mode 100644 scripts/apidocs.js create mode 100644 scripts/apidocs.js.map create mode 100644 scripts/checkLicenses.d.ts create mode 100644 scripts/checkLicenses.js create mode 100644 scripts/checkLicenses.js.map create mode 100644 scripts/manage-devdeps.d.ts create mode 100644 scripts/prepare_doc_deploy.d.ts create mode 100644 scripts/prepare_doc_deploy.js create mode 100644 scripts/prepare_doc_deploy.js.map create mode 100644 test/ImportTest.d.ts create mode 100644 test/ImportTest.js create mode 100644 test/ImportTest.js.map create mode 100644 test/LicenseHeaderTest.d.ts create mode 100644 test/LicenseHeaderTest.js create mode 100644 test/LicenseHeaderTest.js.map create mode 100644 test/performance/LinesPerformanceTest.d.ts create mode 100644 test/performance/LinesPerformanceTest.js create mode 100644 test/performance/LinesPerformanceTest.js.map create mode 100644 test/performance/OmvDecoderPerformanceTest.d.ts create mode 100644 test/performance/OmvDecoderPerformanceTest.js create mode 100644 test/performance/OmvDecoderPerformanceTest.js.map create mode 100644 test/rendering/ClipPlanesRenderingTest.d.ts create mode 100644 test/rendering/ClipPlanesRenderingTest.js create mode 100644 test/rendering/ClipPlanesRenderingTest.js.map create mode 100644 test/rendering/GeoJsonDataRendering.d.ts create mode 100644 test/rendering/GeoJsonDataRendering.js create mode 100644 test/rendering/GeoJsonDataRendering.js.map create mode 100644 test/rendering/GeoJsonFeaturesRendering.d.ts create mode 100644 test/rendering/GeoJsonFeaturesRendering.js create mode 100644 test/rendering/GeoJsonFeaturesRendering.js.map create mode 100644 test/rendering/ScreenSpaceRenderingTests.d.ts create mode 100644 test/rendering/ScreenSpaceRenderingTests.js create mode 100644 test/rendering/ScreenSpaceRenderingTests.js.map create mode 100644 test/rendering/StylingTest.d.ts create mode 100644 test/rendering/StylingTest.js create mode 100644 test/rendering/StylingTest.js.map create mode 100644 test/rendering/WebTileDataRendering.d.ts create mode 100644 test/rendering/WebTileDataRendering.js create mode 100644 test/rendering/WebTileDataRendering.js.map create mode 100644 test/rendering/utils/GeoJsonStore.d.ts create mode 100644 test/rendering/utils/GeoJsonStore.js create mode 100644 test/rendering/utils/GeoJsonStore.js.map create mode 100644 test/rendering/utils/GeoJsonTest.d.ts create mode 100644 test/rendering/utils/GeoJsonTest.js create mode 100644 test/rendering/utils/GeoJsonTest.js.map create mode 100644 test/rendering/utils/ThemeBuilder.d.ts create mode 100644 test/rendering/utils/ThemeBuilder.js create mode 100644 test/rendering/utils/ThemeBuilder.js.map diff --git a/@flywave/flywave-draco/src/draco-format.d.ts b/@flywave/flywave-draco/src/draco-format.d.ts new file mode 100644 index 0000000..7be5add --- /dev/null +++ b/@flywave/flywave-draco/src/draco-format.d.ts @@ -0,0 +1,12 @@ +/** + * Draco3D compressed geometries + */ +export declare const DracoFormat: { + readonly name: "Draco"; + readonly id: "draco"; + readonly module: "draco"; + readonly extensions: readonly ["drc"]; + readonly mimeTypes: readonly ["application/octet-stream"]; + readonly binary: true; + readonly tests: readonly ["DRACO"]; +}; diff --git a/@flywave/flywave-draco/src/draco-format.js b/@flywave/flywave-draco/src/draco-format.js new file mode 100644 index 0000000..fc2e419 --- /dev/null +++ b/@flywave/flywave-draco/src/draco-format.js @@ -0,0 +1,14 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +/** + * Draco3D compressed geometries + */ +export const DracoFormat = { + name: "Draco", + id: "draco", + module: "draco", + extensions: ["drc"], + mimeTypes: ["application/octet-stream"], + binary: true, + tests: ["DRACO"] +}; +//# sourceMappingURL=draco-format.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/draco-loader.d.ts b/@flywave/flywave-draco/src/draco-loader.d.ts new file mode 100644 index 0000000..1a5904c --- /dev/null +++ b/@flywave/flywave-draco/src/draco-loader.d.ts @@ -0,0 +1,65 @@ +import type { DracoParseOptions } from "./loader/draco-parser"; +import type { DracoMesh } from "./loader/draco-types"; +export interface DracoLoaderOptions { + headers?: Record; + draco?: DracoParseOptions & { + /** @deprecated WASM decoding is faster but JS is more backwards compatible */ + decoderType?: "wasm" | "js"; + /** @deprecated Specify where to load the Draco decoder library */ + libraryPath?: string; + /** Override the URL to the worker bundle (by default loads from unpkg.com) */ + workerUrl?: string; + }; +} +/** + * Worker loader for Draco3D compressed geometries + */ +export declare const DracoWorkerLoader: { + readonly dataType: DracoMesh; + readonly batchType: never; + readonly name: "Draco"; + readonly id: "draco"; + readonly module: "draco"; + readonly version: any; + readonly worker: true; + readonly extensions: readonly ["drc"]; + readonly mimeTypes: readonly ["application/octet-stream"]; + readonly binary: true; + readonly tests: readonly ["DRACO"]; + readonly options: { + readonly draco: { + readonly decoderType: "wasm" | "js"; + readonly libraryPath: "libs/"; + readonly extraAttributes: {}; + readonly attributeNameEntry: any; + }; + }; +}; +/** + * Loader for Draco3D compressed geometries + */ +export declare const DracoLoader: { + readonly parse: typeof parse; + readonly dataType: DracoMesh; + readonly batchType: never; + readonly name: "Draco"; + readonly id: "draco"; + readonly module: "draco"; + readonly version: any; + readonly worker: true; + readonly extensions: readonly ["drc"]; + readonly mimeTypes: readonly ["application/octet-stream"]; + readonly binary: true; + readonly tests: readonly ["DRACO"]; + readonly options: { + readonly draco: { + readonly decoderType: "wasm" | "js"; + readonly libraryPath: "libs/"; + readonly extraAttributes: {}; + readonly attributeNameEntry: any; + }; + }; +}; +declare function parse(arrayBuffer: ArrayBuffer, options?: DracoLoaderOptions, context?: any): Promise; +export declare function loadDraco(url: string, loader: typeof DracoLoader, options?: DracoLoaderOptions, context?: any): Promise; +export {}; diff --git a/@flywave/flywave-draco/src/draco-loader.js b/@flywave/flywave-draco/src/draco-loader.js new file mode 100644 index 0000000..0393bca --- /dev/null +++ b/@flywave/flywave-draco/src/draco-loader.js @@ -0,0 +1,69 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { loadDracoDecoderModule } from "./loader/draco-module-loader"; +import DracoParser from "./loader/draco-parser"; +import { VERSION } from "./loader/utils/version"; +/** + * Worker loader for Draco3D compressed geometries + */ +export const DracoWorkerLoader = { + dataType: null, + batchType: null, + name: "Draco", + id: "draco", + module: "draco", + // shapes: ['mesh'], + version: VERSION, + worker: true, + extensions: ["drc"], + mimeTypes: ["application/octet-stream"], + binary: true, + tests: ["DRACO"], + options: { + draco: { + decoderType: typeof WebAssembly === "object" ? "wasm" : "js", // 'js' for IE11 + libraryPath: "libs/", + extraAttributes: {}, + attributeNameEntry: undefined + } + } +}; +/** + * Loader for Draco3D compressed geometries + */ +export const DracoLoader = { + ...DracoWorkerLoader, + parse +}; +async function parse(arrayBuffer, options, context) { + const { draco } = await loadDracoDecoderModule(options); + const dracoParser = new DracoParser(draco); + try { + return dracoParser.parseSync(arrayBuffer, options?.draco); + } + finally { + dracoParser.destroy(); + } +} +export async function loadDraco(url, loader, options, context) { + const fetchFn = context?.fetch || globalThis.fetch; + if (!fetchFn) { + throw new Error("Fetch function is required to load subtree"); + } + try { + // 1. Get subtree file + const response = await fetchFn(url, { + headers: options.headers + }); + if (!response.ok) { + throw new Error(`Failed to fetch subtree: ${response.status} ${response.statusText}`); + } + // 2. Read binary data + const arrayBuffer = await response.arrayBuffer(); + // 3. Parse data using loader + return await loader.parse(arrayBuffer, options, context); + } + catch (error) { + throw new Error(`Subtree loading failed: ${error.message}`); + } +} +//# sourceMappingURL=draco-loader.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/draco-writer.d.ts b/@flywave/flywave-draco/src/draco-writer.d.ts new file mode 100644 index 0000000..66ba2ca --- /dev/null +++ b/@flywave/flywave-draco/src/draco-writer.d.ts @@ -0,0 +1,46 @@ +import type { DracoBuildOptions } from "./loader/draco-builder"; +import type { DracoMesh } from "./loader/draco-types"; +/** Writer Options for draco */ +export interface DracoWriterOptions { + draco?: DracoBuildOptions & { + method?: "MESH_EDGEBREAKER_ENCODING" | "MESH_SEQUENTIAL_ENCODING"; + speed?: [number, number]; + quantization?: Record; + attributeNameEntry?: string; + }; +} +/** + * Browser worker doesn't work because of issue during "draco_encoder.js" loading. + * Refused to execute script from 'https://raw.githubusercontent.com/google/draco/1.4.1/javascript/draco_encoder.js' because its MIME type ('') is not executable. + */ +export declare const DracoWriterWorker: { + id: string; + name: string; + module: string; + version: any; + worker: boolean; + options: { + draco: {}; + source: any; + }; +}; +/** + * Exporter for Draco3D compressed geometries + */ +export declare const DracoWriter: { + readonly name: "DRACO"; + readonly id: "draco"; + readonly module: "draco"; + readonly version: any; + readonly extensions: readonly ["drc"]; + readonly mimeTypes: readonly ["application/octet-stream"]; + readonly options: { + readonly draco: { + pointcloud: boolean; + attributeNameEntry: string; + }; + }; + readonly encode: typeof encode; +}; +declare function encode(data: DracoMesh, options?: DracoWriterOptions): Promise; +export {}; diff --git a/@flywave/flywave-draco/src/draco-writer.js b/@flywave/flywave-draco/src/draco-writer.js new file mode 100644 index 0000000..799fba3 --- /dev/null +++ b/@flywave/flywave-draco/src/draco-writer.js @@ -0,0 +1,56 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import DRACOBuilder from "./loader/draco-builder"; +import { loadDracoEncoderModule } from "./loader/draco-module-loader"; +import { VERSION } from "./loader/utils/version"; +const DEFAULT_DRACO_WRITER_OPTIONS = { + pointcloud: false, // Set to true if pointcloud (mode: 0, no indices) + attributeNameEntry: "name" + // Draco Compression Parameters + // method: 'MESH_EDGEBREAKER_ENCODING', // Use draco defaults + // speed: [5, 5], // Use draco defaults + // quantization: { // Use draco defaults + // POSITION: 10 + // } +}; +/** + * Browser worker doesn't work because of issue during "draco_encoder.js" loading. + * Refused to execute script from 'https://raw.githubusercontent.com/google/draco/1.4.1/javascript/draco_encoder.js' because its MIME type ('') is not executable. + */ +export const DracoWriterWorker = { + id: "draco-writer", + name: "Draco compressed geometry writer", + module: "draco", + version: VERSION, + worker: true, + options: { + draco: {}, + source: null + } +}; +/** + * Exporter for Draco3D compressed geometries + */ +export const DracoWriter = { + name: "DRACO", + id: "draco", + module: "draco", + version: VERSION, + extensions: ["drc"], + mimeTypes: ["application/octet-stream"], + options: { + draco: DEFAULT_DRACO_WRITER_OPTIONS + }, + encode +}; +async function encode(data, options = {}) { + // Dynamically load draco + const { draco } = await loadDracoEncoderModule(options); + const dracoBuilder = new DRACOBuilder(draco); + try { + return dracoBuilder.encodeSync(data, options.draco); + } + finally { + dracoBuilder.destroy(); + } +} +//# sourceMappingURL=draco-writer.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/draco3d/draco3d-types.d.ts b/@flywave/flywave-draco/src/draco3d/draco3d-types.d.ts new file mode 100644 index 0000000..352580d --- /dev/null +++ b/@flywave/flywave-draco/src/draco3d/draco3d-types.d.ts @@ -0,0 +1,294 @@ +/** Draco3D untyped memory pointer */ +type VoidPtr = any; +/** Draco3D geometry attribute type */ +export declare enum draco_GeometryAttribute_Type { + "draco_GeometryAttribute::INVALID" = 0, + "draco_GeometryAttribute::POSITION" = 1, + "draco_GeometryAttribute::NORMAL" = 2, + "draco_GeometryAttribute::COLOR" = 3, + "draco_GeometryAttribute::TEX_COORD" = 4, + "draco_GeometryAttribute::GENERIC" = 5 +} +/** Draco3D encoded geometry type */ +export declare enum draco_EncodedGeometryType { + "draco::INVALID_GEOMETRY_TYPE" = 0, + "draco::POINT_CLOUD" = 1, + "draco::TRIANGULAR_MESH" = 2 +} +/** Draco3D data type */ +export declare enum draco_DataType { + "draco::DT_INVALID" = 0, + "draco::DT_INT8" = 1, + "draco::DT_UINT8" = 2, + "draco::DT_INT16" = 3, + "draco::DT_UINT16" = 4, + "draco::DT_INT32" = 5, + "draco::DT_UINT32" = 6, + "draco::DT_INT64" = 7, + "draco::DT_UINT64" = 8, + "draco::DT_FLOAT32" = 9, + "draco::DT_FLOAT64" = 10, + "draco::DT_BOOL" = 11, + "draco::DT_TYPES_COUNT" = 12 +} +/** Draco3D status code */ +export declare enum draco_StatusCode { + "draco_Status::OK" = 0, + "draco_Status::DRACO_ERROR" = 1, + "draco_Status::IO_ERROR" = 2, + "draco_Status::INVALID_PARAMETER" = 3, + "draco_Status::UNSUPPORTED_VERSION" = 4, + "draco_Status::UNKNOWN_VERSION" = 5 +} +/** Draco3D decoder buffer allocated on emscripten heap */ +export declare class DecoderBuffer { + constructor(); + Init(data: Int8Array, data_size: number): void; +} +/** Draco3D attribute transform data */ +export declare class AttributeTransformData { + constructor(); + transform_type(): number; +} +/** Draco3D geometry attribute */ +export declare class GeometryAttribute { + constructor(); +} +/** Draco3D point attribute */ +export declare class PointAttribute { + ptr: VoidPtr; + constructor(); + size(): number; + GetAttributeTransformData(): AttributeTransformData; + attribute_type(): number; + data_type(): number; + num_components(): number; + normalized(): boolean; + byte_stride(): number; + byte_offset(): number; + unique_id(): number; +} +/** Draco3D attribute transform */ +export declare class AttributeQuantizationTransform { + constructor(); + InitFromAttribute(att: PointAttribute): boolean; + quantization_bits(): number; + min_value(axis: number): number; + range(): number; +} +/** Draco3D attribute transform */ +export declare class AttributeOctahedronTransform { + constructor(); + InitFromAttribute(att: PointAttribute): boolean; + quantization_bits(): number; +} +/** Draco3D point cloud */ +export declare class PointCloud { + ptr: VoidPtr; + constructor(); + num_attributes(): number; + num_points(): number; +} +/** Draco3D mesh */ +export declare class Mesh extends PointCloud { + constructor(); + num_faces(): number; +} +/** Draco3D metadata */ +export declare class Metadata { + ptr: VoidPtr; + constructor(); +} +/** Draco3D status */ +export declare class Status { + constructor(); + code(): draco_StatusCode; + ok(): boolean; + error_msg(): string; +} +/** Draco3D Float32Array allocated on the emscripten heap */ +export declare class DracoFloat32Array { + constructor(); + GetValue(index: number): number; + size(): number; +} +/** Draco3D Int8Array allocated on the emscripten heap */ +export declare class DracoInt8Array { + constructor(); + GetValue(index: number): number; + size(): number; +} +/** Draco3D Uint8Array allocated on the emscripten heap */ +export declare class DracoUInt8Array { + GetValue(index: number): number; + size(): number; +} +/** Draco3D Int16Array allocated on the emscripten heap */ +export declare class DracoInt16Array { + constructor(); + GetValue(index: number): number; + size(): number; +} +/** Draco3D Uint16Array allocated on the emscripten heap */ +export declare class DracoUInt16Array { + constructor(); + GetValue(index: number): number; + size(): number; +} +/** Draco3D Int32Array allocated on the emscripten heap */ +export declare class DracoInt32Array { + constructor(); + GetValue(index: number): number; + size(): number; +} +/** Draco3D Uint32Array allocated on the emscripten heap */ +export declare class DracoUInt32Array { + constructor(); + GetValue(index: number): number; + size(): number; +} +/** Draco3D metadata querier */ +export declare class MetadataQuerier { + constructor(); + HasEntry(metadata: Metadata, entry_name: string): string; + GetIntEntry(metadata: Metadata, entry_name: string): any; + GetIntEntryArray(metadata: Metadata, entry_name: string, out_values: DracoInt32Array): any; + GetDoubleEntry(metadata: Metadata, entry_name: string): number; + GetStringEntry(metadata: Metadata, entry_name: string): string; + NumEntries(metadata: Metadata): number; + GetEntryName(metadata: Metadata, entry_id: number): string; +} +/** + * Draco3D Decoder class + */ +export declare class Decoder { + constructor(); + GetEncodedGeometryType(in_buffer: DecoderBuffer): draco_EncodedGeometryType; + DecodeBufferToPointCloud(in_buffer: DecoderBuffer, out_point_cloud: PointCloud): Status; + DecodeBufferToMesh(in_buffer: DecoderBuffer, out_mesh: Mesh): Status; + GetAttributeId(pc: PointCloud, type: draco_GeometryAttribute_Type): number; + GetAttributeIdByName(pc: PointCloud, name: string): number; + GetAttributeIdByMetadataEntry(pc: PointCloud, name: string, value: string): number; + GetAttribute(pc: PointCloud, att_id: number): PointAttribute; + GetAttributeByUniqueId(pc: PointCloud, unique_id: number): PointAttribute; + GetMetadata(pc: PointCloud): Metadata; + GetAttributeMetadata(pc: PointCloud, att_id: number): Metadata; + GetFaceFromMesh(m: Mesh, face_id: number, out_values: DracoInt32Array): boolean; + GetTriangleStripsFromMesh(m: Mesh, strip_values: DracoInt32Array): any; + GetTrianglesUInt16Array(m: Mesh, out_size: number, out_values: VoidPtr): boolean; + GetTrianglesUInt32Array(m: Mesh, out_size: number, out_values: VoidPtr): boolean; + GetAttributeFloat(pa: PointAttribute, att_index: number, out_values: DracoFloat32Array): boolean; + GetAttributeFloatForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoFloat32Array): boolean; + GetAttributeIntForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoInt32Array): boolean; + GetAttributeInt8ForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoInt8Array): boolean; + GetAttributeUInt8ForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoUInt8Array): boolean; + GetAttributeInt16ForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoInt16Array): boolean; + GetAttributeUInt16ForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoUInt16Array): boolean; + GetAttributeInt32ForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoInt32Array): boolean; + GetAttributeUInt32ForAllPoints(pc: PointCloud, pa: PointAttribute, out_values: DracoUInt32Array): boolean; + GetAttributeDataArrayForAllPoints(pc: PointCloud, pa: PointAttribute, data_type: draco_DataType, out_size: number, out_values: VoidPtr): boolean; + SkipAttributeTransform(att_type: draco_GeometryAttribute_Type): void; +} +/** Draco3D metadata builder */ +export declare class MetadataBuilder { + constructor(); + AddStringEntry(metadata: Metadata, entry_name: string, entry_value: string): any; + AddIntEntry(metadata: Metadata, entry_name: string, entry_value: number): any; + AddDoubleEntry(metadata: Metadata, entry_name: string, entry_value: number): any; + AddIntEntryArray(metadata: Metadata, entry_name: string, entry_value: Int32Array, num_values: number): any; +} +/** Draco3D point cloud builder */ +export declare class PointCloudBuilder { + constructor(); + PointCloudBuilder(): void; + AddFloatAttribute(pc: PointCloud, type: draco_GeometryAttribute_Type, num_vertices: number, num_components: number, att_values: Float32Array): any; + AddInt8Attribute(pc: PointCloud, type: draco_GeometryAttribute_Type, num_vertices: number, num_components: number, att_values: Int8Array): any; + AddUInt8Attribute(pc: PointCloud, type: draco_GeometryAttribute_Type, num_vertices: number, num_components: number, att_values: Uint8Array): any; + AddInt16Attribute(pc: PointCloud, type: draco_GeometryAttribute_Type, num_vertices: number, num_components: number, att_values: Int16Array): any; + AddUInt16Attribute(pc: PointCloud, type: draco_GeometryAttribute_Type, num_vertices: number, num_components: number, att_values: Uint16Array): any; + AddInt32Attribute(pc: PointCloud, type: draco_GeometryAttribute_Type, num_vertices: number, num_components: number, att_values: Int32Array): any; + AddUInt32Attribute(pc: PointCloud, type: draco_GeometryAttribute_Type, num_vertices: number, num_components: number, att_values: Uint32Array): any; + AddMetadata(pc: PointCloud, metadata: Metadata): boolean; + SetMetadataForAttribute(pc: PointCloud, attribute_id: number, metadata: Metadata): any; +} +/** Draco3D mesh builder */ +export declare class MeshBuilder extends PointCloudBuilder { + constructor(); + AddFacesToMesh(mesh: Mesh, num_faces: number, faces: number[]): boolean; +} +/** Draco3D encoder */ +export declare class Encoder { + constructor(); + Encoder(): void; + SetEncodingMethod(method: number): void; + SetAttributeQuantization(type: draco_GeometryAttribute_Type, quantization_bits: number): any; + SetAttributeExplicitQuantization(type: draco_GeometryAttribute_Type, quantization_bits: number, num_components: number, origin: number[], range: number): any; + SetSpeedOptions(encoding_speed: number, decoding_speed: number): void; + SetTrackEncodedProperties(flag: boolean): void; + EncodeMeshToDracoBuffer(mesh: Mesh, encoded_data: DracoInt8Array): any; + EncodePointCloudToDracoBuffer(pc: PointCloud, deduplicate_values: boolean, encoded_data: DracoInt8Array): any; + GetNumberOfEncodedPoints(): number; + GetNumberOfEncodedFaces(): number; +} +/** Draco3D expert encoder */ +export declare class ExpertEncoder { + constructor(); + ExpertEncoder(pc: PointCloud): void; + SetEncodingMethod(method: number): void; + SetAttributeQuantization(att_id: number, quantization_bits: number): any; + SetAttributeExplicitQuantization(att_id: number, quantization_bits: number, num_components: number, origin: number[], range: number): any; + SetSpeedOptions(encoding_speed: number, decoding_speed: number): void; + SetTrackEncodedProperties(flag: boolean): void; + EncodeToDracoBuffer(deduplicate_values: boolean, encoded_data: DracoInt8Array): any; + GetNumberOfEncodedPoints(): number; + GetNumberOfEncodedFaces(): number; +} +/** Draco3D module interface */ +export interface Draco3D { + readonly INVALID_GEOMETRY_TYPE: draco_EncodedGeometryType; + readonly POINT_CLOUD: draco_EncodedGeometryType; + readonly TRIANGULAR_MESH: draco_EncodedGeometryType; + readonly INVALID: draco_GeometryAttribute_Type; + readonly POSITION: draco_GeometryAttribute_Type; + readonly NORMAL: draco_GeometryAttribute_Type; + readonly COLOR: draco_GeometryAttribute_Type; + readonly TEX_COORD: draco_GeometryAttribute_Type; + readonly GENERIC: draco_GeometryAttribute_Type; + readonly DT_INVALID: draco_DataType; + readonly DT_INT8: draco_DataType; + readonly DT_UINT8: draco_DataType; + readonly DT_INT16: draco_DataType; + readonly DT_UINT16: draco_DataType; + readonly DT_INT32: draco_DataType; + readonly DT_UINT32: draco_DataType; + readonly DT_INT64: draco_DataType; + readonly DT_UINT64: draco_DataType; + readonly DT_FLOAT32: draco_DataType; + readonly DT_FLOAT64: draco_DataType; + readonly DT_BOOL: draco_DataType; + readonly DT_TYPES_COUNT: draco_DataType; + readonly Mesh: typeof Mesh; + readonly PointCloud: typeof PointCloud; + readonly Metadata: typeof Metadata; + readonly Encoder: typeof Encoder; + readonly MeshBuilder: typeof MeshBuilder; + readonly MetadataBuilder: typeof MetadataBuilder; + readonly MetadataQuerier: typeof MetadataQuerier; + readonly Decoder: typeof Decoder; + readonly DecoderBuffer: typeof DecoderBuffer; + readonly DracoFloat32Array: typeof DracoFloat32Array; + readonly DracoInt8Array: typeof DracoInt8Array; + readonly DracoUInt8Array: typeof DracoUInt8Array; + readonly DracoInt16Array: typeof DracoInt16Array; + readonly DracoUInt16Array: typeof DracoUInt16Array; + readonly DracoInt32Array: typeof DracoInt32Array; + readonly DracoUInt32Array: typeof DracoUInt32Array; + readonly AttributeQuantizationTransform: typeof AttributeQuantizationTransform; + destroy(resource: any): void; + _malloc(byteLength: number): number; + _free(ptr: number): void; + HEAPF32: { + buffer: ArrayBuffer; + }; +} +export {}; diff --git a/@flywave/flywave-draco/src/draco3d/draco3d-types.js b/@flywave/flywave-draco/src/draco3d/draco3d-types.js new file mode 100644 index 0000000..19a3273 --- /dev/null +++ b/@flywave/flywave-draco/src/draco3d/draco3d-types.js @@ -0,0 +1,47 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +// DRACO WEB DECODER IDL +/** Draco3D geometry attribute type */ +export var draco_GeometryAttribute_Type; +(function (draco_GeometryAttribute_Type) { + draco_GeometryAttribute_Type[draco_GeometryAttribute_Type["draco_GeometryAttribute::INVALID"] = 0] = "draco_GeometryAttribute::INVALID"; + draco_GeometryAttribute_Type[draco_GeometryAttribute_Type["draco_GeometryAttribute::POSITION"] = 1] = "draco_GeometryAttribute::POSITION"; + draco_GeometryAttribute_Type[draco_GeometryAttribute_Type["draco_GeometryAttribute::NORMAL"] = 2] = "draco_GeometryAttribute::NORMAL"; + draco_GeometryAttribute_Type[draco_GeometryAttribute_Type["draco_GeometryAttribute::COLOR"] = 3] = "draco_GeometryAttribute::COLOR"; + draco_GeometryAttribute_Type[draco_GeometryAttribute_Type["draco_GeometryAttribute::TEX_COORD"] = 4] = "draco_GeometryAttribute::TEX_COORD"; + draco_GeometryAttribute_Type[draco_GeometryAttribute_Type["draco_GeometryAttribute::GENERIC"] = 5] = "draco_GeometryAttribute::GENERIC"; +})(draco_GeometryAttribute_Type || (draco_GeometryAttribute_Type = {})); +/** Draco3D encoded geometry type */ +export var draco_EncodedGeometryType; +(function (draco_EncodedGeometryType) { + draco_EncodedGeometryType[draco_EncodedGeometryType["draco::INVALID_GEOMETRY_TYPE"] = 0] = "draco::INVALID_GEOMETRY_TYPE"; + draco_EncodedGeometryType[draco_EncodedGeometryType["draco::POINT_CLOUD"] = 1] = "draco::POINT_CLOUD"; + draco_EncodedGeometryType[draco_EncodedGeometryType["draco::TRIANGULAR_MESH"] = 2] = "draco::TRIANGULAR_MESH"; +})(draco_EncodedGeometryType || (draco_EncodedGeometryType = {})); +/** Draco3D data type */ +export var draco_DataType; +(function (draco_DataType) { + draco_DataType[draco_DataType["draco::DT_INVALID"] = 0] = "draco::DT_INVALID"; + draco_DataType[draco_DataType["draco::DT_INT8"] = 1] = "draco::DT_INT8"; + draco_DataType[draco_DataType["draco::DT_UINT8"] = 2] = "draco::DT_UINT8"; + draco_DataType[draco_DataType["draco::DT_INT16"] = 3] = "draco::DT_INT16"; + draco_DataType[draco_DataType["draco::DT_UINT16"] = 4] = "draco::DT_UINT16"; + draco_DataType[draco_DataType["draco::DT_INT32"] = 5] = "draco::DT_INT32"; + draco_DataType[draco_DataType["draco::DT_UINT32"] = 6] = "draco::DT_UINT32"; + draco_DataType[draco_DataType["draco::DT_INT64"] = 7] = "draco::DT_INT64"; + draco_DataType[draco_DataType["draco::DT_UINT64"] = 8] = "draco::DT_UINT64"; + draco_DataType[draco_DataType["draco::DT_FLOAT32"] = 9] = "draco::DT_FLOAT32"; + draco_DataType[draco_DataType["draco::DT_FLOAT64"] = 10] = "draco::DT_FLOAT64"; + draco_DataType[draco_DataType["draco::DT_BOOL"] = 11] = "draco::DT_BOOL"; + draco_DataType[draco_DataType["draco::DT_TYPES_COUNT"] = 12] = "draco::DT_TYPES_COUNT"; +})(draco_DataType || (draco_DataType = {})); +/** Draco3D status code */ +export var draco_StatusCode; +(function (draco_StatusCode) { + draco_StatusCode[draco_StatusCode["draco_Status::OK"] = 0] = "draco_Status::OK"; + draco_StatusCode[draco_StatusCode["draco_Status::DRACO_ERROR"] = 1] = "draco_Status::DRACO_ERROR"; + draco_StatusCode[draco_StatusCode["draco_Status::IO_ERROR"] = 2] = "draco_Status::IO_ERROR"; + draco_StatusCode[draco_StatusCode["draco_Status::INVALID_PARAMETER"] = 3] = "draco_Status::INVALID_PARAMETER"; + draco_StatusCode[draco_StatusCode["draco_Status::UNSUPPORTED_VERSION"] = 4] = "draco_Status::UNSUPPORTED_VERSION"; + draco_StatusCode[draco_StatusCode["draco_Status::UNKNOWN_VERSION"] = 5] = "draco_Status::UNKNOWN_VERSION"; +})(draco_StatusCode || (draco_StatusCode = {})); +//# sourceMappingURL=draco3d-types.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/index.d.ts b/@flywave/flywave-draco/src/index.d.ts new file mode 100644 index 0000000..e1cf7f3 --- /dev/null +++ b/@flywave/flywave-draco/src/index.d.ts @@ -0,0 +1,6 @@ +export { DRACO_EXTERNAL_LIBRARIES, DRACO_EXTERNAL_LIBRARY_URLS } from "./loader/draco-module-loader"; +export type { DracoMesh, DracoLoaderData } from "./loader/draco-types"; +export type { DracoWriterOptions } from "./draco-writer"; +export { DracoWriterWorker, DracoWriter } from "./draco-writer"; +export type { DracoLoaderOptions, loadDraco } from "./draco-loader"; +export { DracoWorkerLoader, DracoLoader } from "./draco-loader"; diff --git a/@flywave/flywave-draco/src/index.js b/@flywave/flywave-draco/src/index.js new file mode 100644 index 0000000..9fdb5ad --- /dev/null +++ b/@flywave/flywave-draco/src/index.js @@ -0,0 +1,6 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +// Module constants +export { DRACO_EXTERNAL_LIBRARIES, DRACO_EXTERNAL_LIBRARY_URLS } from "./loader/draco-module-loader"; +export { DracoWriterWorker, DracoWriter } from "./draco-writer"; +export { DracoWorkerLoader, DracoLoader } from "./draco-loader"; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/libs/draco_encoder.d.ts b/@flywave/flywave-draco/src/libs/draco_encoder.d.ts new file mode 100644 index 0000000..1c63c04 --- /dev/null +++ b/@flywave/flywave-draco/src/libs/draco_encoder.d.ts @@ -0,0 +1,5 @@ +export = DracoEncoderModule; +declare function DracoEncoderModule(DracoEncoderModule: any, ...args: any[]): any; +declare namespace DracoEncoderModule { + export { DracoEncoderModule }; +} diff --git a/@flywave/flywave-draco/src/libs/draco_wasm_wrapper.d.ts b/@flywave/flywave-draco/src/libs/draco_wasm_wrapper.d.ts new file mode 100644 index 0000000..e973d4a --- /dev/null +++ b/@flywave/flywave-draco/src/libs/draco_wasm_wrapper.d.ts @@ -0,0 +1,5 @@ +export = DracoDecoderModule; +declare function DracoDecoderModule(n: any): any; +declare namespace DracoDecoderModule { + export { DracoDecoderModule }; +} diff --git a/@flywave/flywave-draco/src/loader/draco-builder.d.ts b/@flywave/flywave-draco/src/loader/draco-builder.d.ts new file mode 100644 index 0000000..baad793 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-builder.d.ts @@ -0,0 +1,93 @@ +import type { TypedArray } from "three"; +import * as THREE from "three"; +import type { draco_GeometryAttribute_Type, Draco3D, Encoder, Mesh, MeshBuilder, Metadata, MetadataBuilder, PointCloud } from "../draco3d/draco3d-types"; +import type { DracoMesh } from "./draco-types"; +export interface DracoBuildOptions { + pointcloud?: boolean; + metadata?: { + [key: string]: string; + }; + attributesMetadata?: {}; + log?: any; + speed?: [number, number]; + method?: string; + quantization?: { + [attributeName: string]: number; + }; +} +export default class DracoBuilder { + draco: Draco3D; + dracoEncoder: Encoder; + dracoMeshBuilder: MeshBuilder; + dracoMetadataBuilder: MetadataBuilder; + log: any; + constructor(draco: Draco3D); + destroy(): void; + destroyEncodedObject(object: any): void; + /** + * Encode mesh or point cloud + * @param mesh =({}) + * @param options + */ + encodeSync(mesh: DracoMesh, options?: DracoBuildOptions): ArrayBuffer; + _getAttributesFromMesh(mesh: DracoMesh): { + [key: string]: THREE.BufferAttribute; + }; + _encodePointCloud(pointcloud: DracoMesh, options: DracoBuildOptions): ArrayBuffer; + _encodeMesh(mesh: DracoMesh, options: DracoBuildOptions): ArrayBuffer; + /** + * Set encoding options. + * @param {{speed?: any; method?: any; quantization?: any;}} options + */ + _setOptions(options: DracoBuildOptions): void; + /** + * @param {Mesh} dracoMesh + * @param {object} attributes + * @returns {Mesh} + */ + _createDracoMesh(dracoMesh: Mesh, attributes: any, options: DracoBuildOptions): Mesh; + /** + * @param {} dracoPointCloud + * @param {object} attributes + */ + _createDracoPointCloud(dracoPointCloud: PointCloud, attributes: object, options: DracoBuildOptions): PointCloud; + /** + * @param mesh + * @param attributeName + * @param attribute + * @param vertexCount + */ + _addAttributeToMesh(mesh: PointCloud, attributeName: string, attribute: TypedArray, vertexCount: number): number; + /** + * DRACO can compress attributes of know type better + * TODO - expose an attribute type map? + * @param attributeName + */ + _getDracoAttributeType(attributeName: string): draco_GeometryAttribute_Type | "indices"; + _getPositionAttribute(attributes: any): any; + /** + * Add metadata for the geometry. + * @param dracoGeometry - WASM Draco Object + * @param metadata + */ + _addGeometryMetadata(dracoGeometry: PointCloud, metadata: { + [key: string]: string; + }): void; + /** + * Add metadata for an attribute to geometry. + * @param dracoGeometry - WASM Draco Object + * @param uniqueAttributeId + * @param metadata + */ + _addAttributeMetadata(dracoGeometry: PointCloud, uniqueAttributeId: number, metadata: Map | { + [key: string]: string; + }): void; + /** + * Add contents of object or map to a WASM Draco Metadata Object + * @param dracoMetadata - WASM Draco Object + * @param metadata + */ + _populateDracoMetadata(dracoMetadata: Metadata, metadata: Map | { + [key: string]: string; + }): void; +} diff --git a/@flywave/flywave-draco/src/loader/draco-builder.js b/@flywave/flywave-draco/src/loader/draco-builder.js new file mode 100644 index 0000000..bc642d3 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-builder.js @@ -0,0 +1,352 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import * as THREE from "three"; +// Native Draco attribute names to GLTF attribute names. +const GLTF_TO_DRACO_ATTRIBUTE_NAME_MAP = { + POSITION: "POSITION", + NORMAL: "NORMAL", + COLOR_0: "COLOR", + TEXCOORD_0: "TEX_COORD" +}; +const noop = () => { }; +export default class DracoBuilder { + // draco - the draco decoder, either import `draco3d` or load dynamically + constructor(draco) { + this.draco = draco; + this.dracoEncoder = new this.draco.Encoder(); + this.dracoMeshBuilder = new this.draco.MeshBuilder(); + this.dracoMetadataBuilder = new this.draco.MetadataBuilder(); + } + destroy() { + this.destroyEncodedObject(this.dracoMeshBuilder); + this.destroyEncodedObject(this.dracoEncoder); + this.destroyEncodedObject(this.dracoMetadataBuilder); + // @ts-ignore + this.dracoMeshBuilder = null; + // @ts-ignore + this.dracoEncoder = null; + // @ts-ignore + this.draco = null; + } + // TBD - when does this need to be called? + destroyEncodedObject(object) { + if (object) { + this.draco.destroy(object); + } + } + /** + * Encode mesh or point cloud + * @param mesh =({}) + * @param options + */ + encodeSync(mesh, options = {}) { + this.log = noop; // TODO + this._setOptions(options); + return options.pointcloud + ? this._encodePointCloud(mesh, options) + : this._encodeMesh(mesh, options); + } + // PRIVATE + _getAttributesFromMesh(mesh) { + // Extract attributes from Three.js geometry + const attributes = {}; + // Iterate through all geometry attributes + mesh.geometry.attributes = mesh.geometry.attributes || {}; + for (const [name, attribute] of Object.entries(mesh.geometry.attributes)) { + if (attribute instanceof THREE.BufferAttribute) { + attributes[name] = attribute; + } + } + // Add index data + if (mesh.geometry.index) { + attributes.indices = new THREE.BufferAttribute(mesh.geometry.index.array, 1 // The itemSize of the index is fixed to 1 + ); + } + return attributes; + } + _encodePointCloud(pointcloud, options) { + const dracoPointCloud = new this.draco.PointCloud(); + if (options.metadata) { + this._addGeometryMetadata(dracoPointCloud, options.metadata); + } + const attributes = this._getAttributesFromMesh(pointcloud); + // Build a `DracoPointCloud` from the input data + this._createDracoPointCloud(dracoPointCloud, attributes, options); + const dracoData = new this.draco.DracoInt8Array(); + try { + const encodedLen = this.dracoEncoder.EncodePointCloudToDracoBuffer(dracoPointCloud, false, dracoData); + if (!(encodedLen > 0)) { + throw new Error("Draco encoding failed."); + } + this.log(`DRACO encoded ${dracoPointCloud.num_points()} points + with ${dracoPointCloud.num_attributes()} attributes into ${encodedLen} bytes`); + return dracoInt8ArrayToArrayBuffer(dracoData); + } + finally { + this.destroyEncodedObject(dracoData); + this.destroyEncodedObject(dracoPointCloud); + } + } + _encodeMesh(mesh, options) { + const dracoMesh = new this.draco.Mesh(); + if (options.metadata) { + this._addGeometryMetadata(dracoMesh, options.metadata); + } + const attributes = this._getAttributesFromMesh(mesh); + // Build a `DracoMesh` from the input data + this._createDracoMesh(dracoMesh, attributes, options); + const dracoData = new this.draco.DracoInt8Array(); + try { + const encodedLen = this.dracoEncoder.EncodeMeshToDracoBuffer(dracoMesh, dracoData); + if (encodedLen <= 0) { + throw new Error("Draco encoding failed."); + } + this.log(`DRACO encoded ${dracoMesh.num_points()} points + with ${dracoMesh.num_attributes()} attributes into ${encodedLen} bytes`); + return dracoInt8ArrayToArrayBuffer(dracoData); + } + finally { + this.destroyEncodedObject(dracoData); + this.destroyEncodedObject(dracoMesh); + } + } + /** + * Set encoding options. + * @param {{speed?: any; method?: any; quantization?: any;}} options + */ + _setOptions(options) { + if ("speed" in options) { + // @ts-ignore + this.dracoEncoder.SetSpeedOptions(...options.speed); + } + if ("method" in options) { + const dracoMethod = this.draco[options.method || "MESH_SEQUENTIAL_ENCODING"]; + // assert(dracoMethod) + this.dracoEncoder.SetEncodingMethod(dracoMethod); + } + if ("quantization" in options) { + for (const attribute in options.quantization) { + const bits = options.quantization[attribute]; + const dracoPosition = this.draco[attribute]; + this.dracoEncoder.SetAttributeQuantization(dracoPosition, bits); + } + } + } + /** + * @param {Mesh} dracoMesh + * @param {object} attributes + * @returns {Mesh} + */ + _createDracoMesh(dracoMesh, attributes, options) { + const optionalMetadata = options.attributesMetadata || {}; + try { + const positions = this._getPositionAttribute(attributes); + if (!positions) { + throw new Error("positions"); + } + const vertexCount = positions.length / 3; + for (let attributeName in attributes) { + const attribute = attributes[attributeName]; + attributeName = GLTF_TO_DRACO_ATTRIBUTE_NAME_MAP[attributeName] || attributeName; + const uniqueId = this._addAttributeToMesh(dracoMesh, attributeName, attribute, vertexCount); + if (uniqueId !== -1) { + this._addAttributeMetadata(dracoMesh, uniqueId, { + name: attributeName, + ...(optionalMetadata[attributeName] || {}) + }); + } + } + } + catch (error) { + this.destroyEncodedObject(dracoMesh); + throw error; + } + return dracoMesh; + } + /** + * @param {} dracoPointCloud + * @param {object} attributes + */ + _createDracoPointCloud(dracoPointCloud, attributes, options) { + const optionalMetadata = options.attributesMetadata || {}; + try { + const positions = this._getPositionAttribute(attributes); + if (!positions) { + throw new Error("positions"); + } + const vertexCount = positions.length / 3; + for (let attributeName in attributes) { + const attribute = attributes[attributeName]; + attributeName = GLTF_TO_DRACO_ATTRIBUTE_NAME_MAP[attributeName] || attributeName; + const uniqueId = this._addAttributeToMesh(dracoPointCloud, attributeName, attribute, vertexCount); + if (uniqueId !== -1) { + this._addAttributeMetadata(dracoPointCloud, uniqueId, { + name: attributeName, + ...(optionalMetadata[attributeName] || {}) + }); + } + } + } + catch (error) { + this.destroyEncodedObject(dracoPointCloud); + throw error; + } + return dracoPointCloud; + } + /** + * @param mesh + * @param attributeName + * @param attribute + * @param vertexCount + */ + _addAttributeToMesh(mesh, attributeName, attribute, vertexCount) { + if (!ArrayBuffer.isView(attribute)) { + return -1; + } + const type = this._getDracoAttributeType(attributeName); + // @ts-ignore TODO/fix types + const size = attribute.length / vertexCount; + if (type === "indices") { + // @ts-ignore TODO/fix types + const numFaces = attribute.length / 3; + this.log(`Adding attribute ${attributeName}, size ${numFaces}`); + // @ts-ignore assumes mesh is a Mesh, not a point cloud + this.dracoMeshBuilder.AddFacesToMesh(mesh, numFaces, attribute); + return -1; + } + this.log(`Adding attribute ${attributeName}, size ${size}`); + const builder = this.dracoMeshBuilder; + const { buffer } = attribute; + switch (attribute.constructor) { + case Int8Array: + return builder.AddInt8Attribute(mesh, type, vertexCount, size, new Int8Array(buffer)); + case Int16Array: + return builder.AddInt16Attribute(mesh, type, vertexCount, size, new Int16Array(buffer)); + case Int32Array: + return builder.AddInt32Attribute(mesh, type, vertexCount, size, new Int32Array(buffer)); + case Uint8Array: + case Uint8ClampedArray: + return builder.AddUInt8Attribute(mesh, type, vertexCount, size, new Uint8Array(buffer)); + case Uint16Array: + return builder.AddUInt16Attribute(mesh, type, vertexCount, size, new Uint16Array(buffer)); + case Uint32Array: + return builder.AddUInt32Attribute(mesh, type, vertexCount, size, new Uint32Array(buffer)); + case Float32Array: + return builder.AddFloatAttribute(mesh, type, vertexCount, size, new Float32Array(buffer)); + default: + // eslint-disable-next-line no-console + console.warn("Unsupported attribute type", attribute); + return -1; + } + // case Float64Array: + // Add attribute does not seem to be exposed + // return builder.AddAttribute(mesh, type, vertexCount, size, new Float32Array(buffer)); + } + /** + * DRACO can compress attributes of know type better + * TODO - expose an attribute type map? + * @param attributeName + */ + _getDracoAttributeType(attributeName) { + switch (attributeName.toLowerCase()) { + case "indices": + return "indices"; + case "position": + case "positions": + case "vertices": + return this.draco.POSITION; + case "normal": + case "normals": + return this.draco.NORMAL; + case "color": + case "colors": + return this.draco.COLOR; + case "texcoord": + case "texcoords": + return this.draco.TEX_COORD; + default: + return this.draco.GENERIC; + } + } + _getPositionAttribute(attributes) { + for (const attributeName in attributes) { + const attribute = attributes[attributeName]; + const dracoType = this._getDracoAttributeType(attributeName); + if (dracoType === this.draco.POSITION) { + return attribute; + } + } + return null; + } + /** + * Add metadata for the geometry. + * @param dracoGeometry - WASM Draco Object + * @param metadata + */ + _addGeometryMetadata(dracoGeometry, metadata) { + const dracoMetadata = new this.draco.Metadata(); + this._populateDracoMetadata(dracoMetadata, metadata); + this.dracoMeshBuilder.AddMetadata(dracoGeometry, dracoMetadata); + } + /** + * Add metadata for an attribute to geometry. + * @param dracoGeometry - WASM Draco Object + * @param uniqueAttributeId + * @param metadata + */ + _addAttributeMetadata(dracoGeometry, uniqueAttributeId, metadata) { + // Note: Draco JS IDL doesn't seem to expose draco.AttributeMetadata, however it seems to + // create such objects automatically from draco.Metadata object. + const dracoAttributeMetadata = new this.draco.Metadata(); + this._populateDracoMetadata(dracoAttributeMetadata, metadata); + // Draco3d doc note: Directly add attribute metadata to geometry. + // You can do this without explicitly adding |GeometryMetadata| to mesh. + this.dracoMeshBuilder.SetMetadataForAttribute(dracoGeometry, uniqueAttributeId, dracoAttributeMetadata); + } + /** + * Add contents of object or map to a WASM Draco Metadata Object + * @param dracoMetadata - WASM Draco Object + * @param metadata + */ + _populateDracoMetadata(dracoMetadata, metadata) { + for (const [key, value] of getEntries(metadata)) { + switch (typeof value) { + case "number": + if (Math.trunc(value) === value) { + this.dracoMetadataBuilder.AddIntEntry(dracoMetadata, key, value); + } + else { + this.dracoMetadataBuilder.AddDoubleEntry(dracoMetadata, key, value); + } + break; + case "object": + if (value instanceof Int32Array) { + this.dracoMetadataBuilder.AddIntEntryArray(dracoMetadata, key, value, value.length); + } + break; + case "string": + default: + this.dracoMetadataBuilder.AddStringEntry(dracoMetadata, key, value); + } + } + } +} +// HELPER FUNCTIONS +/** + * Copy encoded data to buffer + * @param dracoData + */ +function dracoInt8ArrayToArrayBuffer(dracoData) { + const byteLength = dracoData.size(); + const outputBuffer = new ArrayBuffer(byteLength); + const outputData = new Int8Array(outputBuffer); + for (let i = 0; i < byteLength; ++i) { + outputData[i] = dracoData.GetValue(i); + } + return outputBuffer; +} +/** Enable iteration over either an object or a map */ +function getEntries(container) { + const hasEntriesFunc = container.entries && !container.hasOwnProperty("entries"); + return hasEntriesFunc ? container.entries() : Object.entries(container); +} +//# sourceMappingURL=draco-builder.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/loader/draco-module-loader.d.ts b/@flywave/flywave-draco/src/loader/draco-module-loader.d.ts new file mode 100644 index 0000000..1261985 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-module-loader.d.ts @@ -0,0 +1,18 @@ +export declare const DRACO_EXTERNAL_LIBRARIES: { + /** The primary Draco3D encoder, javascript wrapper part */ + DECODER: string; + /** The primary draco decoder, compiled web assembly part */ + DECODER_WASM: string; + /** Fallback decoder for non-webassebly environments. Very big bundle, lower performance */ + FALLBACK_DECODER: string; + /** Draco encoder */ + ENCODER: string; +}; +export declare const DRACO_EXTERNAL_LIBRARY_URLS: { + [DRACO_EXTERNAL_LIBRARIES.DECODER]: string; + [DRACO_EXTERNAL_LIBRARIES.DECODER_WASM]: string; + [DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER]: string; + [DRACO_EXTERNAL_LIBRARIES.ENCODER]: string; +}; +export declare function loadDracoDecoderModule(options: any): Promise; +export declare function loadDracoEncoderModule(options: any): Promise; diff --git a/@flywave/flywave-draco/src/loader/draco-module-loader.js b/@flywave/flywave-draco/src/loader/draco-module-loader.js new file mode 100644 index 0000000..6b7f791 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-module-loader.js @@ -0,0 +1,106 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +// Dynamic DRACO module loading inspired by THREE.DRACOLoader +// https://github.com/mrdoob/three.js/blob/398c4f39ebdb8b23eefd4a7a5ec49ec0c96c7462/examples/jsm/loaders/DRACOLoader.js +// by Don McCurdy / https://www.donmccurdy.com / MIT license +import { loadLibrary } from "@flywave/flywave-utils"; +const DRACO_DECODER_VERSION = "1.5.6"; +const DRACO_ENCODER_VERSION = "1.4.1"; +const STATIC_DECODER_URL = `https://www.gstatic.com/draco/versioned/decoders/${DRACO_DECODER_VERSION}`; +export const DRACO_EXTERNAL_LIBRARIES = { + /** The primary Draco3D encoder, javascript wrapper part */ + DECODER: "draco_wasm_wrapper.js", + /** The primary draco decoder, compiled web assembly part */ + DECODER_WASM: "draco_decoder.wasm", + /** Fallback decoder for non-webassebly environments. Very big bundle, lower performance */ + FALLBACK_DECODER: "draco_decoder.js", + /** Draco encoder */ + ENCODER: "draco_encoder.js" +}; +export const DRACO_EXTERNAL_LIBRARY_URLS = { + [DRACO_EXTERNAL_LIBRARIES.DECODER]: `${STATIC_DECODER_URL}/${DRACO_EXTERNAL_LIBRARIES.DECODER}`, + [DRACO_EXTERNAL_LIBRARIES.DECODER_WASM]: `${STATIC_DECODER_URL}/${DRACO_EXTERNAL_LIBRARIES.DECODER_WASM}`, + [DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER]: `${STATIC_DECODER_URL}/${DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER}`, + [DRACO_EXTERNAL_LIBRARIES.ENCODER]: `https://raw.githubusercontent.com/google/draco/${DRACO_ENCODER_VERSION}/javascript/${DRACO_EXTERNAL_LIBRARIES.ENCODER}` +}; +let loadDecoderPromise; +let loadEncoderPromise; +export async function loadDracoDecoderModule(options) { + const modules = options.modules || {}; + // Check if a bundled draco3d library has been supplied by application + if (modules.draco3d) { + loadDecoderPromise || (loadDecoderPromise = modules.draco3d.createDecoderModule({}).then(draco => { + return { draco }; + })); + } + else { + // If not, dynamically load the WASM script from our CDN + loadDecoderPromise || (loadDecoderPromise = loadDracoDecoder(options)); + } + return loadDecoderPromise; +} +export async function loadDracoEncoderModule(options) { + const modules = options.modules || {}; + // Check if a bundled draco3d library has been supplied by application + if (modules.draco3d) { + loadEncoderPromise || (loadEncoderPromise = modules.draco3d.createEncoderModule({}).then(draco => { + return { draco }; + })); + } + else { + // If not, dynamically load the WASM script from our CDN + loadEncoderPromise || (loadEncoderPromise = loadDracoEncoder(options)); + } + return loadEncoderPromise; +} +// DRACO DECODER LOADING +async function loadDracoDecoder(options) { + let DracoDecoderModule; + let wasmBinary; + const DRACO_EXTERNAL_LIBRARY_URLS_ = options.draco?.libraryPath + ? { + [DRACO_EXTERNAL_LIBRARIES.DECODER]: `${options.draco.libraryPath}/${DRACO_EXTERNAL_LIBRARIES.DECODER}`, + [DRACO_EXTERNAL_LIBRARIES.DECODER_WASM]: `${options.draco.libraryPath}/${DRACO_EXTERNAL_LIBRARIES.DECODER_WASM}`, + [DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER]: `${options.draco.libraryPath}/${DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER}`, + [DRACO_EXTERNAL_LIBRARIES.ENCODER]: `${options.draco.libraryPath}/${DRACO_EXTERNAL_LIBRARIES.ENCODER}` + } + : DRACO_EXTERNAL_LIBRARY_URLS; + switch (options.draco && options.draco.decoderType) { + case "js": + DracoDecoderModule = await loadLibrary(DRACO_EXTERNAL_LIBRARY_URLS_[DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER], "draco", options, DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER); + break; + case "wasm": + default: + [DracoDecoderModule, wasmBinary] = await Promise.all([ + await loadLibrary(DRACO_EXTERNAL_LIBRARY_URLS_[DRACO_EXTERNAL_LIBRARIES.DECODER], "draco", options, DRACO_EXTERNAL_LIBRARIES.DECODER), + await loadLibrary(DRACO_EXTERNAL_LIBRARY_URLS_[DRACO_EXTERNAL_LIBRARIES.DECODER_WASM], "draco", options, DRACO_EXTERNAL_LIBRARIES.DECODER_WASM) + ]); + } + // Depends on how import happened... + // @ts-ignore + DracoDecoderModule = DracoDecoderModule || globalThis.DracoDecoderModule; + return await initializeDracoDecoder(DracoDecoderModule, wasmBinary); +} +function initializeDracoDecoder(DracoDecoderModule, wasmBinary) { + const options = {}; + if (wasmBinary) { + options.wasmBinary = wasmBinary; + } + return new Promise(resolve => { + DracoDecoderModule({ + ...options, + onModuleLoaded: draco => resolve({ draco }) // Module is Promise-like. Wrap in object to avoid loop. + }); + }); +} +// ENCODER +async function loadDracoEncoder(options) { + let DracoEncoderModule = await loadLibrary(DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.ENCODER], "draco", options, DRACO_EXTERNAL_LIBRARIES.ENCODER); + // @ts-ignore + DracoEncoderModule = DracoEncoderModule || globalThis.DracoEncoderModule; + return await new Promise(resolve => { + DracoEncoderModule({ + onModuleLoaded: draco => resolve({ draco }) // Module is Promise-like. Wrap in object to avoid loop. + }); + }); +} +//# sourceMappingURL=draco-module-loader.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/loader/draco-parser.d.ts b/@flywave/flywave-draco/src/loader/draco-parser.d.ts new file mode 100644 index 0000000..f77b6d4 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-parser.d.ts @@ -0,0 +1,137 @@ +import * as THREE from "three"; +import type { Decoder, Draco3D, Mesh, Metadata, MetadataQuerier, PointAttribute, PointCloud } from "../draco3d/draco3d-types"; +import type { DracoAttribute, DracoLoaderData, DracoMesh, DracoMetadataEntry, DracoOctahedronTransform, DracoQuantizationTransform } from "./draco-types"; +/** Options to control draco parsing */ +export interface DracoParseOptions { + /** How triangle indices should be generated (mesh only) */ + topology?: "triangle-list" | "triangle-strip"; + /** Specify which attribute metadata entry stores the attribute name */ + attributeNameEntry?: string; + /** Names and ids of extra attributes to include in the output */ + extraAttributes?: { + [uniqueId: string]: number; + }; + /** Skip transforms specific quantized attributes */ + quantizedAttributes?: Array<"POSITION" | "NORMAL" | "COLOR" | "TEX_COORD" | "GENERIC">; + /** Skip transforms specific octahedron encoded attributes */ + octahedronAttributes?: Array<"POSITION" | "NORMAL" | "COLOR" | "TEX_COORD" | "GENERIC">; + /** Attribute name mapping */ + attributeMap?: { + [key: string]: string; + }; +} +export default class DracoParser { + draco: Draco3D; + decoder: Decoder; + metadataQuerier: MetadataQuerier; + constructor(draco: Draco3D); + /** + * Destroy draco resources + */ + destroy(): void; + /** + * NOTE: caller must call `destroyGeometry` on the return value after using it + * @param arrayBuffer + * @param options + */ + parseSync(arrayBuffer: ArrayBuffer, options?: DracoParseOptions): DracoMesh; + /** + * Extract + * @param dracoGeometry + * @param geometry_type + * @param options + * @returns + */ + _getDracoLoaderData(dracoGeometry: Mesh | PointCloud, geometry_type: any, options: DracoParseOptions): DracoLoaderData; + /** + * Extract all draco provided information and metadata for each attribute + * @param dracoGeometry + * @param options + * @returns + */ + _getDracoAttributes(dracoGeometry: Mesh | PointCloud, options: DracoParseOptions): { + [unique_id: number]: DracoAttribute; + }; + /** + * Get standard loaders.gl mesh category data + * Extracts the geometry from draco + * @param dracoGeometry + * @param options + */ + _getMeshData(dracoGeometry: Mesh | PointCloud, loaderData: DracoLoaderData, options: DracoParseOptions): THREE.BufferGeometry; + private _getMeshAttributes; + /** + * For meshes, we need indices to define the faces. + * @param dracoGeometry + */ + _getTriangleListIndices(dracoGeometry: Mesh): Uint32Array; + /** + * For meshes, we need indices to define the faces. + * @param dracoGeometry + */ + _getTriangleStripIndices(dracoGeometry: Mesh): Int32Array; + /** + * + * @param dracoGeometry + * @param dracoAttribute + * @param attributeName + */ + _getAttributeValues(dracoGeometry: Mesh | PointCloud, attribute: DracoAttribute): { + value: THREE.TypedArray; + size: number; + } | null; + /** + * DRACO does not store attribute names - We need to deduce an attribute name + * for each attribute + _getAttributeNames( + dracoGeometry: Mesh | PointCloud, + options: DracoParseOptions + ): {[unique_id: number]: string} { + const attributeNames: {[unique_id: number]: string} = {}; + for (let attributeId = 0; attributeId < dracoGeometry.num_attributes(); attributeId++) { + const dracoAttribute = this.decoder.GetAttribute(dracoGeometry, attributeId); + const attributeName = this._deduceAttributeName(dracoAttribute, options); + attributeNames[attributeName] = attributeName; + } + return attributeNames; + } + */ + /** + * Deduce an attribute name. + * @note DRACO does not save attribute names, just general type (POSITION, COLOR) + * to help optimize compression. We generate GLTF compatible names for the Draco-recognized + * types + * @param attributeData + */ + _deduceAttributeName(attribute: DracoAttribute, options: DracoParseOptions): string; + /** Get top level metadata */ + _getTopLevelMetadata(dracoGeometry: Mesh | PointCloud): { + [entry: string]: DracoMetadataEntry; + }; + /** Get per attribute metadata */ + _getAttributeMetadata(dracoGeometry: Mesh | PointCloud, attributeId: number): { + [entry: string]: DracoMetadataEntry; + }; + /** + * Extract metadata field values + * @param dracoMetadata + * @returns + */ + _getDracoMetadata(dracoMetadata: Metadata): { + [entry: string]: DracoMetadataEntry; + }; + /** + * Extracts possible values for one metadata entry by name + * @param dracoMetadata + * @param entryName + */ + _getDracoMetadataField(dracoMetadata: Metadata, entryName: string): DracoMetadataEntry; + /** Skip transforms for specific attribute types */ + _disableAttributeTransforms(options: DracoParseOptions): void; + /** + * Extract (and apply?) Position Transform + * @todo not used + */ + _getQuantizationTransform(dracoAttribute: PointAttribute, options: DracoParseOptions): DracoQuantizationTransform | null; + _getOctahedronTransform(dracoAttribute: PointAttribute, options: DracoParseOptions): DracoOctahedronTransform | null; +} diff --git a/@flywave/flywave-draco/src/loader/draco-parser.js b/@flywave/flywave-draco/src/loader/draco-parser.js new file mode 100644 index 0000000..92d9e25 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-parser.js @@ -0,0 +1,471 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import * as THREE from "three"; +import { getDracoSchema } from "./utils/get-draco-schema"; +// @ts-ignore +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const GEOMETRY_TYPE = { + TRIANGULAR_MESH: 0, + POINT_CLOUD: 1 +}; +// Native Draco attribute names to GLTF attribute names. +const DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP = { + POSITION: "POSITION", + NORMAL: "NORMAL", + COLOR: "COLOR_0", + TEX_COORD: "TEXCOORD_0" +}; +const DRACO_DATA_TYPE_TO_TYPED_ARRAY_MAP = { + 1: Int8Array, + 2: Uint8Array, + 3: Int16Array, + 4: Uint16Array, + 5: Int32Array, + 6: Uint32Array, + // 7: BigInt64Array, + // 8: BigUint64Array, + 9: Float32Array + // 10: Float64Array + // 11: BOOL - What array type do we use for this? +}; +const INDEX_ITEM_SIZE = 4; +export default class DracoParser { + // draco - the draco decoder, either import `draco3d` or load dynamically + constructor(draco) { + this.draco = draco; + this.decoder = new this.draco.Decoder(); + this.metadataQuerier = new this.draco.MetadataQuerier(); + } + /** + * Destroy draco resources + */ + destroy() { + this.draco.destroy(this.decoder); + this.draco.destroy(this.metadataQuerier); + } + /** + * NOTE: caller must call `destroyGeometry` on the return value after using it + * @param arrayBuffer + * @param options + */ + parseSync(arrayBuffer, options = {}) { + const buffer = new this.draco.DecoderBuffer(); + buffer.Init(new Int8Array(arrayBuffer), arrayBuffer.byteLength); + this._disableAttributeTransforms(options); + const geometry_type = this.decoder.GetEncodedGeometryType(buffer); + const dracoGeometry = geometry_type === this.draco.TRIANGULAR_MESH + ? new this.draco.Mesh() + : new this.draco.PointCloud(); + try { + let dracoStatus; + switch (geometry_type) { + case this.draco.TRIANGULAR_MESH: + dracoStatus = this.decoder.DecodeBufferToMesh(buffer, dracoGeometry); + break; + case this.draco.POINT_CLOUD: + dracoStatus = this.decoder.DecodeBufferToPointCloud(buffer, dracoGeometry); + break; + default: + throw new Error("DRACO: Unknown geometry type."); + } + if (!dracoStatus.ok() || !dracoGeometry.ptr) { + const message = `DRACO decompression failed: ${dracoStatus.error_msg()}`; + // console.error(message); + throw new Error(message); + } + const loaderData = this._getDracoLoaderData(dracoGeometry, geometry_type, options); + const geometry = this._getMeshData(dracoGeometry, loaderData, options); + const boundingBox = geometry.boundingBox; + // Pass additional attribute mapping options + const schema = getDracoSchema(geometry, loaderData); + const data = { + loader: "draco", + loaderData, + header: { + vertexCount: dracoGeometry.num_points(), + boundingBox + }, + geometry, + schema + }; + return data; + } + finally { + this.draco.destroy(buffer); + if (dracoGeometry) { + this.draco.destroy(dracoGeometry); + } + } + } + // Draco specific "loader data" + /** + * Extract + * @param dracoGeometry + * @param geometry_type + * @param options + * @returns + */ + _getDracoLoaderData(dracoGeometry, geometry_type, options) { + const metadata = this._getTopLevelMetadata(dracoGeometry); + const attributes = this._getDracoAttributes(dracoGeometry, options); + return { + geometry_type, + num_attributes: dracoGeometry.num_attributes(), + num_points: dracoGeometry.num_points(), + num_faces: dracoGeometry instanceof this.draco.Mesh ? dracoGeometry.num_faces() : 0, + metadata, + attributes + }; + } + /** + * Extract all draco provided information and metadata for each attribute + * @param dracoGeometry + * @param options + * @returns + */ + _getDracoAttributes(dracoGeometry, options) { + const dracoAttributes = {}; + for (let attributeId = 0; attributeId < dracoGeometry.num_attributes(); attributeId++) { + // Note: Draco docs do not seem clear on `GetAttribute` ids just being a zero-based index, + // but it does seems to work this way + const dracoAttribute = this.decoder.GetAttribute(dracoGeometry, attributeId); + const metadata = this._getAttributeMetadata(dracoGeometry, attributeId); + dracoAttributes[dracoAttribute.unique_id()] = { + unique_id: dracoAttribute.unique_id(), + attribute_type: dracoAttribute.attribute_type(), + data_type: dracoAttribute.data_type(), + num_components: dracoAttribute.num_components(), + byte_offset: dracoAttribute.byte_offset(), + byte_stride: dracoAttribute.byte_stride(), + normalized: dracoAttribute.normalized(), + attribute_index: attributeId, + metadata + }; + // Add transformation parameters for any attributes app wants untransformed + const quantization = this._getQuantizationTransform(dracoAttribute, options); + if (quantization) { + dracoAttributes[dracoAttribute.unique_id()].quantization_transform = quantization; + } + const octahedron = this._getOctahedronTransform(dracoAttribute, options); + if (octahedron) { + dracoAttributes[dracoAttribute.unique_id()].octahedron_transform = octahedron; + } + } + return dracoAttributes; + } + /** + * Get standard loaders.gl mesh category data + * Extracts the geometry from draco + * @param dracoGeometry + * @param options + */ + _getMeshData(dracoGeometry, loaderData, options) { + const geometry = new THREE.BufferGeometry(); + const attributes = this._getMeshAttributes(loaderData, dracoGeometry, options); + // Set geometry attributes + for (const [name, attribute] of Object.entries(attributes)) { + geometry.setAttribute(name.toLowerCase(), attribute); + } + // Process mesh indices + if (dracoGeometry instanceof this.draco.Mesh) { + let indices; + switch (options.topology) { + case "triangle-strip": + indices = new THREE.BufferAttribute(this._getTriangleStripIndices(dracoGeometry), 1); + geometry.setIndex(indices); + geometry.setDrawRange(0, indices.count); + break; + case "triangle-list": + default: + indices = new THREE.BufferAttribute(this._getTriangleListIndices(dracoGeometry), 1); + geometry.setIndex(indices); + break; + } + } + // Automatically calculate normals and bounding box + geometry.computeVertexNormals(); + geometry.computeBoundingBox(); + return geometry; + } + _getMeshAttributes(loaderData, dracoGeometry, options) { + const attributes = {}; + for (const loaderAttribute of Object.values(loaderData.attributes)) { + const attributeName = this._deduceAttributeName(loaderAttribute, options); + const values = this._getAttributeValues(dracoGeometry, loaderAttribute); + if (values) { + // Convert attribute names to Three.js specification + const threeName = DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP[attributeName]?.toLowerCase() || + attributeName.toLowerCase(); + attributes[threeName] = new THREE.BufferAttribute(values.value, values.size); + } + } + return attributes; + } + // MESH INDICES EXTRACTION + /** + * For meshes, we need indices to define the faces. + * @param dracoGeometry + */ + _getTriangleListIndices(dracoGeometry) { + // Example on how to retrieve mesh and attributes. + const numFaces = dracoGeometry.num_faces(); + const numIndices = numFaces * 3; + const byteLength = numIndices * INDEX_ITEM_SIZE; + const ptr = this.draco._malloc(byteLength); + try { + this.decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr); + return new Uint32Array(this.draco.HEAPF32.buffer, ptr, numIndices).slice(); + } + finally { + this.draco._free(ptr); + } + } + /** + * For meshes, we need indices to define the faces. + * @param dracoGeometry + */ + _getTriangleStripIndices(dracoGeometry) { + const dracoArray = new this.draco.DracoInt32Array(); + try { + /* const numStrips = */ this.decoder.GetTriangleStripsFromMesh(dracoGeometry, dracoArray); + return getUint32Array(dracoArray); + } + finally { + this.draco.destroy(dracoArray); + } + } + /** + * + * @param dracoGeometry + * @param dracoAttribute + * @param attributeName + */ + _getAttributeValues(dracoGeometry, attribute) { + const TypedArrayCtor = DRACO_DATA_TYPE_TO_TYPED_ARRAY_MAP[attribute.data_type]; + if (!TypedArrayCtor) { + // eslint-disable-next-line no-console + console.warn(`DRACO: Unsupported attribute type ${attribute.data_type}`); + return null; + } + const numComponents = attribute.num_components; + const numPoints = dracoGeometry.num_points(); + const numValues = numPoints * numComponents; + const byteLength = numValues * TypedArrayCtor.BYTES_PER_ELEMENT; + const dataType = getDracoDataType(this.draco, TypedArrayCtor); + let value; + const ptr = this.draco._malloc(byteLength); + try { + const dracoAttribute = this.decoder.GetAttribute(dracoGeometry, attribute.attribute_index); + this.decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, dracoAttribute, dataType, byteLength, ptr); + value = new TypedArrayCtor(this.draco.HEAPF32.buffer, ptr, numValues).slice(); + } + finally { + this.draco._free(ptr); + } + return { value, size: numComponents }; + } + // Attribute names + /** + * DRACO does not store attribute names - We need to deduce an attribute name + * for each attribute + _getAttributeNames( + dracoGeometry: Mesh | PointCloud, + options: DracoParseOptions + ): {[unique_id: number]: string} { + const attributeNames: {[unique_id: number]: string} = {}; + for (let attributeId = 0; attributeId < dracoGeometry.num_attributes(); attributeId++) { + const dracoAttribute = this.decoder.GetAttribute(dracoGeometry, attributeId); + const attributeName = this._deduceAttributeName(dracoAttribute, options); + attributeNames[attributeName] = attributeName; + } + return attributeNames; + } + */ + /** + * Deduce an attribute name. + * @note DRACO does not save attribute names, just general type (POSITION, COLOR) + * to help optimize compression. We generate GLTF compatible names for the Draco-recognized + * types + * @param attributeData + */ + _deduceAttributeName(attribute, options) { + // Deduce name based on application provided map + const uniqueId = attribute.unique_id; + for (const [attributeName, attributeUniqueId] of Object.entries(options.extraAttributes || {})) { + if (attributeUniqueId === uniqueId) { + return attributeName; + } + } + // Deduce name based on attribute type + const thisAttributeType = attribute.attribute_type; + for (const dracoAttributeConstant in DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP) { + const attributeType = this.draco[dracoAttributeConstant]; + if (attributeType === thisAttributeType) { + // TODO - Return unique names if there multiple attributes per type + // (e.g. multiple TEX_COORDS or COLORS) + return DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP[dracoAttributeConstant]; + } + } + // Look up in metadata + // TODO - shouldn't this have priority? + const entryName = options.attributeNameEntry || "name"; + if (attribute.metadata[entryName]) { + return attribute.metadata[entryName].string; + } + // Attribute of "GENERIC" type, we need to assign some name + return `CUSTOM_ATTRIBUTE_${uniqueId}`; + } + // METADATA EXTRACTION + /** Get top level metadata */ + _getTopLevelMetadata(dracoGeometry) { + const dracoMetadata = this.decoder.GetMetadata(dracoGeometry); + return this._getDracoMetadata(dracoMetadata); + } + /** Get per attribute metadata */ + _getAttributeMetadata(dracoGeometry, attributeId) { + const dracoMetadata = this.decoder.GetAttributeMetadata(dracoGeometry, attributeId); + return this._getDracoMetadata(dracoMetadata); + } + /** + * Extract metadata field values + * @param dracoMetadata + * @returns + */ + _getDracoMetadata(dracoMetadata) { + // The not so wonderful world of undocumented Draco APIs :( + if (!dracoMetadata || !dracoMetadata.ptr) { + return {}; + } + const result = {}; + const numEntries = this.metadataQuerier.NumEntries(dracoMetadata); + for (let entryIndex = 0; entryIndex < numEntries; entryIndex++) { + const entryName = this.metadataQuerier.GetEntryName(dracoMetadata, entryIndex); + result[entryName] = this._getDracoMetadataField(dracoMetadata, entryName); + } + return result; + } + /** + * Extracts possible values for one metadata entry by name + * @param dracoMetadata + * @param entryName + */ + _getDracoMetadataField(dracoMetadata, entryName) { + const dracoArray = new this.draco.DracoInt32Array(); + try { + // Draco metadata fields can hold int32 arrays + this.metadataQuerier.GetIntEntryArray(dracoMetadata, entryName, dracoArray); + const intArray = getInt32Array(dracoArray); + return { + int: this.metadataQuerier.GetIntEntry(dracoMetadata, entryName), + string: this.metadataQuerier.GetStringEntry(dracoMetadata, entryName), + double: this.metadataQuerier.GetDoubleEntry(dracoMetadata, entryName), + intArray + }; + } + finally { + this.draco.destroy(dracoArray); + } + } + // QUANTIZED ATTRIBUTE SUPPORT (NO DECOMPRESSION) + /** Skip transforms for specific attribute types */ + _disableAttributeTransforms(options) { + const { quantizedAttributes = [], octahedronAttributes = [] } = options; + const skipAttributes = [...quantizedAttributes, ...octahedronAttributes]; + for (const dracoAttributeName of skipAttributes) { + this.decoder.SkipAttributeTransform(this.draco[dracoAttributeName]); + } + } + /** + * Extract (and apply?) Position Transform + * @todo not used + */ + _getQuantizationTransform(dracoAttribute, options) { + const { quantizedAttributes = [] } = options; + const attribute_type = dracoAttribute.attribute_type(); + const skip = quantizedAttributes.map(type => this.decoder[type]).includes(attribute_type); + if (skip) { + const transform = new this.draco.AttributeQuantizationTransform(); + try { + if (transform.InitFromAttribute(dracoAttribute)) { + return { + quantization_bits: transform.quantization_bits(), + range: transform.range(), + min_values: new Float32Array([1, 2, 3]).map(i => transform.min_value(i)) + }; + } + } + finally { + this.draco.destroy(transform); + } + } + return null; + } + _getOctahedronTransform(dracoAttribute, options) { + const { octahedronAttributes = [] } = options; + const attribute_type = dracoAttribute.attribute_type(); + const octahedron = octahedronAttributes + .map(type => this.decoder[type]) + .includes(attribute_type); + if (octahedron) { + const transform = new this.draco.AttributeQuantizationTransform(); + try { + if (transform.InitFromAttribute(dracoAttribute)) { + return { + quantization_bits: transform.quantization_bits() + }; + } + } + finally { + this.draco.destroy(transform); + } + } + return null; + } +} +/** + * Get draco specific data type by TypedArray constructor type + * @param attributeType + * @returns draco specific data type + */ +function getDracoDataType(draco, attributeType) { + switch (attributeType) { + case Float32Array: + return draco.DT_FLOAT32; + case Int8Array: + return draco.DT_INT8; + case Int16Array: + return draco.DT_INT16; + case Int32Array: + return draco.DT_INT32; + case Uint8Array: + return draco.DT_UINT8; + case Uint16Array: + return draco.DT_UINT16; + case Uint32Array: + return draco.DT_UINT32; + default: + return draco.DT_INVALID; + } +} +/** + * Copy a Draco int32 array into a JS typed array + */ +function getInt32Array(dracoArray) { + const numValues = dracoArray.size(); + const intArray = new Int32Array(numValues); + for (let i = 0; i < numValues; i++) { + intArray[i] = dracoArray.GetValue(i); + } + return intArray; +} +/** + * Copy a Draco int32 array into a JS typed array + */ +function getUint32Array(dracoArray) { + const numValues = dracoArray.size(); + const intArray = new Int32Array(numValues); + for (let i = 0; i < numValues; i++) { + intArray[i] = dracoArray.GetValue(i); + } + return intArray; +} +//# sourceMappingURL=draco-parser.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/loader/draco-types.d.ts b/@flywave/flywave-draco/src/loader/draco-types.d.ts new file mode 100644 index 0000000..c11125f --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-types.d.ts @@ -0,0 +1,70 @@ +import * as THREE from "three"; +export interface DracoMetadataEntry { + int: number; + string: string; + double: number; + intArray: Int32Array; +} +/** For attributes that have not been fully decompressed */ +export interface DracoQuantizationTransform { + quantization_bits?: number; + range?: number; + min_values?: Float32Array; +} +/** For attributes that have not been fully decompressed */ +export interface DracoOctahedronTransform { + quantization_bits?: number; +} +/** Draco attribute fields */ +export interface DracoAttribute { + unique_id: number; + num_components: number; + attribute_type: number; + data_type: number; + byte_offset: number; + byte_stride: number; + normalized: boolean; + name?: string; + quantization_transform?: DracoQuantizationTransform; + octahedron_transform?: DracoOctahedronTransform; + metadata: { + [key: string]: DracoMetadataEntry; + }; + attribute_index: number; +} +/** + * Draco format specific data + * The `data.loaderData` field will have this layout when `data.loader === 'draco'`. + * @todo Metadata should also be available in normalized form in a standard `Schema`. + */ +export interface DracoLoaderData { + geometry_type: number; + num_attributes: number; + num_points: number; + num_faces: number; + metadata: { + [entry: string]: DracoMetadataEntry; + }; + attributes: { + [unique_id: number]: DracoAttribute; + }; +} +/** + * Mesh with Draco specific data + */ +export interface DracoMesh { + loader: "draco"; + loaderData: DracoLoaderData; + geometry: THREE.BufferGeometry; + header: { + vertexCount: number; + boundingBox: THREE.Box3; + }; + schema: { + attributes: { + [name: string]: THREE.BufferAttribute; + }; + index?: THREE.BufferAttribute; + metadata: Record; + }; +} diff --git a/@flywave/flywave-draco/src/loader/draco-types.js b/@flywave/flywave-draco/src/loader/draco-types.js new file mode 100644 index 0000000..c01294e --- /dev/null +++ b/@flywave/flywave-draco/src/loader/draco-types.js @@ -0,0 +1,3 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +export {}; +//# sourceMappingURL=draco-types.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/loader/utils/get-draco-schema.d.ts b/@flywave/flywave-draco/src/loader/utils/get-draco-schema.d.ts new file mode 100644 index 0000000..4783ad9 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/utils/get-draco-schema.d.ts @@ -0,0 +1,11 @@ +import * as THREE from "three"; +/** Extract an arrow-like schema from a Draco mesh */ +interface DracoSchema { + attributes: { + [name: string]: THREE.BufferAttribute; + }; + index?: THREE.BufferAttribute; + metadata: Record; +} +export declare function getDracoSchema(geometry: THREE.BufferGeometry, loaderData: any): DracoSchema; +export {}; diff --git a/@flywave/flywave-draco/src/loader/utils/get-draco-schema.js b/@flywave/flywave-draco/src/loader/utils/get-draco-schema.js new file mode 100644 index 0000000..62454c5 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/utils/get-draco-schema.js @@ -0,0 +1,38 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import * as THREE from "three"; +export function getDracoSchema(geometry, loaderData) { + const schema = { + attributes: {}, + metadata: makeMetadata(loaderData.metadata) + }; + // Process vertex attributes + geometry.attributes = geometry.attributes || {}; + for (const [name, attribute] of Object.entries(geometry.attributes)) { + if (attribute instanceof THREE.BufferAttribute) { + schema.attributes[name] = createThreeAttribute(name, attribute, loaderData.attributes[name]); + } + } + // Process indices + if (geometry.index) { + schema.index = createThreeIndex(geometry.index); + } + return schema; +} +function createThreeAttribute(name, attribute, loaderData) { + return new THREE.BufferAttribute(attribute.array, attribute.itemSize, attribute.normalized).setUsage(THREE.StaticDrawUsage); +} +function createThreeIndex(index) { + return new THREE.BufferAttribute(index.array, 1 // The itemSize of the index is fixed to 1 + ).setUsage(THREE.StaticDrawUsage); +} +function makeMetadata(metadata) { + const result = {}; + for (const key in metadata) { + result[key] = { + value: metadata[key].value, + type: typeof metadata[key].value + }; + } + return result; +} +//# sourceMappingURL=get-draco-schema.js.map \ No newline at end of file diff --git a/@flywave/flywave-draco/src/loader/utils/version.d.ts b/@flywave/flywave-draco/src/loader/utils/version.d.ts new file mode 100644 index 0000000..7594755 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/utils/version.d.ts @@ -0,0 +1 @@ +export declare const VERSION: any; diff --git a/@flywave/flywave-draco/src/loader/utils/version.js b/@flywave/flywave-draco/src/loader/utils/version.js new file mode 100644 index 0000000..990f2c8 --- /dev/null +++ b/@flywave/flywave-draco/src/loader/utils/version.js @@ -0,0 +1,6 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +// Version constant cannot be imported, it needs to correspond to the build version of **this** module. +// __VERSION__ is injected by babel-plugin-version-inline +// @ts-ignore TS2304: Cannot find name '__VERSION__'. +export const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest"; +//# sourceMappingURL=version.js.map \ No newline at end of file diff --git a/@flywave/flywave-examples/codebrowser.d.ts b/@flywave/flywave-examples/codebrowser.d.ts new file mode 100644 index 0000000..4c883b5 --- /dev/null +++ b/@flywave/flywave-examples/codebrowser.d.ts @@ -0,0 +1 @@ +import "style-loader!css-loader!highlight.js/styles/default.css"; diff --git a/@flywave/flywave-examples/codebrowser.js.map b/@flywave/flywave-examples/codebrowser.js.map new file mode 100644 index 0000000..cde0968 --- /dev/null +++ b/@flywave/flywave-examples/codebrowser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"codebrowser.js","sourceRoot":"","sources":["codebrowser.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,OAAO,yDAAyD,CAAC;AAEjE,OAAO,KAAK,IAAI,MAAM,cAAc,CAAC;AAErC,CAAC,GAAG,EAAE;IACF,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,QAAQ,GAAG,gCAAgC,CAAC;IAElD,KAAK,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;SACrC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACb,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC,CAAC;SACD,IAAI,CAAC,QAAQ,CAAC,EAAE;QACb,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;QAC/D,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAErE,IAAI,eAAe,GAAG,mBAAmB,CAAC,KAAK,CAAC;QAChD,eAAe,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;YAClE,OAAO,GAAG,EAAE,YAAY,QAAQ,CAAC,QAAQ,QAAQ,kBAAkB,CAC/D,OAAO,GAAG,GAAG,GAAG,EAAE,GAAG,KAAK,CAC7B,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,WAAW,CAAC,SAAS,GAAG,eAAe,CAAC;IAC5C,CAAC,CAAC,CAAC;AACX,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/@flywave/flywave-examples/decoder/decoder.d.ts b/@flywave/flywave-examples/decoder/decoder.d.ts new file mode 100644 index 0000000..1170bfd --- /dev/null +++ b/@flywave/flywave-examples/decoder/decoder.d.ts @@ -0,0 +1 @@ +import "@flywave/flywave.gl/DecoderBundleMain"; diff --git a/@flywave/flywave-examples/decoder/decoder.js.map b/@flywave/flywave-examples/decoder/decoder.js.map new file mode 100644 index 0000000..411788f --- /dev/null +++ b/@flywave/flywave-examples/decoder/decoder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"decoder.js","sourceRoot":"","sources":["decoder.ts"],"names":[],"mappings":"AACA,OAAQ,uCAAuC,CAAC"} \ No newline at end of file diff --git a/@flywave/flywave-examples/example-browser.d.ts b/@flywave/flywave-examples/example-browser.d.ts new file mode 100644 index 0000000..4585ca7 --- /dev/null +++ b/@flywave/flywave-examples/example-browser.d.ts @@ -0,0 +1,11 @@ +type ExampleDefinitions = Record; +/** + * Example browser HTML / DOM app. + */ +declare function exampleBrowser(exampleDefinitions: ExampleDefinitions): void; +/** + * Maps pageUrl to srcUrl. + * + * Loaded using + + + + + + + `; + // 清空容器并添加 iframe + const container = containerRef.current; + while (container.firstChild) { + container.removeChild(container.firstChild); + } + container.appendChild(iframe); + // 写入 iframe 内容 + const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document; + if (iframeDoc) { + iframeDoc.open(); + iframeDoc.write(iframeContent); + iframeDoc.close(); + } + // 清理函数 + return () => { + if (container.firstChild === iframe) { + container.removeChild(iframe); + } + }; + }, []); + return
; +}; +export default FlywaveGlobe; +//# sourceMappingURL=FlywaveGlobe.js.map \ No newline at end of file diff --git a/docs/src/components/FlywaveGlobe.js.map b/docs/src/components/FlywaveGlobe.js.map new file mode 100644 index 0000000..15b5d31 --- /dev/null +++ b/docs/src/components/FlywaveGlobe.js.map @@ -0,0 +1 @@ +{"version":3,"file":"FlywaveGlobe.js","sourceRoot":"","sources":["FlywaveGlobe.tsx"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/docs/src/examples/index.d.ts b/docs/src/examples/index.d.ts new file mode 100644 index 0000000..80f0137 --- /dev/null +++ b/docs/src/examples/index.d.ts @@ -0,0 +1,2 @@ +import type { Example } from "../pages/example-detail"; +export declare const EXAMPLES_CONFIG: Example[]; diff --git a/docs/src/examples/index.js b/docs/src/examples/index.js new file mode 100644 index 0000000..755ed20 --- /dev/null +++ b/docs/src/examples/index.js @@ -0,0 +1,88 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { EXAMPLE_CATEGORIES } from "@flywave/flywave-examples/src/example-categories"; +// 动态导入所有示例配置 +const examples = []; +// 通过模块导入方式动态获取示例列表和配置 +// 仅扫描@flywave/flywave-examples/src目录下的示例文件夹 +const exampleContext = require.context("@flywave/flywave-examples/src", true, /config\.ts$/); +// 用于跟踪已添加的示例ID,防止重复 +const addedExampleIds = new Set(); +// 获取当前语言环境 +const getCurrentLocale = () => { + if (typeof window !== 'undefined') { + // 尝试从 URL 获取语言参数 + const urlParams = new URLSearchParams(window.location.search); + const lang = urlParams.get('locale'); + if (lang && (lang === 'zh' || lang === 'en')) + return lang; + // 尝试从 localStorage 获取 + const storedLocale = localStorage.getItem('locale'); + if (storedLocale && (storedLocale === 'zh' || storedLocale === 'en')) + return storedLocale; + // 尝试从 Docusaurus 的语言路径获取 + if (window.location.pathname.startsWith('/zh/')) { + return 'zh'; + } + // 检查 HTML 根元素的语言属性 + const htmlLang = document.documentElement.lang; + if (htmlLang && (htmlLang.includes('zh') || htmlLang.includes('en'))) { + return htmlLang.includes('zh') ? 'zh' : 'en'; + } + } + return 'en'; // 默认语言 +}; +// 动态导入每个示例的配置和代码 +exampleContext.keys().forEach((configKey) => { + try { + // 确保只处理@flywave/flywave-examples/src目录下的config.ts文件 + if (configKey.startsWith("./") && configKey.includes("/config.ts")) { + // 从路径中提取示例名称 + const examplePath = configKey.replace("./", "").replace("/config.ts", ""); + const pathParts = examplePath.split("/"); + const exampleId = pathParts[0]; + // 检查示例是否已经添加过,防止重复 + if (exampleId && exampleId !== "src" && !addedExampleIds.has(exampleId)) { + // 导入配置文件 + const config = exampleContext(configKey).default; + // 获取编译后的示例代码作为原始字符串资源 + let code = ""; + try { + const jsModule = require(`!!raw-loader!@flywave/flywave-examples/src/${exampleId}/index.js`); + code = jsModule.default || jsModule; + } + catch (codeError) { + console.warn(`无法获取示例代码: ${exampleId}`, codeError); + } + // 根据当前语言环境决定使用哪种语言的标题和描述 + const currentLocale = getCurrentLocale(); + const title = currentLocale === 'zh' && config.titleZh ? config.titleZh : config.title; + const description = currentLocale === 'zh' && config.descriptionZh ? config.descriptionZh : config.description; + // 根据分类code获取分类名称(根据当前语言环境) + const categoryInfo = EXAMPLE_CATEGORIES.find(cat => cat.code === config.code); + let categoryName = config.code || "未分类"; + if (categoryInfo) { + categoryName = currentLocale === 'zh' && categoryInfo.nameZh ? categoryInfo.nameZh : categoryInfo.name; + } + examples.push({ + id: exampleId, + title: title, + description: description, + category: categoryName, // 使用映射后的分类名称 + categoryCode: config.code, // 保存分类code用于排序 + order: config.order || 0, // 保存排序字段 + code: code, + language: "javascript", + image: config.thumbnail || "" + }); + // 记录已添加的示例ID + addedExampleIds.add(exampleId); + } + } + } + catch (error) { + console.error(`加载示例配置失败: ${configKey}`, error); + } +}); +// 导出示例配置 +export const EXAMPLES_CONFIG = examples; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/docs/src/examples/index.js.map b/docs/src/examples/index.js.map new file mode 100644 index 0000000..6fc66cb --- /dev/null +++ b/docs/src/examples/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/docs/src/pages/example-detail.d.ts b/docs/src/pages/example-detail.d.ts new file mode 100644 index 0000000..9066452 --- /dev/null +++ b/docs/src/pages/example-detail.d.ts @@ -0,0 +1,13 @@ +import React from "react"; +export interface Example { + id: string; + title: string; + description: string; + category: string; + categoryCode?: string; + order?: number; + code: string; + language: string; + image?: string; +} +export default function ExampleDetail(): React.JSX.Element; diff --git a/docs/src/pages/example-detail.js b/docs/src/pages/example-detail.js new file mode 100644 index 0000000..16690bb --- /dev/null +++ b/docs/src/pages/example-detail.js @@ -0,0 +1,534 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import React, { useState, useRef, useEffect, useCallback, useReducer } from "react"; +import { useLocation } from "@docusaurus/router"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import Layout from "@theme/Layout"; +import { Editor } from "@monaco-editor/react"; +import styles from "./example-detail.module.css"; +import { EXAMPLES_CONFIG } from "../examples"; +import { EXAMPLE_CATEGORIES } from "@flywave/flywave-examples/src/example-categories"; +import { CESIUM_ION_TOKEN } from "@flywave/flywave-examples/src/token-config"; +// 使用 useReducer 来强制更新组件 +const updateReducer = (state) => state + 1; +export default function ExampleDetail() { + const location = useLocation(); + const { siteConfig } = useDocusaurusContext(); + const previewRef = useRef(null); + const [exampleId, setExampleId] = useState("hello-world"); + const [code, setCode] = useState(""); + const [isRunning, setIsRunning] = useState(false); + const [editorWidth, setEditorWidth] = useState(50); + const [isResizing, setIsResizing] = useState(false); + const [isDarkTheme, setIsDarkTheme] = useState(true); + const [copyrightText, setCopyrightText] = useState(""); + const [isLoading, setIsLoading] = useState(true); + const [, forceUpdate] = useReducer(updateReducer, 0); // 用于强制更新 + // 获取当前示例对象 + const currentExample = EXAMPLES_CONFIG.find(ex => ex.id === exampleId) || EXAMPLES_CONFIG[0]; + // 初始化版权信息 + useEffect(() => { + const config = siteConfig; + if (config?.customFields?.copyright) { + setCopyrightText(config.customFields.copyright); + } + else if (config?.themeConfig?.footer?.copyright) { + setCopyrightText(config.themeConfig.footer.copyright); + } + else { + setCopyrightText(`Copyright © ${new Date().getFullYear()} flywave.gl. Built with Docusaurus.`); + } + }, [siteConfig]); + // 初始化和处理URL参数 + useEffect(() => { + const initExample = () => { + if (EXAMPLES_CONFIG.length === 0) { + console.error("示例配置为空"); + setIsLoading(false); + return; + } + // 支持两种URL参数格式:查询参数 ?id=... 或路径参数 /example-detail/... + // 首先尝试从查询参数获取 + const urlParams = new URLSearchParams(location.search); + let urlExampleId = urlParams.get("id"); + // 如果查询参数中没有找到id,尝试从路径中解析(处理类似 /example-detail/xxx 的格式) + if (!urlExampleId) { + const pathSegments = location.pathname.split('/'); + // 查找可能包含id的路径段 + for (let i = 0; i < pathSegments.length; i++) { + if (pathSegments[i] === 'example-detail' && i + 1 < pathSegments.length) { + const potentialId = pathSegments[i + 1]; + // 检查是否是有效的示例ID(存在于EXAMPLES_CONFIG中) + if (EXAMPLES_CONFIG.some(ex => ex.id === potentialId)) { + urlExampleId = potentialId; + break; + } + } + } + } + // 如果仍然没有找到,使用默认值 + if (!urlExampleId) { + urlExampleId = "hello-world"; + } + // 确保示例存在 + const targetExample = EXAMPLES_CONFIG.find(ex => ex.id === urlExampleId) || EXAMPLES_CONFIG[0]; + // 设置示例ID和代码 + setExampleId(targetExample.id); + setCode(targetExample.code); + setIsLoading(false); + // 立即运行示例,使用目标示例的代码,避免依赖可能未更新的状态 + setTimeout(() => { + if (previewRef.current) { + runCodeWithContent(targetExample.code); + } + }, 50); + }; + // 确保 EXAMPLES_CONFIG 已加载 + if (EXAMPLES_CONFIG.length > 0) { + initExample(); + } + else { + // 如果 EXAMPLES_CONFIG 还没加载,等待一会儿再试 + const timer = setTimeout(initExample, 100); + return () => clearTimeout(timer); + } + }, [location.pathname, location.search, EXAMPLES_CONFIG.length]); // 监听 EXAMPLES_CONFIG 长度变化 + // 监听浏览器的 popstate 事件,处理前进后退和语言切换 + useEffect(() => { + const handlePopState = () => { + // URL发生变化时重新解析参数 + const urlParams = new URLSearchParams(location.search); + let urlExampleId = urlParams.get("id"); + if (!urlExampleId) { + const pathSegments = location.pathname.split('/'); + for (let i = 0; i < pathSegments.length; i++) { + if (pathSegments[i] === 'example-detail' && i + 1 < pathSegments.length) { + const potentialId = pathSegments[i + 1]; + if (EXAMPLES_CONFIG.some(ex => ex.id === potentialId)) { + urlExampleId = potentialId; + break; + } + } + } + } + if (!urlExampleId) { + urlExampleId = "hello-world"; + } + const targetExample = EXAMPLES_CONFIG.find(ex => ex.id === urlExampleId) || EXAMPLES_CONFIG[0]; + if (targetExample.id !== exampleId) { + setExampleId(targetExample.id); + setCode(targetExample.code); + setTimeout(() => { + if (previewRef.current) { + runCodeWithContent(targetExample.code); + } + }, 0); + } + }; + window.addEventListener('popstate', handlePopState); + return () => { + window.removeEventListener('popstate', handlePopState); + }; + }, [location.pathname, location.search, EXAMPLES_CONFIG, exampleId]); + // 监听主题变化 + useEffect(() => { + const handleThemeChange = () => { + const isDark = document.documentElement.getAttribute("data-theme") === "dark"; + setIsDarkTheme(isDark); + }; + handleThemeChange(); + const observer = new MutationObserver(handleThemeChange); + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ["data-theme"] + }); + return () => observer.disconnect(); + }, []); + // 处理拖拽事件 + useEffect(() => { + const handleMouseMove = (e) => { + if (!isResizing) + return; + const container = document.querySelector(`.${styles.panelsContainer}`); + if (!container) + return; + const containerRect = container.getBoundingClientRect(); + const relativeX = e.clientX - containerRect.left; + const percentage = Math.min(Math.max((relativeX / containerRect.width) * 100, 20), 80); + setEditorWidth(percentage); + }; + const handleMouseUp = () => setIsResizing(false); + if (isResizing) { + document.addEventListener("mousemove", handleMouseMove); + document.addEventListener("mouseup", handleMouseUp); + document.body.style.cursor = "col-resize"; + document.body.style.userSelect = "none"; + } + return () => { + document.removeEventListener("mousemove", handleMouseMove); + document.removeEventListener("mouseup", handleMouseUp); + document.body.style.cursor = ""; + document.body.style.userSelect = ""; + }; + }, [isResizing]); + const handleRunCode = useCallback(() => { + runCodeWithContent(code); + }, [code]); + const handleResetCode = () => { + setCode(currentExample.code); + }; + const handleFullscreen = () => { + if (previewRef.current) { + const iframe = previewRef.current.querySelector("iframe"); + if (iframe) { + iframe.requestFullscreen?.().catch(err => { + console.error("全屏模式错误:", err); + }); + } + } + }; + const handleBackToHome = () => { + // 获取当前语言前缀 + const currentLangPrefix = window.location.pathname.startsWith('/zh/') ? '/zh' : + window.location.pathname.startsWith('/en/') ? '/en' : ''; + // 返回示例页面,保持语言前缀,确保路径格式正确 + // 修复:移除多余的斜杠,统一使用不带结尾斜杠的格式 + const homeUrl = currentLangPrefix ? `${currentLangPrefix}/examples` : '/examples'; + window.location.href = homeUrl; + }; + const handleExampleSelect = (selectedExampleId) => { + // 确保示例存在 + const selectedExample = EXAMPLES_CONFIG.find(ex => ex.id === selectedExampleId); + if (!selectedExample) { + console.error(`找不到示例: ${selectedExampleId}`); + return; + } + // 同时更新ID和代码,确保同步 + setExampleId(selectedExample.id); + setCode(selectedExample.code); + // 更新URL参数 + const newUrl = new URL(window.location.href); + newUrl.searchParams.set('id', selectedExample.id); + window.history.replaceState({}, '', newUrl.toString()); + // 立即运行新代码 + setTimeout(() => { + if (previewRef.current) { + runCodeWithContent(selectedExample.code); + } + }, 0); + }; + // 新增一个函数,直接使用代码内容运行,避免依赖状态 + const runCodeWithContent = (codeContent) => { + if (!previewRef.current || !codeContent) + return; + setIsRunning(true); + // 清除之前的预览内容 + previewRef.current.innerHTML = '
正在加载示例...
'; + // 创建 iframe 来运行代码 + const iframe = document.createElement("iframe"); + iframe.style.width = "100%"; + iframe.style.height = "100%"; + iframe.style.border = "none"; + iframe.setAttribute("title", "示例预览"); + // 添加加载超时处理 + const timeoutId = setTimeout(() => { + if (previewRef.current) { + previewRef.current.innerHTML = '
加载超时,请检查网络连接或重试
'; + setIsRunning(false); + } + }, 15000); + // 等待 iframe 加载完成 + iframe.onload = () => { + clearTimeout(timeoutId); + try { + const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document; + if (!iframeDoc) { + throw new Error("无法访问 iframe 文档"); + } + const isDarkTheme = document.documentElement.getAttribute("data-theme") === "dark"; + iframeDoc.open(); + iframeDoc.write(` + + + + + + + + + + + + + `); + iframeDoc.close(); + } + catch (error) { + clearTimeout(timeoutId); + if (previewRef.current) { + previewRef.current.innerHTML = `
运行错误: ${error.message}
`; + } + setIsRunning(false); + } + finally { + setIsRunning(false); + } + }; + // iframe 加载错误处理 + iframe.onerror = () => { + clearTimeout(timeoutId); + if (previewRef.current) { + previewRef.current.innerHTML = '
iframe 加载失败,请检查网络连接或重试
'; + } + setIsRunning(false); + }; + // 将 iframe 添加到预览区域 + previewRef.current.innerHTML = ""; + previewRef.current.appendChild(iframe); + }; + // 按类别分组示例 + const examplesByCategory = {}; + EXAMPLES_CONFIG.forEach(example => { + const categoryKey = example.categoryCode || example.category; + if (!examplesByCategory[categoryKey]) { + examplesByCategory[categoryKey] = []; + } + examplesByCategory[categoryKey].push(example); + }); + // 对每个分类中的示例按order字段排序 + Object.keys(examplesByCategory).forEach(categoryKey => { + examplesByCategory[categoryKey].sort((a, b) => { + if (a.order !== undefined && b.order !== undefined) { + return a.order - b.order; + } + if (a.order !== undefined) { + return -1; + } + if (b.order !== undefined) { + return 1; + } + return a.title.localeCompare(b.title); + }); + }); + // 获取当前语言环境 + const currentLocale = typeof window !== 'undefined' ? + (window.location.pathname.startsWith('/zh/') || document.documentElement.lang.includes('zh') ? 'zh' : 'en') : 'en'; + // 根据EXAMPLE_CATEGORIES定义的顺序对分类进行排序 + const sortedCategories = [...EXAMPLE_CATEGORIES]; + const categoriesWithExamples = sortedCategories.filter(category => examplesByCategory[category.code] && examplesByCategory[category.code].length > 0); + const definedCategoryCodes = new Set(EXAMPLE_CATEGORIES.map(cat => cat.code)); + const undefinedCategories = Object.keys(examplesByCategory).filter(categoryCode => !definedCategoryCodes.has(categoryCode)); + if (isLoading || EXAMPLES_CONFIG.length === 0) { + //@ts-ignore + return ( +
+
+
加载中...
+
+
+
); + } + return ( + //@ts-ignore + +
+
+
+
+

+ {currentLocale === 'zh' ? '示例列表' : 'Example List'} +

+
+ +
+
+
+ {/* 显示已定义的分类 */} + {categoriesWithExamples.map(category => { + const examples = examplesByCategory[category.code] || []; + return (
+
+ {currentLocale === 'zh' && category.nameZh ? category.nameZh : category.name} +
+ {examples.map(ex => (
handleExampleSelect(ex.id)}> +
+ {ex.image ? ({ex.title}) : (
+ {ex.title} +
)} +
+
+
+ {ex.title} +
+
+ {ex.description} +
+
+
))} +
); + })} + + {/* 显示未定义的分类 */} + {undefinedCategories.map(categoryCode => { + const examples = examplesByCategory[categoryCode] || []; + const categoryName = examples.length > 0 ? examples[0].category : categoryCode; + return (
+
{categoryName}
+ {examples.map(ex => (
handleExampleSelect(ex.id)}> +
+ {ex.image ? ({ex.title}) : (
+ {ex.title} +
)} +
+
+
+ {ex.title} +
+
+ {ex.description} +
+
+
))} +
); + })} +
+
+
+
+
+

{currentExample.title}

+
+ + + +
+
+
+
+
+
+ {currentLocale === 'zh' ? "代码编辑器" : "Code Editor"} +
+
+ setCode(value || "")} theme={isDarkTheme ? "vs-dark" : "light"} options={{ + minimap: { enabled: false }, + scrollBeyondLastLine: false, + automaticLayout: true, + fontSize: 13, + lineNumbers: "on", + roundedSelection: false, + smoothScrolling: true, + wordWrap: "on", + folding: true, + renderLineHighlight: "all", + scrollbar: { + vertical: "auto", + horizontal: "auto" + } + }}/> +
+
setIsResizing(true)}/> +
+
+
+ {currentLocale === 'zh' ? "实时预览" : "Live Preview"} +
+
+
+
+

{currentLocale === 'zh' ? "实时预览区域" : "Live Preview Area"}

+

{currentLocale === 'zh' ? '点击"运行代码"按钮查看效果' : 'Click "Run Code" button to see the result'}

+

{currentLocale === 'zh' ? `当前示例: ${currentExample.title}` : `Current Example: ${currentExample.title}`}

+
+
+
+
+
+
+
+ {/* 动态读取配置的底部版权信息 */} +
+
{copyrightText}
+
+
+ ); +} +//# sourceMappingURL=example-detail.js.map \ No newline at end of file diff --git a/docs/src/pages/example-detail.js.map b/docs/src/pages/example-detail.js.map new file mode 100644 index 0000000..977d3c8 --- /dev/null +++ b/docs/src/pages/example-detail.js.map @@ -0,0 +1 @@ +{"version":3,"file":"example-detail.js","sourceRoot":"","sources":["example-detail.tsx"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/docs/src/pages/examples.d.ts b/docs/src/pages/examples.d.ts new file mode 100644 index 0000000..2582b56 --- /dev/null +++ b/docs/src/pages/examples.d.ts @@ -0,0 +1,2 @@ +import type { ReactNode } from "react"; +export default function Examples(): ReactNode; diff --git a/docs/src/pages/examples.js b/docs/src/pages/examples.js new file mode 100644 index 0000000..3633ea0 --- /dev/null +++ b/docs/src/pages/examples.js @@ -0,0 +1,133 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import React from "react"; +import Link from "@docusaurus/Link"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import Layout from "@theme/Layout"; +import Translate from '@docusaurus/Translate'; +const Heading = require("@theme/Heading").default; +import styles from "./examples.module.css"; +import { EXAMPLES_CONFIG } from "../examples"; +import { EXAMPLE_CATEGORIES } from "@flywave/flywave-examples/src/example-categories"; +function ExamplesHeader() { + const { siteConfig } = useDocusaurusContext(); + return (
+
+ + + Examples + + +

+ + Learn various features of flywave.gl through practical examples + +

+
+
); +} +function getExampleLink(exampleId) { + // 获取当前语言前缀 + const currentLangPrefix = typeof window !== 'undefined' + ? (window.location.pathname.startsWith('/zh/') ? '/zh' : + window.location.pathname.startsWith('/en/') ? '/en' : '') + : ''; + // 跳转到示例详情页,保持语言前缀,确保路径格式正确 + // 修复:移除多余的斜杠,统一使用不带结尾斜杠的格式 + return currentLangPrefix ? `${currentLangPrefix}/example-detail?id=${exampleId}` : `/example-detail?id=${exampleId}`; +} +function ExampleCard({ example }) { + return (
+
+ {example.image ? ({example.title}) : (
{example.title}
)} +
+
+

{example.title}

+

{example.description}

+

{example.category}

+ + + View Details + + +
+
); +} +export default function Examples() { + // 按类别分组示例 + const examplesByCategory = {}; + EXAMPLES_CONFIG.forEach(example => { + // 使用categoryCode作为键进行分组,如果没有则使用category + const categoryKey = example.categoryCode || example.category; + if (!examplesByCategory[categoryKey]) { + examplesByCategory[categoryKey] = []; + } + examplesByCategory[categoryKey].push(example); + }); + // 对每个分类中的示例按order字段排序 + Object.keys(examplesByCategory).forEach(categoryKey => { + examplesByCategory[categoryKey].sort((a, b) => { + // 如果都有order字段,按order排序 + if (a.order !== undefined && b.order !== undefined) { + return a.order - b.order; + } + // 如果只有a有order字段,a排在前面 + if (a.order !== undefined) { + return -1; + } + // 如果只有b有order字段,b排在前面 + if (b.order !== undefined) { + return 1; + } + // 如果都没有order字段,按标题排序 + return a.title.localeCompare(b.title); + }); + }); + // 根据EXAMPLE_CATEGORIES定义的顺序对分类进行排序 + const sortedCategories = [...EXAMPLE_CATEGORIES]; + // 获取当前语言环境 + const currentLocale = typeof window !== 'undefined' ? + (window.location.pathname.startsWith('/zh/') || document.documentElement.lang.includes('zh') ? 'zh' : 'en') : 'en'; + // 过滤出有示例的分类 + const categoriesWithExamples = sortedCategories.filter(category => examplesByCategory[category.code] && examplesByCategory[category.code].length > 0); + // 添加没有在EXAMPLE_CATEGORIES中定义但有示例的分类 + const definedCategoryCodes = new Set(EXAMPLE_CATEGORIES.map(cat => cat.code)); + const undefinedCategories = Object.keys(examplesByCategory).filter(categoryCode => !definedCategoryCodes.has(categoryCode)); + return ( + +
+
+ {/* 显示已定义的分类 */} + {categoriesWithExamples.map(category => { + const examples = examplesByCategory[category.code] || []; + return (
+ + {currentLocale === 'zh' && category.nameZh ? category.nameZh : category.name} + +
+ {examples.map(example => (
+ +
))} +
+
); + })} + + {/* 显示未定义的分类 */} + {undefinedCategories.map(categoryCode => { + const examples = examplesByCategory[categoryCode] || []; + const categoryName = examples.length > 0 ? examples[0].category : categoryCode; + return (
+ + {categoryName} + +
+ {examples.map(example => (
+ +
))} +
+
); + })} +
+
+
); +} +//# sourceMappingURL=examples.js.map \ No newline at end of file diff --git a/docs/src/pages/examples.js.map b/docs/src/pages/examples.js.map new file mode 100644 index 0000000..2c08223 --- /dev/null +++ b/docs/src/pages/examples.js.map @@ -0,0 +1 @@ +{"version":3,"file":"examples.js","sourceRoot":"","sources":["examples.tsx"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/docs/src/pages/index.d.ts b/docs/src/pages/index.d.ts new file mode 100644 index 0000000..5869616 --- /dev/null +++ b/docs/src/pages/index.d.ts @@ -0,0 +1,26 @@ +import type { ReactNode } from "react"; +export declare const GlobeIcon: ({ size, color }: { + size?: number; + color?: string; +}) => import("react").JSX.Element; +export declare const GamepadIcon: ({ size, color }: { + size?: number; + color?: string; +}) => import("react").JSX.Element; +export declare const LinkIcon: ({ size, color }: { + size?: number; + color?: string; +}) => import("react").JSX.Element; +export declare const TextIcon: ({ size, color }: { + size?: number; + color?: string; +}) => import("react").JSX.Element; +export declare const ShieldIcon: ({ size, color }: { + size?: number; + color?: string; +}) => import("react").JSX.Element; +export declare const CubeIcon: ({ size, color }: { + size?: number; + color?: string; +}) => import("react").JSX.Element; +export default function Home(): ReactNode; diff --git a/docs/src/pages/index.js b/docs/src/pages/index.js new file mode 100644 index 0000000..fa76d7b --- /dev/null +++ b/docs/src/pages/index.js @@ -0,0 +1,144 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import Link from "@docusaurus/Link"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import Layout from "@theme/Layout"; +import Translate from '@docusaurus/Translate'; +const Heading = require("@theme/Heading").default; +import styles from "./index.module.css"; +//@ts-ignore +import FlywaveGlobe from "@site/src/components/FlywaveGlobe"; +// src/components/icons/index.js +export const GlobeIcon = ({ size = 24, color = "currentColor" }) => ( + + + + ); +export const GamepadIcon = ({ size = 24, color = "currentColor" }) => ( + + + + ); +export const LinkIcon = ({ size = 24, color = "currentColor" }) => ( + + + ); +export const TextIcon = ({ size = 24, color = "currentColor" }) => ( + + ); +export const ShieldIcon = ({ size = 24, color = "currentColor" }) => ( + + ); +export const CubeIcon = ({ size = 24, color = "currentColor" }) => ( + + + + ); +function HomepageHeader() { + const { siteConfig } = useDocusaurusContext(); + return (
+
+
+
+ {siteConfig.title} +

{siteConfig.tagline}

+
+

+ + 一个基于 TypeScript 构建的开源 3D 地图渲染引擎,利用 WebGL 和 Three.js + 实现高性能、可扩展且模块化的地图可视化解决方案。 + +

+
+
+ + + 入门指南 - 5分钟 ⏱️ + + + + + 查看示例 + + +
+
+
+ +
+
+
+
); +} +function FeatureCard({ icon, title, description }) { + return (
+
{icon}
+

{title}

+

{description}

+
); +} +function FeaturesSection() { + return (
+
+
+
+ FEATURES +
+

+ + Flywave.gl 提供全面的 3D 地图渲染能力,专为高性能可视化设计 + +

+
+
+ 多源数据支持} description={全面支持 3D Tiles、地形数据(DEM、Quantized Mesh等)、矢量瓦片等多种数据格式,构建丰富的三维地理信息可视化。}/> + 流畅交互操作} description={优化的地图漫游体验,支持平滑的缩放、旋转和倾斜操作,提供直观自然的3D地图交互体验。}/> + Three.js 深度集成} description={与 Three.js 无缝集成,充分利用 WebGL 的强大功能,便于复用 Three.js 生态资源和扩展自定义功能。}/> + 高级文字系统} description={支持多语言的高质量文本渲染系统,包含中文在内的多种语言显示,以及灵活的标注功能。}/> + TypeScript 优势} description={采用 TypeScript 构建,提供完整的类型定义和智能提示,增强代码可维护性,模块化架构支持按需加载。}/> + 模块化架构} description={基于模块化设计,支持灵活的功能组合和扩展,便于构建高度定制化的3D地图应用。}/> +
+
+
); +} +function QuickStartSection() { + return (
+
+ + + 快速开始 + + +

+ + 要开始使用 flywave.gl,您可以查看我们的示例教程,了解如何创建第一个地图应用。 + +

+
+ + + 查看示例 + + + + + 教程概览 + + +
+
+
); +} +export default function Home() { + return ( + +
+
+ +
+
+ +
+
+
); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/docs/src/pages/index.js.map b/docs/src/pages/index.js.map new file mode 100644 index 0000000..63e36ae --- /dev/null +++ b/docs/src/pages/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/docs/test-server.d.ts b/docs/test-server.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/docs/test-server.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/karma.conf.d.ts b/karma.conf.d.ts new file mode 100644 index 0000000..d623d21 --- /dev/null +++ b/karma.conf.d.ts @@ -0,0 +1,2 @@ +declare function _exports(config: any): void; +export = _exports; diff --git a/scripts/apidocs.d.ts b/scripts/apidocs.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/scripts/apidocs.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/scripts/apidocs.js b/scripts/apidocs.js new file mode 100644 index 0000000..6886233 --- /dev/null +++ b/scripts/apidocs.js @@ -0,0 +1,133 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +/* eslint-disable no-console */ +import { Extractor, ExtractorConfig } from "@microsoft/api-extractor"; +import { execSync } from "child_process"; +import * as fs from "fs"; +import * as path from "path"; +import { createRequire } from "module"; +const require = createRequire(import.meta.url); +/** + * 修复可能导致 acorn 解析错误的内容 + * 基于搜索到的资料:TypeDoc 注释中的花括号需要转义 + */ +function fixAcornConflicts(content) { + return (content + // 转义花括号以避免 acorn 解析错误 + .replace(/{/g, "{") + .replace(/}/g, "}") + .replace(//g, "<T>") + .replace("**Returns:**", "**Returns:**\n\n```typescript\n")); +} +/** + * 处理生成的 Markdown 文件以修复 acorn 解析错误 + */ +function processGeneratedMarkdownFiles() { + const apiDocsPath = path.resolve("docs/docs/api"); + if (!fs.existsSync(apiDocsPath)) { + console.log("API docs directory not found, skipping acorn fixes"); + return; + } + const files = fs.readdirSync(apiDocsPath); + let fixedFiles = 0; + files.forEach(file => { + if (file.endsWith(".md")) { + const filePath = path.join(apiDocsPath, file); + let content = fs.readFileSync(filePath, "utf8"); + // 使用统一的函数处理所有非TypeScript代码块 + content = fixAcornConflicts(content); + fs.writeFileSync(filePath, content); + fixedFiles++; + } + }); + console.log("✅ Fixed acorn conflicts in " + fixedFiles + " markdown files"); +} +async function main() { + const reportFolder = path.resolve("input"); + const reportTempFolder = path.resolve("temp"); + fs.mkdirSync(reportFolder, { recursive: true }); + fs.mkdirSync(reportTempFolder, { recursive: true }); + // 定义所有要处理的包 + const packages = [ + "@flywave/flywave-mapview", + "@flywave/flywave-features-datasource", + "@flywave/flywave-geojson-datasource", + "@flywave/flywave-webtile-datasource", + "@flywave/flywave-terrain-datasource", + "@flywave/flywave-vectortile-datasource", + "@flywave/flywave-3dtile-datasource", + "@flywave/flywave-draw-controls", + "@flywave/flywave-map-controls", + "@flywave/flywave-inspector" + ]; + // 先构建所有包 + for (const packageName of packages) { + const packageJson = require(`${packageName}/package.json`); + const config = ExtractorConfig.prepare({ + packageJson, + packageJsonFullPath: path.resolve(`${packageName}/package.json`), + configObjectFullPath: path.resolve(`${packageName}`), + configObject: { + projectFolder: path.resolve(packageName), + mainEntryPointFilePath: path.resolve(`${packageName}/lib/src/index.d.ts`), + compiler: { + tsconfigFilePath: path.resolve(`${packageName}/tsconfig.json`), + overrideTsconfig: { + include: ["lib/**/*.d.ts"], + exclude: [ + "src/**/*", + "node_modules/**/*", + "dist/**/*", + "**/*.test.ts", + "**/*.spec.ts", + "**/test/**/*" + ] + } + }, + docModel: { + enabled: true, + apiJsonFilePath: `${reportFolder}/.api.json` + }, + apiReport: { + enabled: true, + reportFolder, + reportTempFolder, + reportFileName: ".api.md" + } + } + }); + const result = Extractor.invoke(config, { + localBuild: true, + messageCallback: message => { + let loc = ""; + if (message.sourceFilePath !== undefined) { + loc += `${message.sourceFilePath}:`; + if (message.sourceFileLine !== undefined) { + loc += `${message.sourceFileLine}:`; + if (message.sourceFileColumn !== undefined) { + loc += `${message.sourceFileColumn}:`; + } + } + loc += " "; + } + console.warn(`${loc}(${message.category}) ${message.text} (${message.messageId})`); + } + }); + if (!result.succeeded) { + throw new Error(`failed to extract api when processing '${packageName}'`); + } + } + // 生成文档 + console.log(execSync("pnpm exec api-documenter markdown --output-folder docs/docs/api ").toString()); + // 修复 acorn 解析错误 + console.log("🔧 Fixing acorn parsing conflicts..."); + processGeneratedMarkdownFiles(); + // 删除临时文件夹 + if (fs.existsSync(reportFolder)) { + fs.rmSync(reportFolder, { recursive: true, force: true }); + } + if (fs.existsSync(reportTempFolder)) { + fs.rmSync(reportTempFolder, { recursive: true, force: true }); + } +} +main().catch(console.error); +//# sourceMappingURL=apidocs.js.map \ No newline at end of file diff --git a/scripts/apidocs.js.map b/scripts/apidocs.js.map new file mode 100644 index 0000000..2ebce88 --- /dev/null +++ b/scripts/apidocs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"apidocs.js","sourceRoot":"","sources":["apidocs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/scripts/checkLicenses.d.ts b/scripts/checkLicenses.d.ts new file mode 100644 index 0000000..5650444 --- /dev/null +++ b/scripts/checkLicenses.d.ts @@ -0,0 +1,13 @@ +/** + * Checks whether specified source files contain license matching the specified RegExp. + * @param sourceFiles The source files to check + * @param licenseRegEx RegExp to match the license. + * IMPORTANT, RegExp match should match the whole license and in the match groups returns the + * following: + * - match[1] - copyright start year + * - match[2] - copyright end year (if specified) + * @param callback The callback function to execute upon completion. Array of errors strings is passed back, + * in case not matching file is found. + * @param [fix=false] Flag indicating whether correct licenses should be automatically fixed. Default is false. + */ +export declare function checkLicenses(sourceFiles: string[], licenseRegEx: RegExp, callback: (errors: string[]) => void, fix?: boolean): void; diff --git a/scripts/checkLicenses.js b/scripts/checkLicenses.js new file mode 100644 index 0000000..5b3f60d --- /dev/null +++ b/scripts/checkLicenses.js @@ -0,0 +1,101 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { exec } from "child_process"; +import * as fs from "fs"; +/** + * To determine the first and last commit year of the file and check against the year(s) in the file's copyright: + * @param sourceFile Path of the source file + * @param match License match result + * @param callback Callback to call once check is completed. Error message should be passed back + */ +function checkYear(sourceFile, [start, end], callback) { + const currentYear = String(new Date().getFullYear()); + exec([ + // Added + `git --no-pager log --follow --diff-filter=A -n 1 --format=%ad --date=format:%Y -- ${sourceFile}`, + // Last modified + `git --no-pager log --follow --diff-filter=MRCA -n 1 --format=%ad --date=format:%Y -- ${sourceFile}` + ].join(" && "), (error, stdOut, stdErr) => { + const copyrightStart = start; + const hasRange = end !== undefined; + const copyrightEnd = hasRange ? end : start; + const found = `${copyrightStart}${hasRange ? "-" + copyrightEnd : ""}`; + if (error) { + callback(error.message); + } + else if (stdErr) { + callback(stdErr.toString()); + } + else if (stdOut.toString() === "") { + // The file is not in Git repository yet, we can't detect the years. + // Please commit first and re-run. + callback(); + } + else if (!/^\d{4}\n\d{4}\n$/.test(stdOut.toString())) { + callback(`Can't determine first/last year of Git commit for file ${sourceFile}`); + } + else { + const [firstCommit, lastCommit] = stdOut.toString().split("\n"); + if (copyrightStart !== firstCommit || + copyrightEnd !== lastCommit || + (hasRange && copyrightStart === copyrightEnd)) { + // Since a new commit is needed to fix it, the new commit must contain the current year: + const expected = `${firstCommit}${firstCommit !== currentYear ? "-" + currentYear : ""}`; + if (found !== expected) { + callback(`${sourceFile} expected: ${expected}, found: ${found}`); + } + else { + callback(); + } + } + else { + callback(); + } + } + }); +} +/** + * Checks whether specified source files contain license matching the specified RegExp. + * @param sourceFiles The source files to check + * @param licenseRegEx RegExp to match the license. + * IMPORTANT, RegExp match should match the whole license and in the match groups returns the + * following: + * - match[1] - copyright start year + * - match[2] - copyright end year (if specified) + * @param callback The callback function to execute upon completion. Array of errors strings is passed back, + * in case not matching file is found. + * @param [fix=false] Flag indicating whether correct licenses should be automatically fixed. Default is false. + */ +export function checkLicenses(sourceFiles, licenseRegEx, callback, fix = false) { + const total = sourceFiles.length; + const errors = []; + let current = 0; + function checkIfDone() { + if (++current >= total) { + callback(errors); + } + } + sourceFiles.forEach(sourceFile => { + const content = fs.readFileSync(sourceFile, { encoding: "utf8" }); + const match = licenseRegEx.exec(content); + if (match === null) { + errors.push(`${sourceFile} has no valid copyright notice`); + checkIfDone(); + } + else { + checkYear(sourceFile, [match[1], match[2]], error => { + if (error) { + // Let's fix it in case of wrong year(s) found and AUTO_FIX is activated: + const errorMatch = /expected: (.+), found: (.+)/.exec(error); + if (fix && errorMatch !== null) { + fs.writeFileSync(sourceFile, content.replace(licenseRegEx, match[0].replace(errorMatch[2], errorMatch[1])), { encoding: "utf8" }); + } + else { + errors.push(error); + } + } + checkIfDone(); + }); + } + }); +} +//# sourceMappingURL=checkLicenses.js.map \ No newline at end of file diff --git a/scripts/checkLicenses.js.map b/scripts/checkLicenses.js.map new file mode 100644 index 0000000..840e60e --- /dev/null +++ b/scripts/checkLicenses.js.map @@ -0,0 +1 @@ +{"version":3,"file":"checkLicenses.js","sourceRoot":"","sources":["checkLicenses.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/scripts/manage-devdeps.d.ts b/scripts/manage-devdeps.d.ts new file mode 100644 index 0000000..b798801 --- /dev/null +++ b/scripts/manage-devdeps.d.ts @@ -0,0 +1,2 @@ +#!/usr/bin/env node +export {}; diff --git a/scripts/prepare_doc_deploy.d.ts b/scripts/prepare_doc_deploy.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/scripts/prepare_doc_deploy.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/scripts/prepare_doc_deploy.js b/scripts/prepare_doc_deploy.js new file mode 100644 index 0000000..59b52b2 --- /dev/null +++ b/scripts/prepare_doc_deploy.js @@ -0,0 +1,55 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { execSync } from "child_process"; +import { writeFileSync } from "fs"; +import { copySync, ensureDirSync, removeSync } from "fs-extra"; +import { glob } from "glob"; +import { gt } from "semver"; +const fetch = require("node-fetch"); +//This script prepares the documentation and flywave.gl website to be deployed to S3 +// Precondition: documentation ready on /dist folder +// including docs and examples (e.g. after pnpm run build && pnpm run typedoc) +// See: https://docs.github.com/en/actions/reference/environment-variables +const branch = process.env.GITHUB_REF; +const commitHash = execSync("git rev-parse --short HEAD").toString().trimRight(); +// We store releases using the short commit hash +const isReleaseBranch = branch?.includes("release"); +const refName = isReleaseBranch ? commitHash : "master"; +// create the following directory structure +// dist +// ├──s3_deploy (to be deployed to s3) +// │ ├── [ master | {githash} ] (folder with docs and examples) +// │ ├── index.html (and assets for minisite) +// │ ├── releases.json (list all releases in order) +const targetFolder = `dist/s3_deploy/`; +removeSync(targetFolder); +ensureDirSync(targetFolder); +copySync("www/dist/", `${targetFolder}/`); +copySync("dist/doc/", `${targetFolder}/docs/${refName}/doc`); +copySync("dist/doc-snippets/", `${targetFolder}/docs/${refName}/doc-snippets/`); +copySync("dist/examples/", `${targetFolder}/docs/${refName}/examples/`); +if (isReleaseBranch) { + const now = new Date(); + // WARNING, dates are 0 indexed, hence +1 + const dateString = `${now.getDate()}-${now.getMonth() + 1}-${now.getFullYear()}`; + const allPackages = glob.sync("@flywave/*/package.json"); + const newRelease = { + date: dateString, + hash: commitHash, + version: "" + }; + for (const testPackage of allPackages) { + const mapviewPackage = require(testPackage); + if (newRelease.version === "" || gt(mapviewPackage.version, newRelease.version)) { + newRelease.version = mapviewPackage.version; + } + } + fetch("https://www.flywave.net/releases.json") + .then((res) => { + return res.json(); + }) + .then((releases) => { + const newReleases = [newRelease, ...releases]; + writeFileSync(`${targetFolder}/releases.json`, JSON.stringify(newReleases, undefined, 2)); + }); +} +//# sourceMappingURL=prepare_doc_deploy.js.map \ No newline at end of file diff --git a/scripts/prepare_doc_deploy.js.map b/scripts/prepare_doc_deploy.js.map new file mode 100644 index 0000000..dbccf6d --- /dev/null +++ b/scripts/prepare_doc_deploy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"prepare_doc_deploy.js","sourceRoot":"","sources":["prepare_doc_deploy.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAEpC,oFAAoF;AACpF,oDAAoD;AACpD,8EAA8E;AAE9E,0EAA0E;AAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;AACtC,MAAM,UAAU,GAAG,QAAQ,CAAC,4BAA4B,CAAC,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,CAAC;AACjF,gDAAgD;AAChD,MAAM,eAAe,GAAG,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;AACpD,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;AAExD,2CAA2C;AAC3C,OAAO;AACP,sCAAsC;AACtC,iEAAiE;AACjE,+CAA+C;AAC/C,qDAAqD;AAErD,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAEvC,UAAU,CAAC,YAAY,CAAC,CAAC;AACzB,aAAa,CAAC,YAAY,CAAC,CAAC;AAC5B,QAAQ,CAAC,WAAW,EAAE,GAAG,YAAY,GAAG,CAAC,CAAC;AAC1C,QAAQ,CAAC,WAAW,EAAE,GAAG,YAAY,SAAS,OAAO,MAAM,CAAC,CAAC;AAC7D,QAAQ,CAAC,oBAAoB,EAAE,GAAG,YAAY,SAAS,OAAO,gBAAgB,CAAC,CAAC;AAChF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,YAAY,SAAS,OAAO,YAAY,CAAC,CAAC;AAoBxE,IAAI,eAAe,EAAE,CAAC;IAClB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,yCAAyC;IACzC,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;IACjF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACzD,MAAM,UAAU,GAAY;QACxB,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,EAAE;KACd,CAAC;IACF,KAAK,MAAM,WAAW,IAAI,WAAW,EAAE,CAAC;QACpC,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,UAAU,CAAC,OAAO,KAAK,EAAE,IAAI,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9E,UAAU,CAAC,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC;QAChD,CAAC;IACL,CAAC;IAED,KAAK,CAAC,uCAAuC,CAAC;SACzC,IAAI,CAAC,CAAC,GAAa,EAAE,EAAE;QACpB,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,QAAmB,EAAE,EAAE;QAC1B,MAAM,WAAW,GAAG,CAAC,UAAU,EAAE,GAAG,QAAQ,CAAC,CAAC;QAC9C,aAAa,CACT,GAAG,YAAY,gBAAgB,EAC/B,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAC5C,CAAC;IACN,CAAC,CAAC,CAAC;AACX,CAAC"} \ No newline at end of file diff --git a/test/ImportTest.d.ts b/test/ImportTest.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/ImportTest.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/ImportTest.js b/test/ImportTest.js new file mode 100644 index 0000000..64f0814 --- /dev/null +++ b/test/ImportTest.js @@ -0,0 +1,186 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +/* + * Copyright (C) 2018-2021 HERE Europe B.V. + * Licensed under Apache 2.0, see full license in LICENSE + * SPDX-License-Identifier: Apache-2.0 + */ +import { assert } from "chai"; +import * as fs from "fs"; +import * as glob from "glob"; +import * as path from "path"; +// these dependencies are ok to include in files using node.js +const nodeDependencyWhitelist = { + http: true, + https: true, + util: true, + url: true, + fs: true, + path: true +}; +function checkImports() { + // first, read all package.json files and remember the dependencies + const packageDependencies = {}; + const packageConfigs = {}; + const packageJsonFiles = [...glob.sync(__dirname + "/../@flywave/*/package.json")]; + for (const packageJsonFile of packageJsonFiles) { + const moduleName = "@flywave/" + packageJsonFile.split(path.sep).slice(-2, -1)[0]; + packageConfigs[moduleName] = JSON.parse(fs.readFileSync(packageJsonFile, "utf-8")); + } + // recursively gets all direct and indirect dependencies + function getDependencies(moduleName, deps) { + if (deps[moduleName]) { + return; + } + deps[moduleName] = true; + const config = packageConfigs[moduleName]; + if (config) { + for (const dep in config.dependencies) { + getDependencies(dep, deps); + } + for (const dep in config.peerDependencies) { + getDependencies(dep, deps); + } + } + } + for (const moduleName in packageConfigs) { + const config = packageConfigs[moduleName]; + const dependencies = {}; + for (const dep in config.dependencies) { + getDependencies(dep, dependencies); + } + for (const dep in config.devDependencies) { + getDependencies(dep, dependencies); + } + for (const dep in config.peerDependencies) { + getDependencies(dep, dependencies); + } + packageDependencies[moduleName] = dependencies; + } + // now, iterate all typescript source files + const sourceFiles = glob + .sync(__dirname + "/../@flywave/**/*.ts") + .filter(sourcePath => !sourcePath.includes("node_modules") && !sourcePath.includes("generator-flywave.gl")); + // regular expression catching all imported modules + const importRE = /(.*)?import\s*{[\s\S]*?}\s*from\s+["'](.*)["']/gi; + const environmentRE = /@flywave:check-imports:environment:(.*)/gi; + const errors = new Array(); + for (const sourceFile of sourceFiles) { + const contents = fs.readFileSync(sourceFile, "utf-8"); + let env = "browser"; + const relativePath = path.relative(__dirname + "/../@flywave", sourceFile); + const moduleName = "@flywave/" + relativePath.split(path.sep)[0]; + const modulePath = path.resolve(__dirname + "/../", moduleName); + const environmentMatch = environmentRE.exec(contents); + if (environmentMatch) { + env = environmentMatch[1]; + if (env !== "browser" && env !== "node") { + errors.push(`Error: ${relativePath} unknown '@flywave:environment:' type: ${env}. Supported types: 'node', 'browser'`); + env = "browser"; + } + } + // iterate through all matched imported modules + let matches; + while ((matches = importRE.exec(contents)) != null) { + const beginningOfLine = matches[1] || ""; + // If the line is a comment, ignore it + if (beginningOfLine.includes("//") || + beginningOfLine.includes("/*") || + beginningOfLine.includes("*")) { + continue; + } + const importedModule = matches[2]; + // 1) Make sure we don't self-import + if (importedModule === moduleName) { + errors.push(`Error: ${relativePath} contains wrong module import "${importedModule}", change it to a relative import`); + } + // 2) Make sure we don't include unknown dependencies + const localModule = importedModule.startsWith("."); + const allowedNodeModule = env === "node" && nodeDependencyWhitelist[importedModule]; + if (!localModule && !allowedNodeModule) { + const importedModuleName = importedModule.startsWith("@") + ? importedModule.split("/").slice(0, 2).join("/") + : importedModule.split("/")[0]; + if (packageDependencies[moduleName] !== undefined && + packageDependencies[moduleName][importedModuleName] === undefined) { + errors.push(`Error: unknown module ${importedModuleName} used in ${moduleName}: ` + + `${relativePath}`); + } + } + // 3) Make sure we don't include other @flywave modules via relative paths + if (importedModule.startsWith("..")) { + const resolvedImportedModule = path.resolve(path.dirname(sourceFile), importedModule); + if (!path.dirname(resolvedImportedModule).startsWith(modulePath)) { + errors.push(`Error: the module ${importedModule} is imported via a relative path in ${sourceFile}`); + } + } + } + } + // 4) Look for circular dependencies (Tarjan's SCC algorithm) + function detectCircularDependencies() { + let index = 0; + const stack = new Array(); + const modules = new Map(); + for (const moduleName in packageConfigs) { + const dependencies = Object.keys(packageDependencies[moduleName]).filter(dependencyName => dependencyName.startsWith("@flywave/") && dependencyName !== moduleName); + const module = { + name: moduleName, + index: undefined, + lowLink: undefined, + onStack: false, + dependencies + }; + modules.set(moduleName, module); + } + modules.forEach(function (module) { + if (module.index === undefined) { + strongConnect(module); + } + }); + function strongConnect(module) { + module.index = index; + module.lowLink = index; + index++; + stack.push(module); + module.onStack = true; + for (let i = 0; i < module.dependencies.length; i++) { + const successorName = module.dependencies[i]; + const successor = modules.get(successorName); + if (successor === undefined) { + continue; + } + if (successor.index === undefined) { + strongConnect(successor); + module.lowLink = Math.min(module.lowLink, successor.lowLink); + } + else if (stack.includes(successor)) { + module.lowLink = Math.min(module.lowLink, successor.index); + } + } + if (module.lowLink === module.index) { + // module is a root node + let circularDependency = false; + let errorMessage = `Loop detected: ${module.name}`; + let dependency = stack.pop(); + while (dependency !== undefined && dependency.name !== module.name) { + module.onStack = false; + errorMessage += ` -> ${dependency.name}`; + dependency = stack.pop(); + circularDependency = true; + } + if (circularDependency) { + errorMessage += ` -> ${module.name}`; + errors.push(errorMessage); + } + } + } + } + detectCircularDependencies(); + return errors; +} +describe("ImportCheck", function () { + it("Uses correct imports", function () { + const errors = checkImports(); + assert.deepEqual(errors, []); + }); +}); +//# sourceMappingURL=ImportTest.js.map \ No newline at end of file diff --git a/test/ImportTest.js.map b/test/ImportTest.js.map new file mode 100644 index 0000000..1a2182e --- /dev/null +++ b/test/ImportTest.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ImportTest.js","sourceRoot":"","sources":["ImportTest.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/LicenseHeaderTest.d.ts b/test/LicenseHeaderTest.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/LicenseHeaderTest.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/LicenseHeaderTest.js b/test/LicenseHeaderTest.js new file mode 100644 index 0000000..e77e6ae --- /dev/null +++ b/test/LicenseHeaderTest.js @@ -0,0 +1,26 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { assert } from "chai"; +import * as glob from "glob"; +import * as path from "path"; +import { checkLicenses } from "../scripts/checkLicenses"; +const APACHE_LICENSE = /\/\*\n \* Copyright \(C\) (\d{4})(?:-(\d{4}))? HERE Europe B\.V\.\n \* Licensed under Apache 2\.0\, see full license in LICENSE\n \* SPDX\-License\-Identifier\: Apache\-2\.0\n \*\//; +// To fix wrong year(s) of the copyright notice on a local machine automatically: +const AUTO_FIX = process.argv.slice(2).includes("--fix"); +describe("LicenseHeaderCheck", function () { + it("Contains correct license header", function (done) { + // In some cases (coverage run on CI) --no-timeouts flag is not passed, + // so we have to set it here specifically. + this.timeout(180000); // 3 mins + const sourceFiles = glob + .sync(path.join(__dirname, "..", "**/*.ts")) + .filter(file => !file.includes("/node_modules/")) + .filter(file => !file.includes("/dist/")) + .filter(file => !file.endsWith(".d.ts")) + .sort(); + checkLicenses(sourceFiles, APACHE_LICENSE, errors => { + assert.deepEqual(errors, []); + done(); + }, AUTO_FIX); + }); +}); +//# sourceMappingURL=LicenseHeaderTest.js.map \ No newline at end of file diff --git a/test/LicenseHeaderTest.js.map b/test/LicenseHeaderTest.js.map new file mode 100644 index 0000000..9e2e9f9 --- /dev/null +++ b/test/LicenseHeaderTest.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LicenseHeaderTest.js","sourceRoot":"","sources":["LicenseHeaderTest.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,cAAc,GAChB,sLAAsL,CAAC;AAC3L,iFAAiF;AACjF,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAEzD,QAAQ,CAAC,oBAAoB,EAAE;IAC3B,EAAE,CAAC,iCAAiC,EAAE,UAAU,IAAI;QAChD,uEAAuE;QACvE,0CAA0C;QAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC/B,MAAM,WAAW,GAAG,IAAI;aACnB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;aAC3C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;aAChD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;aACxC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aACvC,IAAI,EAAE,CAAC;QAEZ,aAAa,CACT,WAAW,EACX,cAAc,EACd,MAAM,CAAC,EAAE;YACL,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC7B,IAAI,EAAE,CAAC;QACX,CAAC,EACD,QAAQ,CACX,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/test/performance/LinesPerformanceTest.d.ts b/test/performance/LinesPerformanceTest.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/performance/LinesPerformanceTest.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/performance/LinesPerformanceTest.js b/test/performance/LinesPerformanceTest.js new file mode 100644 index 0000000..8aa0652 --- /dev/null +++ b/test/performance/LinesPerformanceTest.js @@ -0,0 +1,43 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { mercatorProjection } from "@flywave/flywave-geoutils"; +import { createLineGeometry } from "@flywave/flywave-lines"; +import { measureThroughputSync } from "@flywave/flywave-test-utils/lib/ProfileHelper"; +import * as THREE from "three"; +if (typeof window === "undefined") { + const perfHooks = require("perf_hooks"); + global.performance = perfHooks.performance; + global.PerformanceObserver = perfHooks.PerformanceObserver; + global.PerformanceEntry = perfHooks.PerformanceEntry; +} +describe(`lines`, function () { + this.timeout(0); + const center = new THREE.Vector3(); + const tests = [ + { segments: 2 }, + { segments: 4 }, + { segments: 16 }, + { segments: 64 }, + { segments: 256 } + ]; + before(function () { + this.timeout(0); + tests.forEach(test => { + const segments = test.segments; + test.points = []; + const radius = 100; + for (let i = 0; i < segments; i++) { + const angle = (i * 360) / segments; + test.points.push(Math.cos(THREE.MathUtils.degToRad(angle) * radius), Math.cos(THREE.MathUtils.degToRad(angle) * radius), 0); + } + }); + }); + tests.forEach(test => { + it(`createLineGeometry segments=${test.segments}`, async function () { + this.timeout(0); + await measureThroughputSync(`createLineGeometry segments=${test.segments}`, 1000, function () { + createLineGeometry(center, test.points, mercatorProjection); + }); + }); + }); +}); +//# sourceMappingURL=LinesPerformanceTest.js.map \ No newline at end of file diff --git a/test/performance/LinesPerformanceTest.js.map b/test/performance/LinesPerformanceTest.js.map new file mode 100644 index 0000000..f293fb5 --- /dev/null +++ b/test/performance/LinesPerformanceTest.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LinesPerformanceTest.js","sourceRoot":"","sources":["LinesPerformanceTest.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAEvC,MAAc,CAAC,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;IACnD,MAAc,CAAC,mBAAmB,GAAG,SAAS,CAAC,mBAAmB,CAAC;IACnE,MAAc,CAAC,gBAAgB,GAAG,SAAS,CAAC,gBAAgB,CAAC;AAClE,CAAC;AAED,QAAQ,CAAC,OAAO,EAAE;IACd,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;IAEnC,MAAM,KAAK,GAAmD;QAC1D,EAAE,QAAQ,EAAE,CAAC,EAAE;QACf,EAAE,QAAQ,EAAE,CAAC,EAAE;QACf,EAAE,QAAQ,EAAE,EAAE,EAAE;QAChB,EAAE,QAAQ,EAAE,EAAE,EAAE;QAChB,EAAE,QAAQ,EAAE,GAAG,EAAE;KACpB,CAAC;IAEF,MAAM,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC/B,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,GAAG,CAAC;YACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;gBACnC,IAAI,CAAC,MAAM,CAAC,IAAI,CACZ,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,EAClD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,EAClD,CAAC,CACJ,CAAC;YACN,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACjB,EAAE,CAAC,+BAA+B,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK;YACpD,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAChB,MAAM,qBAAqB,CACvB,+BAA+B,IAAI,CAAC,QAAQ,EAAE,EAC9C,IAAI,EACJ;gBACI,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAO,EAAE,kBAAkB,CAAC,CAAC;YACjE,CAAC,CACJ,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/test/performance/OmvDecoderPerformanceTest.d.ts b/test/performance/OmvDecoderPerformanceTest.d.ts new file mode 100644 index 0000000..18d30b4 --- /dev/null +++ b/test/performance/OmvDecoderPerformanceTest.d.ts @@ -0,0 +1,33 @@ +import { type Theme } from "@flywave/flywave-datasource-protocol"; +import { type OmvRestClientParameters } from "@flywave/flywave-vectortile-datasource"; +export interface OMVDecoderPerformanceTestOptions { + /** + * + */ + repeats?: number; + /** + * Theme url or object. + * + * Will be resolved using [[ThemeLoader.load]]. + */ + theme: Theme | string; + /** + * Styleset name, defaults to `tilezen`. + */ + styleSetName?: string; + /** + * Morton codes of tiles. + */ + tiles: number[]; + /** + * Requires settings for [[OmvRestClient]] to download tiles. + */ + omvRestClientOptions: OmvRestClientParameters; +} +/** + * Create tests that downloads some OMV tiles from real datasource, then decodes them using + * particular style. + * + * @see OMVDecoderPerformanceTestOptions + */ +export declare function createOMVDecoderPerformanceTest(name: string, options: OMVDecoderPerformanceTestOptions): void; diff --git a/test/performance/OmvDecoderPerformanceTest.js b/test/performance/OmvDecoderPerformanceTest.js new file mode 100644 index 0000000..0309d49 --- /dev/null +++ b/test/performance/OmvDecoderPerformanceTest.js @@ -0,0 +1,165 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { MapEnv, StyleSetEvaluator } from "@flywave/flywave-datasource-protocol/index-decoder"; +import { apikey } from "@flywave/flywave-examples/config"; +import { mercatorProjection, sphereProjection, TileKey, webMercatorProjection } from "@flywave/flywave-geoutils"; +import { ThemeLoader } from "@flywave/flywave-mapview"; +import { getTestResourceUrl } from "@flywave/flywave-test-utils/index.node"; +import { measurePerformanceSync } from "@flywave/flywave-test-utils/lib/ProfileHelper"; +import { APIFormat, AuthenticationMethod, OmvRestClient } from "@flywave/flywave-vectortile-datasource"; +import { OmvDataAdapter } from "@flywave/flywave-vectortile-datasource/lib/adapters/omv/OmvDataAdapter"; +import { DecodeInfo } from "@flywave/flywave-vectortile-datasource/lib/DecodeInfo"; +import { VectorTileDataProcessor } from "@flywave/flywave-vectortile-datasource/lib/VectorTileDecoder"; +import { assert } from "chai"; +if (typeof window === "undefined") { + const perfHooks = require("perf_hooks"); + global.performance = perfHooks.performance; + global.PerformanceObserver = perfHooks.PerformanceObserver; + global.PerformanceEntry = perfHooks.PerformanceEntry; +} +/** + * Create tests that downloads some OMV tiles from real datasource, then decodes them using + * particular style. + * + * @see OMVDecoderPerformanceTestOptions + */ +export function createOMVDecoderPerformanceTest(name, options) { + const repeats = options.repeats ?? 10; + const styleSetName = options.styleSetName ?? "tilezen"; + describe(`OMVDecoderPerformanceTest - ${name}`, function () { + this.timeout(0); + let omvTiles; + let theme; + before(async function () { + this.timeout(10000); + const omvDataProvider = new OmvRestClient(options.omvRestClientOptions); + await omvDataProvider.connect(); + assert(omvDataProvider.ready()); + omvTiles = await Promise.all(options.tiles.map(async (mortonCode) => { + const tileKey = TileKey.fromMortonCode(mortonCode); + const tile = await omvDataProvider.getTile(tileKey); + assert(tile instanceof ArrayBuffer); + return [tileKey, tile]; + })); + theme = await ThemeLoader.load(options.theme); + assert.isObject(theme.styles); + assert.isArray(theme.styles[styleSetName]); + }); + it(`measure feature matching time`, async () => { + const counterName = `OMVDecoderPerformanceTest-${name} styleMatchOnly`; + this.timeout(0); + const styleSetEvaluator = new StyleSetEvaluator({ + styleSet: theme.styles[styleSetName], + definitions: theme.definitions + }); + const geometryProcessor = { + processPointFeature(layerName, tileExtents, geometry, properties) { + const env = new MapEnv(properties); + styleSetEvaluator.getMatchingTechniques(env, layerName, "point"); + }, + processLineFeature(layerName, tileExtents, geometry, properties) { + const env = new MapEnv(properties); + styleSetEvaluator.getMatchingTechniques(env, layerName, "line"); + }, + processPolygonFeature(layerName, tileExtents, geometry, properties) { + const env = new MapEnv(properties); + styleSetEvaluator.getMatchingTechniques(env, layerName, "polygon"); + } + }; + await measurePerformanceSync(counterName, repeats, function () { + for (const [tileKey, tileData] of omvTiles) { + const decoder = new OmvDataAdapter(); + const decodeInfo = new DecodeInfo(mercatorProjection, tileKey, 0); + decoder.process(tileData, decodeInfo, geometryProcessor); + } + }); + }); + it(`measure decode time - webMercator`, async () => { + const counterName = `OMVDecoderPerformanceTest-${name} webMercator`; + this.timeout(0); + const projection = webMercatorProjection; + const styleSetEvaluator = new StyleSetEvaluator({ + styleSet: theme.styles[styleSetName], + definitions: theme.definitions + }); + await measurePerformanceSync(counterName, repeats, function () { + for (const [tileKey, tileData] of omvTiles) { + const decoder = new VectorTileDataProcessor(tileKey, projection, styleSetEvaluator, new OmvDataAdapter()); + decoder.getDecodedTile(tileData); + } + }); + }); + it(`measure decode time - sphereProjection`, async () => { + this.timeout(0); + const counterName = `OMVDecoderPerformanceTest-${name} sphere`; + const projection = sphereProjection; + const styleSetEvaluator = new StyleSetEvaluator({ + styleSet: theme.styles[styleSetName], + definitions: theme.definitions + }); + await measurePerformanceSync(counterName, repeats, function () { + for (const [tileKey, tileData] of omvTiles) { + const decoder = new VectorTileDataProcessor(tileKey, projection, styleSetEvaluator, new OmvDataAdapter()); + decoder.getDecodedTile(tileData); + } + }); + }); + }); +} +const BERLIN_CENTER_TILES = [371506851, 371506850, 371506849, 371506848]; +createOMVDecoderPerformanceTest("theme=berlin tiles=4 region=berlin data=herebase", { + theme: getTestResourceUrl("@flywave/flywave-map-theme", "resources/tilezen_base.json"), + tiles: BERLIN_CENTER_TILES, + omvRestClientOptions: { + baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc", + apiFormat: APIFormat.XYZOMV, + authenticationCode: apikey, + authenticationMethod: { + method: AuthenticationMethod.QueryString, + name: "apikey" + } + } +}); +createOMVDecoderPerformanceTest("theme=berlin tiles=4 region=berlin data=osmbase", { + theme: getTestResourceUrl("@flywave/flywave-map-theme", "resources/tilezen_base.json"), + tiles: BERLIN_CENTER_TILES, + omvRestClientOptions: { + baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc", + apiFormat: APIFormat.XYZOMV, + authenticationCode: apikey, + authenticationMethod: { + method: AuthenticationMethod.QueryString, + name: "apikey" + } + } +}); +const NEW_YORK_TILES = [ + 327439127, 327439124, 327439125, 327439168, 327439170, + 327438781, 327438783, 327438826, 327438782, 327438824 +]; +createOMVDecoderPerformanceTest("theme=berlin tiles=10 region=ny data=herebase", { + theme: getTestResourceUrl("@flywave/flywave-map-theme", "resources/tilezen_base.json"), + tiles: NEW_YORK_TILES, + omvRestClientOptions: { + baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc", + apiFormat: APIFormat.XYZOMV, + authenticationCode: apikey, + authenticationMethod: { + method: AuthenticationMethod.QueryString, + name: "apikey" + } + } +}); +createOMVDecoderPerformanceTest("theme=berlin tiles=10 region=ny data=osmbase", { + theme: getTestResourceUrl("@flywave/flywave-map-theme", "resources/tilezen_base.json"), + tiles: NEW_YORK_TILES, + omvRestClientOptions: { + baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc", + apiFormat: APIFormat.XYZOMV, + authenticationCode: apikey, + authenticationMethod: { + method: AuthenticationMethod.QueryString, + name: "apikey" + } + } +}); +//# sourceMappingURL=OmvDecoderPerformanceTest.js.map \ No newline at end of file diff --git a/test/performance/OmvDecoderPerformanceTest.js.map b/test/performance/OmvDecoderPerformanceTest.js.map new file mode 100644 index 0000000..e49ac18 --- /dev/null +++ b/test/performance/OmvDecoderPerformanceTest.js.map @@ -0,0 +1 @@ +{"version":3,"file":"OmvDecoderPerformanceTest.js","sourceRoot":"","sources":["OmvDecoderPerformanceTest.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/ClipPlanesRenderingTest.d.ts b/test/rendering/ClipPlanesRenderingTest.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/rendering/ClipPlanesRenderingTest.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/rendering/ClipPlanesRenderingTest.js b/test/rendering/ClipPlanesRenderingTest.js new file mode 100644 index 0000000..05f3695 --- /dev/null +++ b/test/rendering/ClipPlanesRenderingTest.js @@ -0,0 +1,216 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { mercatorProjection, sphereProjection } from "@flywave/flywave-geoutils"; +import { CameraUtils } from "@flywave/flywave-mapview"; +import * as THREE from "three"; +import { GeoJsonTest } from "./utils/GeoJsonTest"; +import { ThemeBuilder } from "./utils/ThemeBuilder"; +const style = [ + { + when: "$geometryType == 'polygon'", + technique: "fill", + attr: { + color: ["get", "color"], + opacity: 1.0, + minZoomLevel: ["get", "minZoom"], + maxZoomLevel: ["get", "maxZoom"] + } + } +]; +const theme = { clearColor: "black", lights: ThemeBuilder.lights, styles: { geojson: style } }; +const seaworld = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { color: "#436981" }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-180, -90], + [180, -90], + [180, 90], + [-180, 90], + [-180, -90] + ] + ] + } + }, + // Crosshair at camera target [0,0] for high zoom levels. + { + type: "Feature", + properties: { color: "red", minZoom: 6 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-0.002, -0.02], + [0.002, -0.02], + [0.002, 0.02], + [-0.002, 0.02], + [-0.002, -0.02] + ] + ] + } + }, + { + type: "Feature", + properties: { color: "red", minZoom: 6 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-0.02, -0.002], + [0.02, -0.002], + [0.02, 0.002], + [-0.02, 0.002], + [-0.02, -0.002] + ] + ] + } + }, + // Crosshair at camera target [0,0] for low zoom levels. + { + type: "Feature", + properties: { color: "red", maxZoom: 6 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-0.1, -1], + [0.1, -1], + [0.1, 1], + [-0.1, 1], + [-0.1, -1] + ] + ] + } + }, + { + type: "Feature", + properties: { color: "red", maxZoom: 6 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-1, -0.1], + [1, -0.1], + [1, 0.1], + [-1, 0.1], + [-1, -0.1] + ] + ] + } + } + ] +}; +describe("ClipPlanes rendering test", function () { + this.timeout(5000); + let geoJsonTest; + beforeEach(function () { + geoJsonTest = new GeoJsonTest(); + }); + afterEach(() => { + geoJsonTest.dispose(); + }); + const tests = [ + { + projection: mercatorProjection, + zoomLevel: 11, + tilt: 65 + }, + { + projection: mercatorProjection, + zoomLevel: 11, + tilt: 65, + principalPointNDC: [0, -0.5] + }, + { + projection: mercatorProjection, + zoomLevel: 11, + tilt: 70 + }, + { + projection: mercatorProjection, + zoomLevel: 11, + tilt: 70, + principalPointNDC: [0, 0.5] + }, + { + projection: sphereProjection, + zoomLevel: 11, + tilt: 65 + }, + { + projection: sphereProjection, + zoomLevel: 11, + tilt: 65, + principalPointNDC: [0, -0.5] + }, + { + projection: sphereProjection, + zoomLevel: 11, + tilt: 70 + }, + { + projection: sphereProjection, + zoomLevel: 11, + tilt: 70, + principalPointNDC: [0, 0.5] + }, + { + projection: sphereProjection, + zoomLevel: 4, + tilt: 10 + }, + { + projection: sphereProjection, + zoomLevel: 4, + tilt: 10, + principalPointNDC: [0, -0.9] + }, + { + projection: sphereProjection, + zoomLevel: 4, + principalPointNDC: [-0.7, 0] + }, + { + projection: sphereProjection, + zoomLevel: 4, + principalPointNDC: [0.7, 0] + }, + { + projection: sphereProjection, + zoomLevel: 3, + principalPointNDC: [0, 0.9] + } + ]; + for (const test of tests) { + const projection = test.projection; + const zoomLevel = test.zoomLevel; + const tilt = test.tilt ?? 0; + const principalPoint = test.principalPointNDC ?? [0, 0]; + const projName = projection === mercatorProjection ? "mercator" : "sphere"; + const testName = `${projName}, zl${zoomLevel}, tilt ${tilt}, ppal point ${principalPoint}`; + // For image name, replace test name spaces and commas with dashes and make lower case. + const testImageName = "clip-planes-" + testName.replace(/[,\s]+/g, "-").toLowerCase(); + it(`${testName}`, async function () { + await geoJsonTest.run({ + mochaTest: this, + testImageName, + theme, + geoJson: seaworld, + lookAt: { + zoomLevel, + target: [0, 0], + tilt + }, + projection, + beforeFinishCallback: mapView => { + CameraUtils.setPrincipalPoint(mapView.camera, new THREE.Vector2().fromArray(principalPoint)); + } + }); + }); + } +}); +//# sourceMappingURL=ClipPlanesRenderingTest.js.map \ No newline at end of file diff --git a/test/rendering/ClipPlanesRenderingTest.js.map b/test/rendering/ClipPlanesRenderingTest.js.map new file mode 100644 index 0000000..2b31cca --- /dev/null +++ b/test/rendering/ClipPlanesRenderingTest.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ClipPlanesRenderingTest.js","sourceRoot":"","sources":["ClipPlanesRenderingTest.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/GeoJsonDataRendering.d.ts b/test/rendering/GeoJsonDataRendering.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/rendering/GeoJsonDataRendering.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/rendering/GeoJsonDataRendering.js b/test/rendering/GeoJsonDataRendering.js new file mode 100644 index 0000000..f99eb94 --- /dev/null +++ b/test/rendering/GeoJsonDataRendering.js @@ -0,0 +1,928 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { clipLineString } from "@flywave/flywave-geometry/src/ClipLineString"; +import { wrapLineString } from "@flywave/flywave-geometry/src/WrapLineString"; +import { wrapPolygon } from "@flywave/flywave-geometry/src/WrapPolygon"; +import { EarthConstants, GeoBox, GeoCoordinates, webMercatorProjection, webMercatorTilingScheme } from "@flywave/flywave-geoutils"; +import { DataProvider } from "@flywave/flywave-mapview-decoder"; +import * as turf from "@turf/turf"; +import { Vector3 } from "three"; +import * as polygon_crossing_antimeridian from "../resources/polygon_crossing_antimeridian.json"; +import { GeoJsonStore } from "./utils/GeoJsonStore"; +import { GeoJsonTest } from "./utils/GeoJsonTest"; +import { ThemeBuilder } from "./utils/ThemeBuilder"; +// Mocha discourages using arrow functions, see https://mochajs.org/#arrow-functions +describe("MapView + OmvDataSource + GeoJsonDataProvider rendering test", function () { + const geoJsonTest = new GeoJsonTest(); + // get the default lighting set up.fterEach(() => geoJsonTest.dispose()); + const lights = ThemeBuilder.lights; + afterEach(() => { + geoJsonTest.dispose(); + }); + it("renders flat polygon using fill technique", async function () { + this.timeout(5000); + const greenStyle = [ + { + when: "$geometryType == 'polygon'", + technique: "fill", + attr: { + color: "#008000", + opacity: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-polygon-fill", + theme: { lights, styles: { geojson: greenStyle } }, + geoJson: "../dist/resources/basic_polygon.json" + }); + }); + it("renders flat polygon using extruded-polygon technique", async function () { + this.timeout(5000); + const greenStyle = [ + { + when: "$geometryType == 'polygon'", + technique: "extruded-polygon", + attr: { + height: 0, + color: "#008000", + opacity: 0.9, + lineWidth: 1, + lineColor: "#172023", + lineColorMix: 0.6, + metalness: 0.5, + roughness: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-extruded-polygon-flat", + theme: { + lights, + styles: { geojson: greenStyle } + }, + geoJson: "../dist/resources/basic_polygon.json", + lookAt: { + tilt: 45, + heading: 30 + } + }); + }); + it("renders japanese flag with enabled as dynamic expression", async function () { + this.timeout(50000); + const greenStyle = [ + { + when: ["==", ["geometry-type"], "Point"], + technique: "circles", + renderOrder: 10000, + // select the color based on the the value of the dynamic property `correct`. + color: "#BC002D", + // This causes the bug FLYWAVE-12247 + enabled: ["get", "enabled", ["dynamic-properties"]], + size: ["get", "size", ["dynamic-properties"]] + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-point-enabled-as-dynamic-expression", + theme: { lights, styles: { geojson: greenStyle } }, + geoJson: "../dist/resources/basic_polygon.json", + size: 150 + }); + }); + it("renders extruded polygons with height", async function () { + this.timeout(5000); + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "extruded-polygon", + attr: { + vertexColors: false, + lineWidth: 1, + lineColor: "#172023", + lineColorMix: 0.6, + metalness: 0.5, + roughness: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-extruded-polygon-with-height", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: "../dist/resources/basic_polygon.json", + lookAt: { + tilt: 45, + heading: 30 + } + }); + }); + it("renders extruded polygons with height and color", async function () { + this.timeout(5000); + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "extruded-polygon", + attr: { + vertexColors: true, + color: ["string", ["get", "color"], "#5050f0"], + lineWidth: 1, + lineColor: "#172023", + lineColorMix: 0.6, + metalness: 0.5, + roughness: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-extruded-polygon-with-height-color", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: "../dist/resources/basic_polygon.json", + lookAt: { + tilt: 45, + heading: 30 + } + }); + }); + it("renders extruded polygons with height and color - no batching", async function () { + this.timeout(5000); + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "extruded-polygon", + attr: { + color: ["string", ["get", "color"], "#5050f0"], + lineWidth: 1, + lineColor: "#172023", + lineColorMix: 0.6, + metalness: 0.5, + roughness: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-extruded-polygon-with-height-color-no-batching", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: "../dist/resources/basic_polygon.json", + lookAt: { + tilt: 45, + heading: 30 + } + }); + }); + it("renders extruded polygons with height, without outline", async function () { + this.timeout(5000); + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "extruded-polygon", + attr: { + vertexColors: false, + lineWidth: 0, + lineColor: "#172023", + lineColorMix: 0.6, + metalness: 0.5, + roughness: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-extruded-polygon-with-height-no-outline", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: "../dist/resources/basic_polygon.json", + lookAt: { + tilt: 45, + heading: 30 + } + }); + }); + it("renders extruded polygons with height, with lineWidth Expression," + " resulting in 0", async function () { + this.timeout(5000); + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "extruded-polygon", + attr: { + vertexColors: false, + lineWidth: { + interpolation: "Discrete", + zoomLevels: [9, 12], + values: [0.0, 1.0] + }, + lineColor: "#172023", + lineColorMix: 0.6, + metalness: 0.5, + roughness: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-extruded-polygon-linewidth-expression-to-zero", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: "../dist/resources/basic_polygon.json", + lookAt: { + tilt: 45, + heading: 30, + zoomLevel: 9 + } + }); + }); + it("renders extruded polygons with height, with lineWidth Expression," + " resulting in 1", async function () { + this.timeout(5000); + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "extruded-polygon", + attr: { + vertexColors: false, + lineWidth: { + interpolation: "Discrete", + zoomLevels: [9, 12], + values: [1.0, 0.0] + }, + lineColor: "#172023", + lineColorMix: 0.6, + metalness: 0.5, + roughness: 0.5 + } + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-extruded-polygon-linewidth-expression-to-one", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: "../dist/resources/basic_polygon.json", + lookAt: { + tilt: 45, + heading: 30, + zoomLevel: 9 + } + }); + }); + it("renders multi line strings", async function () { + this.timeout(5000); + const ourStyle = [ + { + when: ["==", ["geometry-type"], "LineString"], + technique: "solid-line", + color: "red", + lineWidth: "4px" + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-multilinestring", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: "../dist/resources/MatchedLinksShape.json", + lookAt: { + target: [-0.13603, 51.508], + zoomLevel: 15 + } + }); + }); + it("renders geometry touching the tile border", async function () { + this.timeout(5000); + const geoJson = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { + "fill-color": "rgb(255,255,0)", + "stroke-color": "#000" + }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [0, 51.5], + [0.01, 51.5], + [0, 51.49], + [0, 51.5] + ] + ] + } + } + ] + }; + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "fill", + color: ["get", "fill-color"], + lineColor: ["get", "stroke-color"], + lineWidth: 1 + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-stroke-polygons-at-tile-border", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson, + lookAt: { + target: [0, 51.5], + zoomLevel: 13.4 + } + }); + }); + it("renders geometry crossing the tile border", async function () { + this.timeout(5000); + const geoJson = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { + "fill-color": "rgb(255,255,0)", + "stroke-color": "#000" + }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-0.01, 51.5], + [0.01, 51.5], + [0, 51.49], + [-0.01, 51.5] + ] + ] + } + } + ] + }; + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "fill", + color: ["get", "fill-color"], + lineColor: ["get", "stroke-color"], + lineWidth: 1 + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-stroke-polygons-crossing-tile-border", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson, + lookAt: { + target: [0, 51.5], + zoomLevel: 13.4 + } + }); + }); + it("renders geometries touching and crossing tile bounds", async function () { + this.timeout(5000); + const target = GeoCoordinates.fromGeoPoint([0, 51.5]); + const tileKey = webMercatorTilingScheme.getTileKey(target, 13); + const geoBox = webMercatorTilingScheme.getGeoBox(tileKey); + const offset = 0.002; + const geoJson = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { + "fill-color": "rgb(255,255,0)", + "stroke-color": "#000", + "sort-rank": 1 + }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [geoBox.center.longitude, geoBox.north + offset], + [geoBox.east + offset, geoBox.center.latitude], + [geoBox.center.longitude, geoBox.south - offset], + [geoBox.west - offset, geoBox.center.latitude], + [geoBox.center.longitude, geoBox.north + offset] + ] + ] + } + }, + { + type: "Feature", + properties: { + "fill-color": "rgba(0, 0, 0, 0.1)", + "stroke-color": "#000", + "sort-rank": 0 + }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [geoBox.west, geoBox.north], + [geoBox.east, geoBox.north], + [geoBox.east, geoBox.south], + [geoBox.west, geoBox.south], + [geoBox.west, geoBox.north] + ] + ] + } + } + ] + }; + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "fill", + color: ["get", "fill-color"], + lineColor: ["get", "stroke-color"], + lineWidth: 1, + renderOrder: ["get", "sort-rank"] + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-stroke-polygons-touching-and-crossing-tile-border", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson, + lookAt: { + zoomLevel: 13.01, + target: geoBox.center + } + }); + }); + describe("wrap polygon crossing antimeridian", async function () { + const ourStyle = [ + { + when: ["all", ["==", ["geometry-type"], "Polygon"], ["!has", "fragment"]], + technique: "solid-line", + color: "rgba(255,0,0,1)", + lineWidth: "2px" + }, + { + when: [ + "all", + ["==", ["geometry-type"], "Polygon"], + ["==", ["get", "fragment"], "left"] + ], + technique: "fill", + color: "rgba(255,0,0,0.5)", + lineColor: "rgb(0,0,0)", + lineWidth: 1, + renderOrder: 1 + }, + { + when: [ + "all", + ["==", ["geometry-type"], "Polygon"], + ["==", ["get", "fragment"], "middle"] + ], + technique: "fill", + color: "rgba(0,255,0,0.5)", + lineColor: "rgb(0,0,0)", + lineWidth: 1, + renderOrder: 0 + }, + { + when: [ + "all", + ["==", ["geometry-type"], "Polygon"], + ["==", ["get", "fragment"], "right"] + ], + technique: "fill", + color: "rgba(0,0,255,0.5)", + lineColor: "rgb(0,0,0)", + lineWidth: 1, + renderOrder: 1 + }, + { + when: ["==", ["geometry-type"], "LineString"], + technique: "solid-line", + lineWidth: "2px", + color: "rgb(0,0,0)" + } + ]; + // Convert the coordinates of the polygon from GeoJson to GeoCoordinates. + const coordinates = polygon_crossing_antimeridian.features[0].geometry.coordinates[0].map(([lng, lat]) => GeoCoordinates.fromGeoPoint([lng, lat])); + // Split the polygon in 3 parts. + const wrappedPolygon = wrapPolygon(coordinates); + // Extracts a part (left, middle or right) from the wrapped polygon + // and convert it to a GeoJson feature. + const toGeoPolygonFeature = (part) => { + const coordinates = wrappedPolygon[part]; + // Converts an Array of GeoCoordinates to GeoJSON coordinates. + const toGeoJsonCoordinates = (coordinates) => [ + (coordinates ?? []).map(({ lat, lng }) => [lng, lat]) + ]; + return { + type: "Feature", + properties: { + fragment: part + }, + geometry: { + type: "Polygon", + coordinates: toGeoJsonCoordinates(coordinates) + } + }; + }; + const separator = { + type: "Feature", + properties: {}, + geometry: { + type: "LineString", + coordinates: [ + [180, 90], + [180, -90] + ] + } + }; + const lookAt = { + target: [-160, 40], + distance: EarthConstants.EQUATORIAL_CIRCUMFERENCE * 2.5 + }; + it(`polygon to wrap`, async function () { + this.timeout(5000); + await geoJsonTest.run({ + lookAt, + mochaTest: this, + testImageName: `geojson-wrap-polygon-crossing-antimeridian`, + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: polygon_crossing_antimeridian + }); + }); + it(`wrapped polygon - merged`, async function () { + this.timeout(5000); + await geoJsonTest.run({ + lookAt, + mochaTest: this, + testImageName: `geojson-wrap-polygon-crossing-antimeridian-merged`, + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: { + type: "FeatureCollection", + features: [ + toGeoPolygonFeature("left"), + toGeoPolygonFeature("middle"), + toGeoPolygonFeature("right"), + separator + ] + } + }); + }); + for (const part in wrappedPolygon) { + if (!wrappedPolygon.hasOwnProperty(part)) { + continue; + } + const feature = toGeoPolygonFeature(part); + it(`wrapped polygon - ${part}`, async function () { + this.timeout(5000); + await geoJsonTest.run({ + lookAt, + mochaTest: this, + testImageName: `geojson-wrap-polygon-crossing-antimeridian-${part}`, + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: { + type: "FeatureCollection", + features: [feature, separator] + } + }); + }); + } + }); + describe("wrap linestring crossing antimeridian", async function () { + const ourStyle = [ + { + when: ["all", ["==", ["geometry-type"], "Polygon"], ["!has", "fragment"]], + technique: "solid-line", + color: "rgba(255,0,0,1)", + lineWidth: "2px" + }, + { + when: [ + "all", + ["==", ["geometry-type"], "LineString"], + ["==", ["get", "fragment"], "left"] + ], + technique: "solid-line", + color: "rgba(255,0,0,1)", + lineWidth: "2px", + caps: "Round", + renderOrder: 1 + }, + { + when: [ + "all", + ["==", ["geometry-type"], "LineString"], + ["==", ["get", "fragment"], "middle"] + ], + technique: "solid-line", + color: "rgba(0,255,0,1)", + lineWidth: "2px", + renderOrder: 0 + }, + { + when: [ + "all", + ["==", ["geometry-type"], "LineString"], + ["==", ["get", "fragment"], "right"] + ], + technique: "solid-line", + color: "rgba(0,0,255,1)", + lineWidth: "2px", + renderOrder: 1 + }, + { + when: ["all", ["==", ["geometry-type"], "LineString"], ["!has", "fragment"]], + technique: "solid-line", + lineWidth: "2px", + color: "rgb(0,0,0)" + } + ]; + // Convert the coordinates of the polygon from GeoJson to GeoCoordinates. + const coordinates = polygon_crossing_antimeridian.features[0].geometry.coordinates[0].map(([lng, lat]) => GeoCoordinates.fromGeoPoint([lng, lat])); + // Split the polygon in 3 parts. + const wrappedLineString = wrapLineString(coordinates); + // Extracts a part (left, middle or right) from the wrapped polygon + // and convert it to a GeoJson feature. + const toGeoJsonMultiLineString = (part) => { + const coordinates = wrappedLineString[part]; + // Converts an Array of GeoCoordinates to GeoJSON coordinates. + const toGeoJsonCoordinates = (coordinates) => { + coordinates = coordinates ?? []; + return coordinates.map(line => { + return line.map(({ lat, lng }) => [lng, lat]); + }); + }; + return { + type: "Feature", + properties: { + fragment: part + }, + geometry: { + type: "MultiLineString", + coordinates: toGeoJsonCoordinates(coordinates) + } + }; + }; + const separator = { + type: "Feature", + properties: {}, + geometry: { + type: "LineString", + coordinates: [ + [180, 90], + [180, -90] + ] + } + }; + const lookAt = { + target: [-160, 40], + distance: EarthConstants.EQUATORIAL_CIRCUMFERENCE * 2.5 + }; + it(`linestring to wrap`, async function () { + this.timeout(5000); + await geoJsonTest.run({ + lookAt, + mochaTest: this, + testImageName: `geojson-wrap-linestring-crossing-antimeridian`, + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: polygon_crossing_antimeridian + }); + }); + it(`wrapped linestring - merged`, async function () { + this.timeout(5000); + await geoJsonTest.run({ + lookAt, + mochaTest: this, + testImageName: `geojson-wrap-linestring-crossing-antimeridian-merged`, + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: { + type: "FeatureCollection", + features: [ + toGeoJsonMultiLineString("left"), + toGeoJsonMultiLineString("middle"), + toGeoJsonMultiLineString("right"), + separator + ] + } + }); + }); + for (const part in wrappedLineString) { + if (!wrappedLineString.hasOwnProperty(part)) { + continue; + } + const feature = toGeoJsonMultiLineString(part); + it(`wrapped linestring - ${part}`, async function () { + this.timeout(5000); + await geoJsonTest.run({ + lookAt, + mochaTest: this, + testImageName: `geojson-wrap-linestring-crossing-antimeridian-${part}`, + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: { + type: "FeatureCollection", + features: [feature, separator] + } + }); + }); + } + }); + describe("clip lines against bounds", async function () { + it("clip long line string", async function () { + const bounds = [ + [-2.8125, -15.28418511407642], + [76.9921875, -15.28418511407642], + [76.9921875, 54.77534585936447], + [-2.8125, 54.77534585936447], + [-2.8125, -15.28418511407642] + ]; + const geoBox = new GeoBox(GeoCoordinates.fromGeoPoint(bounds[0]), GeoCoordinates.fromGeoPoint(bounds[0])); + bounds.forEach(geoPoint => { + geoBox.growToContain(GeoCoordinates.fromGeoPoint(geoPoint)); + }); + const { west, south, east, north } = geoBox; + const { min, max } = webMercatorTilingScheme.projection.projectBox(geoBox); + const inputLineString = [ + [-28.125, 33.43144133557529], + [-24.609375, 49.38237278700955], + [-9.140625, 39.36827914916014], + [21.4453125, 44.08758502824516], + [25.6640625, 61.60639637138628], + [45, 45.82879925192134], + [56.6015625, 62.2679226294176], + [61.87499999999999, 43.32517767999296], + [88.24218749999999, 39.639537564366684], + [84.72656249999999, 14.26438308756265], + [53.78906249999999, 13.923403897723347], + [33.3984375, 27.994401411046148], + [52.734375, 35.17380831799959], + [58.71093750000001, 28.613459424004414], + [61.52343749999999, 35.460669951495305], + [38.67187499999999, 39.639537564366684], + [16.875, 32.24997445586331], + [12.65625, 14.604847155053898], + [-14.0625, -4.214943141390639], + [41.1328125, -26.11598592533351] + ]; + const points = inputLineString.map(geoPos => { + const { x, y } = webMercatorProjection.projectPoint(GeoCoordinates.fromGeoPoint(geoPos)); + return new Vector3(x, y, 0); + }); + const lineStrings = clipLineString(points, min.x, min.y, max.x, max.y); + const coordinates = lineStrings.map(lineString => lineString.map(({ x, y }) => webMercatorProjection.unprojectPoint(new Vector3(x, y, 0)).toGeoPoint())); + const geoJson = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: {}, + geometry: { + type: "Polygon", + coordinates: [ + [ + [west, south], + [east, south], + [east, north], + [west, north], + [west, south] + ] + ] + } + }, + { + type: "Feature", + properties: { + color: "#00ff00" + }, + geometry: { + type: "LineString", + coordinates: inputLineString + } + }, + { + type: "Feature", + properties: { + color: "#ff0000" + }, + geometry: { + type: "MultiLineString", + coordinates + } + } + ] + }; + const ourStyle = [ + { + when: ["==", ["geometry-type"], "Polygon"], + technique: "fill", + color: "rgba(100,100,100,0.5)", + lineWidth: 2 + }, + { + when: ["==", ["geometry-type"], "LineString"], + technique: "solid-line", + metricUnit: "Pixel", + color: ["get", "color"], + lineWidth: 2 + } + ]; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-clip-line-against-tile-border", + theme: { lights, styles: { geojson: ourStyle } }, + geoJson: geoJson, + lookAt: { + zoomLevel: 2, + target: geoBox.center + } + }); + }); + }); + describe("Tiled GeoJson", async function () { + it("Circle with an hole with same winding as the outer ring", async function () { + const dataProvider = new (class extends DataProvider { + ready() { + return true; + } + async getTile(tileKey) { + const geoBox = webMercatorTilingScheme.getGeoBox(tileKey); + const { longitudeSpan, center } = geoBox; + const [cx, cy] = center.toGeoPoint(); + const circle = turf.circle([cx, cy], longitudeSpan * 0.1, { + units: "degrees" + }); + const innerCircle = turf.circle([cx, cy], longitudeSpan * 0.04, { + units: "degrees" + }); + const ring = turf.polygon([ + ...circle.geometry.coordinates, + ...innerCircle.geometry.coordinates + ]); + return turf.featureCollection([ring]); + } + async connect() { } + dispose() { } + })(); + await geoJsonTest.run({ + dataProvider, + mochaTest: this, + testImageName: "geojson-polygon-holes-windings", + theme: { + styles: [ + { + styleSet: "geojson", + when: ["==", ["geometry-type"], "Polygon"], + technique: "fill", + color: "red", + lineColor: "#000", + lineWidth: 1 + } + ] + }, + lookAt: { + zoomLevel: 14.0, + target: webMercatorTilingScheme.getGeoBox(webMercatorTilingScheme.getTileKey(GeoCoordinates.fromGeoPoint([-90, -42.52556]), 13)).center + } + }); + }); + }); + describe("Polygons", async function () { + it("Triangle with a hole rendered at zoom level 2", async function () { + const theme = { + lights, + styles: [ + { + styleSet: "geojson", + when: ["==", ["geometry-type"], "Polygon"], + technique: "fill", + color: "rgba(100,100,100,0.5)", + lineWidth: 2 + } + ] + }; + const polygon = turf.polygon([ + [ + [0, 0, 0], + [170, 35, 0], + [170, -35, 0], + [0, 0, 0] + ], + [ + [0, 0, 0], + [170, 15, 0], + [170, -15, 0], + [0, 0, 0] + ] + ]); + const [lng, lat] = turf.center(polygon).geometry.coordinates; + const geoJsonStore = new GeoJsonStore(); + geoJsonStore.features.insert(polygon); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-triangle-with-hole-at-zoom-level-2", + dataProvider: geoJsonStore, + theme, + lookAt: { + zoomLevel: 2, + target: [lng, lat] + } + }); + }); + }); +}); +//# sourceMappingURL=GeoJsonDataRendering.js.map \ No newline at end of file diff --git a/test/rendering/GeoJsonDataRendering.js.map b/test/rendering/GeoJsonDataRendering.js.map new file mode 100644 index 0000000..874037d --- /dev/null +++ b/test/rendering/GeoJsonDataRendering.js.map @@ -0,0 +1 @@ +{"version":3,"file":"GeoJsonDataRendering.js","sourceRoot":"","sources":["GeoJsonDataRendering.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/GeoJsonFeaturesRendering.d.ts b/test/rendering/GeoJsonFeaturesRendering.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/rendering/GeoJsonFeaturesRendering.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/rendering/GeoJsonFeaturesRendering.js b/test/rendering/GeoJsonFeaturesRendering.js new file mode 100644 index 0000000..c5c0f06 --- /dev/null +++ b/test/rendering/GeoJsonFeaturesRendering.js @@ -0,0 +1,290 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import * as turf from "@turf/turf"; +import { assert } from "chai"; +import * as THREE from "three"; +import { GeoJsonStore } from "./utils/GeoJsonStore"; +import { GeoJsonTest } from "./utils/GeoJsonTest"; +import { ThemeBuilder } from "./utils/ThemeBuilder"; +const strokePolygonLayer = (params = {}) => { + return { + id: "stroke-polygon", + styleSet: "geojson", + technique: "solid-line", + color: "orange", + lineWidth: ["world-ppi-scale", 20], + secondaryColor: "magenta", + secondaryWidth: ["world-ppi-scale", 35], + ...params + }; +}; +describe("GeoJson features", function () { + const geoJsonTest = new GeoJsonTest(); + const lights = ThemeBuilder.lights; + afterEach(() => { + geoJsonTest.dispose(); + }); + it("Stroke Circle", async function () { + const pos = [13.2, 53.2]; + const circle = turf.circle(pos, 600, { + units: "meters" + }); + const geoJson = turf.featureCollection([circle]); + await geoJsonTest.run({ + testImageName: "geojson-stroke-circle", + mochaTest: this, + geoJson: geoJson, + lookAt: { + target: pos, + zoomLevel: 14 + }, + theme: { + lights, + styles: [ + strokePolygonLayer({ + lineWidth: ["world-ppi-scale", 50], + secondaryWidth: ["world-ppi-scale", 80] + }) + ] + } + }); + }); + it("Extrude Circle", async function () { + const pos = [13.2, 53.2]; + const circle = turf.circle(pos, 600, { + units: "meters" + }); + const geoJson = turf.featureCollection([circle]); + await geoJsonTest.run({ + testImageName: "geojson-extruded-circle", + mochaTest: this, + geoJson: geoJson, + lookAt: { + target: pos, + zoomLevel: 14, + tilt: 60 + }, + theme: { + lights, + styles: [ + { + styleSet: "geojson", + technique: "extruded-polygon", + color: "red", + constantHeight: true, + height: 700 + } + ] + } + }); + }); + describe("Stroke Arcs", async function () { + const lineCaps = ["None", "Round", "Square", "TriangleIn", "TriangleOut"]; + lineCaps.forEach(caps => { + it(`Stroke Arc using from 0 to 300 using '${caps}' caps`, async function () { + const center = [13.2, 53.2]; + const arc = turf.lineArc(center, 5, 0, 300); + const geoJson = turf.featureCollection([arc]); + await geoJsonTest.run({ + mochaTest: this, + geoJson: geoJson, + testImageName: `stroke-arc-with-caps-${caps}`, + lookAt: { + target: center, + zoomLevel: 10 + }, + theme: { + lights, + styles: [strokePolygonLayer({ caps })] + } + }); + }); + }); + }); + describe("Stroke Circles created using lineArc", async function () { + const lineCaps = ["None", "Round", "Square", "TriangleIn", "TriangleOut"]; + lineCaps.forEach(caps => { + it(`Stroke Arc from 0 to 360 using '${caps}' caps`, async function () { + const center = [13.2, 53.2]; + const arc = turf.lineArc(center, 5, 0, 360); + const geoJson = turf.featureCollection([arc]); + await geoJsonTest.run({ + mochaTest: this, + geoJson: geoJson, + testImageName: `stroke-circles-creates-from-arcs-${caps}`, + lookAt: { + target: center, + zoomLevel: 10 + }, + theme: { + lights, + styles: [strokePolygonLayer({ caps })] + } + }); + }); + }); + }); + describe("extruded-polygon technique", async function () { + // Helper function to test the winding of the rings. + const isClockWise = (ring) => THREE.ShapeUtils.isClockWise(ring.map(p => new THREE.Vector2().fromArray(p))); + // the theme used by this test suite. + const theme = { + lights, + styles: [ + { + styleSet: "geojson", + technique: "extruded-polygon", + color: "#0335a2", + lineWidth: 1, + lineColor: "red", + constantHeight: true, + height: 300 + } + ] + }; + // the polygon feature + const polygon = turf.polygon([ + [ + [0.00671649362467299, 51.49353450058163, 0], + [0.006598810705050831, 51.48737650885326, 0], + [0.015169103358567556, 51.48731300784492, 0], + [0.015286786278189713, 51.49347100814989, 0], + [0.006716493624672999, 51.49353450058163, 0], + [0.00671649362467299, 51.49353450058163, 0] + ] + ]); + // the center geo location of the polygon + const [longitude, latitude] = turf.center(polygon).geometry.coordinates; + // the default camera setup used by this test suite. + const lookAt = { + target: [longitude, latitude], + zoomLevel: 15, + tilt: 40, + heading: 45 + }; + it("Clockwise polygon touching tile border", async function () { + const dataProvider = new GeoJsonStore(); + dataProvider.features.insert(polygon); + await geoJsonTest.run({ + mochaTest: this, + dataProvider, + testImageName: `geojson-extruded-polygon-touching-tile-bounds`, + lookAt, + theme + }); + }); + it("Clockwise polygon with a hole", async function () { + const dataProvider = new GeoJsonStore(); + const innerPolygon = turf.transformScale(polygon, 0.8, { origin: "center" }); + const polygonWithHole = turf.difference(polygon, innerPolygon); + dataProvider.features.insert(polygonWithHole); + assert.strictEqual(polygonWithHole?.geometry?.coordinates.length, 2); + const outerRing = polygonWithHole.geometry.coordinates[0]; + const innerRing = polygonWithHole.geometry.coordinates[1]; + // test that the winding of the inner ring is opposite to the winding + // of the outer ring. + assert.notStrictEqual(isClockWise(outerRing), isClockWise(innerRing)); + await geoJsonTest.run({ + mochaTest: this, + dataProvider, + testImageName: `geojson-extruded-polygon-cw-with-hole`, + lookAt, + theme + }); + }); + it("Clockwise polygon with a hole wrong winding", async function () { + const dataProvider = new GeoJsonStore(); + const innerPolygon = turf.transformScale(polygon, 0.8, { origin: "center" }); + const polygonWithHole = turf.difference(polygon, innerPolygon); + dataProvider.features.insert(polygonWithHole); + assert.strictEqual(polygonWithHole?.geometry?.coordinates.length, 2); + const outerRing = polygonWithHole.geometry.coordinates[0]; + const innerRing = polygonWithHole.geometry.coordinates[1]; + // reverse the winding of the inner ring so to have the same winding + // of the outer ring + innerRing.reverse(); + // verify that the winding of the rings is the same + assert.strictEqual(isClockWise(outerRing), isClockWise(innerRing)); + await geoJsonTest.run({ + mochaTest: this, + dataProvider, + testImageName: `geojson-extruded-polygon-cw-wrong-winding-of-inner-ring`, + lookAt, + theme + }); + }); + it("Clockwise multi-polygon with a hole wrong winding", async function () { + const dataProvider = new GeoJsonStore(); + const scaledPolygon = turf.transformScale(polygon, 0.5, { origin: "center" }); + const innerPolygon = turf.transformScale(scaledPolygon, 0.8, { origin: "center" }); + const polygonWithHole = turf.difference(scaledPolygon, innerPolygon); + const otherPolygonWithHole = turf.clone(polygonWithHole); + turf.transformTranslate(polygonWithHole, 200, 90, { units: "meters", mutate: true }); + turf.transformTranslate(otherPolygonWithHole, 200, -90, { + units: "meters", + mutate: true + }); + const multi = turf.union(polygonWithHole, otherPolygonWithHole); + assert.strictEqual(multi.geometry?.type, "MultiPolygon"); + dataProvider.features.insert(multi); + await geoJsonTest.run({ + mochaTest: this, + dataProvider, + testImageName: `geojson-extruded-multi-polygon-cw-wrong-winding-of-inner-ring`, + lookAt, + theme + }); + }); + }); + describe("fill technqiue", async function () { + it("Stroked enclosed polygons", async function () { + const box1 = turf.bboxPolygon([-0.1, -0.1, 0.1, 0.1]); + box1.properties = { + "fill-color": "rgba(0, 255, 0, 0.5)", + "render-order": 2, + "stroke-color": "rgba(0, 255, 255, 0.5)", + "stroke-size": 40, + "stroke-render-order": 2.5 + }; + const box2 = turf.bboxPolygon([-0.4, -0.4, 0.4, 0.4]); + box2.properties = { + "fill-color": "rgba(255, 0, 0, 0.5)", + "render-order": 1, + "stroke-color": "rgba(0, 0, 255, 0.5)", + "stroke-size": 40, + "stroke-render-order": 1.5 + }; + const dataProvider = new GeoJsonStore(); + dataProvider.features.insert(box1); + dataProvider.features.insert(box2); + await geoJsonTest.run({ + mochaTest: this, + dataProvider, + testImageName: `geojson-stroked-enclosed-polygons`, + lookAt: { + target: [0, 0], + zoomLevel: 8.8 + }, + theme: { + lights: ThemeBuilder.lights, + styles: [ + { + styleSet: "geojson", + technique: "fill", + color: ["get", "fill-color"], + renderOrder: ["get", "render-order"] + }, + { + styleSet: "geojson", + technique: "solid-line", + color: ["get", "stroke-color"], + lineWidth: ["world-ppi-scale", ["get", "stroke-size"]], + renderOrder: ["get", "stroke-render-order"], + clipping: true + } + ] + } + }); + }); + }); +}); +//# sourceMappingURL=GeoJsonFeaturesRendering.js.map \ No newline at end of file diff --git a/test/rendering/GeoJsonFeaturesRendering.js.map b/test/rendering/GeoJsonFeaturesRendering.js.map new file mode 100644 index 0000000..237a2a6 --- /dev/null +++ b/test/rendering/GeoJsonFeaturesRendering.js.map @@ -0,0 +1 @@ +{"version":3,"file":"GeoJsonFeaturesRendering.js","sourceRoot":"","sources":["GeoJsonFeaturesRendering.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/ScreenSpaceRenderingTests.d.ts b/test/rendering/ScreenSpaceRenderingTests.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/rendering/ScreenSpaceRenderingTests.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/rendering/ScreenSpaceRenderingTests.js b/test/rendering/ScreenSpaceRenderingTests.js new file mode 100644 index 0000000..81281e3 --- /dev/null +++ b/test/rendering/ScreenSpaceRenderingTests.js @@ -0,0 +1,373 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { EarthConstants, sphereProjection } from "@flywave/flywave-geoutils"; +import { GeoJsonTest } from "./utils/GeoJsonTest"; +import { ThemeBuilder } from "./utils/ThemeBuilder"; +// Mocha discourages using arrow functions, see https://mochajs.org/#arrow-functions +describe("ScreenSpaceRendering Test", function () { + const geoJsonTest = new GeoJsonTest(); + it("renders icon without text, if fontcatalog not found ", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-no-text-icon", + theme: new ThemeBuilder().withInvalidFontCatalog().withMarkerStyle().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "Marker" }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + } + ] + }, + lookAt: { tilt: 80, zoomLevel: 19 }, + tileGeoJson: false + }); + }); + it("renders interleaved icon and text", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-interleaved-icon-text", + theme: new ThemeBuilder().withFontCatalog().withMarkerStyle().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { + text: "Marker0", + color: "red", + imageTexture: "red-icon", + renderOrder: 0 + }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + }, + { + type: "Feature", + properties: { + text: "Marker1", + color: "green", + imageTexture: "green-icon", + renderOrder: 1 + }, + geometry: { type: "Point", coordinates: [14.6, 53.32] } + }, + { + type: "Feature", + properties: { + text: "Marker2", + color: "blue", + imageTexture: "white-icon", + renderOrder: 2 + }, + geometry: { type: "Point", coordinates: [14.6, 53.28] } + } + ] + }, + lookAt: { tilt: 0, zoomLevel: 10 }, + tileGeoJson: false + }); + }); + it("renders icons and text using double precision coordinates", async function () { + this.timeout(5000); + // FLYWAVE-14465: Text and cross icon must be centered on green square. + const squaresStyle = { + when: "$geometryType == 'point'", + technique: "squares", + color: "green", + size: 17, + styleSet: "geojson" + }; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-precision-icon-text", + theme: new ThemeBuilder() + .withFontCatalog() + .withMarkerStyle() + .withStyle(squaresStyle) + .build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { + text: "o", + color: "white", + imageTexture: "plus-icon", + iconYOffset: 0, + size: 18 + }, + geometry: { + type: "MultiPoint", + coordinates: [ + [14.60015, 53.30007], + [14.60015, 53.29993], + [14.59985, 53.29993], + [14.59985, 53.30007] + ] + } + } + ] + }, + lookAt: { tilt: 0, zoomLevel: 20 }, + tileGeoJson: false + }); + }); + it("renders point using marker technique, with theme set to datasource", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-point-after-theme-reset-in-datasource", + theme: new ThemeBuilder().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "Marker", renderOrder: 1 }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + } + ] + }, + lookAt: { tilt: 0, zoomLevel: 10 }, + tileGeoJson: false, + beforeFinishCallback: async (mapView) => { + await mapView + .getDataSourceByName("geojson") + ?.setTheme({ styles: [ThemeBuilder.markerStyle] }); + } + }); + }); + it("renders point using marker technique, after fontcatalog added in set theme", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-point-after-font-added", + theme: new ThemeBuilder().withMarkerStyle().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "Marker", renderOrder: 1 }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + } + ] + }, + lookAt: { tilt: 0, zoomLevel: 10 }, + tileGeoJson: false, + beforeFinishCallback: async (mapView) => { + await mapView + .getDataSourceByName("geojson") + ?.setTheme(new ThemeBuilder(true).withMarkerStyle().build()); + await mapView.setTheme(new ThemeBuilder().withFontCatalog().build()); + } + }); + }); + it("renders point using marker technique, after theme reset", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-point-after-theme-reset", + theme: new ThemeBuilder().withMarkerStyle().withFontCatalog().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "Marker", renderOrder: 1, color: "blue" }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + } + ] + }, + lookAt: { tilt: 0, zoomLevel: 10 }, + tileGeoJson: false, + beforeFinishCallback: async (mapView) => { + await mapView.setTheme(new ThemeBuilder().withMarkerStyle().withFontCatalog().build()); + } + }); + }); + it("removes marker, after datasource is removed", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-after-datasource-removed", + theme: new ThemeBuilder().withMarkerStyle().withFontCatalog().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "Marker", renderOrder: 1, color: "blue" }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + } + ] + }, + lookAt: { tilt: 0, zoomLevel: 10 }, + tileGeoJson: false, + beforeFinishCallback: async (mapView) => { + await mapView.removeDataSource(mapView.getDataSourceByName("geojson")); + } + }); + }); + it("renders elevated point using marker technique", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-elevated-point", + theme: new ThemeBuilder().withMarkerStyle().withFontCatalog().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "Marker" }, + geometry: { type: "Point", coordinates: [14.6, 53.3, 15] } + } + ] + }, + lookAt: { tilt: 80, zoomLevel: 19 }, + tileGeoJson: false + }); + }); + it("renders a point which is elevated above MAX_BUILDING_HEIGHT", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-elevated-point-above-max-building-height", + theme: new ThemeBuilder().withMarkerStyle().withFontCatalog().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "Marker" }, + geometry: { + type: "Point", + coordinates: [14.6, 53.3, 2 * EarthConstants.MAX_BUILDING_HEIGHT] + } + } + ] + }, + lookAt: { zoomLevel: 14 }, + tileGeoJson: false + }); + }); + it("renders point markers using dataSourceOrder", async function () { + this.timeout(5000); + const markerStyle = { + when: ["==", ["geometry-type"], "Point"], + technique: "labeled-icon", + imageTexture: ["get", "icon"], + text: ["get", "text"], + size: 15, + iconMayOverlap: true, + iconReserveSpace: false, + textMayOverlap: true, + textReserveSpace: false, + color: "black", + renderOrder: ["get", "renderOrder"], + styleSet: "geojson" + }; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "markers-with-different-dataSourceOrders", + theme: new ThemeBuilder().withStyle(markerStyle).withFontCatalog().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "1", icon: "red-icon", renderOrder: 1 }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + }, + { + type: "Feature", + properties: { text: "2", icon: "red-icon", renderOrder: 2 }, + geometry: { type: "Point", coordinates: [14.65, 53.33] } + } + ] + }, + extraDataSource: { + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { text: "3", icon: "green-icon", renderOrder: 0 }, + geometry: { type: "Point", coordinates: [14.68, 53.26] } + } + ] + }, + dataSourceOrder: 1 + } + }); + }); + it("renders marker correctly on zoomed out globe", async function () { + const geoJson = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { color: "#436981" }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-180, -90], + [180, -90], + [180, 90], + [-180, 90], + [-180, -90] + ] + ] + } + }, + { + type: "Feature", + geometry: { type: "Point", coordinates: [0, 0] } + } + ] + }; + await geoJsonTest.run({ + mochaTest: this, + testImageName: "marker-on-zoomed-out-globe", + theme: new ThemeBuilder().withMarkerStyle().withFontCatalog().build(), + geoJson, + lookAt: { + zoomLevel: 3, + target: [0, 0] + }, + projection: sphereProjection + }); + }); + it("renders icon after image is loaded", async function () { + this.timeout(5000); + await geoJsonTest.run({ + mochaTest: this, + testImageName: "geojson-icon-after-image-loaded", + theme: new ThemeBuilder().withFontCatalog().withMarkerStyle().build(), + geoJson: { + type: "FeatureCollection", + features: [ + { + type: "Feature", + properties: { + text: "Marker0", + color: "red", + imageTexture: "icon-to-load", + renderOrder: 0 + }, + geometry: { type: "Point", coordinates: [14.6, 53.3] } + } + ] + }, + lookAt: { tilt: 0, zoomLevel: 10 }, + tileGeoJson: false + }); + }); +}); +//# sourceMappingURL=ScreenSpaceRenderingTests.js.map \ No newline at end of file diff --git a/test/rendering/ScreenSpaceRenderingTests.js.map b/test/rendering/ScreenSpaceRenderingTests.js.map new file mode 100644 index 0000000..da675f4 --- /dev/null +++ b/test/rendering/ScreenSpaceRenderingTests.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ScreenSpaceRenderingTests.js","sourceRoot":"","sources":["ScreenSpaceRenderingTests.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/StylingTest.d.ts b/test/rendering/StylingTest.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/rendering/StylingTest.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/rendering/StylingTest.js b/test/rendering/StylingTest.js new file mode 100644 index 0000000..320bd18 --- /dev/null +++ b/test/rendering/StylingTest.js @@ -0,0 +1,948 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +// Mocha discourages using arrow functions, see https://mochajs.org/#arrow-functions +import { TextureCoordinateType } from "@flywave/flywave-datasource-protocol"; +import { FeaturesDataSource } from "@flywave/flywave-features-datasource"; +import { OrientedBox3, ProjectionType } from "@flywave/flywave-geoutils"; +import { MapView, MapViewEventNames } from "@flywave/flywave-mapview"; +import { GeoJsonTiler } from "@flywave/flywave-mapview-decoder/index-worker"; +import { getPlatform, RenderingTestHelper, waitForEvent } from "@flywave/flywave-test-utils"; +import { getReferenceImageUrl } from "@flywave/flywave-test-utils/lib/rendering/ReferenceImageLocator"; +import { getOptionValue } from "@flywave/flywave-utils"; +import { VectorTileDecoder } from "@flywave/flywave-vectortile-datasource/index-worker"; +import { assert } from "chai"; +import * as THREE from "three"; +function baseRenderingTest(name, options, testFun, cleanupFun) { + const commonTestOptions = { module: "flywave.gl" }; + const imageUrl = getReferenceImageUrl({ ...commonTestOptions, platform: getPlatform(), name }); + RenderingTestHelper.cachedLoadImageData(imageUrl).catch(_ => { + // We can ignore error here, as _if_ this file was really needed, then test + // will try to resolve this promise and report failure in test context. + }); + it(name, async function () { + this.timeout(100000); + let canvas; + // TODO: remove `module` name from RenderingTestHalper API + try { + const ibct = new RenderingTestHelper(this, commonTestOptions); + canvas = document.createElement("canvas"); + canvas.width = options.width ?? options.height ?? 100; + canvas.height = options.height ?? options.width ?? 100; + await testFun(canvas); + await ibct.assertCanvasMatchesReference(canvas, name, options); + } + finally { + if (cleanupFun !== undefined) { + cleanupFun(); + } + if (canvas !== undefined) { + canvas.width = 0; + canvas.height = 0; + canvas = undefined; + } + } + }); +} +function mapViewFitGeoBox(mapView, geoBox, margin = 0.1) { + if (mapView.projection.type !== ProjectionType.Planar) { + throw new Error("mapViewFitGeoBox doesn't support non-planar projections"); + } + const boundingBox = new THREE.Box3(); + const tmpVec3 = new THREE.Vector3(); + mapView.projection.projectBox(geoBox, boundingBox); + const size = boundingBox.getSize(tmpVec3); + const viewSize = Math.max(size.x, size.y); + const fov = mapView.camera.fov; + const height = (viewSize / 2) * (1 / Math.tan(THREE.MathUtils.degToRad(fov / 2))); + const distance = height * (1 + margin); + boundingBox.getCenter(tmpVec3); + const target = mapView.projection.unprojectPoint(tmpVec3); + return { + target, + distance, + tilt: 0, + heading: 0 + }; +} +function mapViewFeaturesRenderingTest(name, options, testFun) { + let mapView; + baseRenderingTest(name, options, async function (canvas) { + //document.body.appendChild(canvas); + mapView = new MapView({ + canvas, + theme: options.theme ?? {}, + preserveDrawingBuffer: true, + disableFading: true, + pixelRatio: 1 + }); + mapView.animatedExtrusionHandler.enabled = false; + const dataSource = new FeaturesDataSource({ + styleSetName: "geojson", + geojson: options.geoJson, + decoder: new VectorTileDecoder(), + tiler: new GeoJsonTiler(), + gatherFeatureAttributes: true + }); + options.dynamicProperties?.forEach(dynamicProperty => { + mapView?.setDynamicProperty(dynamicProperty.name, dynamicProperty.value); + }); + mapView.addDataSource(dataSource); + const geoBox = dataSource.getGeoBox(); + assert.isDefined(geoBox); + const defaultLookAt = mapViewFitGeoBox(mapView, geoBox, getOptionValue(options.margin, 0.15)); + const lookAt = { ...defaultLookAt, ...options.lookAt }; + mapView.lookAt(lookAt); + if (options.grid !== undefined) { + const gridDivisions = 4; + const gridSize = options.grid * gridDivisions; + const position = geoBox.center; + const box = new OrientedBox3(); + mapView.projection.localTangentSpace(position, box); + const grid = new THREE.GridHelper(gridSize, gridDivisions, 0xff0000, 0x00ff00); + grid.geometry.rotateX(Math.PI / 2); + grid.anchor = position; + grid.setRotationFromMatrix(box.getRotationMatrix()); + mapView.mapAnchors.add(grid); + } + mapView.update(); + if (testFun !== undefined) { + await testFun(mapView, dataSource); + } + else { + await waitForEvent(mapView, MapViewEventNames.FrameComplete); + } + // Don't dispose mapView yet b/c the context will be lost since three.js 0.115 + // when WebGLRenderer.dispose is called (i.e. actual IBCT image will be empty). + }, () => { + if (mapView !== undefined) { + mapView.dispose(); + mapView = undefined; + } + }); +} +describe("MapView Styling Test", function () { + const referenceBackground = { + // background polygon, taking about half of view + type: "Feature", + geometry: { + type: "Polygon", + coordinates: [ + [ + [0.004, 0.004], + [-0.0, 0.004], + [-0.0, -0.004], + [0.004, -0.004], + [0.004, 0.004] + ] + ] + }, + properties: { + kind: "background" + } + }; + const referenceBackroundStyle = { + when: "$geometryType == 'polygon' && kind == 'background'", + technique: "fill", + final: true, + attr: { + color: "#22f" + } + }; + const themeTextSettings = { + fontCatalogs: [ + { + name: "fira", + url: "../dist/resources/fonts/Default_FontCatalog.json" + } + ], + images: { + "my-marker-icon": { + url: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIyLjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZlcnNpb249IjEuMSIgaWQ9Imx1aS1pY29uLWRlc3RpbmF0aW9ucGluLW9uZGFyay1zb2xpZC1sYXJnZSIKCSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ4IDQ4IgoJIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQ4IDQ4IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGc+Cgk8ZyBpZD0ibHVpLWljb24tZGVzdGluYXRpb25waW4tb25kYXJrLXNvbGlkLWxhcmdlLWJvdW5kaW5nLWJveCIgb3BhY2l0eT0iMCI+CgkJPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTQ3LDF2NDZIMVYxSDQ3IE00OCwwSDB2NDhoNDhWMEw0OCwweiIvPgoJPC9nPgoJPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNmZmZmZmYiIGQ9Ik0yNCwyQzEzLjg3MDgsMiw1LjY2NjcsMTAuMTU4NCw1LjY2NjcsMjAuMjIzMwoJCWMwLDUuMDMyNSwyLjA1MzMsOS41ODg0LDUuMzcxNywxMi44ODgzTDI0LDQ2bDEyLjk2MTctMTIuODg4M2MzLjMxODMtMy4zLDUuMzcxNy03Ljg1NTgsNS4zNzE3LTEyLjg4ODMKCQlDNDIuMzMzMywxMC4xNTg0LDM0LjEyOTIsMiwyNCwyeiBNMjQsMjVjLTIuNzY1LDAtNS0yLjIzNS01LTVzMi4yMzUtNSw1LTVzNSwyLjIzNSw1LDVTMjYuNzY1LDI1LDI0LDI1eiIvPgo8L2c+Cjwvc3ZnPgo=", + preload: true + } + }, + imageTextures: [ + { + name: "my-marker-icon", + image: "my-marker-icon" + } + ] + }; + describe("point features", function () { + const points = [ + { + type: "Feature", + geometry: { + type: "Point", + coordinates: [0.003, 0.001] + }, + properties: { + name: "aBcD" + } + }, + { + type: "Feature", + geometry: { + type: "Point", + coordinates: [-0.003, 0.001] + }, + properties: { + name: "aBcD" + } + }, + { + type: "Feature", + geometry: { + type: "Point", + coordinates: [0.0, -0.002] + }, + properties: { + name: "aBcD" + } + } + ]; + function makePointTextTestCases(testCases, options) { + for (const testCase in testCases) { + const attr = testCases[testCase]; + mapViewFeaturesRenderingTest(`solid-line-styling-${testCase}`, { + geoJson: { + type: "FeatureCollection", + features: [ + // tested horizontal line + ...points, + referenceBackground + ] + }, + theme: { + ...themeTextSettings, + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'point'", + technique: "text", + attr + } + ] + } + }, + ...options + }); + } + } + function makePointPoiTestCases(testCases, options) { + for (const testCase in testCases) { + const attr = testCases[testCase]; + mapViewFeaturesRenderingTest(`poi-styling-${testCase}`, { + geoJson: { + type: "FeatureCollection", + features: [ + // tested horizontal line + ...points, + referenceBackground + ] + }, + theme: { + ...themeTextSettings, + clearColor: "#a0a0a0", + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'point'", + technique: "labeled-icon", + attr + } + ] + } + }, + ...options + }); + } + } + function makePointTestCases(testCases, options) { + for (const testCase in testCases) { + const attr = testCases[testCase]; + mapViewFeaturesRenderingTest(`solid-line-styling-${testCase}`, { + geoJson: { + type: "FeatureCollection", + features: [ + // tested horizontal line + ...points, + referenceBackground + ] + }, + theme: { + ...themeTextSettings, + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'point'", + technique: "circles", + attr + } + ] + } + }, + ...options + }); + } + } + describe("text", function () { + makePointTextTestCases({ + "point-text-basic": { color: "#f0f", size: 16 }, + "point-text-rgba": { color: "#f0f9", size: 16 }, + "point-text-bg-rgba": { + color: "#f0f", + backgroundSize: 6, + backgroundColor: "#0008", + size: 16 + } + }, { + margin: 0.5 + }); + }); + describe("poi", function () { + makePointPoiTestCases({ + "poi-basic-icon-only": { + imageTexture: "my-marker-icon", + size: 10, + screenHeight: 20, + screenWidth: 20, + text: "", + iconBrightness: 0.7 + }, + "poi-basic-text-only": { + color: "#fe09", + size: 16, + screenHeight: 20, + screenWidth: 20 + }, + "poi-basic-both": { + color: "#fe0", + size: 16, + imageTexture: "my-marker-icon", + screenHeight: 20, + screenWidth: 20, + iconYOffset: 16, + iconColor: "#e22" + } + }, { + margin: 0.1 + }); + }); + describe("circles", function () { + makePointTestCases({ + "point-circles-basic": { color: "#ca6", size: 10 }, + "point-circles-rgba": { color: "#ca69", size: 10 }, + "point-circles-rgb-opacity": { color: "#ca6", opacity: 0.5, size: 10 }, + "point-circles-rgba-opacity": { color: "#ca69", opacity: 0.5, size: 10 } + }, { + margin: 0.5 + }); + }); + }); + describe("line features", function () { + const straightLine = { + type: "Feature", + geometry: { + type: "LineString", + coordinates: [ + [0.004, 0.001], + [-0.004, 0.001] + ] + } + }; + const shortLine = { + type: "Feature", + geometry: { + type: "LineString", + coordinates: [ + [0.004, 0.001], + [0.0, 0.001] + ] + } + }; + const diagonalLine = { + type: "Feature", + geometry: { + type: "LineString", + coordinates: [ + [0.004, -0.004], + [-0.004, 0.004] + ] + } + }; + function makeLineTestCase(testCases, lineGeometry = straightLine) { + for (const testCase in testCases) { + for (const clipping of [true, false]) { + const postfix = clipping === true ? "" : "-no-clipping"; + const attr = JSON.parse(JSON.stringify(testCases[testCase])); + attr.clipping = clipping; + mapViewFeaturesRenderingTest(`solid-line-styling-${testCase}${postfix}`, { + geoJson: { + type: "FeatureCollection", + features: [lineGeometry, referenceBackground] + }, + theme: { + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'line'", + technique: "solid-line", + attr + } + ] + } + } + // grid: 100 + }); + } + } + } + describe("solid-line technique", function () { + describe("basic", function () { + makeLineTestCase({ + "basic-100m": { lineWidth: 100, color: "#0b97c4" }, + "basic-dash-100m": { + lineWidth: 100, + color: "#0b97c4", + dashSize: 100, + gapSize: 100 + }, + "basic-dash-10px-world-ppi-scale": { + lineWidth: ["world-ppi-scale", 10], + color: "#0b97c4", + dashSize: ["world-ppi-scale", 10], + gapSize: ["world-ppi-scale", 10] + }, + "basic-dash-10px-string": { + lineWidth: "10px", + color: "#0b97c4", + dashSize: "10px", + gapSize: "10px" + }, + "basic-100m-rgba": { lineWidth: 100, color: "#0b97c470" }, + "basic-100m-rgba-square": { + lineWidth: 100, + color: "#0b97c470", + caps: "Square" + }, + "basic-100m-rgba-triangle-out": { + lineWidth: 100, + color: "#0b97c470", + caps: "TriangleIn" + }, + "basic-100m-rgba-trianglein": { + lineWidth: 100, + color: "#0b97c470", + caps: "TriangleOut" + }, + "basic-100m-rgba-none": { lineWidth: 100, color: "#0b97c470", caps: "None" }, + "basic-10px-rgba": { lineWidth: "10px", color: "#0b97c470" } + }); + // Short line that ends on tile border + makeLineTestCase({ + "short-100m": { lineWidth: 100, color: "#0b97c4" }, + "short-100m-rgba": { lineWidth: 100, color: "#0b97c470" }, + "short-100m-rgba-square": { + lineWidth: 100, + color: "#0b97c470", + caps: "Square" + }, + "short-100m-rgba-triangle-out": { + lineWidth: 100, + color: "#0b97c470", + caps: "TriangleIn" + }, + "short-100m-rgba-trianglein": { + lineWidth: 100, + color: "#0b97c470", + caps: "TriangleOut" + }, + "short-100m-rgba-none": { + lineWidth: 100, + color: "#0b97c470", + caps: "None" + }, + "short-10px-rgba": { lineWidth: "10px", color: "#0b97c470" } + }, shortLine); + // Diagonal lines are buggy at the moment + makeLineTestCase({ + "diagonal-100m": { lineWidth: 100, color: "#0b97c4" }, + "diagonal-dash-100m": { + lineWidth: 100, + color: "#0b97c4", + dashSize: 80, + gapSize: 80 + }, + "diagonal-100m-rgba": { lineWidth: 100, color: "#0b97c470" }, + "diagonal-100m-rgba-square": { + lineWidth: 100, + color: "#0b97c470", + caps: "Square" + }, + "diagonal-100m-rgba-triangle-out": { + lineWidth: 100, + color: "#0b97c470", + caps: "TriangleIn" + }, + "diagonal-100m-rgba-trianglein": { + lineWidth: 100, + color: "#0b97c470", + caps: "TriangleOut" + }, + "diagonal-100m-rgba-none": { + lineWidth: 100, + color: "#0b97c470", + caps: "None" + }, + "diagonal-10px-rgba": { lineWidth: "10px", color: "#0b97c470" } + }, diagonalLine); + }); + describe("with outline", function () { + makeLineTestCase({ + "outline-10px-2px": { + // BUGGY ? + lineWidth: "10px", + color: "#0b97c4", + outlineWidth: "2px", + outlineColor: "#7f7" + }, + "outline-10px-2px-rgba": { + lineWidth: "10px", + color: "#0b97c470", + outlineWidth: "2px", + outlineColor: "#7f7" + } + }); + // Short line that end on tile border + makeLineTestCase({ + "short-outline-10px-2px": { + // BUGGY ? + lineWidth: "10px", + color: "#0b97c4", + outlineWidth: "2px", + outlineColor: "#7f7" + }, + "short-outline-10px-2px-rgba": { + lineWidth: "10px", + color: "#0b97c470", + outlineWidth: "2px", + outlineColor: "#7f7" + } + }, shortLine); + // Diagonal lines are buggy at the moment + makeLineTestCase({ + "diagonal-outline-10px-2px": { + lineWidth: "10px", + color: "#0b97c4", + outlineWidth: "2px", + outlineColor: "#7f7" + }, + "diagonal-outline-10px-2px-rgba": { + lineWidth: "10px", + color: "#0b97c470", + outlineWidth: "2px", + outlineColor: "#7f7" + } + }, diagonalLine); + }); + }); + describe("text from lines", function () { + mapViewFeaturesRenderingTest(`line-text-basic`, { + width: 200, + height: 200, + geoJson: { + type: "FeatureCollection", + features: [ + // tested horizontal line + straightLine, + referenceBackground + ] + }, + theme: { + ...themeTextSettings, + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'line'", + technique: "solid-line", + attr: { + color: "#E3D49A", + outlineColor: "#3A4C69", + lineWidth: 40, + outlineWidth: 10, + clipping: true + } + }, + { + when: "$geometryType == 'line'", + technique: "text", + attr: { + text: "Test", + color: "#2f3", + backgroundColor: "#cfe", + size: 20, + backgroundSize: 5, + fontStyle: "Bold", + vAlignment: "Above" + } + } + ] + } + } + }); + }); + }); + describe("polygon features", function () { + const lights = [ + { + type: "ambient", + color: "#FFFFFF", + name: "ambientLight", + intensity: 0.5 + }, + { + type: "directional", + color: "#FFFFFF", + name: "light1", + intensity: 0.5, + direction: { + x: -5, + y: -2, + z: 10 + } + } + ]; + const rectangle1 = { + // sample rectangular polygon + type: "Feature", + geometry: { + type: "Polygon", + coordinates: [ + [ + [0.001, 0.001], + [-0.004, 0.001], + [-0.004, -0.002], + [0.001, -0.002], + [0.001, 0.001] + ] + ] + }, + properties: { + name: "Awesome Building", + kind: "building", + height: 200, + bbox: [-0.004, -0.002, 0.001, 0.001] + } + }; + const rectangle2 = { + type: "Feature", + geometry: { + type: "Polygon", + coordinates: [ + [ + [0.001, 0.002], + [0.004, 0.002], + [0.004, -0.002], + [0.001, -0.002] + ] + ] + }, + properties: { + name: "Not So Awesome Building", + kind: "building", + height: 200 + } + }; + function makePolygonTestCases(technique, testCases, options) { + let extraFeatures = []; + if (options && options.geoJson) { + extraFeatures = + options.geoJson.type === "FeatureCollection" ? options.geoJson.features : []; + options = { ...options }; + delete options.geoJson; + } + for (const testCase in testCases) { + const attr = testCases[testCase]; + mapViewFeaturesRenderingTest(`polygon-styling-${testCase}`, { + geoJson: { + type: "FeatureCollection", + features: [ + // tested horizontal line + rectangle1, + rectangle2, + referenceBackground, + ...extraFeatures + ] + }, + theme: { + lights, + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'polygon'", + technique: technique, + attr: attr + } + ] + } + }, + ...options + }); + } + } + describe("fill technique", function () { + describe("no outline", function () { + makePolygonTestCases("fill", { + fill: { color: "#0b97c4" }, + "fill-rgba": { color: "#0b97c470" } + }); + }); + describe("with outline", function () { + makePolygonTestCases("fill", { + // all tests are buggy ? because all outlines have 1px width + "fill-outline-200m": { color: "#0b97c4", lineColor: "#7f7", lineWidth: 200 }, + "fill-rgba-outline-200m": { + color: "#0b97c470", + lineColor: "#7f7", + lineWidth: 200 + }, + "fill-rgba-outline-rgba-200m": { + color: "#0b97c470", + lineColor: "#7f77", + lineWidth: 200 + }, + "fill-outline-disabled": { + color: "#0b97c4", + lineColor: "#7f7", + lineWidth: 200, + enabled: false + }, + "fill-outline-partially-disabled": { + color: "#0b97c4", + lineColor: "#7f7", + lineWidth: 200, + enabled: ["match", ["get", "name"], "Awesome Building", true, false] + } + // TODO: not supported by typings + // "rect-rgba-outline-rgba-5px": { + // color: "#0b97c470", + // lineColor: "#7f77", + // lineWidth: "5px" + // } + }); + }); + describe("textured", function () { + const textureUrl = "../dist/resources/radar.png"; + makePolygonTestCases("fill", { + "fill-texture-feature-space": { + color: "#ffffff", + map: textureUrl, + mapProperties: { flipY: true, minFilter: "linear" }, + transparent: true, + textureCoordinateType: TextureCoordinateType.FeatureSpace, + enabled: ["match", ["get", "name"], "Awesome Building", true, false] + }, + "fill-texture-dynamic": { + color: "#ffffff", + map: ["get", "dynamic-texture", ["dynamic-properties"]], + mapProperties: { flipY: true, minFilter: "linear" }, + transparent: true, + textureCoordinateType: TextureCoordinateType.FeatureSpace, + enabled: ["match", ["get", "name"], "Awesome Building", true, false] + } + }, { + dynamicProperties: [{ name: "dynamic-texture", value: textureUrl }] + }); + }); + }); + describe("standard technique", function () { + mapViewFeaturesRenderingTest(`polygon-dynamic-color`, { + geoJson: { + type: "FeatureCollection", + features: [rectangle1, rectangle2, referenceBackground] + }, + theme: { + lights, + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'polygon'", + technique: "standard", + attr: { + color: ["get", "dynamic-color", ["dynamic-properties"]] + } + } + ] + } + }, + dynamicProperties: [{ name: "dynamic-color", value: "green" }] + }); + mapViewFeaturesRenderingTest(`polygon-standard-texture`, { + geoJson: { + type: "FeatureCollection", + features: [rectangle1, rectangle2, referenceBackground] + }, + theme: { + lights, + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'polygon'", + technique: "standard", + attr: { + color: "#ffffff", + map: "../dist/resources/wests_textures/paving.png", + mapProperties: { + repeatU: 10, + repeatV: 10, + wrapS: "repeat", + wrapT: "repeat" + }, + textureCoordinateType: TextureCoordinateType.TileSpace + } + } + ] + } + } + }, async () => { + // we have no API to know when texture is already loaded + await new Promise(resolve => setTimeout(resolve, 500)); + }); + mapViewFeaturesRenderingTest(`polygon-standard-texture-transparent`, { + geoJson: { + type: "FeatureCollection", + features: [rectangle1, referenceBackground] + }, + theme: { + lights, + styles: { + geojson: [ + referenceBackroundStyle, + { + when: "$geometryType == 'polygon'", + technique: "standard", + attr: { + color: "#ffffff", + opacity: 0.5, + map: "../dist/resources/wests_textures/paving.png", + mapProperties: { + repeatU: 10, + repeatV: 10, + wrapS: "repeat", + wrapT: "repeat" + }, + textureCoordinateType: TextureCoordinateType.TileSpace + } + } + ] + } + } + }, async () => { + // we have no API to know when texture is already loaded + await new Promise(resolve => setTimeout(resolve, 500)); + }); + }); + describe("extruded-polygon technique", function () { + const tower = { + // sample polygon, that is smaller and higher than previous one + type: "Feature", + geometry: { + type: "Polygon", + coordinates: [ + [ + [0.002, 0.001], + [-0.002, 0.001], + [-0.002, -0.001], + [0.002, -0.001], + [0.002, 0.001] + ] + ] + }, + properties: { + kind: "tower", + height: 400 + } + }; + const viewOptions = { + margin: 0.3, + lookAt: { + tilt: 35, + heading: 30 + } + }; + describe("flat", function () { + makePolygonTestCases("extruded-polygon", { + "extruded-polygon-flat": { color: "#0b97c4", height: 0 }, + "extruded-polygon-flat-rgba": { color: "#0b97c470", height: 0 }, + "extruded-polygon-flat-rgba-outline": { + color: "#0b97c470", + height: 0, + lineWidth: 1, + lineColor: "#aaa" + } + }, viewOptions); + }); + describe("3d", function () { + makePolygonTestCases("extruded-polygon", { + "extruded-polygon-3d": { color: "#0b97c4" }, + "extruded-polygon-3d-rgba": { + color: "#0b97c480" + }, + "extruded-polygon-3d-rgba-disabled": { + color: "#0b97c480", + enabled: false + }, + "extruded-polygon-3d-rgba-outline": { + color: "#0b97c480", + lineWidth: 1, + lineColorMix: 0, + lineColor: "#7f7" + }, + "extruded-polygon-3d-rgba-outline-disabled": { + color: "#0b97c480", + lineWidth: 1, + lineColorMix: 0, + lineColor: "#7f7", + enabled: false + }, + "extruded-polygon-3d-rgba-outline-partialy-disabled": { + color: "#0b97c480", + lineWidth: 1, + lineColorMix: 0, + lineColor: "#7f7", + enabled: ["match", ["get", "name"], "Awesome Building", true, false] + } + }, viewOptions); + }); + describe("3d overlapping", function () { + makePolygonTestCases("extruded-polygon", { + "extruded-polygon-3d-overlap": { color: "#0b97c4" }, + "extruded-polygon-3d-overlap-rgba": { + color: "#0b97c480" + }, + "extruded-polygon-3d-overlap-rgba-outline": { + color: "#0b97c480", + lineWidth: 1, + lineColorMix: 0, + lineColor: "#7f7" + } + }, { + geoJson: { + type: "FeatureCollection", + features: [tower] + }, + ...viewOptions + }); + }); + }); + }); +}); +//# sourceMappingURL=StylingTest.js.map \ No newline at end of file diff --git a/test/rendering/StylingTest.js.map b/test/rendering/StylingTest.js.map new file mode 100644 index 0000000..db99073 --- /dev/null +++ b/test/rendering/StylingTest.js.map @@ -0,0 +1 @@ +{"version":3,"file":"StylingTest.js","sourceRoot":"","sources":["StylingTest.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/WebTileDataRendering.d.ts b/test/rendering/WebTileDataRendering.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/test/rendering/WebTileDataRendering.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/test/rendering/WebTileDataRendering.js b/test/rendering/WebTileDataRendering.js new file mode 100644 index 0000000..eaf6abf --- /dev/null +++ b/test/rendering/WebTileDataRendering.js @@ -0,0 +1,288 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { sphereProjection } from "@flywave/flywave-geoutils"; +import { MapView, MapViewEventNames, TextureLoader } from "@flywave/flywave-mapview"; +import { RenderingTestHelper, waitForEvent } from "@flywave/flywave-test-utils"; +import { WebTileDataSource } from "@flywave/flywave-webtile-datasource"; +// Mocha discourages using arrow functions, see https://mochajs.org/#arrow-functions +describe("MapView + WebTileData rendering test", function () { + let mapView; + afterEach(() => { + if (mapView !== undefined) { + mapView.dispose(); + } + }); + async function webTileTest(options) { + const ibct = new RenderingTestHelper(options.mochaTest, { module: "mapview" }); + const canvas = document.createElement("canvas"); + canvas.width = 400; + canvas.height = 300; + mapView = new MapView({ + canvas, + theme: { clearColor: options.clearColor }, + preserveDrawingBuffer: true, + pixelRatio: 1, + projection: options.projection + }); + const defaultLookAt = { + target: { lat: 53.3, lng: 14.6 }, + zoomLevel: 2, + tilt: 0, + heading: 0 + }; + const lookAt = { ...defaultLookAt, ...options.lookAt }; + mapView.lookAt(lookAt); + // Shutdown errors cause by firefox bug + mapView.renderer.getContext().getShaderInfoLog = (x) => { + return ""; + }; + const webTileDataSource = new WebTileDataSource(Object.assign({ + dataProvider: { + getTexture: options.getTexture + }, + name: "webtile" + }, options.webTileOptions)); + mapView.addDataSource(webTileDataSource); + if (options.runBeforeFinish !== undefined) { + await options.runBeforeFinish(); + } + await waitForEvent(mapView, MapViewEventNames.FrameComplete); + await ibct.assertCanvasMatchesReference(canvas, options.testImageName); + } + it("renders webtile from loaded texture png", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-clover", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/clover.png"), + [] + ]); + } + }); + }); + it("renders webtile from loaded texture png on sphere", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-clover-sphere", + projection: sphereProjection, + clearColor: "#ff0000", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/clover.png"), + [] + ]); + } + }); + }); + it("renders webtile from loaded texture with opacity", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-opacity", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/clover.png"), + [] + ]); + }, + webTileOptions: { renderingOptions: { opacity: 0.5 } } + }); + }); + it("renders webtile from loaded texture with opacity on sphere", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-opacity-sphere", + projection: sphereProjection, + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/clover.png"), + [] + ]); + }, + webTileOptions: { renderingOptions: { opacity: 0.5 } } + }); + }); + it("renders webtile from loaded texture png with alpha", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-questionmark", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/replacementCharacter.png"), + [] + ]); + } + }); + }); + it("renders webtile from loaded texture png with alpha, with minDataLevel", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-min-data-level", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/replacementCharacter.png"), + [] + ]); + }, + webTileOptions: { minDataLevel: 3 } + }); + }); + it("renders webtile from loaded texture png with alpha, with minDisplayLevel", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-min-display-level", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/replacementCharacter.png"), + [] + ]); + }, + webTileOptions: { minDisplayLevel: 3 } + }); + }); + it("renders 3 layered webTileDataSources with renderOrder", async function () { + this.timeout(5000); + const runBeforeFinish = async function () { + const webTileDataSource = new WebTileDataSource({ + dataSourceOrder: 2000, + renderingOptions: { + transparent: true + }, + minDataLevel: 3, + dataProvider: { + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/replacementCharacter.png"), + [] + ]); + } + }, + name: "webtile-transparent" + }); + await mapView.addDataSource(webTileDataSource); + const webTileDataSourcePavement = new WebTileDataSource({ + dataSourceOrder: 0, + dataProvider: { + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/paving.png"), + [] + ]); + } + }, + name: "webtile-paving" + }); + await mapView.addDataSource(webTileDataSourcePavement); + }; + await webTileTest({ + mochaTest: this, + testImageName: "webtile-layered-order", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/clover.png"), + [] + ]); + }, + webTileOptions: { + renderingOptions: { + opacity: 0.5 + }, + dataSourceOrder: 1000, + name: "webtile-clover" + }, + runBeforeFinish + }); + }); + it("renders 3 layered webTileDataSources with opaque on top renderOrder", async function () { + this.timeout(5000); + const runBeforeFinish = async function () { + const webTileDataSource = new WebTileDataSource({ + renderingOptions: { + renderOrder: 3, + transparent: true + }, + minDataLevel: 3, + dataProvider: { + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/replacementCharacter.png"), + [] + ]); + } + }, + name: "webtile-transparent" + }); + await mapView.addDataSource(webTileDataSource); + const webTileDataSourcePavement = new WebTileDataSource({ + renderingOptions: { + renderOrder: 2 + }, + dataProvider: { + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/paving.png"), + [] + ]); + } + }, + name: "webtile-paving" + }); + await mapView.addDataSource(webTileDataSourcePavement); + }; + await webTileTest({ + mochaTest: this, + testImageName: "webtile-layered-render-order-opaque-top", + getTexture: (tile) => { + return Promise.all([ + new TextureLoader().load("../dist/resources/wests_textures/clover.png"), + [] + ]); + }, + webTileOptions: { + renderingOptions: { + opacity: 0.5, + renderOrder: 1 + }, + name: "webtile-clover" + }, + runBeforeFinish + }); + }); + it("renders webtiles on antimeridian without cracks for planar projection", async function () { + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-antimeridan-planar", + getTexture: (tile) => { + return Promise.all([new TextureLoader().load("../dist/resources/sea.png"), []]); + }, + lookAt: { + target: { lat: 64, lng: 180 }, + zoomLevel: 20 + } + }); + }); + it("renders webtiles on antimeridian without cracks for sphere projection", async function () { + // To be fixed. + this.timeout(5000); + await webTileTest({ + mochaTest: this, + testImageName: "webtile-antimeridan-sphere", + getTexture: (tile) => { + return Promise.all([new TextureLoader().load("../dist/resources/sea.png"), []]); + }, + lookAt: { + target: { lat: 64, lng: 180 }, + zoomLevel: 20 + }, + projection: sphereProjection + }); + }); +}); +//# sourceMappingURL=WebTileDataRendering.js.map \ No newline at end of file diff --git a/test/rendering/WebTileDataRendering.js.map b/test/rendering/WebTileDataRendering.js.map new file mode 100644 index 0000000..a691f4c --- /dev/null +++ b/test/rendering/WebTileDataRendering.js.map @@ -0,0 +1 @@ +{"version":3,"file":"WebTileDataRendering.js","sourceRoot":"","sources":["WebTileDataRendering.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/utils/GeoJsonStore.d.ts b/test/rendering/utils/GeoJsonStore.d.ts new file mode 100644 index 0000000..a3bc443 --- /dev/null +++ b/test/rendering/utils/GeoJsonStore.d.ts @@ -0,0 +1,34 @@ +import { type TileKey } from "@flywave/flywave-geoutils"; +import { DataProvider } from "@flywave/flywave-mapview-decoder"; +/** + * A simple {@link @flywave/flywave-mapview-decoder/DataProvider} that organizes GeoJson features using an rtree. + * + * The `GeoJsonStore` can be used as a {@link @flywave/flywave-mapview-decoder/DataProvider} + * of {@link @flywave/flywave-vectortile-datasource/VectorTileDataSource}s. + * + * @example + * ```typescript + * const geoJsonStore = new GeoJsonStore(); + * + * const dataSource = new VectorTileDataSource({ + * dataProvider: geoJsonStore, + * // ... + * }); + * + * geoJsonStore.features.insert(polygonFeature); + * geoJsonStore.features.insert(lineStringFeature); + * // ... + * ``` + */ +export declare class GeoJsonStore extends DataProvider { + /** + * The set of GeoJson features organized by this this `GeoJsonStore`. + */ + readonly features: import("geojson-rbush").RBush; + ready(): boolean; + getTile(tileKey: TileKey): Promise>; + protected connect(): Promise; + protected dispose(): void; +} diff --git a/test/rendering/utils/GeoJsonStore.js b/test/rendering/utils/GeoJsonStore.js new file mode 100644 index 0000000..817fa75 --- /dev/null +++ b/test/rendering/utils/GeoJsonStore.js @@ -0,0 +1,44 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { webMercatorTilingScheme } from "@flywave/flywave-geoutils"; +import { DataProvider } from "@flywave/flywave-mapview-decoder"; +import RBush from "geojson-rbush"; +/** + * A simple {@link @flywave/flywave-mapview-decoder/DataProvider} that organizes GeoJson features using an rtree. + * + * The `GeoJsonStore` can be used as a {@link @flywave/flywave-mapview-decoder/DataProvider} + * of {@link @flywave/flywave-vectortile-datasource/VectorTileDataSource}s. + * + * @example + * ```typescript + * const geoJsonStore = new GeoJsonStore(); + * + * const dataSource = new VectorTileDataSource({ + * dataProvider: geoJsonStore, + * // ... + * }); + * + * geoJsonStore.features.insert(polygonFeature); + * geoJsonStore.features.insert(lineStringFeature); + * // ... + * ``` + */ +export class GeoJsonStore extends DataProvider { + constructor() { + super(...arguments); + /** + * The set of GeoJson features organized by this this `GeoJsonStore`. + */ + this.features = RBush(); + } + ready() { + return true; + } + async getTile(tileKey) { + const { west, south, east, north } = webMercatorTilingScheme.getGeoBox(tileKey); + const features = this.features.search([west, south, east, north]); + return features; + } + async connect() { } + dispose() { } +} +//# sourceMappingURL=GeoJsonStore.js.map \ No newline at end of file diff --git a/test/rendering/utils/GeoJsonStore.js.map b/test/rendering/utils/GeoJsonStore.js.map new file mode 100644 index 0000000..6050483 --- /dev/null +++ b/test/rendering/utils/GeoJsonStore.js.map @@ -0,0 +1 @@ +{"version":3,"file":"GeoJsonStore.js","sourceRoot":"","sources":["GeoJsonStore.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,OAAO,EAAgB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,KAAK,MAAM,eAAe,CAAC;AAElC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,YAAa,SAAQ,YAAY;IAA9C;;QACI;;WAEG;QACM,aAAQ,GAAG,KAAK,EAAE,CAAC;IAehC,CAAC;IAbG,KAAK;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAgB;QAC1B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,uBAAuB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC;IACpB,CAAC;IAES,KAAK,CAAC,OAAO,KAAmB,CAAC;IAEjC,OAAO,KAAU,CAAC;CAC/B"} \ No newline at end of file diff --git a/test/rendering/utils/GeoJsonTest.d.ts b/test/rendering/utils/GeoJsonTest.d.ts new file mode 100644 index 0000000..3469e74 --- /dev/null +++ b/test/rendering/utils/GeoJsonTest.d.ts @@ -0,0 +1,28 @@ +import { type FlatTheme, type GeoJson, type Theme } from "@flywave/flywave-datasource-protocol"; +import { type Projection } from "@flywave/flywave-geoutils"; +import { type LookAtParams, MapView } from "@flywave/flywave-mapview"; +import { type DataProvider } from "@flywave/flywave-mapview-decoder"; +export interface GeoJsonDataSourceTestOptions { + geoJson?: string | GeoJson; + tileGeoJson?: boolean; + dataProvider?: DataProvider; + dataSourceOrder?: number; +} +export interface GeoJsonTestOptions extends GeoJsonDataSourceTestOptions { + mochaTest: Mocha.Context; + testImageName: string; + theme: Theme | FlatTheme; + geoJson?: string | GeoJson; + lookAt?: Partial; + tileGeoJson?: boolean; + dataProvider?: DataProvider; + extraDataSource?: GeoJsonDataSourceTestOptions; + beforeFinishCallback?: (mapView: MapView) => void; + size?: number; + projection?: Projection; +} +export declare class GeoJsonTest { + mapView: MapView; + dispose(): void; + run(options: GeoJsonTestOptions): Promise; +} diff --git a/test/rendering/utils/GeoJsonTest.js b/test/rendering/utils/GeoJsonTest.js new file mode 100644 index 0000000..a81353f --- /dev/null +++ b/test/rendering/utils/GeoJsonTest.js @@ -0,0 +1,75 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { GeoJsonDataProvider } from "@flywave/flywave-geojson-datasource/src"; +import { MapView, MapViewEventNames } from "@flywave/flywave-mapview"; +import { GeoJsonTiler } from "@flywave/flywave-mapview-decoder/index-worker"; +import { RenderingTestHelper, waitForEvent } from "@flywave/flywave-test-utils"; +import { VectorTileDataSource } from "@flywave/flywave-vectortile-datasource"; +import { VectorTileDecoder } from "@flywave/flywave-vectortile-datasource/index-worker"; +import * as sinon from "sinon"; +function createDataSource(name, options) { + const tiler = new GeoJsonTiler(); + if (options.tileGeoJson === false) { + sinon.stub(tiler, "getTile").resolves(options.geoJson); + } + return new VectorTileDataSource({ + decoder: new VectorTileDecoder(), + dataProvider: options.dataProvider ?? + new GeoJsonDataProvider("geojson", typeof options.geoJson === "string" + ? new URL(options.geoJson, window.location.href) + : options.geoJson, { tiler }), + name, + styleSetName: "geojson", + dataSourceOrder: options.dataSourceOrder + }); +} +export class GeoJsonTest { + dispose() { + this.mapView?.dispose(); + } + async run(options) { + const ibct = new RenderingTestHelper(options.mochaTest, { module: "mapview" }); + const canvas = document.createElement("canvas"); + canvas.width = 400; + canvas.height = 300; + this.mapView = new MapView({ + canvas, + theme: options.theme, + preserveDrawingBuffer: true, + pixelRatio: 1, + disableFading: true, + projection: options.projection + }); + this.mapView.animatedExtrusionHandler.enabled = false; + const defaultLookAt = { + target: { lat: 53.3, lng: 14.6 }, + distance: 200000, + tilt: 0, + heading: 0 + }; + const lookAt = { ...defaultLookAt, ...options.lookAt }; + this.mapView.lookAt(lookAt); + // Shutdown errors cause by firefox bug + this.mapView.renderer.getContext().getShaderInfoLog = (x) => { + return ""; + }; + const tiler = new GeoJsonTiler(); + if (options.tileGeoJson === false) { + sinon.stub(tiler, "getTile").resolves(options.geoJson); + } + const dataSource = createDataSource("geojson", options); + this.mapView.setDynamicProperty("enabled", true); + if (options.size) { + this.mapView.setDynamicProperty("size", options.size); + } + await this.mapView.addDataSource(dataSource); + if (options.extraDataSource) { + await this.mapView.addDataSource(createDataSource("geojson2", options.extraDataSource)); + } + if (options.beforeFinishCallback) { + await options.beforeFinishCallback?.(this.mapView); + } + await waitForEvent(this.mapView, MapViewEventNames.FrameComplete); + await ibct.assertCanvasMatchesReference(canvas, options.testImageName); + } +} +//# sourceMappingURL=GeoJsonTest.js.map \ No newline at end of file diff --git a/test/rendering/utils/GeoJsonTest.js.map b/test/rendering/utils/GeoJsonTest.js.map new file mode 100644 index 0000000..7949e64 --- /dev/null +++ b/test/rendering/utils/GeoJsonTest.js.map @@ -0,0 +1 @@ +{"version":3,"file":"GeoJsonTest.js","sourceRoot":"","sources":["GeoJsonTest.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/test/rendering/utils/ThemeBuilder.d.ts b/test/rendering/utils/ThemeBuilder.d.ts new file mode 100644 index 0000000..f29bab1 --- /dev/null +++ b/test/rendering/utils/ThemeBuilder.d.ts @@ -0,0 +1,45 @@ +import { type FlatTheme, type ImageTexture, type Light, type Style } from "@flywave/flywave-datasource-protocol"; +/** + * Utility Class for Rendering IBCT Tests + */ +export declare class ThemeBuilder { + private readonly m_useEmptyTheme; + static readonly imageTextures: ImageTexture[]; + static readonly lights: Light[]; + static readonly markerStyle: Style; + static readonly images: { + "icon-to-load": { + preload: boolean; + url: any; + }; + "red-icon": { + url: string; + preload: boolean; + }; + "green-icon": { + url: string; + preload: boolean; + }; + "white-icon": { + url: string; + preload: boolean; + }; + "plus-icon": { + url: string; + preload: boolean; + }; + }; + private readonly m_baseTheme; + private m_theme; + /** + * + * @param m_useEmptyTheme - If `true` initializes with an empty Theme, @default `false` + * The default uses some basic theme settings for initialization. + */ + constructor(m_useEmptyTheme?: boolean); + build(): FlatTheme; + withFontCatalog(): this; + withInvalidFontCatalog(): this; + withMarkerStyle(): this; + withStyle(style: Style): this; +} diff --git a/test/rendering/utils/ThemeBuilder.js b/test/rendering/utils/ThemeBuilder.js new file mode 100644 index 0000000..67a373b --- /dev/null +++ b/test/rendering/utils/ThemeBuilder.js @@ -0,0 +1,142 @@ +/* Copyright (C) 2025 flywave.gl contributors */ +import { getAppBaseUrl, resolveReferenceUri } from "@flywave/flywave-utils"; +// Mocha discourages using arrow functions, see https://mochajs.org/#arrow-functions +/** + * Utility Class for Rendering IBCT Tests + */ +export class ThemeBuilder { + /** + * + * @param m_useEmptyTheme - If `true` initializes with an empty Theme, @default `false` + * The default uses some basic theme settings for initialization. + */ + constructor(m_useEmptyTheme = false) { + this.m_useEmptyTheme = m_useEmptyTheme; + this.m_baseTheme = { + lights: ThemeBuilder.lights, + sky: { + type: "gradient", + topColor: "#161719", + bottomColor: "#262829", + groundColor: "#262829" + }, + clearColor: "#4A4D4E", + images: ThemeBuilder.images, + imageTextures: ThemeBuilder.imageTextures, + styles: [] + }; + this.m_theme = { styles: [] }; + if (!this.m_useEmptyTheme) { + this.m_theme = this.m_baseTheme; + } + } + build() { + return this.m_theme; + } + withFontCatalog() { + this.m_theme = { + ...this.m_theme, + fontCatalogs: [ + { + name: "fira", + url: "../dist/resources/fonts/Default_FontCatalog.json" + } + ] + }; + return this; + } + withInvalidFontCatalog() { + this.m_theme = { + ...this.m_theme, + fontCatalogs: [ + { + name: "invalid", + url: "invalid.json" + } + ] + }; + return this; + } + withMarkerStyle() { + return this.withStyle(ThemeBuilder.markerStyle); + } + withStyle(style) { + this.m_theme.styles.push(style); + return this; + } +} +ThemeBuilder.imageTextures = [ + { + name: "white-icon", + image: "white-icon" + }, + { + name: "red-icon", + image: "red-icon" + }, + { + name: "green-icon", + image: "green-icon" + }, + { + name: "plus-icon", + image: "plus-icon" + } +]; +ThemeBuilder.lights = [ + { + type: "ambient", + color: "#FFFFFF", + name: "ambientLight", + intensity: 0.9 + }, + { + type: "directional", + color: "#FFFFFF", + name: "light1", + intensity: 0.8, + direction: { + x: 1, + y: 5, + z: 0.5 + } + } +]; +ThemeBuilder.markerStyle = { + id: "baseOrder", + when: ["==", ["geometry-type"], "Point"], + technique: "labeled-icon", + // imageTexture: "white-icon", + size: ["number", ["get", "size"], 15], + iconYOffset: ["number", ["get", "iconYOffset"], 30], + text: ["get", "text"], + color: ["get", "color"], + imageTexture: ["string", ["get", "imageTexture"], "white-icon"], + renderOrder: ["get", "renderOrder"], + textReserveSpace: false, + iconReserveSpace: false, + styleSet: "geojson" +}; +ThemeBuilder.images = { + "icon-to-load": { + preload: false, + url: resolveReferenceUri(getAppBaseUrl(), "../dist/resources/icon-128x128.png") + }, + "red-icon": { + url: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOCIgaGVpZ2h0PSI0NyIgdmlld0JveD0iMCAwIDM4IDQ3Ij48ZyBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjMEYxNjIxIiBmaWxsLW9wYWNpdHk9Ii40IiBkPSJNMTUgNDZjMCAuMzE3IDEuNzkuNTc0IDQgLjU3NHM0LS4yNTcgNC0uNTc0YzAtLjMxNy0xLjc5LS41NzQtNC0uNTc0cy00IC4yNTctNCAuNTc0eiI+PC9wYXRoPjxwYXRoIGZpbGw9IiNiNjAxMDEiIGQ9Ik0zMy4yNSAzMS42NTJBMTkuMDE1IDE5LjAxNSAwIDAgMCAzOCAxOS4wNkMzOCA4LjU0OSAyOS40NzggMCAxOSAwUzAgOC41NSAwIDE5LjA1OWMwIDQuODIzIDEuNzk1IDkuMjMzIDQuNzUgMTIuNTkzTDE4Ljk3NSA0NiAzMy4yNSAzMS42NTJ6Ij48L3BhdGg+PHBhdGggZmlsbD0iIzZBNkQ3NCIgZmlsbC1vcGFjaXR5PSIuNSIgZD0iTTI2Ljg2MiAzNy41bDQuNzE0LTQuNzdjMy44MjItMy41NzYgNS45MjQtOC40MTEgNS45MjQtMTMuNjJDMzcuNSA4Ljg0NyAyOS4yLjUgMTkgLjVTLjUgOC44NDguNSAxOS4xMWMwIDUuMjA5IDIuMTAyIDEwLjA0NCA1LjkxOSAxMy42MTRsNC43MTkgNC43NzZoMTUuNzI0ek0xOSAwYzEwLjQ5MyAwIDE5IDguNTI1IDE5IDE5LjA0MSAwIDUuNTA3LTIuMzQ4IDEwLjQ1NC02LjA3OSAxMy45MzJMMTkgNDYgNi4wNzkgMzIuOTczQzIuMzQ4IDI5LjQ5NSAwIDI0LjU0OCAwIDE5LjA0IDAgOC41MjUgOC41MDcgMCAxOSAweiI+PC9wYXRoPjwvZz48L3N2Zz4K", + preload: true + }, + "green-icon": { + url: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOCIgaGVpZ2h0PSI0NyIgdmlld0JveD0iMCAwIDM4IDQ3Ij48ZyBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjMEYxNjIxIiBmaWxsLW9wYWNpdHk9Ii40IiBkPSJNMTUgNDZjMCAuMzE3IDEuNzkuNTc0IDQgLjU3NHM0LS4yNTcgNC0uNTc0YzAtLjMxNy0xLjc5LS41NzQtNC0uNTc0cy00IC4yNTctNCAuNTc0eiI+PC9wYXRoPjxwYXRoIGZpbGw9IiMwNGI2MDEiIGQ9Ik0zMy4yNSAzMS42NTJBMTkuMDE1IDE5LjAxNSAwIDAgMCAzOCAxOS4wNkMzOCA4LjU0OSAyOS40NzggMCAxOSAwUzAgOC41NSAwIDE5LjA1OWMwIDQuODIzIDEuNzk1IDkuMjMzIDQuNzUgMTIuNTkzTDE4Ljk3NSA0NiAzMy4yNSAzMS42NTJ6Ij48L3BhdGg+PHBhdGggZmlsbD0iIzZBNkQ3NCIgZmlsbC1vcGFjaXR5PSIuNSIgZD0iTTI2Ljg2MiAzNy41bDQuNzE0LTQuNzdjMy44MjItMy41NzYgNS45MjQtOC40MTEgNS45MjQtMTMuNjJDMzcuNSA4Ljg0NyAyOS4yLjUgMTkgLjVTLjUgOC44NDguNSAxOS4xMWMwIDUuMjA5IDIuMTAyIDEwLjA0NCA1LjkxOSAxMy42MTRsNC43MTkgNC43NzZoMTUuNzI0ek0xOSAwYzEwLjQ5MyAwIDE5IDguNTI1IDE5IDE5LjA0MSAwIDUuNTA3LTIuMzQ4IDEwLjQ1NC02LjA3OSAxMy45MzJMMTkgNDYgNi4wNzkgMzIuOTczQzIuMzQ4IDI5LjQ5NSAwIDI0LjU0OCAwIDE5LjA0IDAgOC41MjUgOC41MDcgMCAxOSAweiI+PC9wYXRoPjwvZz48L3N2Zz4K", + preload: true + }, + "white-icon": { + url: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIyLjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZlcnNpb249IjEuMSIgaWQ9Imx1aS1pY29uLWRlc3RpbmF0aW9ucGluLW9uZGFyay1zb2xpZC1sYXJnZSIKCSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ4IDQ4IgoJIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQ4IDQ4IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGc+Cgk8ZyBpZD0ibHVpLWljb24tZGVzdGluYXRpb25waW4tb25kYXJrLXNvbGlkLWxhcmdlLWJvdW5kaW5nLWJveCIgb3BhY2l0eT0iMCI+CgkJPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTQ3LDF2NDZIMVYxSDQ3IE00OCwwSDB2NDhoNDhWMEw0OCwweiIvPgoJPC9nPgoJPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNmZmZmZmYiIGQ9Ik0yNCwyQzEzLjg3MDgsMiw1LjY2NjcsMTAuMTU4NCw1LjY2NjcsMjAuMjIzMwoJCWMwLDUuMDMyNSwyLjA1MzMsOS41ODg0LDUuMzcxNywxMi44ODgzTDI0LDQ2bDEyLjk2MTctMTIuODg4M2MzLjMxODMtMy4zLDUuMzcxNy03Ljg1NTgsNS4zNzE3LTEyLjg4ODMKCQlDNDIuMzMzMywxMC4xNTg0LDM0LjEyOTIsMiwyNCwyeiBNMjQsMjVjLTIuNzY1LDAtNS0yLjIzNS01LTVzMi4yMzUtNSw1LTVzNSwyLjIzNSw1LDVTMjYuNzY1LDI1LDI0LDI1eiIvPgo8L2c+Cjwvc3ZnPgo=", + preload: true + }, + "plus-icon": { + url: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iMTIwIgogICBpZD0ic3ZnMjQ1NCIKICAgc29kaXBvZGk6dmVyc2lvbj0iMC4zMiIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC40NiIKICAgdmVyc2lvbj0iMS4wIgogICBzb2RpcG9kaTpkb2NuYW1lPSJQbHVzIHN5bWJvbC5zdmciCiAgIGlua3NjYXBlOm91dHB1dF9leHRlbnNpb249Im9yZy5pbmtzY2FwZS5vdXRwdXQuc3ZnLmlua3NjYXBlIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzMjQ1NiI+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNTI2LjE4MTA5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9Ijc0NC4wOTQ0OCA6IDUyNi4xODEwOSA6IDEiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMzcyLjA0NzI0IDogMzUwLjc4NzM5IDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI0NjIiIC8+CiAgPC9kZWZzPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0iYmFzZSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMS4wIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp6b29tPSIwLjc5NTQ5NTEzIgogICAgIGlua3NjYXBlOmN4PSIxOTQuNTEzNjEiCiAgICAgaW5rc2NhcGU6Y3k9IjI2Ny43ODMzOSIKICAgICBpbmtzY2FwZTpkb2N1bWVudC11bml0cz0icHgiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ibGF5ZXIxIgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjE0NDAiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iODgxIgogICAgIGlua3NjYXBlOndpbmRvdy14PSItNCIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iLTQiIC8+CiAgPGcKICAgICBpbmtzY2FwZTpsYWJlbD0iTGl2ZWxsbyAxIgogICAgIGlua3NjYXBlOmdyb3VwbW9kZT0ibGF5ZXIiCiAgICAgaWQ9ImxheWVyMSIKICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMikiPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmb250LXNpemU6NDMxLjkyNDIyNDg1cHg7Zm9udC1zdHlsZTpub3JtYWw7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZpbGw6I2ZmMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MXB4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjE7Zm9udC1mYW1pbHk6Qml0c3RyZWFtIFZlcmEgU2FucyIKICAgICAgIGQ9Ik0gMjQxLjk5MjE5LDQwNy45MTAxNiBMIDI0MS45OTIxOSwzMTAuNDQ5MjIgTCAxNDQuNzI2NTYsMzEwLjQ0OTIyIEwgMTQ0LjcyNjU2LDI5NC40MzM1OSBMIDI0MS45OTIxOSwyOTQuNDMzNTkgTCAyNDEuOTkyMTksMTk3LjM2MzI4IEwgMjU3LjYxNzE5LDE5Ny4zNjMyOCBMIDI1Ny42MTcxOSwyOTQuNDMzNTkgTCAzNTUuMjczNDQsMjk0LjQzMzU5IEwgMzU1LjI3MzQ0LDMxMC40NDkyMiBMIDI1Ny42MTcxOSwzMTAuNDQ5MjIgTCAyNTcuNjE3MTksNDA3LjkxMDE2IEwgMjQxLjk5MjE5LDQwNy45MTAxNiB6IgogICAgICAgaWQ9InRleHQyNDY0IiAvPgogIDwvZz4KPC9zdmc+Cg==", + preload: true + } +}; +//# sourceMappingURL=ThemeBuilder.js.map \ No newline at end of file diff --git a/test/rendering/utils/ThemeBuilder.js.map b/test/rendering/utils/ThemeBuilder.js.map new file mode 100644 index 0000000..ba8796b --- /dev/null +++ b/test/rendering/utils/ThemeBuilder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ThemeBuilder.js","sourceRoot":"","sources":["ThemeBuilder.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAQhD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE5E,uFAAuF;AAEvF;;GAEG;AACH,MAAM,OAAO,YAAY;IAgGrB;;;;OAIG;IACH,YAA6B,kBAA2B,KAAK;QAAhC,oBAAe,GAAf,eAAe,CAAiB;QArB5C,gBAAW,GAAc;YACtC,MAAM,EAAE,YAAY,CAAC,MAAM;YAC3B,GAAG,EAAE;gBACD,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,SAAS;gBACnB,WAAW,EAAE,SAAS;gBACtB,WAAW,EAAE,SAAS;aACzB;YACD,UAAU,EAAE,SAAS;YACrB,MAAM,EAAE,YAAY,CAAC,MAAM;YAC3B,aAAa,EAAE,YAAY,CAAC,aAAa;YACzC,MAAM,EAAE,EAAE;SACb,CAAC;QAEM,YAAO,GAAc,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAQxC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,CAAC;IACL,CAAC;IAED,KAAK;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,eAAe;QACX,IAAI,CAAC,OAAO,GAAG;YACX,GAAG,IAAI,CAAC,OAAO;YACf,YAAY,EAAE;gBACV;oBACI,IAAI,EAAE,MAAM;oBACZ,GAAG,EAAE,kDAAkD;iBAC1D;aACJ;SACJ,CAAC;QACF,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,sBAAsB;QAClB,IAAI,CAAC,OAAO,GAAG;YACX,GAAG,IAAI,CAAC,OAAO;YACf,YAAY,EAAE;gBACV;oBACI,IAAI,EAAE,SAAS;oBACf,GAAG,EAAE,cAAc;iBACtB;aACJ;SACJ,CAAC;QACF,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,eAAe;QACX,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,SAAS,CAAC,KAAY;QAClB,IAAI,CAAC,OAAO,CAAC,MAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IAChB,CAAC;;AA/Ie,0BAAa,GAAmB;IAC5C;QACI,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,YAAY;KACtB;IACD;QACI,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KACpB;IACD;QACI,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,YAAY;KACtB;IACD;QACI,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,WAAW;KACrB;CACJ,AAjB4B,CAiB3B;AAEc,mBAAM,GAAY;IAC9B;QACI,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,cAAc;QACpB,SAAS,EAAE,GAAG;KACjB;IACD;QACI,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,GAAG;QACd,SAAS,EAAE;YACP,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,GAAG;SACT;KACJ;CACJ,AAlBqB,CAkBpB;AAEc,wBAAW,GAAU;IACjC,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACxC,SAAS,EAAE,cAAc;IAEzB,qCAAqC;IACrC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IACrC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC;IACnD,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,EAAE,YAAY,CAAC;IAC/D,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;IACnC,gBAAgB,EAAE,KAAK;IACvB,gBAAgB,EAAE,KAAK;IACvB,QAAQ,EAAE,SAAS;CACtB,AAf0B,CAezB;AAEc,mBAAM,GAAG;IACrB,cAAc,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,GAAG,EAAE,mBAAmB,CAAC,aAAa,EAAE,EAAE,oCAAoC,CAAC;KAClF;IACD,UAAU,EAAE;QACR,GAAG,EAAE,4gCAA4gC;QACjhC,OAAO,EAAE,IAAI;KAChB;IACD,YAAY,EAAE;QACV,GAAG,EAAE,4gCAA4gC;QACjhC,OAAO,EAAE,IAAI;KAChB;IACD,YAAY,EAAE;QACV,GAAG,EAAE,gsCAAgsC;QACrsC,OAAO,EAAE,IAAI;KAChB;IACD,WAAW,EAAE;QACT,GAAG,EAAE,g5FAAg5F;QACr5F,OAAO,EAAE,IAAI;KAChB;CACJ,AArBqB,CAqBpB"} \ No newline at end of file